codeblocks --user-config=/home/myusername/.codeblocks-XXX
...Why not use the -p option which specify a different user profile file? (I think using different user profile is enough, no need to specify a different user profile directory, but I may be wrong)
Useful for when you have multiple C::B versions that you want to keep totally isolated. (E.g. they might have different, incompatible user plugins installed)
...
Thoughts?I had a quick look into. Is there a reason why you bind this functionality on CfgMgrBldr instead of ConfigManager as it is done with all the other path's? Its weird to find this method in the builder pattern... (see, how --prefix is handled...)
codeblocks --user-data-dir=/my/writeable/path
Index: src/include/configmanager.h
===================================================================
--- src/include/configmanager.h (revision 9594)
+++ src/include/configmanager.h (working copy)
@@ -87,6 +87,7 @@
};
+class CodeBlocksApp;
/* ------------------------------------------------------------------------------------------------------------------
* ConfigManager class
@@ -94,6 +95,7 @@
class DLLIMPORT ConfigManager
{
friend class CfgMgrBldr;
+ friend class CodeBlocksApp;
TiXmlDocument *doc;
TiXmlElement* root;
@@ -106,18 +108,30 @@
inline void Collapse(wxString& str) const;
wxString InvalidNameMessage(const wxString& what, const wxString& sub, TiXmlElement *localPath) const;
static void InitPaths();
+ static inline wxString GetUserConfigDir();
static wxString config_folder;
static wxString home_folder;
static wxString data_path_user;
static wxString data_path_global;
+
#ifdef CB_AUTOCONF
static wxString plugin_path_global;
#endif
static wxString app_path;
static wxString temp_folder;
static bool relo;
+ static wxString alternate_user_data_path;
+ static bool has_alternate_user_data_path;
+protected:
+ //For use by the CodeBlocksApp when the --user-data-dir switch is set
+ //all of the user config and user plugin data will be set relative to this path
+ static void SetUserDataFolder(const wxString &user_data_path);
+
+ //Used by CfgMgrBldr internally by ConfigManager
+ static wxString GetUserDataFolder();
+
public:
/* -----------------------------------------------------------------------------------------------------
Index: src/sdk/configmanager.cpp
===================================================================
--- src/sdk/configmanager.cpp (revision 9594)
+++ src/sdk/configmanager.cpp (working copy)
@@ -53,6 +53,9 @@
template<> CfgMgrBldr* Mgr<CfgMgrBldr>::instance = nullptr;
template<> bool Mgr<CfgMgrBldr>::isShutdown = false;
+wxString ConfigManager::alternate_user_data_path;
+bool ConfigManager::has_alternate_user_data_path=false;
+
wxString ConfigManager::config_folder;
wxString ConfigManager::home_folder;
wxString ConfigManager::data_path_user;
@@ -64,6 +67,8 @@
wxString ConfigManager::temp_folder;
bool ConfigManager::relo = 0;
+
+
#ifdef __WINDOWS__
inline wxString GetPortableConfigDir()
{
@@ -71,7 +76,7 @@
if (::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
return wxString::Format(_T("%s\\CodeBlocks"), buffer);
else
- return wxStandardPathsBase::Get().GetUserDataDir();
+ return ConfigManager::GetUserDataFolder();
}
#endif
@@ -194,7 +199,7 @@
#ifdef __WINDOWS__
cfg = GetPortableConfigDir() + wxFILE_SEP_PATH + personality + _T(".conf");
#else
- cfg = wxStandardPathsBase::Get().GetUserDataDir() + wxFILE_SEP_PATH + personality + _T(".conf");
+ cfg = ConfigManager::GetUserDataFolder() + wxFILE_SEP_PATH + personality + _T(".conf");
#endif
doc = new TiXmlDocument();
doc->InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
@@ -213,7 +218,7 @@
#ifdef __WINDOWS__
wxString u(GetPortableConfigDir() + wxFILE_SEP_PATH + filename);
#else
- wxString u(wxStandardPathsBase::Get().GetUserDataDir() + wxFILE_SEP_PATH + filename);
+ wxString u(ConfigManager::GetUserDataFolder() + wxFILE_SEP_PATH + filename);
#endif
wxString e(::DetermineExecutablePath() + wxFILE_SEP_PATH + filename);
@@ -439,7 +444,6 @@
return c;
}
-
/*
* Hack to enable Turkish language. wxString::Upper will convert lowercase 'i' to \u0130 instead of \u0069 in Turkish locale,
* which will break the config file when used in a tag
@@ -552,6 +556,20 @@
}
}
+inline wxString ConfigManager::GetUserDataFolder()
+{
+ if (has_alternate_user_data_path)
+ return alternate_user_data_path;
+ return wxStandardPathsBase::Get().GetUserDataDir();
+}
+
+void ConfigManager::SetUserDataFolder(const wxString &user_data_path)
+{
+ //TODO: Check that this is a valid writeable path
+ has_alternate_user_data_path = true;
+ ConfigManager::alternate_user_data_path = user_data_path;
+}
+
wxString ConfigManager::LocateDataFile(const wxString& filename, int search_dirs)
{
wxPathList searchPaths;
@@ -1440,7 +1458,7 @@
#ifdef __WINDOWS__
ConfigManager::config_folder = GetPortableConfigDir();
#else
- ConfigManager::config_folder = wxStandardPathsBase::Get().GetUserDataDir();
+ ConfigManager::config_folder = ConfigManager::GetUserDataFolder();
#endif
ConfigManager::home_folder = wxStandardPathsBase::Get().GetUserConfigDir();
ConfigManager::app_path = ::DetermineExecutablePath();
Index: src/src/app.cpp
===================================================================
--- src/src/app.cpp (revision 9594)
+++ src/src/app.cpp (working copy)
@@ -212,6 +212,8 @@
wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("prefix"), CMD_ENTRY("the shared data dir prefix"),
wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
+ { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("user-data-dir"), CMD_ENTRY("set a custom location for user configuration files"),
+ wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
{ wxCMD_LINE_OPTION, CMD_ENTRY("p"), CMD_ENTRY("personality"), CMD_ENTRY("the personality to use: \"ask\" or <personality-name>"),
wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
{ wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("no-log"), CMD_ENTRY("turn off the application log"),
@@ -313,6 +315,11 @@
if (ParseCmdLine(nullptr) == -1) // only abort if '--help' was passed in the command line
return false;
+ if (m_UserDataDir!=wxEmptyString)
+ ConfigManager::SetUserDataFolder(m_UserDataDir); // if --user-data-dir=path was specified we tell
+ //ConfigManager (and CfgMgrBldr) about it, which will propagate
+ //it through config manager
+
ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
wxString data(wxT(APP_PREFIX));
@@ -1100,6 +1107,7 @@
{
wxString val;
parser.Found(_T("prefix"), &m_Prefix);
+ parser.Found(_T("user-data-dir"), &m_UserDataDir);
#ifdef __WXMSW__
m_DDE = !parser.Found(_T("no-dde"));
m_Assocs = !parser.Found(_T("no-check-associations"));
Index: src/src/app.h
===================================================================
--- src/src/app.h (revision 9594)
+++ src/src/app.h (working copy)
@@ -69,7 +69,8 @@
void SetupPersonality(const wxString& personality);
- wxString m_Prefix; // --prefix switch
+ wxString m_Prefix; // directory specified in --prefix switch
+ wxString m_UserDataDir; // directory specified in --user-data-dir switch
wxString m_BatchTarget;
wxString m_Script;
wxString m_AutoFile; // --file foo.cpp[:line]
For this to work I had to add CodeblocksApp as a friend class of ConfigManager.This sounds bad. As far as I know the ConfigManager is in libcodeblocks and CodeblocksApp is in codeblocks.exe, seems dangerous to me.
For this to work I had to add CodeblocksApp as a friend class of ConfigManager.This sounds bad. As far as I know the ConfigManager is in libcodeblocks and CodeblocksApp is in codeblocks.exe, seems dangerous to me.
Why don't you just stick a big comment above them, explicitly stating that they should be called only by the main application linking libcodeblocks.
Keep in mind that it is possible to have multiple codeblocks.exe versions. For example Jens has a branch where there are two such executables.
I think you need to have it forward declared.
New patch. This version does a simple check for the existence of the user-data-dir, creates if not, and errors out if that doesn't work. ...The patch doesn't work on Windows because of GetPortableConfigDir(). It is called 3 times and would always return $APPDATA/CodeBlocks on most Systems.
diff --git src/sdk/configmanager.cpp src/sdk/configmanager.cpp
index 4f569a6..b7a30ac 100644
--- src/sdk/configmanager.cpp
+++ src/sdk/configmanager.cpp
@@ -68,18 +68,6 @@ wxString ConfigManager::temp_folder;
bool ConfigManager::relo = 0;
-
-#ifdef __WINDOWS__
-inline wxString GetPortableConfigDir()
-{
- TCHAR buffer[MAX_PATH];
- if (::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
- return wxString::Format(_T("%s\\CodeBlocks"), buffer);
- else
- return ConfigManager::GetUserDataFolder();
-}
-#endif
-
namespace CfgMgrConsts
{
const wxString app_path(_T("app_path"));
@@ -196,11 +184,8 @@ CfgMgrBldr::CfgMgrBldr() : doc(nullptr), volatile_doc(nullptr), r(false)
if (cfg.IsEmpty())
{
- #ifdef __WINDOWS__
- cfg = GetPortableConfigDir() + wxFILE_SEP_PATH + personality + _T(".conf");
- #else
cfg = ConfigManager::GetUserDataFolder() + wxFILE_SEP_PATH + personality + _T(".conf");
- #endif
+
doc = new TiXmlDocument();
doc->InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
doc->InsertEndChild(TiXmlElement("CodeBlocksConfig"));
@@ -215,11 +200,7 @@ wxString CfgMgrBldr::FindConfigFile(const wxString& filename)
{
wxPathList searchPaths;
-#ifdef __WINDOWS__
- wxString u(GetPortableConfigDir() + wxFILE_SEP_PATH + filename);
-#else
wxString u(ConfigManager::GetUserDataFolder() + wxFILE_SEP_PATH + filename);
-#endif
wxString e(::DetermineExecutablePath() + wxFILE_SEP_PATH + filename);
if (::wxFileExists(e))
@@ -560,6 +541,11 @@ inline wxString ConfigManager::GetUserDataFolder()
{
if (has_alternate_user_data_path)
return alternate_user_data_path;
+#ifdef __WXMSW__
+ TCHAR buffer[MAX_PATH];
+ if (::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
+ return wxString::Format(_T("%s\\CodeBlocks"), buffer);
+#endif
return wxStandardPathsBase::Get().GetUserDataDir();
}
@@ -1462,11 +1448,7 @@ void ConfigManager::Write(const wxString& name, const ConfigManagerContainer::Se
void ConfigManager::InitPaths()
{
-#ifdef __WINDOWS__
- ConfigManager::config_folder = GetPortableConfigDir();
-#else
ConfigManager::config_folder = ConfigManager::GetUserDataFolder();
-#endif
ConfigManager::home_folder = wxStandardPathsBase::Get().GetUserConfigDir();
ConfigManager::app_path = ::DetermineExecutablePath();
wxString res_path = ::DetermineResourcesPath();
New patch. This version does a simple check for the existence of the user-data-dir, creates if not, and errors out if that doesn't work. ...The patch doesn't work on Windows because of GetPortableConfigDir(). It is called 3 times and would always return $APPDATA/CodeBlocks on most Systems.
Index: src/sdk/configmanager.cpp
===================================================================
--- src/sdk/configmanager.cpp (revision 9594)
+++ src/sdk/configmanager.cpp (working copy)
@@ -68,10 +71,10 @@
inline wxString GetPortableConfigDir()
{
TCHAR buffer[MAX_PATH];
- if (::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
+ if (!ConfigManager::has_alternate_user_data_path && ::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
return wxString::Format(_T("%s\\CodeBlocks"), buffer);
else
Index: src/sdk/configmanager.cpp
===================================================================
--- src/sdk/configmanager.cpp (revision 9594)
+++ src/sdk/configmanager.cpp (working copy)
@@ -213,11 +218,11 @@
#ifdef __WINDOWS__
wxString u(GetPortableConfigDir() + wxFILE_SEP_PATH + filename);
#else
- wxString u(wxStandardPathsBase::Get().GetUserDataDir() + wxFILE_SEP_PATH + filename);
+ wxString u(ConfigManager::GetUserDataFolder() + wxFILE_SEP_PATH + filename);
#endif
wxString e(::DetermineExecutablePath() + wxFILE_SEP_PATH + filename);
- if (::wxFileExists(e))
+ if (!ConfigManager::has_alternate_user_data_path && ::wxFileExists(e))
{
ConfigManager::relo = true;
return e;
Would be nice to see this new option in trunk.
codeblocks --user-data-dir=xyz
... which I think is as simple as the following one liner:CodeIndex: src/sdk/configmanager.cpp
===================================================================
--- src/sdk/configmanager.cpp (revision 9594)
+++ src/sdk/configmanager.cpp (working copy)
@@ -68,10 +71,10 @@
inline wxString GetPortableConfigDir()
{
TCHAR buffer[MAX_PATH];
- if (::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
+ if (!ConfigManager::has_alternate_user_data_path && ::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
return wxString::Format(_T("%s\\CodeBlocks"), buffer);
else
inline wxString ConfigManager::GetUserDataFolder()
{
if (has_alternate_user_data_path)
return alternate_user_data_path;
#ifdef __WXMSW__
TCHAR buffer[MAX_PATH];
if (::GetEnvironmentVariable(_T("APPDATA"), buffer, MAX_PATH))
return wxString::Format(_T("%s\\CodeBlocks"), buffer);
#endif
return wxStandardPathsBase::Get().GetUserDataDir();
}
I also forgot to override the check for default.conf in the executable directory (I think it makes sense to obey the switch if it is specified). See the second change in this part of the patch.Good idea.
One last thing: what if the user specifies a relative path?