Unix: enable use of XDG paths for storing Blender configuration on Linux/BSD/..,
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 25 May 2012 12:08:29 +0000 (12:08 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 25 May 2012 12:08:29 +0000 (12:08 +0000)
starting from version 2.64. Unless you have a special system setup, this means the
will be in ~/.config/blender rather than ~/.blender.

When the version number is changed to 2.64, the "Copy Previous Settings" operator
in the splash will copy the settings to the new location.

XDG base directory specification:
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

16 files changed:
CMakeLists.txt
intern/ghost/CMakeLists.txt
intern/ghost/GHOST_ISystemPaths.h
intern/ghost/GHOST_Path-api.h
intern/ghost/intern/GHOST_Path-api.cpp
intern/ghost/intern/GHOST_SystemPaths.h
intern/ghost/intern/GHOST_SystemPathsCarbon.cpp
intern/ghost/intern/GHOST_SystemPathsCarbon.h
intern/ghost/intern/GHOST_SystemPathsCocoa.h
intern/ghost/intern/GHOST_SystemPathsCocoa.mm
intern/ghost/intern/GHOST_SystemPathsWin32.cpp
intern/ghost/intern/GHOST_SystemPathsWin32.h
intern/ghost/intern/GHOST_SystemPathsX11.cpp
intern/ghost/intern/GHOST_SystemPathsX11.h
source/blender/blenlib/CMakeLists.txt
source/blender/blenlib/intern/path_util.c

index 5632d21..89fe482 100644 (file)
@@ -161,8 +161,6 @@ if(UNIX AND NOT APPLE)
        option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)"   ON)
        option(WITH_X11_XF86VMODE "Enable X11 video mode switching"     ON)
        option(WITH_BUILTIN_GLEW "Use GLEW OpenGL wrapper library bundled with blender" ON)
-       option(WITH_XDG_USER_DIRS    "Build with XDG Base Directory Specification (only config and documents for now)" OFF)
-       mark_as_advanced(WITH_XDG_USER_DIRS)
 
        # freebsd doesn't seems to support XDND
        if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
index eeb924d..277b14e 100644 (file)
@@ -108,10 +108,6 @@ if(WITH_INPUT_NDOF)
        )
 endif()
 
-if(WITH_XDG_USER_DIRS)
-       add_definitions(-DWITH_XDG_USER_DIRS)
-endif()
-
 if(WITH_HEADLESS OR WITH_GHOST_SDL)
        if(WITH_HEADLESS)
                list(APPEND SRC
index f610fde..ee8bd9d 100644 (file)
@@ -72,17 +72,17 @@ protected:
 public:
        /**
         * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
+        * "unpack and run" path, then look for properly installed path, including versioning.
         * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
         */
-       virtual const GHOST_TUns8 *getSystemDir() const = 0;
+       virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0;
 
        /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
+        * Determine the base dir in which user configuration is stored, including versioning.
         * If needed, it will create the base directory.
         * @return Unsigned char string pointing to user dir (eg ~/.blender/).
         */
-       virtual const GHOST_TUns8 *getUserDir() const = 0;
+       virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
 
        /**
         * Determine the directory of the current binary
index 811f39b..a037f2e 100644 (file)
@@ -55,16 +55,16 @@ extern GHOST_TSuccess GHOST_DisposeSystemPaths(void);
 
 /**
  * Determine the base dir in which shared resources are located. It will first try to use
- * "unpack and run" path, then look for properly installed path, not including versioning.
+ * "unpack and run" path, then look for properly installed path, including versioning.
  * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
  */
-extern const GHOST_TUns8 *GHOST_getSystemDir(void);
+extern const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr);
 
 /**
- * Determine the base dir in which user configuration is stored, not including versioning.
+ * Determine the base dir in which user configuration is stored, including versioning.
  * @return Unsigned char string pointing to user dir (eg ~).
  */
-extern const GHOST_TUns8 *GHOST_getUserDir(void);
+extern const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr);
 
 
 /**
index e926233..2bc5851 100644 (file)
@@ -45,16 +45,16 @@ GHOST_TSuccess GHOST_DisposeSystemPaths(void)
        return GHOST_ISystemPaths::dispose();
 }
 
-const GHOST_TUns8 *GHOST_getSystemDir()
+const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr)
 {
        GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
-       return systemPaths ? systemPaths->getSystemDir() : 0;
+       return systemPaths ? systemPaths->getSystemDir(version, versionstr) : 0;
 }
 
-const GHOST_TUns8 *GHOST_getUserDir()
+const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr)
 {
        GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
-       return systemPaths ? systemPaths->getUserDir() : 0; /* shouldn't be NULL */
+       return systemPaths ? systemPaths->getUserDir(version, versionstr) : 0; /* shouldn't be NULL */
 }
 
 const GHOST_TUns8 *GHOST_getBinaryDir()
index a8c43ff..75acbf8 100644 (file)
@@ -52,17 +52,17 @@ public:
 
        /**
         * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
+        * "unpack and run" path, then look for properly installed path, including versioning.
         * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
         */
-       virtual const GHOST_TUns8 *getSystemDir() const = 0;
+       virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0;
 
-       /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
-        * If needed, it will create the base directory.
-        * @return Unsigned char string pointing to user dir (eg ~/.blender/).
-        */
-       virtual const GHOST_TUns8 *getUserDir() const = 0;
+    /**
+         * Determine the base dir in which user configuration is stored, including versioning.
+         * If needed, it will create the base directory.
+         * @return Unsigned char string pointing to user dir (eg ~/.blender/).
+         */
+       virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
 
        /**
         * Determine the directory of the current binary
index f4be03a..7d43392 100644 (file)
@@ -44,21 +44,23 @@ GHOST_SystemPathsCarbon::~GHOST_SystemPathsCarbon()
 {
 }
 
-const GHOST_TUns8 *GHOST_SystemPathsCarbon::getSystemDir() const
+const GHOST_TUns8 *GHOST_SystemPathsCarbon::getSystemDir(int, const char *versionstr) const
 {
-       return (GHOST_TUns8 *)"/Library/Application Support";
+       static char systemPath[1024];
+
+       snprintf(systemPath, sizeof(systemPath), "/Library/Application Support/Blender/%s", versionstr);
+
+       return (GHOST_TUns8*)systemPath;
 }
 
-const GHOST_TUns8 *GHOST_SystemPathsCarbon::getUserDir() const
+const GHOST_TUns8 *GHOST_SystemPathsCarbon::getUserDir(int, const char *versionstr) const
 {
-       static char usrPath[256] = "";
+       static char usrPath[1024];
        char *env = getenv("HOME");
        
        if (env) {
-               strncpy(usrPath, env, 245);
-               usrPath[245] = 0;
-               strcat(usrPath, "/Library/Application Support");
-               return (GHOST_TUns8 *) usrPath;
+               snprintf(usrPath, sizeof(usrPath), "%s/Library/Application Support/Blender/%s", env, versionstr);
+               return (GHOST_TUns8*)usrPath;
        }
        else
                return NULL;
index c005f37..6a94c1d 100644 (file)
@@ -60,17 +60,17 @@ public:
 
        /**
         * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
+        * "unpack and run" path, then look for properly installed path, including versioning.
         * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
         */
-       virtual const GHOST_TUns8 *getSystemDir() const;
+       virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
 
        /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
+        * Determine the base dir in which user configuration is stored, including versioning.
         * If needed, it will create the base directory.
         * @return Unsigned char string pointing to user dir (eg ~/.blender/).
         */
-       virtual const GHOST_TUns8 *getUserDir() const;
+       virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
 
        /**
         * Determine the directory of the current binary
index 77efbf2..ad44396 100644 (file)
@@ -54,17 +54,17 @@ public:
 
        /**
         * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
+        * "unpack and run" path, then look for properly installed path, including versioning.
         * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
         */
-       virtual const GHOST_TUns8 *getSystemDir() const;
+       virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
 
        /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
+        * Determine the base dir in which user configuration is stored, including versioning.
         * If needed, it will create the base directory.
         * @return Unsigned char string pointing to user dir (eg ~/.blender/).
         */
-       virtual const GHOST_TUns8 *getUserDir() const;
+       virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
 
        /**
         * Determine the directory of the current binary
index cce07c2..50ad91e 100644 (file)
@@ -50,9 +50,9 @@ GHOST_SystemPathsCocoa::~GHOST_SystemPathsCocoa()
 
 #pragma mark Base directories retrieval
 
-const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir() const
+const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir(int, const char *versionstr) const
 {
-       static GHOST_TUns8 tempPath[512] = "";
+       static char tempPath[512] = "";
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSString *basePath;
        NSArray *paths;
@@ -66,15 +66,15 @@ const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir() const
                return NULL;
        }
        
-       strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
+       snprintf(tempPath, sizeof(tempPath), "%s/Blender/%s", [basePath cStringUsingEncoding:NSASCIIStringEncoding], versionstr);
        
        [pool drain];
-       return tempPath;
+       return (GHOST_TUns8*)tempPath;
 }
 
-const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir() const
+const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir(int, const char *versionstr) const
 {
-       static GHOST_TUns8 tempPath[512] = "";
+       static char tempPath[512] = "";
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSString *basePath;
        NSArray *paths;
@@ -88,10 +88,10 @@ const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir() const
                return NULL;
        }
 
-       strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
+       snprintf(tempPath, sizeof(tempPath), "%s/Blender/%s", [basePath cStringUsingEncoding:NSASCIIStringEncoding], versionstr);
        
        [pool drain];
-       return tempPath;
+       return (GHOST_TUns8*)tempPath;
 }
 
 const GHOST_TUns8* GHOST_SystemPathsCocoa::getBinaryDir() const
index ecf1046..3a313c7 100644 (file)
@@ -69,9 +69,9 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32()
 {
 }
 
-const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir() const
+const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const
 {
-       static char knownpath[MAX_PATH * 3] = {0}; /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/
+       static char knownpath[MAX_PATH * 3 + 128] = {0}; /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/
        wchar_t knownpath_16[MAX_PATH];
 
        HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
@@ -79,15 +79,17 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir() const
        if (hResult == S_OK)
        {
                conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
-               return (GHOST_TUns8 *)knownpath;
+               strcat(knownpath, "\\Blender Foundation\\Blender\\");
+               strcat(knownpath, versionstr);
+               return (GHOST_TUns8*)knownpath;
        }
 
        return NULL;
 }
 
-const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir() const
+const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const
 {
-       static char knownpath[MAX_PATH * 3] = {0};
+       static char knownpath[MAX_PATH * 3 + 128] = {0};
        wchar_t knownpath_16[MAX_PATH];
 
        HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
@@ -95,7 +97,9 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir() const
        if (hResult == S_OK)
        {
                conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
-               return (GHOST_TUns8 *)knownpath;
+               strcat(knownpath, "\\Blender Foundation\\Blender\\");
+               strcat(knownpath, versionstr);
+               return (GHOST_TUns8*)knownpath;
        }
 
        return NULL;
index 133aa2c..3a243f8 100644 (file)
@@ -64,17 +64,17 @@ public:
 
        /**
         * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
+        * "unpack and run" path, then look for properly installed path, including versioning.
         * @return Unsigned char string pointing to system dir (eg /usr/share/).
         */
-       const GHOST_TUns8 *getSystemDir() const;
+       const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
 
        /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
+        * Determine the base dir in which user configuration is stored, including versioning.
         * If needed, it will create the base directory.
         * @return Unsigned char string pointing to user dir (eg ~/).
         */
-       const GHOST_TUns8 *getUserDir() const;
+       const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
 
        /**
         * Determine the directory of the current binary
index c148a16..95f82fe 100644 (file)
 #include <stdio.h> // for fprintf only
 #include <cstdlib> // for exit
 
-#ifdef WITH_XDG_USER_DIRS
-#  include <pwd.h> // for get home without use getenv()
-#  include <limits.h> // for PATH_MAX
-#endif
+#include <pwd.h> // for get home without use getenv()
+#include <limits.h> // for PATH_MAX
 
 #ifdef PREFIX
 static const char *static_path = PREFIX "/share";
@@ -60,35 +58,51 @@ GHOST_SystemPathsX11::~GHOST_SystemPathsX11()
 {
 }
 
-const GHOST_TUns8 *GHOST_SystemPathsX11::getSystemDir() const
+const GHOST_TUns8 *GHOST_SystemPathsX11::getSystemDir(int, const char *versionstr) const
 {
        /* no prefix assumes a portable build which only uses bundled scripts */
-       return (const GHOST_TUns8 *)static_path;
+       if(static_path) {
+               static char system_path[PATH_MAX];
+               snprintf(system_path, sizeof(system_path), "%s/blender/%s", static_path, versionstr);
+               return (GHOST_TUns8*)system_path;
+       }
+
+       return NULL;
 }
 
-const GHOST_TUns8 *GHOST_SystemPathsX11::getUserDir() const
+const GHOST_TUns8 *GHOST_SystemPathsX11::getUserDir(int version, const char *versionstr) const
 {
-#ifndef WITH_XDG_USER_DIRS
-       return (const GHOST_TUns8 *)getenv("HOME");
-#else /* WITH_XDG_USER_DIRS */
-       const char *home = getenv("XDG_CONFIG_HOME");
+       static char user_path[PATH_MAX];
+
+       /* in blender 2.64, we migrate to XDG. to ensure the copy previous settings
+        * operator works we give a different path depending on the requested version */
+       if(version < 264) {
+               const char *home = getenv("HOME");
 
-       if (home) {
-               return (const GHOST_TUns8 *)home;
+               if(home) {
+                       snprintf(user_path, sizeof(user_path), "%s/.blender/%s", home, versionstr);
+                       return (GHOST_TUns8*)user_path;
+               }
+
+               return NULL;
        }
        else {
-               static char user_path[PATH_MAX];
+               const char *home= getenv("XDG_CONFIG_HOME");
+
+               if (home) {
+                       snprintf(user_path, sizeof(user_path), "%s/blender/%s", home, versionstr);
+               }
+               else {
+                       home= getenv("HOME");
 
-               home = getenv("HOME");
+                       if (home == NULL)
+                               home= getpwuid(getuid())->pw_dir;
 
-               if (home == NULL) {
-                       home = getpwuid(getuid())->pw_dir;
+                       snprintf(user_path, sizeof(user_path), "%s/.config/blender/%s", home, versionstr);
                }
 
-               snprintf(user_path, sizeof(user_path), "%s/.config", home);
                return (const GHOST_TUns8 *)user_path;
        }
-#endif /* WITH_XDG_USER_DIRS */
 }
 
 const GHOST_TUns8 *GHOST_SystemPathsX11::getBinaryDir() const
index 8ded9a3..db6d5a6 100644 (file)
@@ -52,17 +52,17 @@ public:
 
        /**
         * Determine the base dir in which shared resources are located. It will first try to use
-        * "unpack and run" path, then look for properly installed path, not including versioning.
+        * "unpack and run" path, then look for properly installed path, including versioning.
         * @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
         */
-       const GHOST_TUns8 *getSystemDir() const;
+       const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
 
        /**
-        * Determine the base dir in which user configuration is stored, not including versioning.
+        * Determine the base dir in which user configuration is stored, including versioning.
         * If needed, it will create the base directory.
         * @return Unsigned char string pointing to user dir (eg ~/.blender/).
         */
-       const GHOST_TUns8 *getUserDir() const;
+       const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
 
        /**
         * Determine the directory of the current binary
index d4b9bc3..d535e19 100644 (file)
@@ -157,10 +157,6 @@ if(WITH_OPENMP)
        add_definitions(-DPARALLEL=1)
 endif()
 
-if(WITH_XDG_USER_DIRS)
-       add_definitions(-DWITH_XDG_USER_DIRS)
-endif()
-
 if(WIN32)
        list(APPEND INC
                ../../../intern/utfconv
index ed3eedb..3c7e66f 100644 (file)
 #  endif
 #endif /* WIN32 */
 
-/* standard paths */
-#ifdef WIN32
-#  define BLENDER_USER_FORMAT       "%s\\Blender Foundation\\Blender\\%s"
-#  define BLENDER_SYSTEM_FORMAT     "%s\\Blender Foundation\\Blender\\%s"
-#elif defined(__APPLE__)
-#  define BLENDER_USER_FORMAT           "%s/Blender/%s"
-#  define BLENDER_SYSTEM_FORMAT         "%s/Blender/%s"
-#else /* UNIX */
-#  ifndef WITH_XDG_USER_DIRS /* oldschool unix ~/.blender/ */
-#    define BLENDER_USER_FORMAT         "%s/.blender/%s"
-#  else /* new XDG ~/blender/.config/ */
-#    define BLENDER_USER_FORMAT         "%s/blender/%s"
-#  endif // WITH_XDG_USER_DIRS
-#  define BLENDER_SYSTEM_FORMAT         "%s/blender/%s"
-#endif
-
 /* local */
 #define UNIQUE_NAME_MAX 128
 
@@ -822,16 +806,12 @@ void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
 const char *BLI_getDefaultDocumentFolder(void)
 {
 #ifndef WIN32
+       const char *xdg_documents_dir= getenv("XDG_DOCUMENTS_DIR");
 
-#ifdef WITH_XDG_USER_DIRS
-       const char *xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
-       if (xdg_documents_dir) {
+       if (xdg_documents_dir)
                return xdg_documents_dir;
-       }
-#endif
 
        return getenv("HOME");
-
 #else /* Windows */
        static char documentfolder[MAXPATHLEN];
        HRESULT hResult;
@@ -969,10 +949,9 @@ static int get_path_user(char *targetpath, const char *folder_name, const char *
                }
        }
 
-       user_base_path = (const char *)GHOST_getUserDir();
-       if (user_base_path) {
-               BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
-       }
+       user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
+       if (user_base_path)
+               BLI_strncpy(user_path, user_base_path, FILE_MAX);
 
        if (!user_path[0])
                return 0;
@@ -1040,10 +1019,9 @@ static int get_path_system(char *targetpath, const char *folder_name, const char
                }
        }
 
-       system_base_path = (const char *)GHOST_getSystemDir();
-       if (system_base_path) {
-               BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
-       }
+       system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
+       if (system_base_path)
+               BLI_strncpy(system_path, system_base_path, FILE_MAX);
        
        if (!system_path[0])
                return 0;