KiCad PCB EDA Suite
env_paths.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2017 Wayne Stambaugh <stambaughw@verizon.net>
5  * Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
6  * Copyright (C) 2017 CERN
7  * @author Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * This program is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation, either version 3 of the License, or (at your
12  * option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <env_paths.h>
24 
25 static bool normalizeAbsolutePaths( const wxFileName& aPathA,
26  const wxFileName& aPathB,
27  wxString* aResultPath )
28 {
29  wxCHECK_MSG( aPathA.IsAbsolute(), false, aPathA.GetPath() + " is not an absolute path." );
30  wxCHECK_MSG( aPathB.IsAbsolute(), false, aPathB.GetPath() + " is not an absolute path." );
31 
32  if( aPathA.GetPath() == aPathB.GetPath() )
33  return true;
34 
35  if( ( aPathA.GetDirCount() > aPathB.GetDirCount() )
36  || ( aPathA.HasVolume() && !aPathB.HasVolume() )
37  || ( !aPathA.HasVolume() && aPathB.HasVolume() )
38  || ( ( aPathA.HasVolume() && aPathB.HasVolume() )
39  && ( aPathA.GetVolume() != aPathB.GetVolume() ) ) )
40  return false;
41 
42  wxArrayString aDirs = aPathA.GetDirs();
43  wxArrayString bDirs = aPathB.GetDirs();
44 
45  size_t i = 0;
46 
47  while( i < aDirs.GetCount() )
48  {
49  if( aDirs[i] != bDirs[i] )
50  return false;
51 
52  i++;
53  }
54 
55  if( aResultPath )
56  {
57  while( i < bDirs.GetCount() )
58  {
59  *aResultPath += bDirs[i] + wxT( "/" );
60  i++;
61  }
62  }
63 
64  return true;
65 }
66 
67 wxString NormalizePath( const wxFileName& aFilePath, const ENV_VAR_MAP* aEnvVars,
68  const wxString& aProjectPath )
69 {
70  wxFileName envPath;
71  wxString tmp, varName, normalizedFullPath;
72 
73  if( aEnvVars )
74  {
75  for( auto& entry : *aEnvVars )
76  {
77  // Don't bother normalizing paths that don't exist or the user cannot read.
78  if( !wxFileName::DirExists( entry.second.GetValue() )
79  || !wxFileName::IsDirReadable( entry.second.GetValue() ) )
80  continue;
81 
82  envPath.SetPath( entry.second.GetValue() );
83 
84  if( normalizeAbsolutePaths( envPath, aFilePath, &tmp ) )
85  {
86  varName = entry.first;
87  break;
88  }
89  }
90  }
91 
92  if( varName.IsEmpty() && !aProjectPath.IsEmpty()
93  && wxFileName( aProjectPath ).IsAbsolute() && wxFileName( aFilePath ).IsAbsolute() )
94  {
95  envPath.SetPath( aProjectPath );
96 
97  if( normalizeAbsolutePaths( envPath, aFilePath, &tmp ) )
98  varName = PROJECT_VAR_NAME;
99  }
100 
101  if( !varName.IsEmpty() )
102  {
103  normalizedFullPath = wxString::Format( "${%s}/", varName );
104 
105  if( !tmp.IsEmpty() )
106  normalizedFullPath += tmp;
107 
108  normalizedFullPath += aFilePath.GetFullName();
109  }
110 
111  return normalizedFullPath;
112 }
113 
114 wxString NormalizePath( const wxFileName& aFilePath, const ENV_VAR_MAP* aEnvVars,
115  const PROJECT* aProject )
116 {
117  if( aProject )
118  return NormalizePath( aFilePath, aEnvVars, aProject->GetProjectPath() );
119  else
120  return NormalizePath( aFilePath, aEnvVars, "" );
121 }
122 
123 
124 // Create file path by appending path and file name. This approach allows the filename
125 // to contain a relative path, whereas wxFileName::SetPath() would replace the
126 // relative path
127 static wxString createFilePath( const wxString& aPath, const wxString& aFileName )
128 {
129  wxString path( aPath );
130 
131  if( !path.EndsWith( wxFileName::GetPathSeparator() ) )
132  path.Append( wxFileName::GetPathSeparator() );
133 
134  return path + aFileName;
135 }
136 
137 
138 wxString ResolveFile( const wxString& aFileName, const ENV_VAR_MAP* aEnvVars,
139  const PROJECT* aProject )
140 {
141  wxFileName full( aFileName );
142 
143  if( full.IsAbsolute() )
144  return full.GetFullPath();
145 
146  if( aProject )
147  {
148  wxFileName fn( createFilePath( aProject->GetProjectPath(), aFileName ) );
149 
150  if( fn.Exists() )
151  return fn.GetFullPath();
152  }
153 
154  if( aEnvVars )
155  {
156  for( auto& entry : *aEnvVars )
157  {
158  wxFileName fn( createFilePath( entry.second.GetValue(), aFileName ) );
159 
160  if( fn.Exists() )
161  return fn.GetFullPath();
162  }
163  }
164 
165  return wxEmptyString;
166 }
wxString ResolveFile(const wxString &aFileName, const ENV_VAR_MAP *aEnvVars, const PROJECT *aProject)
Searches the default paths trying to find one with the requested file.
Definition: env_paths.cpp:138
Class PROJECT holds project specific data.
Definition: project.h:57
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:37
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
Definition: pgm_base.h:129
static wxString createFilePath(const wxString &aPath, const wxString &aFileName)
Definition: env_paths.cpp:127
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
size_t i
Definition: json11.cpp:597
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:102
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalizes a file path to an environmental variable, if possible.
Definition: env_paths.cpp:67
static bool normalizeAbsolutePaths(const wxFileName &aPathA, const wxFileName &aPathB, wxString *aResultPath)
Definition: env_paths.cpp:25