diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp index 4b15ea8df7..efc2440d86 100644 --- a/libgnucash/core-utils/gnc-filepath-utils.cpp +++ b/libgnucash/core-utils/gnc-filepath-utils.cpp @@ -489,34 +489,58 @@ get_userdata_home(bool create) gboolean gnc_filepath_init(gboolean create) { - auto userdata_home = get_userdata_home(create); - - if (userdata_is_home) + 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) { - /* 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; + gnc_userdata_home_exists = bfs::exists(gnc_userdata_home); + if (!gnc_validate_directory(gnc_userdata_home, create)) + throw (bfs::filesystem_error( + std::string(_("Directory doesn't exist: ")) + + userdata_home.c_str(), userdata_home, + bst::error_code(bst::errc::permission_denied, bst::generic_category()))); + gnc_userdata_home_from_env = true; + } + catch (const bfs::filesystem_error& ex) + { + g_warning("%s (from environment variable 'GNC_DATA_HOME') is not a suitable directory for the user data." + "Trying the default instead.\nThe failure is\n%s", + gnc_userdata_home.c_str(), ex.what()); } } - if (!userdata_is_home) - gnc_userdata_home = userdata_home / PACKAGE_NAME; + if (!gnc_userdata_home_from_env) + { + auto userdata_home = get_userdata_home(create); + if (userdata_is_home) + { + /* 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)) + { + userdata_home = g_get_tmp_dir(); + userdata_is_home = false; + } + } + + 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! */ + gnc_validate_directory(gnc_userdata_home, create); + } - auto try_migrate = false; - if (!userdata_is_home && !bfs::exists(gnc_userdata_home) && create) - try_migrate = true; - /* This may throw and end the program! */ - gnc_validate_directory(gnc_userdata_home, create); auto migrated = FALSE; - if (try_migrate) + if (!userdata_is_home && !gnc_userdata_home_exists && create) migrated = copy_recursive(bfs::path (g_get_home_dir()) / ".gnucash", gnc_userdata_home); diff --git a/libgnucash/core-utils/test/test-userdata-dir.c b/libgnucash/core-utils/test/test-userdata-dir.c index 68bd5e0341..3197a0b406 100644 --- a/libgnucash/core-utils/test/test-userdata-dir.c +++ b/libgnucash/core-utils/test/test-userdata-dir.c @@ -41,20 +41,16 @@ typedef struct usr_confpath_strings_struct usr_confpath_strings; usr_confpath_strings strs2[] = { { - 0, "gnc_build_userdata_path", - PACKAGE_NAME + 0, "gnc_build_userdata_path", "" }, { - 1, "gnc_build_book_path", - PACKAGE_NAME G_DIR_SEPARATOR_S "books" + 1, "gnc_build_book_path", "books" }, { - 2, "gnc_build_translog_path", - PACKAGE_NAME G_DIR_SEPARATOR_S "translog" + 2, "gnc_build_translog_path", "translog" }, { - 3, "gnc_build_data_path", - PACKAGE_NAME G_DIR_SEPARATOR_S "data" + 3, "gnc_build_data_path", "data" }, { 0, NULL, NULL }, }; @@ -66,6 +62,7 @@ main(int argc, char **argv) char *home_dir = NULL; const char *userdata_dir = NULL; const char *tmp_dir = g_get_tmp_dir(); + char *gnc_data_home_dir = NULL; if (argc > 1) /* One can pass a homedir on the command line. This @@ -89,25 +86,25 @@ main(int argc, char **argv) if (strs2[i].func_num == 0) { - wantout = g_build_filename(tmp_dir, strs2[i].output, "foo", + 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, strs2[i].output, "foo", + 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) { - wantout = g_build_filename(tmp_dir, strs2[i].output, "foo", + 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, strs2[i].output, "foo", + wantout = g_build_filename(tmp_dir, PACKAGE_NAME, strs2[i].output, "foo", (gchar *)NULL); daout = gnc_build_data_path("foo"); } @@ -130,25 +127,67 @@ main(int argc, char **argv) if (strs2[i].func_num == 0) { - wantout = g_build_filename(userdata_dir, strs2[i].output, "foo", + wantout = g_build_filename(userdata_dir, PACKAGE_NAME, "foo", (gchar *)NULL); daout = gnc_build_userdata_path("foo"); } else if (strs2[i].func_num == 1) { - wantout = g_build_filename(userdata_dir, strs2[i].output, "foo", + wantout = g_build_filename(userdata_dir, PACKAGE_NAME, 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, strs2[i].output, "foo", + wantout = g_build_filename(userdata_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(userdata_dir, strs2[i].output, "foo", + wantout = g_build_filename(userdata_dir, PACKAGE_NAME, 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); + } + + /* Third run, after setting GNC_DATA_HOME gnc_filepath_init */ + 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); + for (i = 0; strs2[i].funcname != NULL; i++) + { + char *daout; + char *wantout; + + if (strs2[i].func_num == 0) + { + wantout = g_build_filename(gnc_data_home_dir, "foo", + (gchar *)NULL); + daout = gnc_build_userdata_path("foo"); + } + else if (strs2[i].func_num == 1) + { + wantout = g_build_filename(gnc_data_home_dir, strs2[i].output, "foo", + (gchar *)NULL); + daout = gnc_build_book_path("foo"); + } + else if (strs2[i].func_num == 2) + { + wantout = g_build_filename(gnc_data_home_dir, strs2[i].output, "foo", + (gchar *)NULL); + daout = gnc_build_translog_path("foo"); + } + else // if (strs2[i].prefix_home == 3) + { + wantout = g_build_filename(gnc_data_home_dir, strs2[i].output, "foo", (gchar *)NULL); daout = gnc_build_data_path("foo"); }