gnucash maint: Multiple changes pushed

Geert Janssens gjanssens at code.gnucash.org
Fri Dec 28 12:47:16 EST 2018


Updated	 via  https://github.com/Gnucash/gnucash/commit/267852ba (commit)
	 via  https://github.com/Gnucash/gnucash/commit/272ca421 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ac2e0946 (commit)
	from  https://github.com/Gnucash/gnucash/commit/2634f23f (commit)



commit 267852ba763331aa04ab0f7be33d3d74f4297a82
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Fri Dec 28 18:47:06 2018 +0100

    Add a note on cvt and imbuing locales in a boost::filesystem::path object

diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index 01ca259..e612c1c 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -68,7 +68,23 @@ extern "C" {
 #include <boost/locale.hpp>
 #include <iostream>
 
-
+/* Below cvt and bfs_locale should be used with boost::filesystem::path (bfs)
+ * objects created alter in this source file. The rationale is as follows:
+ * - a bfs object has an internal, locale and platform dependent
+ *   representation of a file system path
+ * - glib's internal representation is always utf8
+ * - when creating a bfs object, we should pass a cvt to convert from
+ *   utf8 to the object's internal representation
+ * - if we later want to use the bfs object's internal representation
+ *   in a glib context we should imbue the locale below so that
+ *   bfs will use it to convert back to utf8
+ * - if the bfs object's internal representation will never be used
+ *   in a glib context, imbuing is not needed (although probably more
+ *   future proof)
+ * - also note creating a bfs based on another one will inherit the
+ *   locale from the source path. So in that case there's not need
+ *   to imbue it again.
+ */
 #if PLATFORM(WINDOWS)
 #include <codecvt>
 using codecvt = std::codecvt_utf8<wchar_t, 0x10FFFF, std::little_endian>;

commit 272ca421b73929e5bba1a585c854477414bea91c
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Fri Dec 28 18:36:46 2018 +0100

    Set up filepath utils to determine the GNC_CONFIG_HOME in the same way as GNC_DATA_HOME
    
    Until now GNC_CONFIG_HOME was more or less hard-coded.
    Now it can be set via environment variable GNC_CONFIG_HOME.
    In addition it will automatically be created to avoid potential
    user confusion.

diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index 92bf682..01ca259 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -718,14 +718,89 @@ constexpr auto path_package = PACKAGE_NAME;
 constexpr auto path_package = PACKAGE;
 #endif
 
-
-char *
-gnc_filepath_init (void)
+// Initialize the user's config directory for gnucash
+// creating it if it doesn't exist yet.
+static void
+gnc_file_path_init_config_home (void)
 {
-    // Initialize the user's config directory for gnucash
-    gnc_userconfig_home = get_userconfig_home() / path_package;
+    auto have_valid_userconfig_home = false;
+
+    /* If this code is run while building/testing, use a fake GNC_CONFIG_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 env_build_dir = g_getenv ("GNC_BUILDDIR");
+    bfs::path new_dir(env_build_dir ? env_build_dir : "", cvt);
+    new_dir.imbue(bfs_locale);
+    build_dir = std::move(new_dir);
+    auto running_uninstalled = (g_getenv ("GNC_UNINSTALLED") != NULL);
+    if (running_uninstalled && !build_dir.empty())
+    {
+        gnc_userconfig_home = build_dir / "gnc_config_home";
+        try
+        {
+            gnc_validate_directory (gnc_userconfig_home); // May throw
+            have_valid_userconfig_home = true;
+        }
+        catch (const bfs::filesystem_error& ex)
+        {
+            auto path_string = gnc_userconfig_home.string();
+            g_warning("%s (due to run during at build time) is not a suitable directory for user configuration files. "
+            "Trying another directory instead.\n(Error: %s)",
+                      path_string.c_str(), ex.what());
+        }
+    }
+
+    if (!have_valid_userconfig_home)
+    {
+        /* If environment variable GNC_CONFIG_HOME is set, try whether
+         * it points at a valid directory. */
+        auto gnc_userconfig_home_env = g_getenv ("GNC_CONFIG_HOME");
+        if (gnc_userconfig_home_env)
+        {
+            bfs::path newdir(gnc_userconfig_home_env, cvt);
+            newdir.imbue(bfs_locale);
+            gnc_userconfig_home = std::move(newdir);
+            try
+            {
+                gnc_validate_directory (gnc_userconfig_home); // May throw
+                have_valid_userconfig_home = true;
+            }
+            catch (const bfs::filesystem_error& ex)
+            {
+                auto path_string = gnc_userconfig_home.string();
+                g_warning("%s (from environment variable 'GNC_CONFIG_HOME') is not a suitable directory for user configuration files. "
+                "Trying the default instead.\n(Error: %s)",
+                          path_string.c_str(), ex.what());
+            }
+        }
+    }
 
+    if (!have_valid_userconfig_home)
+    {
+        /* Determine platform dependent default userconfig_home_path
+         * and check whether it's valid */
+        auto userconfig_home = get_userconfig_home();
+        gnc_userconfig_home = userconfig_home / path_package;
+        try
+        {
+            gnc_validate_directory (gnc_userconfig_home);
+        }
+        catch (const bfs::filesystem_error& ex)
+        {
+            g_warning ("User configuration directory doesn't exist, yet could not be created. Proceed with caution.\n"
+            "(Error: %s)", ex.what());
+        }
+    }
+}
 
+// Initialize the user's config directory for gnucash
+// creating it if it didn't exist yet.
+// The function will return true if the directory already
+// existed or false if it had to be created
+static bool
+gnc_file_path_init_data_home (void)
+{
     // Initialize the user's data directory for gnucash
     auto gnc_userdata_home_exists = false;
     auto have_valid_userdata_home = false;
@@ -764,8 +839,8 @@ gnc_filepath_init (void)
         auto gnc_userdata_home_env = g_getenv ("GNC_DATA_HOME");
         if (gnc_userdata_home_env)
         {
-	    bfs::path newdir(gnc_userdata_home_env, cvt);
-	    newdir.imbue(bfs_locale);
+            bfs::path newdir(gnc_userdata_home_env, cvt);
+            newdir.imbue(bfs_locale);
             gnc_userdata_home = std::move(newdir);
             try
             {
@@ -778,7 +853,7 @@ gnc_filepath_init (void)
                 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());
+                          path_string.c_str(), ex.what());
             }
         }
     }
@@ -801,6 +876,25 @@ gnc_filepath_init (void)
         }
     }
 
+    return gnc_userdata_home_exists;
+}
+
+// Initialize the user's config and data directory for gnucash
+// This function will also create these directories if they didn't
+// exist yet.
+// In addition it will trigger a migration if the user's data home
+// didn't exist but the now obsolete GNC_DOT_DIR ($HOME/.gnucash)
+// does.
+// Finally it well ensure a number of default required directories
+// will be created if they don't exist yet.
+char *
+gnc_filepath_init (void)
+{
+    gnc_userconfig_home = get_userconfig_home() / path_package;
+
+    gnc_file_path_init_config_home ();
+    auto gnc_userdata_home_exists = gnc_file_path_init_data_home ();
+
     /* Run migration code before creating the default directories
        If migrating, these default directories are copied instead of created. */
     auto migration_notice = std::string ();

commit ac2e0946eac6e00113bf1c4af48e9735230f1331
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Fri Dec 28 16:13:58 2018 +0100

    Rewrite path scrubbing in a c++ way

diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index 67e930d..92bf682 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -90,26 +90,6 @@ namespace bfs = boost::filesystem;
 namespace bst = boost::system;
 namespace bl = boost::locale;
 
-/**
- * Scrubs a filename by changing "strange" chars (e.g. those that are not
- * valid in a win32 file name) to "_".
- *
- * @param filename File name - updated in place
- */
-static void
-scrub_filename(char* filename)
-{
-    char* p;
-
-#define STRANGE_CHARS "/:"
-    p = strpbrk(filename, STRANGE_CHARS);
-    while (p)
-    {
-        *p = '_';
-        p = strpbrk(filename, STRANGE_CHARS);
-    }
-}
-
 /** Check if the path exists and is a regular file.
  *
  * \param path -- freed if the path doesn't exist or isn't a regular file
@@ -942,14 +922,22 @@ gnc_build_userdata_path (const gchar *filename)
     return g_strdup((gnc_userdata_dir_as_path() / filename).string().c_str());
 }
 
+/* Test whether c is a valid character for a win32 file name.
+ * If so return false, otherwise return true.
+ */
+static bool
+is_invalid_char (char c)
+{
+    return (c == '/') || ( c == ':');
+}
+
 static bfs::path
 gnc_build_userdata_subdir_path (const gchar *subdir, const gchar *filename)
 {
-    gchar* filename_dup = g_strdup(filename);
+    auto fn = std::string(filename);
 
-    scrub_filename(filename_dup);
-    auto result = (gnc_userdata_dir_as_path() / subdir) / filename_dup;
-    g_free(filename_dup);
+    std::replace_if (fn.begin(), fn.end(), is_invalid_char, '_');
+    auto result = (gnc_userdata_dir_as_path() / subdir) / fn;
     return result;
 }
 



Summary of changes:
 libgnucash/core-utils/gnc-filepath-utils.cpp | 164 +++++++++++++++++++++------
 1 file changed, 131 insertions(+), 33 deletions(-)



More information about the gnucash-changes mailing list