mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Fix project lock both working and not working.
Turns out project locks would get created and only stick around for a short duration as the default move constructor was letting the og object free the lock. But if you crashed kicad or managed something weird, you can get a lock file with no override prompt which also creates confusion as some stuff gets set read only. So lets just fix this up. - Implement move constructor on lockfile so that the old object will no longer free the lockfile - Move lock ownership to the project itself, just slightly less weird to handle for the lock override - Implement the override lock prompt
This commit is contained in:
parent
e615fcfe90
commit
9d32d208b8
@ -33,6 +33,7 @@
|
|||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <kiface_ids.h>
|
#include <kiface_ids.h>
|
||||||
#include <kiway.h>
|
#include <kiway.h>
|
||||||
|
#include <lockfile.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <project.h>
|
#include <project.h>
|
||||||
#include <project/project_file.h>
|
#include <project/project_file.h>
|
||||||
@ -42,6 +43,7 @@
|
|||||||
#include <settings/settings_manager.h>
|
#include <settings/settings_manager.h>
|
||||||
#include <title_block.h>
|
#include <title_block.h>
|
||||||
|
|
||||||
|
|
||||||
PROJECT::PROJECT() :
|
PROJECT::PROJECT() :
|
||||||
m_readOnly( false ),
|
m_readOnly( false ),
|
||||||
m_textVarsTicker( 0 ),
|
m_textVarsTicker( 0 ),
|
||||||
@ -460,3 +462,15 @@ DESIGN_BLOCK_LIB_TABLE* PROJECT::DesignBlockLibs()
|
|||||||
|
|
||||||
return tbl;
|
return tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PROJECT::SetProjectLock( LOCKFILE* aLockFile )
|
||||||
|
{
|
||||||
|
m_project_lock.reset( aLockFile );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCKFILE* PROJECT::GetProjectLock() const
|
||||||
|
{
|
||||||
|
return m_project_lock.get();
|
||||||
|
}
|
@ -939,13 +939,11 @@ bool SETTINGS_MANAGER::LoadProject( const wxString& aFullPath, bool aSetActive )
|
|||||||
if( m_projects.count( fullPath ) )
|
if( m_projects.count( fullPath ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool readOnly = false;
|
|
||||||
LOCKFILE lockFile( fullPath );
|
LOCKFILE lockFile( fullPath );
|
||||||
|
|
||||||
if( !lockFile.Valid() )
|
if( !lockFile.Valid() )
|
||||||
{
|
{
|
||||||
wxLogTrace( traceSettings, wxT( "Project %s is locked; opening read-only" ), fullPath );
|
wxLogTrace( traceSettings, wxT( "Project %s is locked; opening read-only" ), fullPath );
|
||||||
readOnly = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No MDI yet
|
// No MDI yet
|
||||||
@ -986,10 +984,10 @@ bool SETTINGS_MANAGER::LoadProject( const wxString& aFullPath, bool aSetActive )
|
|||||||
|
|
||||||
if( success )
|
if( success )
|
||||||
{
|
{
|
||||||
project->SetReadOnly( readOnly || project->GetProjectFile().IsReadOnly() );
|
project->SetReadOnly( !lockFile.Valid() || project->GetProjectFile().IsReadOnly() );
|
||||||
|
|
||||||
if( lockFile && aSetActive )
|
if( lockFile && aSetActive )
|
||||||
m_project_lock.reset( new LOCKFILE( std::move( lockFile ) ) );
|
project->SetProjectLock( new LOCKFILE( std::move( lockFile ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_projects_list.push_back( std::move( project ) );
|
m_projects_list.push_back( std::move( project ) );
|
||||||
@ -1048,9 +1046,6 @@ bool SETTINGS_MANAGER::UnloadProject( PROJECT* aProject, bool aSave )
|
|||||||
// Remove the reference in the environment to the previous project
|
// Remove the reference in the environment to the previous project
|
||||||
wxSetEnv( PROJECT_VAR_NAME, wxS( "" ) );
|
wxSetEnv( PROJECT_VAR_NAME, wxS( "" ) );
|
||||||
|
|
||||||
// Release lock on the file, in case we had one
|
|
||||||
m_project_lock = nullptr;
|
|
||||||
|
|
||||||
if( m_kiway )
|
if( m_kiway )
|
||||||
m_kiway->ProjectChanged();
|
m_kiway->ProjectChanged();
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOCKFILE( LOCKFILE&& other ) noexcept :
|
||||||
|
m_originalFile( std::move( other.m_originalFile ) ),
|
||||||
|
m_lockFilename( std::move( other.m_lockFilename ) ),
|
||||||
|
m_username( std::move( other.m_username ) ),
|
||||||
|
m_hostname( std::move( other.m_hostname ) ),
|
||||||
|
m_fileCreated( other.m_fileCreated ),
|
||||||
|
m_status( other.m_status ),
|
||||||
|
m_removeOnRelease( other.m_removeOnRelease ),
|
||||||
|
m_errorMsg( std::move( other.m_errorMsg ) )
|
||||||
|
{
|
||||||
|
// Disable unlock in the moved-from object
|
||||||
|
other.m_fileCreated = false;
|
||||||
|
}
|
||||||
|
|
||||||
~LOCKFILE()
|
~LOCKFILE()
|
||||||
{
|
{
|
||||||
UnlockFile();
|
UnlockFile();
|
||||||
|
@ -52,6 +52,7 @@ class SYMBOL_LIB_TABLE;
|
|||||||
class FILENAME_RESOLVER;
|
class FILENAME_RESOLVER;
|
||||||
class PROJECT_FILE;
|
class PROJECT_FILE;
|
||||||
class PROJECT_LOCAL_SETTINGS;
|
class PROJECT_LOCAL_SETTINGS;
|
||||||
|
class LOCKFILE;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,9 +218,9 @@ public:
|
|||||||
{
|
{
|
||||||
DOC_PATH,
|
DOC_PATH,
|
||||||
SCH_LIB_PATH,
|
SCH_LIB_PATH,
|
||||||
SCH_LIB_SELECT, // eeschema/selpart.cpp
|
SCH_LIB_SELECT, // eeschema/selpart.cpp
|
||||||
SCH_LIBEDIT_CUR_LIB,
|
SCH_LIBEDIT_CUR_LIB,
|
||||||
SCH_LIBEDIT_CUR_SYMBOL, // eeschema/libeditframe.cpp
|
SCH_LIBEDIT_CUR_SYMBOL, // eeschema/libeditframe.cpp
|
||||||
|
|
||||||
VIEWER_3D_PATH,
|
VIEWER_3D_PATH,
|
||||||
VIEWER_3D_FILTER_INDEX,
|
VIEWER_3D_FILTER_INDEX,
|
||||||
@ -270,11 +271,11 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Clear the _ELEMs and RSTRINGs.
|
* Clear the _ELEMs and RSTRINGs.
|
||||||
*/
|
*/
|
||||||
void Clear() // inline not virtual
|
void Clear() // inline not virtual
|
||||||
{
|
{
|
||||||
elemsClear();
|
elemsClear();
|
||||||
|
|
||||||
for( unsigned i = 0; i<RSTRING_COUNT; ++i )
|
for( unsigned i = 0; i < RSTRING_COUNT; ++i )
|
||||||
SetRString( RSTRING_T( i ), wxEmptyString );
|
SetRString( RSTRING_T( i ), wxEmptyString );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +298,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual DESIGN_BLOCK_LIB_TABLE* DesignBlockLibs();
|
virtual DESIGN_BLOCK_LIB_TABLE* DesignBlockLibs();
|
||||||
|
|
||||||
|
void SetProjectLock( LOCKFILE* aLockFile );
|
||||||
|
|
||||||
|
LOCKFILE* GetProjectLock() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SETTINGS_MANAGER; // so that SM can set project path
|
friend class SETTINGS_MANAGER; // so that SM can set project path
|
||||||
friend class TEST_NETLISTS_FIXTURE; // TODO(JE) make this not required
|
friend class TEST_NETLISTS_FIXTURE; // TODO(JE) make this not required
|
||||||
@ -366,6 +371,9 @@ private:
|
|||||||
|
|
||||||
/// @see this::Elem() and enum ELEM_T.
|
/// @see this::Elem() and enum ELEM_T.
|
||||||
std::array<_ELEM*,static_cast<unsigned int>( PROJECT::ELEM::COUNT )> m_elems;
|
std::array<_ELEM*,static_cast<unsigned int>( PROJECT::ELEM::COUNT )> m_elems;
|
||||||
|
|
||||||
|
/// Lock
|
||||||
|
std::unique_ptr<LOCKFILE> m_project_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -531,9 +531,6 @@ private:
|
|||||||
/// Loaded project files, mapped according to project full name.
|
/// Loaded project files, mapped according to project full name.
|
||||||
std::map<wxString, PROJECT_FILE*> m_project_files;
|
std::map<wxString, PROJECT_FILE*> m_project_files;
|
||||||
|
|
||||||
/// Lock for loaded project (expand to multiple once we support MDI).
|
|
||||||
std::unique_ptr<LOCKFILE> m_project_lock;
|
|
||||||
|
|
||||||
static wxString backupDateTimeFormat;
|
static wxString backupDateTimeFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <kiway.h>
|
#include <kiway.h>
|
||||||
#include <kiway_express.h>
|
#include <kiway_express.h>
|
||||||
#include <launch_ext.h>
|
#include <launch_ext.h>
|
||||||
|
#include <lockfile.h>
|
||||||
#include <notifications_manager.h>
|
#include <notifications_manager.h>
|
||||||
#include <reporter.h>
|
#include <reporter.h>
|
||||||
#include <project/project_local_settings.h>
|
#include <project/project_local_settings.h>
|
||||||
@ -68,6 +69,7 @@
|
|||||||
#include <wx/filedlg.h>
|
#include <wx/filedlg.h>
|
||||||
#include <wx/dnd.h>
|
#include <wx/dnd.h>
|
||||||
#include <wx/process.h>
|
#include <wx/process.h>
|
||||||
|
#include <wx/snglinst.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <update_manager.h>
|
#include <update_manager.h>
|
||||||
#include <jobs/jobset.h>
|
#include <jobs/jobset.h>
|
||||||
@ -1035,7 +1037,42 @@ void KICAD_MANAGER_FRAME::CommonSettingsChanged( int aFlags )
|
|||||||
|
|
||||||
void KICAD_MANAGER_FRAME::ProjectChanged()
|
void KICAD_MANAGER_FRAME::ProjectChanged()
|
||||||
{
|
{
|
||||||
wxString file = GetProjectFileName();
|
wxString file = GetProjectFileName();
|
||||||
|
|
||||||
|
// empty file string means no project loaded
|
||||||
|
if( !Prj().IsNullProject() &&
|
||||||
|
Prj().GetProjectLock() == nullptr )
|
||||||
|
{
|
||||||
|
LOCKFILE lockFile( file );
|
||||||
|
|
||||||
|
if( !lockFile.Valid() && lockFile.IsLockedByMe() )
|
||||||
|
{
|
||||||
|
// If we cannot acquire the lock but we appear to be the one who
|
||||||
|
// locked it, check to see if there is another KiCad instance running.
|
||||||
|
// If there is not, then we can override the lock. This could happen if
|
||||||
|
// KiCad crashed or was interrupted
|
||||||
|
if( !Pgm().SingleInstance()->IsAnotherRunning() )
|
||||||
|
{
|
||||||
|
lockFile.OverrideLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !lockFile.Valid() )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ), file, lockFile.GetUsername(),
|
||||||
|
lockFile.GetHostname() );
|
||||||
|
|
||||||
|
if( AskOverrideLock( this, msg ) )
|
||||||
|
{
|
||||||
|
lockFile.OverrideLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Prj().SetReadOnly( !lockFile.Valid() || Prj().GetProjectFile().IsReadOnly() );
|
||||||
|
Prj().SetProjectLock( new LOCKFILE( std::move( lockFile ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
wxString title;
|
wxString title;
|
||||||
|
|
||||||
if( !file.IsEmpty() )
|
if( !file.IsEmpty() )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user