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 }
static const std::vector< std::string > extensionList
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
#define _(s)
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
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

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 }
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
static bool CopyStreamData(wxInputStream &inputStream, wxOutputStream &outputStream, wxFileOffset size)
#define _(s)

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: