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( "*.gb?" ), wxT( "*.gbrjob" ), // Gerber files
138 wxT( "*.gko" ), wxT( "*.gm1" ),
139 wxT( "*.gm2" ), wxT( "*.g?" ),
140 wxT( "*.gp1" ), wxT( "*.gp2" ),
141 wxT( "*.gpb" ), wxT( "*.gpt" ),
142 wxT( "*.gt?" ),
143 wxT( "*.pos" ), wxT( "*.drl" ), wxT( "*.nc" ), wxT( "*.xnc" ), // Fab files
144 wxT( "*.d356" ), wxT( "*.rpt" ),
145 wxT( "*.net" ), wxT( "*.py" ),
146 wxT( "*.pdf" ), wxT( "*.txt" )
147 };
148
149 bool success = true;
150 wxString msg;
151 wxString oldCwd = wxGetCwd();
152
153 wxSetWorkingDirectory( aSrcDir );
154
155 wxFFileOutputStream ostream( aDestFile );
156
157 if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir
158 {
159 msg.Printf( _( "Failed to create file '%s'." ), aDestFile );
160 aReporter.Report( msg, RPT_SEVERITY_ERROR );
161 return false;
162 }
163
164 wxZipOutputStream zipstream( ostream, -1, wxConvUTF8 );
165
166 // Build list of filenames to put in zip archive
167 wxString currFilename;
168
169 wxArrayString files;
170
171 for( unsigned ii = 0; ii < arrayDim( extensionList ); ii++ )
172 wxDir::GetAllFiles( aSrcDir, &files, extensionList[ii] );
173
174 if( aIncludeExtraFiles )
175 {
176 for( unsigned ii = 0; ii < arrayDim( extraExtensionList ); ii++ )
177 wxDir::GetAllFiles( aSrcDir, &files, extraExtensionList[ii] );
178 }
179
180 files.Sort();
181
182 unsigned long uncompressedBytes = 0;
183
184 for( unsigned ii = 0; ii < files.GetCount(); ii++ )
185 {
186 wxFileSystem fsfile;
187
188 wxFileName curr_fn( files[ii] );
189 curr_fn.MakeRelativeTo( aSrcDir );
190 currFilename = curr_fn.GetFullPath();
191
192 // Read input file and add it to the zip file:
193 wxFSFile* infile = fsfile.OpenFile( wxFileSystem::FileNameToURL( curr_fn ) );
194
195 if( infile )
196 {
197 zipstream.PutNextEntry( currFilename, infile->GetModificationTime() );
198 infile->GetStream()->Read( zipstream );
199 zipstream.CloseEntry();
200
201 uncompressedBytes += infile->GetStream()->GetSize();
202
203 if( aVerbose )
204 {
205 msg.Printf( _( "Archived file '%s'." ), currFilename );
206 aReporter.Report( msg, RPT_SEVERITY_INFO );
207 }
208
209 delete infile;
210 }
211 else
212 {
213 if( aVerbose )
214 {
215 msg.Printf( _( "Failed to archive file '%s'." ), currFilename );
216 aReporter.Report( msg, RPT_SEVERITY_ERROR );
217 }
218
219 success = false;
220 }
221 }
222
223 auto reportSize =
224 []( unsigned long aSize ) -> wxString
225 {
226 constexpr float KB = 1024.0;
227 constexpr float MB = KB * 1024.0;
228
229 if( aSize >= MB )
230 return wxString::Format( wxT( "%0.2f MB" ), aSize / MB );
231 else if( aSize >= KB )
232 return wxString::Format( wxT( "%0.2f KB" ), aSize / KB );
233 else
234 return wxString::Format( wxT( "%lu bytes" ), aSize );
235 };
236
237 size_t zipBytesCnt = ostream.GetSize();
238
239 if( zipstream.Close() )
240 {
241 msg.Printf( _( "Zip archive '%s' created (%s uncompressed, %s compressed)." ),
242 aDestFile,
243 reportSize( uncompressedBytes ),
244 reportSize( zipBytesCnt ) );
245 aReporter.Report( msg, RPT_SEVERITY_INFO );
246 }
247 else
248 {
249 msg.Printf( wxT( "Failed to create file '%s'." ), aDestFile );
250 aReporter.Report( msg, RPT_SEVERITY_ERROR );
251 success = false;
252 }
253
254 wxSetWorkingDirectory( oldCwd );
255 return success;
256}
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: