KiCad PCB EDA Suite
Loading...
Searching...
No Matches
file_utils.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "qa_utils/file_utils.h"
21
22#include <cstdio>
23#include <filesystem>
24#include <stdexcept>
25#include <string>
26
27#include <wx/ffile.h>
28#include <wx/filefn.h>
29#include <wx/filename.h>
30#include <wx/tokenzr.h>
31#include <wx/utils.h>
32#include <wx_filename.h>
33
36
37
38using namespace KI_TEST;
39
40
47static void reportTempDir( const wxString& aMessage )
48{
49 fprintf( stderr, "%s\n", aMessage.utf8_string().c_str() );
50}
51
52
53static bool shouldKeepTemp( const std::filesystem::path& aPath, const wxString& aKeepEnvValue )
54{
55 const wxString envVar = wxT( "KICAD_QA_KEEP_TEMP" );
56 wxString keepEnv;
57
58 if( !wxGetEnv( envVar, &keepEnv ) || keepEnv.IsEmpty() )
59 return false;
60
61 // Split the environment variable on commas (like WXTRACE)
62 wxStringTokenizer tokenizer( keepEnv, wxT( "," ) );
63
64 while( tokenizer.HasMoreTokens() )
65 {
66 wxString token = tokenizer.GetNextToken();
67
68 if( token == aKeepEnvValue || token == wxT( "ALL" ) )
69 {
70 // Probably do want to see this, because if you are keeping the temp dirs, you may
71 // want to know which ones they are.
72 reportTempDir( wxString::Format( wxT( "Keeping temporary directory '%s' because %s is set to '%s'" ),
73 wxString::FromUTF8( aPath.string() ), envVar, keepEnv ) );
74 return true;
75 }
76 }
77
78 return false;
79}
80
81
82static std::filesystem::path createTempDir( const wxString& aPrefix )
83{
84 wxString tempFile = wxFileName::CreateTempFileName( aPrefix + "_" );
85
86 if( tempFile.IsEmpty() )
87 throw std::runtime_error( "Cannot create a temporary directory name with prefix '"
88 + std::string( aPrefix.utf8_str() ) + "'" );
89
90 if( !wxRemoveFile( tempFile ) )
91 throw std::runtime_error( "Cannot reclaim temporary name '" + std::string( tempFile.utf8_str() ) + "'" );
92
93 if( !wxMkdir( tempFile ) )
94 throw std::runtime_error( "Cannot create temporary directory '" + std::string( tempFile.utf8_str() ) + "'" );
95
96 return std::filesystem::path( std::string( tempFile.utf8_str() ) );
97}
98
99
101
102
103SCOPED_TEMP_DIR::SCOPED_TEMP_DIR( const wxString& aPrefix ) :
104 m_path( createTempDir( aPrefix ) ),
105 m_keep( shouldKeepTemp( m_path, aPrefix ) )
106{
107 if( m_keep )
109}
110
111
113{
114 if( m_keep )
115 return;
116
117 try
118 {
119 std::filesystem::remove_all( m_path );
120 }
121 catch( const std::filesystem::filesystem_error& e )
122 {
123 reportTempDir( wxString::Format( wxT( "Cannot remove temporary directory '%s': %s" ),
124 wxString::FromUTF8( m_path.string() ), wxString::FromUTF8( e.what() ) ) );
125 }
126}
127
128
130{
131 m_keep = true;
133
135 wxString::Format( wxT( "Keeping temporary directory '%s'" ), wxString::FromUTF8( m_path.string() ) ) );
136}
137
138
139wxString SCOPED_TEMP_DIR::ChildPathStr( const wxString& aName ) const
140{
141 return wxString::FromUTF8( ( m_path / aName.utf8_string() ).string() );
142}
143
144
145std::filesystem::path SCOPED_TEMP_DIR::CreateChildDir( const wxString& aName ) const
146{
147 std::filesystem::path childPath = m_path / aName.utf8_string();
148
149 if( !std::filesystem::create_directory( childPath ) )
150 throw std::runtime_error( "Cannot create temporary child directory '" + childPath.string() + "'" );
151
152 return childPath;
153}
154
155
156wxString SCOPED_TEMP_DIR::CreateChildDirStr( const wxString& aName ) const
157{
158 return wxString::FromUTF8( CreateChildDir( aName ).string() );
159}
160
161
162std::filesystem::path SCOPED_TEMP_DIR::CreateChildFile( const wxString& aName ) const
163{
164 std::filesystem::path childPath = m_path / aName.utf8_string();
165 wxFFile file( wxString::FromUTF8( childPath.string() ), wxT( "w" ) );
166
167 if( !file.IsOpened() )
168 throw std::runtime_error( "Cannot create temporary child file '" + childPath.string() + "'" );
169
170 return childPath;
171}
172
173
174wxString SCOPED_TEMP_DIR::CreateChildFileStr( const wxString& aName ) const
175{
176 return wxString::FromUTF8( CreateChildFile( aName ).string() );
177}
178
179
181 const wxString& aName ) :
182 m_dir( aPrefix ),
183 m_manager( aManager ),
184 m_project( nullptr )
185{
186 wxFileName projectFile( m_dir.PathStr(), aName, FILEEXT::ProjectFileExtension );
187
188 m_manager.LoadProject( projectFile.GetFullPath() );
189 m_project = m_manager.GetProject( projectFile.GetFullPath() );
190
191 if( !m_project )
192 {
193 throw std::runtime_error( "Cannot load temporary project '"
194 + std::string( projectFile.GetFullPath().utf8_str() ) + "'" );
195 }
196}
197
198
200{
201 m_manager.UnloadProject( m_project, false );
202}
203
204
206 m_dir( aPrefix )
207{
208 const wxString envValue = m_dir.PathStr();
209
210 wxSetEnv( wxT( "TMPDIR" ), envValue ); // This is the POSIX one
211 wxSetEnv( wxT( "TEMP" ), envValue );
212 wxSetEnv( wxT( "TMP" ), envValue );
213}
214
215
217{
218 // If any temporary directory has been retained, we must retain this one too
220 m_dir.Retain();
221}
SCOPED_PROCESS_TEMP_DIR(const wxString &aPrefix)
std::filesystem::path m_path
Definition file_utils.h:123
static bool s_anyTempDirRetained
Definition file_utils.h:127
wxString CreateChildFileStr(const wxString &aName) const
Create and return the path to a direct child file as a wxString.
void Retain()
Keep this directory after all.
static bool AnyTempDirRetained()
Definition file_utils.h:120
wxString ChildPathStr(const wxString &aName) const
Get the path to a direct child of the temporary directory as a wxString, without creating the child.
wxString CreateChildDirStr(const wxString &aName) const
Create and return the path to a direct child directory as a wxString.
SCOPED_TEMP_DIR(const wxString &aPrefix)
Create a temporary directory with a unique name based on the given prefix.
std::filesystem::path CreateChildFile(const wxString &aName) const
Create and return the path to a direct child file.
std::filesystem::path CreateChildDir(const wxString &aName) const
Create and return the path to a direct child directory.
SETTINGS_MANAGER & m_manager
Definition file_utils.h:154
SCOPED_TEMP_PROJECT(SETTINGS_MANAGER &aManager, const wxString &aPrefix, const wxString &aName)
static std::filesystem::path createTempDir(const wxString &aPrefix)
static bool shouldKeepTemp(const std::filesystem::path &aPath, const wxString &aKeepEnvValue)
static void reportTempDir(const wxString &aMessage)
Report a message about a temporary directory.
static const std::string ProjectFileExtension
Definition of file extensions used in Kicad.