Skip to content

Commit

Permalink
API: add proj_context_set_user_writable_directory()
Browse files Browse the repository at this point in the history
Fixes #4142
  • Loading branch information
rouault committed May 9, 2024
1 parent e353e08 commit dda95a0
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 14 deletions.
3 changes: 3 additions & 0 deletions docs/source/resource_files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ The following paths are checked in order:
* on other platforms (Linux), ``${XDG_DATA_HOME}/proj`` if
:envvar:`XDG_DATA_HOME` is defined. Else ``${HOME}/.local/share/proj``

Applications may also customize the user writable directory using
:cpp:func:`proj_context_set_user_writable_directory` (since 9.5)

- Path(s) set with by the environment variable :envvar:`PROJ_DATA`.
Prior to PROJ 9.1, this environment variable was called :envvar:`PROJ_LIB`.
This older name is still supported in PROJ 9.1 as a fallback, but support for it
Expand Down
2 changes: 1 addition & 1 deletion scripts/reference_exported_symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,6 @@ pj_approx_3D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD)
pj_atof(char const*)
pj_chomp(char*)
pj_context_get_grid_cache_filename(pj_ctx*)
pj_context_set_user_writable_directory(pj_ctx*, std::string const&)
pj_ell_set(pj_ctx*, ARG_list*, double*, double*)
pj_fwd(PJ_LP, PJconsts*)
pj_get_datums_ref()
Expand Down Expand Up @@ -875,6 +874,7 @@ proj_context_set(PJconsts*, pj_ctx*)
proj_context_set_search_paths
proj_context_set_sqlite3_vfs_name
proj_context_set_url_endpoint
proj_context_set_user_writable_directory
proj_context_use_proj4_init_rules
proj_convert_conversion_to_other_method
proj_coord
Expand Down
2 changes: 1 addition & 1 deletion src/apps/projsync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ int main(int argc, char *argv[]) {
}

// This is used by projsync() to determine where to write files.
pj_context_set_user_writable_directory(ctx, targetDir);
proj_context_set_user_writable_directory(ctx, targetDir.c_str(), true);
}

if (!endpoint.empty() && endpoint.back() == '/') {
Expand Down
47 changes: 37 additions & 10 deletions src/filemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1130,13 +1130,15 @@ void proj_context_set_sqlite3_vfs_name(PJ_CONTEXT *ctx, const char *name) {

// ---------------------------------------------------------------------------

/** Get the PROJ user writable directory for datumgrid files.
/** Get the PROJ user writable directory for downloadable resource files, such
* as datum shift grids.
*
* @param ctx PROJ context, or NULL
* @param create If set to TRUE, create the directory if it does not exist
* already.
* @return The path to the PROJ user writable directory.
* @since 7.1
* @see proj_context_set_user_writable_directory()
*/

const char *proj_context_get_user_writable_directory(PJ_CONTEXT *ctx,
Expand Down Expand Up @@ -1211,6 +1213,40 @@ const char *proj_context_get_user_writable_directory(PJ_CONTEXT *ctx,
return ctx->user_writable_directory.c_str();
}

// ---------------------------------------------------------------------------

/** Set the PROJ user writable directory for downloadable resource files, such
* as datum shift grids.
*
* If not explicitly set, the following locations are used:
* <ul>
* <li>on Windows, ${LOCALAPPDATA}/proj</li>
* <li>on macOS, ${HOME}/Library/Application Support/proj</li>
* <li>on other platforms (Linux), ${XDG_DATA_HOME}/proj if XDG_DATA_HOME is
* defined. Else ${HOME}/.local/share/proj</li>
* </ul>
*
* @param ctx PROJ context, or NULL
* @param path Path to the PROJ user writable directory. If set to NULL, the
* default location will be used.
* @param create If set to TRUE, create the directory if it does not exist
* already.
* @since 9.5
* @see proj_context_get_user_writable_directory()
*/

void proj_context_set_user_writable_directory(PJ_CONTEXT *ctx, const char *path,
int create) {
if (!ctx)
ctx = pj_get_default_ctx();
ctx->user_writable_directory = path ? path : "";
if (!path || create) {
proj_context_get_user_writable_directory(ctx, create);
}
}

// ---------------------------------------------------------------------------

/** Get the URL endpoint to query for remote grids.
*
* @param ctx PROJ context, or NULL
Expand All @@ -1235,15 +1271,6 @@ const char *proj_context_get_url_endpoint(PJ_CONTEXT *ctx) {

// ---------------------------------------------------------------------------

void pj_context_set_user_writable_directory(PJ_CONTEXT *ctx,
const std::string &path) {
if (!ctx)
ctx = pj_get_default_ctx();
ctx->user_writable_directory = path;
}

// ---------------------------------------------------------------------------

#ifdef WIN32
static const char dir_chars[] = "/\\";
#else
Expand Down
4 changes: 4 additions & 0 deletions src/proj.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,10 @@ const char PROJ_DLL *proj_context_get_url_endpoint(PJ_CONTEXT *ctx);
const char PROJ_DLL *proj_context_get_user_writable_directory(PJ_CONTEXT *ctx,
int create);

void PROJ_DLL proj_context_set_user_writable_directory(PJ_CONTEXT *ctx,
const char *path,
int create);

void PROJ_DLL proj_grid_cache_set_enable(PJ_CONTEXT *ctx, int enabled);

void PROJ_DLL proj_grid_cache_set_filename(PJ_CONTEXT *ctx,
Expand Down
2 changes: 0 additions & 2 deletions src/proj_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -950,8 +950,6 @@ void pj_load_ini(PJ_CONTEXT *ctx);
std::string PROJ_DLL pj_context_get_grid_cache_filename(PJ_CONTEXT *ctx);

// For use by projsync
void PROJ_DLL pj_context_set_user_writable_directory(PJ_CONTEXT *ctx,
const std::string &path);
std::string PROJ_DLL pj_get_relative_share_proj(PJ_CONTEXT *ctx);

std::vector<PJCoordOperation>
Expand Down
24 changes: 24 additions & 0 deletions test/unit/proj_context_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,30 @@ TEST(proj_context, proj_context_set_search_paths) {

// ---------------------------------------------------------------------------

TEST(proj_context, proj_context_set_user_writable_directory) {

auto ctx = proj_context_create();
auto default_path =
std::string(proj_context_get_user_writable_directory(ctx, false));
EXPECT_TRUE(!default_path.empty());

auto new_path = default_path + DIR_CHAR + "temp_proj_dic4";
proj_context_set_user_writable_directory(ctx, new_path.c_str(), true);

EXPECT_STREQ(proj_context_get_user_writable_directory(ctx, false),
new_path.c_str());

proj_context_set_user_writable_directory(ctx, nullptr, false);

EXPECT_STREQ(proj_context_get_user_writable_directory(ctx, false),
default_path.c_str());

proj_context_destroy(ctx);
MyUnlink(new_path);
}

// ---------------------------------------------------------------------------

TEST(proj_context, read_grid_from_user_writable_directory) {

auto ctx = proj_context_create();
Expand Down

0 comments on commit dda95a0

Please sign in to comment.