Index: subversion/svnadmin/main.c =================================================================== --- subversion/svnadmin/main.c (revision 6538) +++ subversion/svnadmin/main.c (working copy) @@ -77,7 +77,8 @@ svnadmin__ignore_uuid, svnadmin__force_uuid, svnadmin__parent_dir, - svnadmin__bdb_txn_nosync + svnadmin__bdb_txn_nosync, + svnadmin__config_dir, }; /* Option codes and descriptions. @@ -128,9 +129,13 @@ {SVN_FS_CONFIG_BDB_TXN_NOSYNC, svnadmin__bdb_txn_nosync, 0, "disable fsync at database transaction commit [Berkeley DB]."}, + {"config-dir", svnadmin__config_dir, 1, + "use configuration files from directory ARG"}, + {NULL} }; +#define SVNADMIN_OPTS_GLOBAL svnadmin__config_dir /* Array of available subcommands. * The entire list must be terminated with an entry of nulls. @@ -140,18 +145,18 @@ {"archive", subcommand_archive, {0}, "usage: svnadmin archive REPOS_PATH\n\n" "Ask Berkeley DB which logfiles can be safely deleted.\n\n", - {0} }, + {SVNADMIN_OPTS_GLOBAL} }, {"create", subcommand_create, {0}, "usage: svnadmin create REPOS_PATH\n\n" "Create a new, empty repository at REPOS_PATH.\n", {svnadmin__on_disk_template, svnadmin__in_repos_template, - svnadmin__bdb_txn_nosync} }, + svnadmin__bdb_txn_nosync, SVNADMIN_OPTS_GLOBAL} }, {"createtxn", subcommand_createtxn, {0}, "usage: svnadmin createtxn REPOS_PATH -r REVISION\n\n" "Create a new transaction based on REVISION.\n", - {'r'} }, + {'r', SVNADMIN_OPTS_GLOBAL} }, {"dump", subcommand_dump, {0}, "usage: svnadmin dump REPOS_PATH [-r LOWER[:UPPER]] [--incremental]\n\n" @@ -161,7 +166,7 @@ "revision trees. If only LOWER is given, dump that one revision tree.\n" "If --incremental is passed, then the first revision dumped will be\n" "a diff against the previous revision, instead of the usual fulltext.\n", - {'r', svnadmin__incremental, 'q'} }, + {'r', svnadmin__incremental, 'q', SVNADMIN_OPTS_GLOBAL} }, {"help", subcommand_help, {"?", "h"}, "usage: svnadmin help [SUBCOMMAND...]\n\n" @@ -174,7 +179,7 @@ "new revisions into the repository's filesystem. If the repository\n" "was previously empty, its UUID will, by default, be changed to the\n" "one specified in the stream. Progress feedback is sent to stdout.\n", - {svnadmin__ignore_uuid, svnadmin__force_uuid, svnadmin__parent_dir} }, + {svnadmin__ignore_uuid, svnadmin__force_uuid, svnadmin__parent_dir, SVNADMIN_OPTS_GLOBAL} }, {"lscr", subcommand_lscr, {0}, "usage: svnadmin lscr REPOS_PATH PATH [--copies]\n\n" @@ -184,12 +189,12 @@ "(For directories, this is, for now, almost guaranteed to be\n" "uninteresting. Also, PATH must exist in the HEAD of the\n" "repository.)\n", - {svnadmin__follow_copies} }, + {svnadmin__follow_copies, SVNADMIN_OPTS_GLOBAL} }, {"lstxns", subcommand_lstxns, {0}, "usage: svnadmin lstxns REPOS_PATH\n\n" "Print the names of all uncommitted transactions.\n", - {0} }, + {SVNADMIN_OPTS_GLOBAL} }, {"recover", subcommand_recover, {0}, "usage: svnadmin recover REPOS_PATH\n\n" @@ -198,19 +203,19 @@ "ought to be run.\n\n" "WARNING: only run this when you are SURE you're the only process\n" "accessing the repository. Requires exclusive access.\n\n", - {0} }, + {SVNADMIN_OPTS_GLOBAL} }, {"rmtxns", subcommand_rmtxns, {0}, "usage: svnadmin rmtxns REPOS_PATH TXN_NAME...\n\n" "Delete the named transaction(s).\n", - {0} }, + {SVNADMIN_OPTS_GLOBAL} }, {"setlog", subcommand_setlog, {0}, "usage: svnadmin setlog REPOS_PATH -r REVISION FILE\n\n" "Set the log-message on revision REVISION to the contents of FILE.\n" "(Note that revision properties are not historied, so this command\n" "will permanently overwrite the previous log message.)\n", - {'r'} }, + {'r', SVNADMIN_OPTS_GLOBAL} }, { NULL, NULL, {0}, NULL, {0} } }; @@ -232,6 +237,8 @@ const char *on_disk; const char *in_repos; const char *parent_dir; + + const char *config_dir; /* Overriding Configuration Directory */ }; /* This implements `svn_opt_subcommand_t'. */ @@ -250,7 +257,7 @@ APR_HASH_KEY_STRING, "1"); } - SVN_ERR (svn_config_get_config (&config, pool)); + SVN_ERR (svn_config_get_config (&config, opt_state->config_dir, pool)); SVN_ERR (svn_repos_create (&repos, opt_state->repository_path, opt_state->on_disk, opt_state->in_repos, config, fs_config, pool)); @@ -750,6 +757,9 @@ case svnadmin__bdb_txn_nosync: opt_state.bdb_txn_nosync = TRUE; break; + case svnadmin__config_dir: + opt_state.config_dir = apr_pstrdup(pool, opt_arg); + break; default: { subcommand_help (NULL, NULL, pool); Index: subversion/include/svn_config.h =================================================================== --- subversion/include/svn_config.h (revision 6538) +++ subversion/include/svn_config.h (working copy) @@ -86,10 +86,11 @@ /** Read configuration information from the standard sources and merge - * it into the hash @a *cfg_hash. That is, first read any system-wide - * configurations (from a file or from the registry), then merge in - * personal configurations (again from file or registry). The hash - * and all its data are allocated in @a pool. + * it into the hash @a *cfg_hash. @a config_dir specifies a directory from + * which to read the configuration files. It overrides everything else. + * Otherwise, first read any system-wide configurations (from a file or from + * the registry), then merge in personal configurations (again from file or + * registry). The hash and all its data are allocated in @a pool. * * @a *cfg_hash is a hash whose keys are @c const char * configuration * categories (@c SVN_CONFIG_CATEGORY_SERVERS, @@ -97,7 +98,8 @@ * svn_config_t * items representing the configuration values for that * category. */ -svn_error_t *svn_config_get_config (apr_hash_t **cfg_hash, +svn_error_t *svn_config_get_config (apr_hash_t **cfg_hash, + const char *config_dir, apr_pool_t *pool); @@ -214,7 +216,8 @@ /** Try to ensure that the user's ~/.subversion/ area exists, and create no-op * template files for any absent config files. Use @a pool for any - * temporary allocation. + * temporary allocation. @a config_dir specifies a directory to which to + * write the configuration files. * * Don't error if something exists but is the wrong kind (for example, * ~/.subversion exists but is a file, or ~/.subversion/servers exists @@ -225,7 +228,7 @@ * succeed in creating a config template file, return error if unable * to initialize its contents. */ -svn_error_t *svn_config_ensure (apr_pool_t *pool); +svn_error_t *svn_config_ensure (const char *config_dir, apr_pool_t *pool); @@ -247,6 +250,8 @@ * and load the file contents into the hash, using @a pool. If the * file doesn't exist, set @a *hash to NULL. * + * @a config_dir overrides the configuration directory. + * * Besides containing the original credential fields, the hash will * also contain @c SVN_CONFIG_REALMSTRING_KEY. The caller can examine * this value as a sanity-check that the correct file was loaded. @@ -257,11 +262,13 @@ svn_error_t * svn_config_read_auth_data (apr_hash_t **hash, const char *cred_kind, const char *realmstring, + const char *config_dir, apr_pool_t *pool); /** Use @a cred_kind and @a realmstring to create or overwrite a file * within the ~/.subversion/auth/ area. Write the contents of @a hash - * into the file. + * into the file. @a config_dir overrides the ~/.subversion/ directory + * to something else if set. * * Also, add @a realmstring to the file, with key @c * SVN_CONFIG_REALMSTRING_KEY. This allows programs (or users) to @@ -273,6 +280,7 @@ svn_error_t * svn_config_write_auth_data (apr_hash_t *hash, const char *cred_kind, const char *realmstring, + const char *config_dir, apr_pool_t *pool); /** @} */ Index: subversion/include/svn_auth.h =================================================================== --- subversion/include/svn_auth.h (revision 6538) +++ subversion/include/svn_auth.h (working copy) @@ -294,6 +294,9 @@ #define SVN_AUTH_PARAM_CONFIG SVN_AUTH_PARAM_PREFIX "config" #define SVN_AUTH_PARAM_SERVER_GROUP SVN_AUTH_PARAM_PREFIX "server-group" +/** A configuration directory that overrides the default + ~/.subversion. */ +#define SVN_AUTH_PARAM_CONFIG_DIR SVN_AUTH_PARAM_PREFIX "config-dir" /** Get an initial set of credentials. * * Ask @a auth_baton to set @a *credentials to a set of credentials Index: subversion/libsvn_wc/log.c =================================================================== --- subversion/libsvn_wc/log.c (revision 6538) +++ subversion/libsvn_wc/log.c (working copy) @@ -30,7 +30,6 @@ #include "svn_xml.h" #include "svn_pools.h" #include "svn_io.h" -#include "svn_config.h" #include "svn_path.h" #include "wc.h" @@ -341,9 +340,6 @@ name = svn_path_join (svn_wc_adm_access_path (loggy->adm_access), name, loggy->pool); - /* Read the configuration. */ - SVN_ERR (svn_config_get_config (&config, loggy->pool)); - /* Now do the merge with our full paths. */ SVN_ERR (svn_wc_merge (left, right, name, loggy->adm_access, left_label, right_label, target_label, Index: subversion/libsvn_subr/config_file.c =================================================================== --- subversion/libsvn_subr/config_file.c (revision 6538) +++ subversion/libsvn_subr/config_file.c (working copy) @@ -285,7 +285,8 @@ svn_error_t * -svn_config__user_config_path (const char **path_p, +svn_config__user_config_path (const char *config_dir, + const char **path_p, const char *fname, apr_pool_t *pool) { @@ -293,6 +294,12 @@ prototype should change? */ *path_p = NULL; + + if (config_dir) + { + *path_p = apr_pstrdup(pool, config_dir); + return SVN_NO_ERROR; + } /* Note that even if fname is null, svn_path_join_many will DTRT. */ @@ -493,7 +500,7 @@ svn_error_t * -svn_config_ensure (apr_pool_t *pool) +svn_config_ensure (const char *config_dir, apr_pool_t *pool) { const char *path; svn_node_kind_t kind; @@ -501,7 +508,7 @@ svn_error_t *err; /* Ensure that the user-specific config directory exists. */ - SVN_ERR (svn_config__user_config_path (&path, NULL, pool)); + SVN_ERR (svn_config__user_config_path (config_dir, &path, NULL, pool)); if (! path) return SVN_NO_ERROR; @@ -534,7 +541,7 @@ /** Ensure that the `README.txt' file exists. **/ SVN_ERR (svn_config__user_config_path - (&path, SVN_CONFIG__USR_README_FILE, pool)); + (config_dir, &path, SVN_CONFIG__USR_README_FILE, pool)); if (! path) /* highly unlikely, since a previous call succeeded */ return SVN_NO_ERROR; @@ -762,7 +769,7 @@ /** Ensure that the `servers' file exists. **/ SVN_ERR (svn_config__user_config_path - (&path, SVN_CONFIG_CATEGORY_SERVERS, pool)); + (config_dir, &path, SVN_CONFIG_CATEGORY_SERVERS, pool)); if (! path) /* highly unlikely, since a previous call succeeded */ return SVN_NO_ERROR; @@ -883,7 +890,7 @@ /** Ensure that the `config' file exists. **/ SVN_ERR (svn_config__user_config_path - (&path, SVN_CONFIG_CATEGORY_CONFIG, pool)); + (config_dir, &path, SVN_CONFIG_CATEGORY_CONFIG, pool)); if (! path) /* highly unlikely, since a previous call succeeded */ return SVN_NO_ERROR; Index: subversion/libsvn_subr/config.c =================================================================== --- subversion/libsvn_subr/config.c (revision 6538) +++ subversion/libsvn_subr/config.c (working copy) @@ -186,6 +186,7 @@ static svn_error_t * get_category_config (svn_config_t **cfg, + const char *config_dir, const char *category, apr_pool_t *pool) { @@ -202,11 +203,23 @@ #endif /* SVN_WIN32 */ SVN_ERR (svn_config__sys_config_path (&sys_cfg_path, category, pool)); - SVN_ERR (svn_config__user_config_path (&usr_cfg_path, category, pool)); - SVN_ERR (read_all (cfg, - sys_reg_path, usr_reg_path, - sys_cfg_path, usr_cfg_path, - pool)); + SVN_ERR (svn_config__user_config_path (config_dir, &usr_cfg_path, category, pool)); + /* + * If config_dir is specified it overrides all the other directories. + * */ + if (config_dir) + { + SVN_ERR (read_all (cfg, + NULL, NULL, config_dir, NULL, + pool)); + } + else + { + SVN_ERR (read_all (cfg, + sys_reg_path, usr_reg_path, + sys_cfg_path, usr_cfg_path, + pool)); + } return SVN_NO_ERROR; } @@ -214,19 +227,21 @@ svn_error_t * svn_config_get_config (apr_hash_t **cfg_hash, - apr_pool_t *pool) + const char *config_dir, + apr_pool_t *pool + ) { svn_config_t *cfg; *cfg_hash = apr_hash_make (pool); #define CATLEN (sizeof (SVN_CONFIG_CATEGORY_SERVERS) - 1) - SVN_ERR (get_category_config (&cfg, SVN_CONFIG_CATEGORY_SERVERS, pool)); + SVN_ERR (get_category_config (&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS, pool)); if (cfg) apr_hash_set (*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, CATLEN, cfg); #undef CATLEN #define CATLEN (sizeof (SVN_CONFIG_CATEGORY_CONFIG) - 1) - SVN_ERR (get_category_config (&cfg, SVN_CONFIG_CATEGORY_CONFIG, pool)); + SVN_ERR (get_category_config (&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG, pool)); if (cfg) apr_hash_set (*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, CATLEN, cfg); #undef CATLEN Index: subversion/libsvn_subr/config_auth.c =================================================================== --- subversion/libsvn_subr/config_auth.c (revision 6538) +++ subversion/libsvn_subr/config_auth.c (working copy) @@ -34,6 +34,7 @@ static const char * auth_file_path (const char *cred_kind, const char *realmstring, + const char *config_dir, apr_pool_t *pool) { const char *authdir_path, *hexname; @@ -42,7 +43,7 @@ /* Construct the path to the directory containing the creds files, e.g. "~/.subversion/auth/svn.simple". The last component is simply the cred_kind. */ - svn_config__user_config_path (&authdir_path, + svn_config__user_config_path (config_dir, &authdir_path, SVN_CONFIG__AUTH_SUBDIR, pool); authdir_path = svn_path_join (authdir_path, cred_kind, pool); @@ -59,10 +60,11 @@ svn_config_read_auth_data (apr_hash_t **hash, const char *cred_kind, const char *realmstring, + const char *config_dir, apr_pool_t *pool) { svn_node_kind_t kind; - const char *auth_path = auth_file_path (cred_kind, realmstring, pool); + const char *auth_path = auth_file_path (cred_kind, realmstring, config_dir, pool); SVN_ERR (svn_io_check_path (auth_path, &kind, pool)); if (kind == svn_node_file) @@ -100,11 +102,12 @@ svn_config_write_auth_data (apr_hash_t *hash, const char *cred_kind, const char *realmstring, + const char *config_dir, apr_pool_t *pool) { apr_status_t status; apr_file_t *authfile = NULL; - const char *auth_path = auth_file_path (cred_kind, realmstring, pool); + const char *auth_path = auth_file_path (cred_kind, realmstring, config_dir, pool); /* Add the realmstring to the hash, so programs (or users) can verify exactly which set of credentials this file holds. */ Index: subversion/libsvn_subr/config_impl.h =================================================================== --- subversion/libsvn_subr/config_impl.h (revision 6538) +++ subversion/libsvn_subr/config_impl.h (working copy) @@ -135,9 +135,13 @@ name of the user's config area. Allocate *PATH_P in POOL. If the user's personal configuration area cannot be located (most - likely under Win32), set *PATH_P to NULL regardless of FNAME. */ + likely under Win32), set *PATH_P to NULL regardless of FNAME. + + CONFIG_DIR overrides this and if set *PATH_P is set to it. + */ svn_error_t * -svn_config__user_config_path (const char **path_p, +svn_config__user_config_path (const char *config_dir, + const char **path_p, const char *fname, apr_pool_t *pool); Index: subversion/libsvn_client/providers.c =================================================================== --- subversion/libsvn_client/providers.c (revision 6538) +++ subversion/libsvn_client/providers.c (working copy) @@ -77,7 +77,13 @@ const char *def_password = apr_hash_get (parameters, SVN_AUTH_PARAM_DEFAULT_PASSWORD, APR_HASH_KEY_STRING); + const char *config_dir; + config_dir = apr_hash_get (parameters, + SVN_AUTH_PARAM_CONFIG_DIR, + APR_HASH_KEY_STRING); + + /* Set the default return values. */ *got_creds = FALSE; *username = NULL; @@ -90,7 +96,7 @@ we failed to get the creds, so allow libsvn_auth to try the next provider. */ svn_config_read_auth_data (&creds_hash, pb->cred_kind, - pb->realmstring, pool); + pb->realmstring, config_dir, pool); if (creds_hash != NULL) { if (! def_username) @@ -132,6 +138,7 @@ provider_baton_t *pb, const char *username, const char *password, + const char *config_dir, apr_pool_t *pool) { const char *auth_file; @@ -161,7 +168,7 @@ /* ...and write to disk. */ err = svn_config_write_auth_data (creds_hash, pb->cred_kind, - pb->realmstring, pool); + pb->realmstring, config_dir, pool); *saved = err ? FALSE : TRUE; } } @@ -179,7 +186,7 @@ /* ...and write to disk. */ err = svn_config_write_auth_data (creds_hash, pb->cred_kind, - pb->realmstring, pool); + pb->realmstring, config_dir, pool); *saved = err ? FALSE : TRUE; } } @@ -235,15 +242,20 @@ svn_auth_cred_simple_t *creds = credentials; provider_baton_t *pb = provider_baton; const char *no_auth_cache; + const char *config_dir; *saved = FALSE; no_auth_cache = apr_hash_get (parameters, SVN_AUTH_PARAM_NO_AUTH_CACHE, APR_HASH_KEY_STRING); + + config_dir = apr_hash_get (parameters, + SVN_AUTH_PARAM_CONFIG_DIR, + APR_HASH_KEY_STRING); if (no_auth_cache == NULL) - SVN_ERR (save_creds (saved, pb, creds->username, creds->password, pool)); + SVN_ERR (save_creds (saved, pb, creds->username, creds->password, config_dir, pool)); return SVN_NO_ERROR; } @@ -316,15 +328,20 @@ svn_auth_cred_simple_t *creds = credentials; provider_baton_t *pb = provider_baton; const char *no_auth_cache; + const char *config_dir; *saved = FALSE; no_auth_cache = apr_hash_get (parameters, SVN_AUTH_PARAM_NO_AUTH_CACHE, APR_HASH_KEY_STRING); + + config_dir = apr_hash_get (parameters, + SVN_AUTH_PARAM_CONFIG_DIR, + APR_HASH_KEY_STRING); if (no_auth_cache == NULL) - SVN_ERR (save_creds (saved, pb, creds->username, NULL, pool)); + SVN_ERR (save_creds (saved, pb, creds->username, NULL, config_dir, pool)); return SVN_NO_ERROR; } Index: subversion/clients/cmdline/cl.h =================================================================== --- subversion/clients/cmdline/cl.h (revision 6538) +++ subversion/clients/cmdline/cl.h (working copy) @@ -67,7 +67,8 @@ svn_cl__ignore_ancestry_opt, svn_cl__editor_cmd_opt, svn_cl__old_cmd_opt, - svn_cl__new_cmd_opt + svn_cl__new_cmd_opt, + svn_cl__config_dir_opt, } svn_cl__longopt_t; @@ -119,6 +120,7 @@ const char *old_target; /* diff target */ const char *new_target; /* diff target */ svn_boolean_t relocate; /* rewrite urls (svn switch) */ + const char * config_dir; /* over-riding configuration directory */ } svn_cl__opt_state_t; Index: subversion/clients/cmdline/main.c =================================================================== --- subversion/clients/cmdline/main.c (revision 6538) +++ subversion/clients/cmdline/main.c (working copy) @@ -121,6 +121,8 @@ "operate on a revision property (use with -r)"}, {"relocate", svn_cl__relocate_opt, 0, "relocate via url-rewriting"}, + {"config-dir", svn_cl__config_dir_opt, 1, + "use configuration files from directory ARG"}, {0, 0, 0, 0} }; @@ -141,18 +143,24 @@ svn_cl__auth_password_opt, \ svn_cl__no_auth_cache_opt, \ svn_cl__non_interactive_opt + +/* + * Options that are common to all commands. + * */ +#define SVN_CL__GLOBAL_OPTIONS svn_cl__config_dir_opt + const svn_opt_subcommand_desc_t svn_cl__cmd_table[] = { { "add", svn_cl__add, {0}, "Put files and directories under revision control, scheduling\n" "them for addition to repository. They will be added in next commit.\n" "usage: add PATH...\n", - {svn_cl__targets_opt, 'N', 'q'} }, + {svn_cl__targets_opt, 'N', 'q', SVN_CL__GLOBAL_OPTIONS} }, { "cat", svn_cl__cat, {0}, "Output the content of specified files or URLs.\n" "usage: cat TARGET...\n", - {'r', SVN_CL__AUTH_OPTIONS} }, + {'r', SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "checkout", svn_cl__checkout, {"co"}, "Check out a working copy from a repository.\n" @@ -161,13 +169,13 @@ " the destination. If multiple URLs are given each will be checked\n" " out into a sub-directory of PATH, with the name of the sub-directory\n" " being the basename of the URL.\n", - {'r', 'q', 'N', SVN_CL__AUTH_OPTIONS} }, + {'r', 'q', 'N', SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "cleanup", svn_cl__cleanup, {0}, "Recursively clean up the working copy, removing locks, resuming\n" "unfinished operations, etc.\n" "usage: cleanup [PATH...]\n", - {0} }, + {SVN_CL__GLOBAL_OPTIONS} }, { "commit", svn_cl__commit, {"ci"}, "Send changes from your working copy to the repository.\n" @@ -175,7 +183,7 @@ " Be sure to use one of -m or -F to send a log message.\n", {'m', 'F', 'q', 'N', svn_cl__targets_opt, svn_cl__force_log_opt, SVN_CL__AUTH_OPTIONS, - svn_cl__editor_cmd_opt, svn_cl__encoding_opt} }, + svn_cl__editor_cmd_opt, svn_cl__encoding_opt, SVN_CL__GLOBAL_OPTIONS} }, { "copy", svn_cl__copy, {"cp"}, "Duplicate something in working copy or repos, remembering history.\n" @@ -186,7 +194,7 @@ " URL -> WC: check out URL into WC, schedule for addition\n" " URL -> URL: complete server-side copy; used to branch & tag\n", {'m', 'F', 'r', 'q', SVN_CL__AUTH_OPTIONS, svn_cl__force_log_opt, - svn_cl__editor_cmd_opt, svn_cl__encoding_opt} }, + svn_cl__editor_cmd_opt, svn_cl__encoding_opt, SVN_CL__GLOBAL_OPTIONS} }, { "delete", svn_cl__delete, {"del", "remove", "rm"}, "Remove files and directories from version control.\n" @@ -202,7 +210,7 @@ " immediate commit.\n", {svn_cl__force_opt, svn_cl__force_log_opt, 'm', 'F', 'q', svn_cl__targets_opt, SVN_CL__AUTH_OPTIONS, - svn_cl__editor_cmd_opt, svn_cl__encoding_opt} }, + svn_cl__editor_cmd_opt, svn_cl__encoding_opt, SVN_CL__GLOBAL_OPTIONS} }, { "diff", svn_cl__diff, {"di"}, "display the differences between two paths.\n" @@ -224,7 +232,7 @@ " Use just 'svn diff' to display local modifications in a working copy\n", {'r', svn_cl__old_cmd_opt, svn_cl__new_cmd_opt, 'x', 'N', svn_cl__diff_cmd_opt, svn_cl__no_diff_deleted, - svn_cl__ignore_ancestry_opt, SVN_CL__AUTH_OPTIONS} }, + svn_cl__ignore_ancestry_opt, SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "export", svn_cl__export, {0}, "export stuff.\n" @@ -237,12 +245,12 @@ " 2. Exports a clean directory tree from the working copy specified by\n" " PATH1 into PATH2. all local changes will be preserved, but files\n" " not under revision control will not be copied.\n", - {'r', 'q', svn_cl__force_opt, SVN_CL__AUTH_OPTIONS} }, + {'r', 'q', svn_cl__force_opt, SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "help", svn_cl__help, {"?", "h"}, "Display this usage message.\n" "usage: help [SUBCOMMAND...]\n", - {svn_cl__version_opt, 'q'} }, + {svn_cl__version_opt, 'q', SVN_CL__GLOBAL_OPTIONS} }, /* We need to support "--help", "-?", and all that good stuff, of course. But those options, since unknown, will result in the help message being printed out anyway, so there's no need to @@ -255,19 +263,19 @@ " If PATH is omitted '.' is assumed. Parent directories are created\n" " as necessary in the repository.\n", {'m', 'F', 'q', 'N', SVN_CL__AUTH_OPTIONS, svn_cl__force_log_opt, - svn_cl__editor_cmd_opt, svn_cl__encoding_opt} }, + svn_cl__editor_cmd_opt, svn_cl__encoding_opt, SVN_CL__GLOBAL_OPTIONS} }, { "info", svn_cl__info, {0}, "Display info about a resource.\n" "usage: info [PATH...]\n\n" " Print information about PATHs.\n", - {svn_cl__targets_opt, 'R'} }, + {svn_cl__targets_opt, 'R', SVN_CL__GLOBAL_OPTIONS} }, { "list", svn_cl__ls, {"ls"}, "List directory entries of a URL.\n" "usage: list URL...\n\n" " If URL is a file, just file entry will be displayed.\n", - {'r', 'v', 'R', SVN_CL__AUTH_OPTIONS} }, + {'r', 'v', 'R', SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "log", svn_cl__log, {0}, "Show the log messages for a set of revision(s) and/or file(s).\n" @@ -288,7 +296,8 @@ " svn log http://www.example.com/repo/project/foo.c\n" " svn log http://www.example.com/repo/project foo.c bar.c\n", {'r', 'q', 'v', svn_cl__targets_opt, svn_cl__strict_opt, - svn_cl__incremental_opt, svn_cl__xml_opt, SVN_CL__AUTH_OPTIONS} }, + svn_cl__incremental_opt, svn_cl__xml_opt, SVN_CL__AUTH_OPTIONS, + SVN_CL__GLOBAL_OPTIONS} }, { "merge", svn_cl__merge, {0}, "apply the differences between two sources to a working copy path.\n" @@ -310,7 +319,7 @@ " in which case, the differences will be applied to that file.\n", {'r', 'N', 'q', svn_cl__force_opt, svn_cl__dry_run_opt, svn_cl__merge_cmd_opt, svn_cl__ignore_ancestry_opt, - SVN_CL__AUTH_OPTIONS} }, + SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "mkdir", svn_cl__mkdir, {0}, "Create a new directory under revision control.\n" @@ -323,7 +332,7 @@ " immediate commit.\n\n" " In both cases, all the intermediate directories must already exist.\n", {'m', 'F', 'q', SVN_CL__AUTH_OPTIONS, svn_cl__editor_cmd_opt, - svn_cl__encoding_opt, svn_cl__force_log_opt} }, + svn_cl__encoding_opt, svn_cl__force_log_opt, SVN_CL__GLOBAL_OPTIONS} }, { "move", svn_cl__move, {"mv", "rename", "ren"}, "Move/rename something in working copy or repository.\n" @@ -333,7 +342,7 @@ " WC -> WC: move and schedule for addition (with history)\n" " URL -> URL: complete server-side rename.\n", {'m', 'F', 'r', 'q', svn_cl__force_opt, SVN_CL__AUTH_OPTIONS, - svn_cl__editor_cmd_opt, svn_cl__encoding_opt, svn_cl__force_log_opt} }, + svn_cl__editor_cmd_opt, svn_cl__encoding_opt, svn_cl__force_log_opt, SVN_CL__GLOBAL_OPTIONS} }, { "propdel", svn_cl__propdel, {"pdel"}, "Remove PROPNAME from files, dirs, or revisions.\n" @@ -341,7 +350,7 @@ " 2. propdel PROPNAME --revprop -r REV [URL]\n\n" " 1. Removes versioned props in working copy.\n" " 2. Removes unversioned remote prop on repos revision.\n", - {'q', 'R', 'r', svn_cl__revprop_opt, SVN_CL__AUTH_OPTIONS} }, + {'q', 'R', 'r', svn_cl__revprop_opt, SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "propedit", svn_cl__propedit, {"pedit", "pe"}, "Edit property PROPNAME with $EDITOR on targets.\n" @@ -350,7 +359,7 @@ " 1. Edits versioned props in working copy.\n" " 2. Edits unversioned remote prop on repos revision.\n", {'r', svn_cl__revprop_opt, SVN_CL__AUTH_OPTIONS, - svn_cl__encoding_opt, svn_cl__editor_cmd_opt, svn_cl__force_opt} }, + svn_cl__encoding_opt, svn_cl__editor_cmd_opt, svn_cl__force_opt, SVN_CL__GLOBAL_OPTIONS} }, { "propget", svn_cl__propget, {"pget", "pg"}, "Print value of PROPNAME on files, dirs, or revisions.\n" @@ -365,7 +374,7 @@ " the --strict option to disable these beautifications (useful,\n" " for example, when redirecting binary property values to a file).\n", {'R', 'r', svn_cl__revprop_opt, svn_cl__strict_opt, - SVN_CL__AUTH_OPTIONS} }, + SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "proplist", svn_cl__proplist, {"plist", "pl"}, "List all properties on files, dirs, or revisions.\n" @@ -373,7 +382,7 @@ " 2. proplist --revprop -r REV [URL]\n\n" " 1. Lists versioned props in working copy.\n" " 2. Lists unversioned remote props on repos revision.\n", - {'v', 'R', 'r', 'q', svn_cl__revprop_opt, SVN_CL__AUTH_OPTIONS} }, + {'v', 'R', 'r', 'q', svn_cl__revprop_opt, SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "propset", svn_cl__propset, {"pset", "ps"}, "Set PROPNAME to PROPVAL on files, dirs, or revisions.\n\n" @@ -409,7 +418,7 @@ " foo http://example.com/repos/zig\n" " foo/bar -r 1234 http://example.com/repos/zag\n", {'F', 'q', 'r', svn_cl__targets_opt, 'R', svn_cl__revprop_opt, - SVN_CL__AUTH_OPTIONS, svn_cl__encoding_opt, svn_cl__force_opt} }, + SVN_CL__AUTH_OPTIONS, svn_cl__encoding_opt, svn_cl__force_opt, SVN_CL__GLOBAL_OPTIONS} }, { "resolve", svn_cl__resolve, {0}, "Remove 'conflicted' state on working copy files or directories.\n" @@ -417,14 +426,14 @@ " Note: this routine does not semantically resolve conflict markers;\n" " it merely removes conflict-related artifact files and allows PATH\n" " to be committed again.\n", - {svn_cl__targets_opt, 'R', 'q'} }, + {svn_cl__targets_opt, 'R', 'q', SVN_CL__GLOBAL_OPTIONS} }, { "revert", svn_cl__revert, {0}, "Restore pristine working copy file (undo all local edits)\n" "usage: revert PATH...\n\n" " Note: this routine does not require network access, and \n" " resolves any conflicted states.\n", - {svn_cl__targets_opt, 'R', 'q'} }, + {svn_cl__targets_opt, 'R', 'q', SVN_CL__GLOBAL_OPTIONS} }, { "status", svn_cl__status, {"stat", "st"}, "Print the status of working copy files and directories.\n" @@ -486,7 +495,8 @@ " A + 965 687 joe wc/qax.c\n" " 965 687 joe wc/zig.c\n" " Head revision: 981\n", - { 'u', 'v', 'N', 'q', svn_cl__no_ignore_opt, SVN_CL__AUTH_OPTIONS} }, + { 'u', 'v', 'N', 'q', svn_cl__no_ignore_opt, SVN_CL__AUTH_OPTIONS, + SVN_CL__GLOBAL_OPTIONS} }, { "switch", svn_cl__switch, {"sw"}, "Update working copy to mirror a new URL\n" @@ -494,7 +504,7 @@ " switch --relocate FROM TO [PATH...]\n\n" " Note: this is the way to move a working copy to a new branch.\n", { 'r', 'N', 'q', svn_cl__merge_cmd_opt, svn_cl__relocate_opt, - SVN_CL__AUTH_OPTIONS} }, + SVN_CL__AUTH_OPTIONS, SVN_CL__GLOBAL_OPTIONS} }, { "update", svn_cl__update, {"up"}, "Bring changes from the repository into the working copy.\n" @@ -513,7 +523,8 @@ "\n" " A character in the first column signifies an update to the actual file,\n" " while updates to the file's props are shown in the second column.\n", - {'r', 'N', 'q', svn_cl__merge_cmd_opt, SVN_CL__AUTH_OPTIONS} }, + {'r', 'N', 'q', svn_cl__merge_cmd_opt, SVN_CL__AUTH_OPTIONS, + SVN_CL__GLOBAL_OPTIONS} }, { NULL, NULL, {0}, NULL, {0} } }; @@ -809,6 +820,9 @@ case svn_cl__new_cmd_opt: opt_state.new_target = apr_pstrdup (pool, opt_arg); break; + case svn_cl__config_dir_opt: + opt_state.config_dir = apr_pstrdup (pool, opt_arg); + break; default: /* Hmmm. Perhaps this would be a good place to squirrel away opts that commands like svn diff might need. Hmmm indeed. */ @@ -826,7 +840,7 @@ hand, the alternative is effective to demand that they call svn_config_ensure() instead, so maybe we should have a generic init function anyway. Thoughts? */ - err = svn_config_ensure (pool); + err = svn_config_ensure (opt_state.config_dir, pool); if (err) { svn_handle_error (err, stderr, 0); @@ -944,7 +958,7 @@ ctx.prompt_func = svn_cl__prompt_user; ctx.prompt_baton = NULL; - if ((err = svn_config_get_config (&(ctx.config), pool))) + if ((err = svn_config_get_config (&(ctx.config), opt_state.config_dir, pool))) { svn_handle_error (err, stderr, 0); svn_pool_destroy (pool); @@ -1043,6 +1057,10 @@ svn_auth_set_parameter(ab, SVN_AUTH_PARAM_NON_INTERACTIVE, (void *) ""); + if (opt_state.config_dir) + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR, + opt_state.config_dir); + /* There are two different ways the user can disable disk caching of credentials: either via --no-auth-cache, or in the config file ('store-password = no'). */