Use a temporary file when saving boards/schematics to make the operation more atomic
Fixes https://gitlab.com/kicad/code/kicad/-/issues/4517
This commit is contained in:
parent
dd42a19319
commit
09cb75b8a1
|
@ -110,7 +110,7 @@ bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName,
|
||||||
if( backupFileName.FileExists() )
|
if( backupFileName.FileExists() )
|
||||||
wxRemoveFile( backupFileName.GetFullPath() );
|
wxRemoveFile( backupFileName.GetFullPath() );
|
||||||
|
|
||||||
if( !wxRenameFile( schematicFileName.GetFullPath(), backupFileName.GetFullPath() ) )
|
if( !wxCopyFile( schematicFileName.GetFullPath(), backupFileName.GetFullPath() ) )
|
||||||
{
|
{
|
||||||
msg.Printf( _( "Could not save backup of file \"%s\"" ),
|
msg.Printf( _( "Could not save backup of file \"%s\"" ),
|
||||||
schematicFileName.GetFullPath() );
|
schematicFileName.GetFullPath() );
|
||||||
|
@ -118,6 +118,10 @@ bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxFileName tempFile( schematicFileName );
|
||||||
|
tempFile.SetName( wxT( "." ) + tempFile.GetName() );
|
||||||
|
tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
wxLogTrace( traceAutoSave,
|
wxLogTrace( traceAutoSave,
|
||||||
wxT( "Saving file <" ) + schematicFileName.GetFullPath() + wxT( ">" ) );
|
wxT( "Saving file <" ) + schematicFileName.GetFullPath() + wxT( ">" ) );
|
||||||
|
@ -128,7 +132,7 @@ bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName,
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pi->Save( schematicFileName.GetFullPath(), aSheet, &Schematic() );
|
pi->Save( tempFile.GetFullPath(), aSheet, &Schematic() );
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& ioe )
|
catch( const IO_ERROR& ioe )
|
||||||
|
@ -137,12 +141,32 @@ bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName,
|
||||||
schematicFileName.GetFullPath(), ioe.What() );
|
schematicFileName.GetFullPath(), ioe.What() );
|
||||||
DisplayError( this, msg );
|
DisplayError( this, msg );
|
||||||
|
|
||||||
msg.Printf( _( "Failed to save \"%s\"" ), schematicFileName.GetFullPath() );
|
msg.Printf( _( "Failed to create temporary file \"%s\"" ), tempFile.GetFullPath() );
|
||||||
AppendMsgPanel( wxEmptyString, msg, CYAN );
|
AppendMsgPanel( wxEmptyString, msg, CYAN );
|
||||||
|
|
||||||
|
// In case we started a file but didn't fully write it, clean up
|
||||||
|
wxRemoveFile( tempFile.GetFullPath() );
|
||||||
|
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( success )
|
||||||
|
{
|
||||||
|
// Replace the original with the temporary file we just wrote
|
||||||
|
success = wxRenameFile( tempFile.GetFullPath(), schematicFileName.GetFullPath() );
|
||||||
|
|
||||||
|
if( !success )
|
||||||
|
{
|
||||||
|
msg.Printf( _( "Error saving schematic file \"%s\".\n"
|
||||||
|
"Failed to rename temporary file %s" ),
|
||||||
|
schematicFileName.GetFullPath(), tempFile.GetFullPath() );
|
||||||
|
DisplayError( this, msg );
|
||||||
|
|
||||||
|
msg.Printf( _( "Failed to rename temporary file \"%s\"" ), tempFile.GetFullPath() );
|
||||||
|
AppendMsgPanel( wxEmptyString, msg, CYAN );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( success )
|
if( success )
|
||||||
{
|
{
|
||||||
// Delete auto save file.
|
// Delete auto save file.
|
||||||
|
|
|
@ -263,9 +263,27 @@ bool PL_EDITOR_FRAME::InsertPageLayoutDescrFile( const wxString& aFullFileName )
|
||||||
|
|
||||||
bool PL_EDITOR_FRAME::SavePageLayoutDescrFile( const wxString& aFullFileName )
|
bool PL_EDITOR_FRAME::SavePageLayoutDescrFile( const wxString& aFullFileName )
|
||||||
{
|
{
|
||||||
if( ! aFullFileName.IsEmpty() )
|
if( !aFullFileName.IsEmpty() )
|
||||||
{
|
{
|
||||||
WS_DATA_MODEL::GetTheInstance().Save( aFullFileName );
|
wxFileName tempFile( aFullFileName );
|
||||||
|
tempFile.SetName( wxT( "." ) + tempFile.GetName() );
|
||||||
|
tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WS_DATA_MODEL::GetTheInstance().Save( tempFile.GetFullPath() );
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
// In case we started a file but didn't fully write it, clean up
|
||||||
|
wxRemoveFile( tempFile.GetFullPath() );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !wxRenameFile( tempFile.GetFullPath(), aFullFileName ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
GetScreen()->ClrModify();
|
GetScreen()->ClrModify();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -685,8 +685,8 @@ wxString PCB_EDIT_FRAME::createBackupFile( const wxString& aFileName )
|
||||||
if( backupFileName.FileExists() )
|
if( backupFileName.FileExists() )
|
||||||
wxRemoveFile( backupFileName.GetFullPath() );
|
wxRemoveFile( backupFileName.GetFullPath() );
|
||||||
|
|
||||||
// Rename the current file from <xxx>.kicad_pcb to <xxx>.kicad_pcb-bak
|
// Copy the current file from <xxx>.kicad_pcb to <xxx>.kicad_pcb-bak
|
||||||
if( !wxRenameFile( fn.GetFullPath(), backupFileName.GetFullPath() ) )
|
if( !wxCopyFile( fn.GetFullPath(), backupFileName.GetFullPath() ) )
|
||||||
{
|
{
|
||||||
wxString msg = wxString::Format( _(
|
wxString msg = wxString::Format( _(
|
||||||
"Warning: unable to create backup file \"%s\"" ),
|
"Warning: unable to create backup file \"%s\"" ),
|
||||||
|
@ -729,6 +729,10 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
|
||||||
backupFileName = createBackupFile( aFileName );
|
backupFileName = createBackupFile( aFileName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxFileName tempFile( aFileName );
|
||||||
|
tempFile.SetName( wxT( "." ) + tempFile.GetName() );
|
||||||
|
tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
|
||||||
|
|
||||||
GetBoard()->SynchronizeNetsAndNetClasses();
|
GetBoard()->SynchronizeNetsAndNetClasses();
|
||||||
|
|
||||||
// Select default Netclass before writing file. Useful to save default values in headers.
|
// Select default Netclass before writing file. Useful to save default values in headers.
|
||||||
|
@ -747,9 +751,9 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
|
||||||
{
|
{
|
||||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
|
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
|
||||||
|
|
||||||
wxASSERT( pcbFileName.IsAbsolute() );
|
wxASSERT( tempFile.IsAbsolute() );
|
||||||
|
|
||||||
pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
|
pi->Save( tempFile.GetFullPath(), GetBoard(), NULL );
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& ioe )
|
catch( const IO_ERROR& ioe )
|
||||||
{
|
{
|
||||||
|
@ -759,7 +763,26 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
|
||||||
);
|
);
|
||||||
DisplayError( this, msg );
|
DisplayError( this, msg );
|
||||||
|
|
||||||
lowerTxt.Printf( _( "Failed to create \"%s\"" ), pcbFileName.GetFullPath() );
|
lowerTxt.Printf( _( "Failed to create temporary file \"%s\"" ), tempFile.GetFullPath() );
|
||||||
|
|
||||||
|
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
||||||
|
|
||||||
|
// In case we started a file but didn't fully write it, clean up
|
||||||
|
wxRemoveFile( tempFile.GetFullPath() );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If save succeeded, replace the original with what we just wrote
|
||||||
|
if( !wxRenameFile( tempFile.GetFullPath(), pcbFileName.GetFullPath() ) )
|
||||||
|
{
|
||||||
|
wxString msg = wxString::Format( _(
|
||||||
|
"Error saving board file \"%s\".\nFailed to rename temporary file \"%s\"" ),
|
||||||
|
pcbFileName.GetFullPath(), tempFile.GetFullPath()
|
||||||
|
);
|
||||||
|
DisplayError( this, msg );
|
||||||
|
|
||||||
|
lowerTxt.Printf( _( "Failed to rename temporary file \"%s\"" ), tempFile.GetFullPath() );
|
||||||
|
|
||||||
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue