KiCad PCB EDA Suite
PROJECT_ARCHIVER Class Reference

#include <project_archiver.h>

Public Member Functions

 PROJECT_ARCHIVER ()
 
 ~PROJECT_ARCHIVER ()=default
 
bool Archive (const wxString &aSrcDir, const wxString &aDestFile, REPORTER &aReporter, bool aVerbose=true, bool aIncludeExtraFiles=false)
 Creates an archive of the project. More...
 
bool Unarchive (const wxString &aSrcFile, const wxString &aDestDir, REPORTER &aReporter)
 Extracts an archive of the current project over existing files Warning: this will overwrite files in the project directory. More...
 

Detailed Description

Definition at line 31 of file project_archiver.h.

Constructor & Destructor Documentation

◆ PROJECT_ARCHIVER()

PROJECT_ARCHIVER::PROJECT_ARCHIVER ( )

Definition at line 39 of file project_archiver.cpp.

40{
41}

◆ ~PROJECT_ARCHIVER()

PROJECT_ARCHIVER::~PROJECT_ARCHIVER ( )
default

Member Function Documentation

◆ Archive()

bool PROJECT_ARCHIVER::Archive ( const wxString &  aSrcDir,
const wxString &  aDestFile,
REPORTER aReporter,
bool  aVerbose = true,
bool  aIncludeExtraFiles = false 
)

Creates an archive of the project.

Parameters
aSrcFileis the full path to the project to be archived
aDestFileis the full path to the zip file to be created
aReporteris used to report status
aVerbosecontrols the verbosity of reported status messages
aIncludeExtraFilesif true will archive legacy and output files
Returns
true if the archive was created successfully

Definition at line 110 of file project_archiver.cpp.

112{
113 // List of file extensions that are always archived
114 static const wxChar* extensionList[] = {
115 wxT( "*.kicad_pro" ),
116 wxT( "*.kicad_prl" ),
117 wxT( "*.kicad_sch" ),
118 wxT( "*.kicad_sym" ),
119 wxT( "*.kicad_pcb" ),
120 wxT( "*.kicad_mod" ),
121 wxT( "*.kicad_dru" ),
122 wxT( "*.kicad_wks" ),
123 wxT( "fp-lib-table" ),
124 wxT( "sym-lib-table" )
125 };
126
127 // List of additional file extensions that are only archived when aIncludeExtraFiles is true
128 static const wxChar* extraExtensionList[] = {
129 wxT( "*.pro" ),
130 wxT( "*.sch" ), // Legacy schematic files
131 wxT( "*.lib" ), wxT( "*.dcm" ), // Legacy schematic library files
132 wxT( "*.cmp" ),
133 wxT( "*.brd" ),
134 wxT( "*.mod" ),
135 wxT( "*.stp" ), wxT( "*.step" ), // 3d files
136 wxT( "*.wrl" ),
137 wxT( "*.g?" ), wxT( "*.g??" ), // Gerber files
138 wxT( "*.gm??" ), wxT( "*.gbrjob" ),
139 wxT( "*.pos" ), wxT( "*.drl" ), wxT( "*.nc" ), wxT( "*.xnc" ), // Fab files
140 wxT( "*.d356" ),
141 wxT( "*.rpt" ),
142 wxT( "*.net" ),
143 wxT( "*.py" ),
144 wxT( "*.pdf" ),
145 wxT( "*.txt" ),
146 wxT( "*.cir" ), wxT( "*.sub" ), wxT( "*.model" ), // SPICE files
147 wxT( "*.ibs" )
148 };
149
150 bool success = true;
151 wxString msg;
152 wxString oldCwd = wxGetCwd();
153
154 wxSetWorkingDirectory( aSrcDir );
155
156 wxFFileOutputStream ostream( aDestFile );
157
158 if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir
159 {
160 msg.Printf( _( "Failed to create file '%s'." ), aDestFile );
161 aReporter.Report( msg, RPT_SEVERITY_ERROR );
162 return false;
163 }
164
165 wxZipOutputStream zipstream( ostream, -1, wxConvUTF8 );
166
167 // Build list of filenames to put in zip archive
168 wxString currFilename;
169
170 wxArrayString files;
171
172 for( unsigned ii = 0; ii < arrayDim( extensionList ); ii++ )
173 wxDir::GetAllFiles( aSrcDir, &files, extensionList[ii] );
174
175 if( aIncludeExtraFiles )
176 {
177 for( unsigned ii = 0; ii < arrayDim( extraExtensionList ); ii++ )
178 wxDir::GetAllFiles( aSrcDir, &files, extraExtensionList[ii] );
179 }
180
181 for( unsigned ii = 0; ii < files.GetCount(); ++ii )
182 {
183 if( files[ii].EndsWith( wxS( ".ibs" ) ) )
184 {
185 wxFileName package( files[ ii ] );
186 package.MakeRelativeTo( aSrcDir );
187 package.SetExt( wxS( "pkg" ) );
188
189 if( package.Exists() )
190 files.push_back( package.GetFullName() );
191 }
192 }
193
194 files.Sort();
195
196 unsigned long uncompressedBytes = 0;
197
198 for( unsigned ii = 0; ii < files.GetCount(); ii++ )
199 {
200 wxFileSystem fsfile;
201
202 wxFileName curr_fn( files[ii] );
203 curr_fn.MakeRelativeTo( aSrcDir );
204 currFilename = curr_fn.GetFullPath();
205
206 // Read input file and add it to the zip file:
207 wxFSFile* infile = fsfile.OpenFile( wxFileSystem::FileNameToURL( curr_fn ) );
208
209 if( infile )
210 {
211 zipstream.PutNextEntry( currFilename, infile->GetModificationTime() );
212 infile->GetStream()->Read( zipstream );
213 zipstream.CloseEntry();
214
215 uncompressedBytes += infile->GetStream()->GetSize();
216
217 if( aVerbose )
218 {
219 msg.Printf( _( "Archived file '%s'." ), currFilename );
220 aReporter.Report( msg, RPT_SEVERITY_INFO );
221 }
222
223 delete infile;
224 }
225 else
226 {
227 if( aVerbose )
228 {
229 msg.Printf( _( "Failed to archive file '%s'." ), currFilename );
230 aReporter.Report( msg, RPT_SEVERITY_ERROR );
231 }
232
233 success = false;
234 }
235 }
236
237 auto reportSize =
238 []( unsigned long aSize ) -> wxString
239 {
240 constexpr float KB = 1024.0;
241 constexpr float MB = KB * 1024.0;
242
243 if( aSize >= MB )
244 return wxString::Format( wxT( "%0.2f MB" ), aSize / MB );
245 else if( aSize >= KB )
246 return wxString::Format( wxT( "%0.2f KB" ), aSize / KB );
247 else
248 return wxString::Format( wxT( "%lu bytes" ), aSize );
249 };
250
251 size_t zipBytesCnt = ostream.GetSize();
252
253 if( zipstream.Close() )
254 {
255 msg.Printf( _( "Zip archive '%s' created (%s uncompressed, %s compressed)." ),
256 aDestFile,
257 reportSize( uncompressedBytes ),
258 reportSize( zipBytesCnt ) );
259 aReporter.Report( msg, RPT_SEVERITY_INFO );
260 }
261 else
262 {
263 msg.Printf( wxT( "Failed to create file '%s'." ), aDestFile );
264 aReporter.Report( msg, RPT_SEVERITY_ERROR );
265 success = false;
266 }
267
268 wxSetWorkingDirectory( oldCwd );
269 return success;
270}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
static const std::vector< std::string > extensionList

References _, arrayDim(), extensionList, Format(), REPORTER::Report(), RPT_SEVERITY_ERROR, and RPT_SEVERITY_INFO.

Referenced by SETTINGS_MANAGER::BackupProject(), and KICAD_MANAGER_FRAME::OnArchiveFiles().

◆ Unarchive()

bool PROJECT_ARCHIVER::Unarchive ( const wxString &  aSrcFile,
const wxString &  aDestDir,
REPORTER aReporter 
)

Extracts an archive of the current project over existing files Warning: this will overwrite files in the project directory.

Use with care. The caller is responsible for doing any reloading of state after taking this action.

Parameters
aSrcFileis the full path to the archive to extract
aDestDiris the target directory to unarchive to
aReporteris used to report status
Returns
true if the archive was created successfully

Definition at line 45 of file project_archiver.cpp.

47{
48 wxFFileInputStream stream( aSrcFile );
49
50 if( !stream.IsOk() )
51 {
52 aReporter.Report( _( "Could not open archive file." ), RPT_SEVERITY_ERROR );
53 return false;
54 }
55
56 const wxArchiveClassFactory* archiveClassFactory =
57 wxArchiveClassFactory::Find( aSrcFile, wxSTREAM_FILEEXT );
58
59 if( !archiveClassFactory )
60 {
61 aReporter.Report( _( "Invalid archive file format." ), RPT_SEVERITY_ERROR );
62 return false;
63 }
64
65 wxScopedPtr<wxArchiveInputStream> archiveStream( archiveClassFactory->NewStream( stream ) );
66
67 wxString fileStatus;
68
69 for( wxArchiveEntry* entry = archiveStream->GetNextEntry(); entry;
70 entry = archiveStream->GetNextEntry() )
71 {
72 fileStatus.Printf( _( "Extracting file '%s'." ), entry->GetName() );
73 aReporter.Report( fileStatus, RPT_SEVERITY_INFO );
74
75 wxString fullname = aDestDir + entry->GetName();
76
77 // Ensure the target directory exists and create it if not
78 wxString t_path = wxPathOnly( fullname );
79
80 if( !wxDirExists( t_path ) )
81 {
82 wxFileName::Mkdir( t_path, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
83 }
84
85 // Directory entries need only be created, not extracted (0 size)
86 if( entry->IsDir() )
87 continue;
88
89
90 wxTempFileOutputStream outputFileStream( fullname );
91
92 if( CopyStreamData( *archiveStream, outputFileStream, entry->GetSize() ) )
93 outputFileStream.Commit();
94 else
95 aReporter.Report( _( "Error extracting file!" ), RPT_SEVERITY_ERROR );
96
97 // Now let's set the filetimes based on what's in the zip
98 wxFileName outputFileName( fullname );
99 wxDateTime fileTime = entry->GetDateTime();
100 // For now we set access, mod, create to the same datetime
101 // create (third arg) is only used on Windows
102 outputFileName.SetTimes( &fileTime, &fileTime, &fileTime );
103 }
104
105 aReporter.Report( wxT( "Extracted project." ), RPT_SEVERITY_INFO );
106 return true;
107}
static bool CopyStreamData(wxInputStream &inputStream, wxOutputStream &outputStream, wxFileOffset size)

References _, CopyStreamData(), REPORTER::Report(), RPT_SEVERITY_ERROR, and RPT_SEVERITY_INFO.

Referenced by KICAD_MANAGER_FRAME::OnUnarchiveFiles().


The documentation for this class was generated from the following files: