gnucash unstable: Simplify filepath init code

Geert Janssens gjanssens at code.gnucash.org
Thu Feb 1 13:17:56 EST 2018


Updated	 via  https://github.com/Gnucash/gnucash/commit/2f16b092 (commit)
	from  https://github.com/Gnucash/gnucash/commit/d345624c (commit)



commit 2f16b092f5f1115550484b9853adea082fbd269b
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Thu Feb 1 19:17:17 2018 +0100

    Simplify filepath init code
    
    It will no longer attempt to use /home/janssege/.gnucash. That was
    requiring lots of extra conditions.
    It will also default to a base directory (gnc_data_home) in the
    build dir if it detects the code is run during building or testing.
    That again allows to simplify it as there's no need for temp dir
    juggling in case the build environment doesn't have a writable home dir.

diff --git a/gnucash/gnucash-bin.c b/gnucash/gnucash-bin.c
index c0446bd..478157d 100644
--- a/gnucash/gnucash-bin.c
+++ b/gnucash/gnucash-bin.c
@@ -788,8 +788,10 @@ main(int argc, char ** argv)
     gnc_parse_command_line(&argc, &argv);
     gnc_print_unstable_message();
 
-    /* Make sure gnucash' user data directory is properly set up */
-    userdata_migrated = gnc_filepath_init(TRUE);
+    /* Make sure gnucash' user data directory is properly set up
+       This must be done before any guile code is called as that would
+       fail the migration message */
+    userdata_migrated = gnc_filepath_init();
     /* Translators: the message below will be completed with two directory names. */
     userdata_migration_msg = g_strdup_printf (
         _("Notice\n\nYour gnucash metadata has been migrated.\n\n"
diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index 881bfcf..fc57483 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -324,17 +324,12 @@ gnc_path_find_localized_html_file (const gchar *file_name)
  * @param dirname The path to check
  */
 static bool
-gnc_validate_directory (const bfs::path &dirname, bool create)
+gnc_validate_directory (const bfs::path &dirname)
 {
     if (dirname.empty())
         return false;
 
-    if (!bfs::exists(dirname) && (!create))
-        throw (bfs::filesystem_error("", dirname,
-                bst::error_code(bst::errc::no_such_file_or_directory,
-                                bst::generic_category())));
-
-    /* Optionally create directories if they don't exist yet
+    /* Create directories if they don't exist yet
      * Note this will do nothing if the directory and its
      * parents already exist, but will fail if the path
      * points to a file or a softlink. So it serves as a test
@@ -355,16 +350,13 @@ gnc_validate_directory (const bfs::path &dirname, bool create)
 #endif
     if ((perms & check_perms) != check_perms)
         throw (bfs::filesystem_error(
-            std::string(_("Insufficient permissions, at least write and access permissions required: "))
+            std::string("Insufficient permissions, at least write and access permissions required: ")
             + dirname.string(), dirname,
             bst::error_code(bst::errc::permission_denied, bst::generic_category())));
 
     return true;
 }
 
-static bool userdata_is_home = false;
-static bool userdata_is_tmp = false;
-static auto userdata_home = bfs::path();
 static auto gnc_userdata_home = bfs::path();
 
 /* Will attempt to copy all files and directories from src to dest
@@ -375,6 +367,10 @@ copy_recursive(const bfs::path& src, const bfs::path& dest)
     if (!bfs::exists(src))
         return false;
 
+    // Don't copy on self
+    if (src.compare(dest) == 0)
+        return false;
+
     auto old_str = src.string();
     auto old_len = old_str.size();
     try
@@ -452,10 +448,11 @@ quarz_get_userdata_home(void)
 #endif
 
 static bfs::path
-get_userdata_home(bool create)
+get_userdata_home(void)
 {
-    auto try_home_dir = true;
+    auto try_tmp_dir = true;
     gchar *data_dir = NULL;
+    auto userdata_home = bfs::path();
 
 #ifdef G_OS_WIN32
     data_dir = win32_get_userdata_home ();
@@ -471,38 +468,30 @@ get_userdata_home(bool create)
     else
         userdata_home = g_get_user_data_dir();
 
+    /* g_get_user_data_dir doesn't check whether the path exists nor attempts to
+     * create it. So while it may return an actual path we may not be able to use it.
+     * Let's check that now */
     if (!userdata_home.empty())
     {
         try
         {
-            gnc_validate_directory(userdata_home, create);  // May throw
-            try_home_dir = false;
+            gnc_validate_directory(userdata_home);  // May throw
+            try_tmp_dir = false;
         }
         catch (const bfs::filesystem_error& ex)
         {
             auto path_string = userdata_home.string();
             g_warning("%s is not a suitable base directory for the user data. "
-            "Trying home directory instead.\n(Error: %s)",
+            "Trying temporary directory instead.\n(Error: %s)",
             path_string.c_str(), ex.what());
         }
     }
 
-    if (try_home_dir)
+    /* The path we got is not usable, so fall back to a path in TMP_DIR.
+       Hopefully we can always write there. */
+    if (try_tmp_dir)
     {
-        userdata_home = g_get_home_dir();
-        try
-        {
-            /* Never attempt to create a home directory, hence the false below */
-            gnc_validate_directory(userdata_home, false);  // May throw
-            userdata_is_home = true;
-        }
-        catch (const bfs::filesystem_error& ex)
-        {
-            g_warning("Cannot find suitable home directory. Using tmp directory instead.\n"
-            "(Error: %s)", ex.what());
-            userdata_home = g_get_tmp_dir();
-            userdata_is_tmp = true;
-        }
+        userdata_home = bfs::path (g_get_tmp_dir ()) / g_get_user_name ();
     }
     g_assert(!userdata_home.empty());
 
@@ -510,90 +499,95 @@ get_userdata_home(bool create)
 }
 
 gboolean
-gnc_filepath_init(gboolean create)
+gnc_filepath_init (void)
 {
-    userdata_is_home = userdata_is_tmp = false;
     auto gnc_userdata_home_exists = false;
-    auto gnc_userdata_home_from_env = false;
-    auto gnc_userdata_home_env = g_getenv("GNC_DATA_HOME");
-    if (gnc_userdata_home_env)
+    auto have_valid_userdata_home = false;
+
+    /* If this code is run while building/testing, use a fake GNC_DATA_HOME
+     * in the base of the build directory. This is to deal with all kinds of
+     * issues when the build environment is not a complete environment (like
+     * it could be missing a valid home directory). */
+    auto builddir = g_getenv ("GNC_BUILDDIR");
+    auto running_uninstalled = (g_getenv ("GNC_UNINSTALLED") != NULL);
+    if (running_uninstalled && builddir)
     {
-        gnc_userdata_home = bfs::path(gnc_userdata_home_env);
+        auto build_home = g_build_filename (builddir, "gnc_data_home", NULL);
+        gnc_userdata_home = bfs::path(build_home);
+        g_free (build_home);
         try
         {
-            gnc_userdata_home_exists = bfs::exists(gnc_userdata_home);
-            gnc_validate_directory(gnc_userdata_home, create); // May throw
-            gnc_userdata_home_from_env = true;
+            gnc_validate_directory(gnc_userdata_home); // May throw
+            have_valid_userdata_home = true;
+            gnc_userdata_home_exists = true; // To prevent possible migration further down
         }
         catch (const bfs::filesystem_error& ex)
         {
-            auto path_string = userdata_home.string();
-            g_warning("%s (from environment variable 'GNC_DATA_HOME') is not a suitable directory for the user data. "
-            "Trying the default instead.\n(Error: %s)",
-            path_string.c_str(), ex.what());
+            auto path_string = gnc_userdata_home.string();
+            g_warning("%s (due to run during at build time) is not a suitable directory for user data. "
+            "Trying another directory instead.\n(Error: %s)",
+                      path_string.c_str(), ex.what());
         }
     }
 
-    if (!gnc_userdata_home_from_env)
+
+    if (!have_valid_userdata_home)
     {
-        auto userdata_home = get_userdata_home(create);
-        if (userdata_is_home)
+        /* If environment variable GNC_DATA_HOME is set, try whether
+         * it points at a valid directory. */
+        auto gnc_userdata_home_env = g_getenv("GNC_DATA_HOME");
+        if (gnc_userdata_home_env)
         {
-            /* If we get here that means the platform
-            * dependent gnc_userdata_home is not available for
-            * some reason. If legacy .gnucash directory still exists,
-            * use it as first fallback, but never create it (we want
-            * it to go away eventually).
-            * If missing, fall back to tmp_dir instead */
-            gnc_userdata_home = userdata_home / ".gnucash";
-            if (!bfs::exists(gnc_userdata_home))
+            gnc_userdata_home = bfs::path(gnc_userdata_home_env);
+            try
             {
-                userdata_home = g_get_tmp_dir();
-                userdata_is_home = false;
-                userdata_is_tmp = true;
+                gnc_userdata_home_exists = bfs::exists(gnc_userdata_home);
+                gnc_validate_directory(gnc_userdata_home); // May throw
+                have_valid_userdata_home = true;
+            }
+            catch (const bfs::filesystem_error& ex)
+            {
+                auto path_string = gnc_userdata_home.string();
+                g_warning("%s (from environment variable 'GNC_DATA_HOME') is not a suitable directory for user data. "
+                "Trying the default instead.\n(Error: %s)",
+                path_string.c_str(), ex.what());
             }
         }
+    }
 
-        /* The fall back to the tmp dir is to accomodate for very restricted
-         * distribution build environments. In some such cases
-         * there is no home directory available, which would cause the build
-         * to fail (as this code is actually run while compiling guile scripts).
-         * This is worked around by continuing with a userdata directory
-         * in the temporary directory which always exists. */
-        if (!userdata_is_home)
-            gnc_userdata_home = userdata_home / PACKAGE_NAME;
-        gnc_userdata_home_exists = bfs::exists(gnc_userdata_home);
-        /* This may throw and end the program!
-         * Note we always allow to create in the tmp_dir. This will
-         * skip migrating to that location in the next step but that's
-         * a good thing.
-         */
+    if (!have_valid_userdata_home)
+    {
+        /* Determine platform dependent default userdata_home_path
+         * and check whether it's valid */
+        auto userdata_home = get_userdata_home();
+        gnc_userdata_home = userdata_home / PACKAGE;
         try
         {
-            gnc_validate_directory(gnc_userdata_home, (create || userdata_is_tmp));
+            gnc_userdata_home_exists = bfs::exists(gnc_userdata_home);
+            gnc_validate_directory(gnc_userdata_home);
         }
         catch (const bfs::filesystem_error& ex)
         {
-            g_warning("User data directory doesn't exist, yet the calling code requested not to create it. Proceed with caution.\n"
+            g_warning("User data directory doesn't exist, yet could not be created. Proceed with caution.\n"
             "(Error: %s)", ex.what());
         }
     }
 
     auto migrated = FALSE;
-    if (!userdata_is_home && !gnc_userdata_home_exists && create)
+    if (!gnc_userdata_home_exists)
         migrated = copy_recursive(bfs::path (g_get_home_dir()) / ".gnucash",
                                   gnc_userdata_home);
 
     /* Try to create the standard subdirectories for gnucash' user data */
     try
     {
-        gnc_validate_directory(gnc_userdata_home / "books", (create || userdata_is_tmp));
-        gnc_validate_directory(gnc_userdata_home / "checks", (create || userdata_is_tmp));
-        gnc_validate_directory(gnc_userdata_home / "translog", (create || userdata_is_tmp));
+        gnc_validate_directory(gnc_userdata_home / "books");
+        gnc_validate_directory(gnc_userdata_home / "checks");
+        gnc_validate_directory(gnc_userdata_home / "translog");
     }
     catch (const bfs::filesystem_error& ex)
     {
-        g_warning("Default user data subdirectories don't exist, yet the calling code requested not to create them. Proceed with caution.\n"
+        g_warning("Default user data subdirectories don't exist, yet could not be created. Proceed with caution.\n"
         "(Error: %s)", ex.what());
     }
 
@@ -642,7 +636,7 @@ const gchar *
 gnc_userdata_dir (void)
 {
     if (gnc_userdata_home.empty())
-        gnc_filepath_init(false);
+        gnc_filepath_init();
 
     return gnc_userdata_home.string().c_str();
 }
@@ -657,7 +651,7 @@ gnc_userdata_dir_as_path (void)
          * code most likely) very early in application startup.
          * This call is just a fallback to prevent the code from
          * crashing because no directories were configured. */
-        gnc_filepath_init(false);
+        gnc_filepath_init();
 
     return gnc_userdata_home;
 }
diff --git a/libgnucash/core-utils/gnc-filepath-utils.h b/libgnucash/core-utils/gnc-filepath-utils.h
index d0e9ff4..465d404 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.h
+++ b/libgnucash/core-utils/gnc-filepath-utils.h
@@ -87,22 +87,13 @@ gchar *gnc_path_find_localized_html_file (const gchar *file_name);
  * This function should be called very early at startup (before any
  * other of the user data directory related function gets called).
  *
- * @param create If true the function will attempt to create the
- * gnucash user data directory its subdirectories and parent directories
- * if they don't exist yet. Note it won't attempt to create a home directory
- * if that is missing. In that case the system's default temporary
- * directory will be used instead. If false it will not attempt to create
- * any directories at all unless they are in the temporary directory. This
- * is a fallback measure to allow the calling application to more or less
- * function even if gnc_filepath_init was never called.
- *
  * @note If the necessary directories did get created this
  * function will also try to copy files from $HOME/.gnucash
  * to there if that old location exists.
  *
  * @return whether files got copied from the old location.
  */
-gboolean gnc_filepath_init(gboolean create);
+gboolean gnc_filepath_init (void);
 
 const gchar *gnc_userdata_dir (void);
 gchar *gnc_build_userdata_path (const gchar *filename);
diff --git a/libgnucash/core-utils/test/test-userdata-dir-invalid-home.c b/libgnucash/core-utils/test/test-userdata-dir-invalid-home.c
index cce4bbb..9595147 100644
--- a/libgnucash/core-utils/test/test-userdata-dir-invalid-home.c
+++ b/libgnucash/core-utils/test/test-userdata-dir-invalid-home.c
@@ -42,19 +42,19 @@ usr_confpath_strings strs2[] =
 {
     {
         0, "gnc_build_userdata_path",
-        PACKAGE_NAME
+        PACKAGE
     },
     {
         1, "gnc_build_book_path",
-        PACKAGE_NAME G_DIR_SEPARATOR_S "books"
+        PACKAGE G_DIR_SEPARATOR_S "books"
     },
     {
         2, "gnc_build_translog_path",
-        PACKAGE_NAME G_DIR_SEPARATOR_S "translog"
+        PACKAGE G_DIR_SEPARATOR_S "translog"
     },
     {
         3, "gnc_build_data_path",
-        PACKAGE_NAME G_DIR_SEPARATOR_S "data"
+        PACKAGE G_DIR_SEPARATOR_S "data"
     },
     { 0, NULL, NULL },
 };
@@ -62,9 +62,21 @@ usr_confpath_strings strs2[] =
 int
 main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
 {
+/* Don't run this test on Windows or OS X. This
+   test attempts to fool the code into using a non-existent
+   home directory, but the way this is done only works on linux
+   */
+#ifndef MAC_INTEGRATION
+#ifndef G_OS_WIN32
     int i;
     const char *tmp_dir = g_get_tmp_dir();
 
+    /* Assume we're not in a build environment to test
+     * the function's actual behaviour in a real world use case, using
+     * a non-existent homedir. */
+    g_unsetenv("GNC_BUILDDIR");
+    g_unsetenv("GNC_UNINSTALLED");
+
     /* Run usr conf dir tests with an invalid homedir
      * The code should fall back to using the temporary
      * directory in that case. */
@@ -76,25 +88,25 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
 
         if (strs2[i].func_num == 0)
         {
-            wantout = g_build_filename(tmp_dir, strs2[i].output, "foo",
+            wantout = g_build_filename(tmp_dir, g_get_user_name (), strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_userdata_path("foo");
         }
         else if (strs2[i].func_num == 1)
         {
-            wantout = g_build_filename(tmp_dir, strs2[i].output, "foo",
+            wantout = g_build_filename(tmp_dir, g_get_user_name (), strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_book_path("foo");
         }
         else if (strs2[i].func_num == 2)
         {
-            wantout = g_build_filename(tmp_dir, strs2[i].output, "foo",
+            wantout = g_build_filename(tmp_dir, g_get_user_name (), strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_translog_path("foo");
         }
         else // if (strs2[i].prefix_home == 3)
         {
-            wantout = g_build_filename(tmp_dir, strs2[i].output, "foo",
+            wantout = g_build_filename(tmp_dir, g_get_user_name (), strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_data_path("foo");
         }
@@ -109,4 +121,6 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
 
     print_test_results();
     return get_rv();
+#endif
+#endif
 }
diff --git a/libgnucash/core-utils/test/test-userdata-dir.c b/libgnucash/core-utils/test/test-userdata-dir.c
index 377a2f8..d72d9b8 100644
--- a/libgnucash/core-utils/test/test-userdata-dir.c
+++ b/libgnucash/core-utils/test/test-userdata-dir.c
@@ -87,6 +87,8 @@ main(int argc, char **argv)
     char *tmp_dir = NULL;
     char *userdata_dir = NULL;
     char *gnc_data_home_dir = NULL;
+    const char *builddir = g_getenv("GNC_BUILDDIR");
+    const char *uninstalled = g_getenv("GNC_UNINSTALLED");
 
     if (argc > 1)
     {
@@ -96,61 +98,68 @@ main(int argc, char **argv)
          * test error messages should then show the system's temporary
          * directory to be used instead */
         home_dir = g_strdup(argv[1]);
-        tmp_dir = g_strdup(g_get_tmp_dir());
     }
     else
     {
         /* Set up a fake home directory to play with */
 #ifdef MAC_INTEGRATION
         home_dir = test_get_userdatadir();
-        tmp_dir = g_strdup(home_dir);
 #else
         home_dir = g_dir_make_tmp("gnucashXXXXXX", NULL);
-        tmp_dir = g_strdup(g_get_tmp_dir());
 #endif
     }
-    /* Run usr conf dir tests with a valid and writable homedir */
+    /* Run usr conf dir tests with a valid and writable fake homedir */
     g_setenv("HOME", home_dir, TRUE);
 
-    /* First run, before calling gnc_filepath_init */
-    for (i = 0; strs2[i].funcname != NULL; i++)
+    /* First run, assuming GNC_BUILDDIR and GNC_UNINSTALLED are set */
+    if (builddir && uninstalled)
     {
-        char *daout;
-        char *wantout;
-
-        if (strs2[i].func_num == 0)
-        {
-            wantout = g_build_filename(tmp_dir, PACKAGE_NAME, "foo",
-                                       (gchar *)NULL);
-            daout = gnc_build_userdata_path("foo");
-        }
-        else if (strs2[i].func_num == 1)
-        {
-            wantout = g_build_filename(tmp_dir, PACKAGE_NAME, strs2[i].output, "foo",
-                                       (gchar *)NULL);
-            daout = gnc_build_book_path("foo");
-        }
-        else if (strs2[i].func_num == 2)
+        for (i = 0; strs2[i].funcname != NULL; i++)
         {
-            wantout = g_build_filename(tmp_dir, PACKAGE_NAME, strs2[i].output, "foo",
-                                       (gchar *)NULL);
-            daout = gnc_build_translog_path("foo");
-        }
-        else // if (strs2[i].prefix_home == 3)
-        {
-            wantout = g_build_filename(tmp_dir, PACKAGE_NAME, strs2[i].output, "foo",
-                                       (gchar *)NULL);
-            daout = gnc_build_data_path("foo");
-        }
+            char *daout;
+            char *wantout;
 
-        do_test_args(g_strcmp0(daout, wantout) == 0,
-                     "gnc_build_x_path",
-                     __FILE__, __LINE__,
-                     "%s (%s) vs %s", daout, strs2[i].funcname, wantout);
-        g_free(wantout);
-        g_free(daout);
+            if (strs2[i].func_num == 0)
+            {
+                wantout = g_build_filename(builddir, "gnc_data_home", "foo",
+                                        (gchar *)NULL);
+                daout = gnc_build_userdata_path("foo");
+            }
+            else if (strs2[i].func_num == 1)
+            {
+                wantout = g_build_filename(builddir, "gnc_data_home", strs2[i].output, "foo",
+                                        (gchar *)NULL);
+                daout = gnc_build_book_path("foo");
+            }
+            else if (strs2[i].func_num == 2)
+            {
+                wantout = g_build_filename(builddir, "gnc_data_home", strs2[i].output, "foo",
+                                        (gchar *)NULL);
+                daout = gnc_build_translog_path("foo");
+            }
+            else // if (strs2[i].prefix_home == 3)
+            {
+                wantout = g_build_filename(builddir, "gnc_data_home", strs2[i].output, "foo",
+                                        (gchar *)NULL);
+                daout = gnc_build_data_path("foo");
+            }
+
+            do_test_args(g_strcmp0(daout, wantout) == 0,
+                        "gnc_build_x_path",
+                        __FILE__, __LINE__,
+                        "%s (%s) vs %s", daout, strs2[i].funcname, wantout);
+            g_free(wantout);
+            g_free(daout);
+        }
     }
 
+    /* Further tests should be run assuming we're not in a build environment to test
+     * the function's actual behaviour in a real world use case, but still using
+     * the fake, writable homedir. */
+    g_unsetenv("GNC_BUILDDIR");
+    g_unsetenv("GNC_UNINSTALLED");
+
+
     /* Second run, with existing userdata_dir, but without the GnuCash subdir
        This test can not be run on OS X or Windows, as our code is not using
        XDG_DATA_HOME on these platforms */
@@ -159,7 +168,7 @@ main(int argc, char **argv)
     userdata_dir = g_build_filename(home_dir, ".local", "share", (gchar *)NULL);
     g_mkdir_with_parents(userdata_dir, 0750);
     g_setenv("XDG_DATA_HOME", userdata_dir, TRUE);
-    gnc_filepath_init(FALSE);
+    gnc_filepath_init();
     for (i = 0; strs2[i].funcname != NULL; i++)
     {
         char *daout;
@@ -167,25 +176,25 @@ main(int argc, char **argv)
 
         if (strs2[i].func_num == 0)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_userdata_path("foo");
         }
         else if (strs2[i].func_num == 1)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, strs2[i].output, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_book_path("foo");
         }
         else if (strs2[i].func_num == 2)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, strs2[i].output, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_translog_path("foo");
         }
         else // if (strs2[i].prefix_home == 3)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, strs2[i].output, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_data_path("foo");
         }
@@ -197,20 +206,32 @@ main(int argc, char **argv)
         g_free(wantout);
         g_free(daout);
     }
-    /* Remove intermediate directories again in order to test their automatic
-     * creation in the next test run */
-    g_rmdir(userdata_dir);
-    g_free(userdata_dir);
-    userdata_dir = g_build_filename(home_dir, ".local", (gchar *)NULL);
+    g_unsetenv("XDG_DATA_HOME");
+    /* Remove intermediate directories again */
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, "data", (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, "translog", (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, "books", (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
     g_rmdir(userdata_dir);
+    tmp_dir = g_path_get_dirname(userdata_dir);
+    g_rmdir(tmp_dir);
+    g_free (tmp_dir);
     g_free(userdata_dir);
 #endif
 #endif
 
-    /* Third run, with GNC_DATA_HOME not set and having run gnc_filepath_init */
+    /* Third run, with neither XDG_DATA_HOME nor GNC_DATA_HOME set */
     g_unsetenv("GNC_DATA_HOME");
-    gnc_filepath_init(TRUE);
     userdata_dir = test_get_userdatadir();
+    gnc_filepath_init();
     for (i = 0; strs2[i].funcname != NULL; i++)
     {
         char *daout;
@@ -218,25 +239,25 @@ main(int argc, char **argv)
 
         if (strs2[i].func_num == 0)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_userdata_path("foo");
         }
         else if (strs2[i].func_num == 1)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, strs2[i].output, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_book_path("foo");
         }
         else if (strs2[i].func_num == 2)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, strs2[i].output, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_translog_path("foo");
         }
         else // if (strs2[i].prefix_home == 3)
         {
-            wantout = g_build_filename(userdata_dir, PACKAGE_NAME, strs2[i].output, "foo",
+            wantout = g_build_filename(userdata_dir, PACKAGE, strs2[i].output, "foo",
                                        (gchar *)NULL);
             daout = gnc_build_data_path("foo");
         }
@@ -248,12 +269,34 @@ main(int argc, char **argv)
         g_free(wantout);
         g_free(daout);
     }
+    /* Remove intermediate directories again */
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, "data", (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, "translog", (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, "books", (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+#ifndef MAC_INTEGRATION
+#ifndef G_OS_WIN32
+    /* Don't delete these on OS X or Windows. They may point at real user directories */
+    tmp_dir = g_build_filename(userdata_dir, PACKAGE, (gchar *)NULL);
+    g_rmdir (tmp_dir);
+    g_free (tmp_dir);
+    g_rmdir(userdata_dir);
+    tmp_dir = g_path_get_dirname(userdata_dir);
+    g_rmdir(tmp_dir);
+    g_free (tmp_dir);
+#endif
+#endif
     g_free(userdata_dir);
 
-    /* Fourth run, with GNC_DATA_HOME set and having run gnc_filepath_init */
+    /* Fourth run, with GNC_DATA_HOME */
     gnc_data_home_dir = g_build_filename(home_dir, "Test", NULL);
     g_setenv("GNC_DATA_HOME", gnc_data_home_dir, TRUE);
-    gnc_filepath_init(TRUE);
+    gnc_filepath_init();
     for (i = 0; strs2[i].funcname != NULL; i++)
     {
         char *daout;



Summary of changes:
 gnucash/gnucash-bin.c                              |   6 +-
 libgnucash/core-utils/gnc-filepath-utils.cpp       | 156 ++++++++++-----------
 libgnucash/core-utils/gnc-filepath-utils.h         |  11 +-
 .../test/test-userdata-dir-invalid-home.c          |  30 ++--
 libgnucash/core-utils/test/test-userdata-dir.c     | 155 ++++++++++++--------
 5 files changed, 201 insertions(+), 157 deletions(-)



More information about the gnucash-changes mailing list