Author: julianfoad
Date: Mon Mar 5 16:32:52 2018
New Revision: 1825911
URL: http://svn.apache.org/viewvc?rev=1825911&view=rev
Log:
Shelving: new 'shelf-list-by-paths' command.
* subversion/svn/cl.h
(svn_cl__shelf_list_by_paths): New.
* subversion/svn/shelf-cmd.c
(targets_relative_to_wcs,
targets_relative_to_a_wc,
shelf_list_by_paths,
svn_cl__shelf_list_by_paths): New.
* subversion/svn/svn.c
(svn_cl__cmd_table): Describe the new command.
* tools/client-side/bash_completion
(_svn): Add the new command.
Modified:
subversion/trunk/subversion/svn/cl.h
subversion/trunk/subversion/svn/shelf-cmd.c
subversion/trunk/subversion/svn/svn.c
subversion/trunk/tools/client-side/bash_completion
Modified: subversion/trunk/subversion/svn/cl.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1825911&r1=1825910&r2=1825911&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Mon Mar 5 16:32:52 2018
@@ -307,6 +307,7 @@ svn_opt_subcommand_t
svn_cl__shelf_diff,
svn_cl__shelf_drop,
svn_cl__shelf_list,
+ svn_cl__shelf_list_by_paths,
svn_cl__shelf_log,
svn_cl__shelf_save,
svn_cl__shelf_shelve,
Modified: subversion/trunk/subversion/svn/shelf-cmd.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/shelf-cmd.c?rev=1825911&r1=1825910&r2=1825911&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/shelf-cmd.c (original)
+++ subversion/trunk/subversion/svn/shelf-cmd.c Mon Mar 5 16:32:52 2018
@@ -55,6 +55,79 @@ get_next_argument(const char **arg,
return SVN_NO_ERROR;
}
+/* Parse the remaining arguments as paths relative to a WC.
+ *
+ * TARGETS are relative to current working directory.
+ *
+ * Set *targets_by_wcroot to a hash mapping (char *)wcroot_abspath to
+ * (apr_array_header_t *)array of relpaths relative to that WC root.
+ */
+static svn_error_t *
+targets_relative_to_wcs(apr_hash_t **targets_by_wcroot_p,
+ apr_array_header_t *targets,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_t *targets_by_wcroot = apr_hash_make(result_pool);
+ int i;
+
+ /* Make each target relative to the WC root. */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+ const char *wcroot_abspath;
+ apr_array_header_t *paths;
+
+ SVN_ERR(svn_dirent_get_absolute(&target, target, result_pool));
+ SVN_ERR(svn_client_get_wc_root(&wcroot_abspath, target,
+ ctx, result_pool, scratch_pool));
+ paths = svn_hash_gets(targets_by_wcroot, wcroot_abspath);
+ if (! paths)
+ {
+ paths = apr_array_make(result_pool, 0, sizeof(char *));
+ svn_hash_sets(targets_by_wcroot, wcroot_abspath, paths);
+ }
+ target = svn_dirent_skip_ancestor(wcroot_abspath, target);
+
+ if (target)
+ APR_ARRAY_PUSH(paths, const char *) = target;
+ }
+ *targets_by_wcroot_p = targets_by_wcroot;
+ return SVN_NO_ERROR;
+}
+
+/* Return targets relative to a WC. Error if they refer to more than one WC. */
+static svn_error_t *
+targets_relative_to_a_wc(const char **wc_root_abspath_p,
+ apr_array_header_t **paths_p,
+ apr_getopt_t *os,
+ const apr_array_header_t *known_targets,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *targets;
+ apr_hash_t *targets_by_wcroot;
+ apr_hash_index_t *hi;
+
+ SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+ known_targets,
+ ctx, FALSE,
result_pool));
+ svn_opt_push_implicit_dot_target(targets, result_pool);
+
+ SVN_ERR(targets_relative_to_wcs(&targets_by_wcroot, targets,
+ ctx, result_pool, scratch_pool));
+ if (apr_hash_count(targets_by_wcroot) != 1)
+ return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("All targets must be in the same WC"));
+
+ hi = apr_hash_first(scratch_pool, targets_by_wcroot);
+ *wc_root_abspath_p = apr_hash_this_key(hi);
+ *paths_p = apr_hash_this_val(hi);
+ return SVN_NO_ERROR;
+}
+
/* Return a human-friendly description of DURATION.
*/
static char *
@@ -952,6 +1025,112 @@ svn_cl__shelf_list(apr_getopt_t *os,
return SVN_NO_ERROR;
}
+/* "svn shelf-list-by-paths [PATH...]"
+ *
+ * TARGET_RELPATHS are all within the same WC, relative to WC_ROOT_ABSPATH.
+ */
+static svn_error_t *
+shelf_list_by_paths(apr_array_header_t *target_relpaths,
+ const char *wc_root_abspath,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *shelves;
+ apr_hash_t *paths_to_shelf_name = apr_hash_make(scratch_pool);
+ apr_array_header_t *array;
+ int i;
+
+ SVN_ERR(list_sorted_by_date(&shelves,
+ wc_root_abspath, ctx, scratch_pool));
+
+ /* Check paths are valid */
+ for (i = 0; i < target_relpaths->nelts; i++)
+ {
+ char *target_relpath = APR_ARRAY_IDX(target_relpaths, i, char *);
+
+ if (svn_path_is_url(target_relpath))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"),
target_relpath);
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(target_relpath));
+ }
+
+ /* Find the most recent shelf for each affected path */
+ for (i = 0; i < shelves->nelts; i++)
+ {
+ svn_sort__item_t *item = &APR_ARRAY_IDX(shelves, i, svn_sort__item_t);
+ const char *name = item->key;
+ svn_client_shelf_t *shelf;
+ svn_client_shelf_version_t *shelf_version;
+ apr_hash_t *shelf_paths;
+ int j;
+
+ SVN_ERR(svn_client_shelf_open_existing(&shelf,
+ name, wc_root_abspath,
+ ctx, scratch_pool));
+ SVN_ERR(svn_client_shelf_version_open(&shelf_version,
+ shelf, shelf->max_version,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_client_shelf_paths_changed(&shelf_paths,
+ shelf_version,
+ scratch_pool, scratch_pool));
+ for (j = 0; j < target_relpaths->nelts; j++)
+ {
+ char *target_relpath = APR_ARRAY_IDX(target_relpaths, j, char *);
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, shelf_paths);
+ hi; hi = apr_hash_next(hi))
+ {
+ const char *shelf_path = apr_hash_this_key(hi);
+
+ if (svn_relpath_skip_ancestor(target_relpath, shelf_path))
+ {
+ if (! svn_hash_gets(paths_to_shelf_name, shelf_path))
+ {
+ svn_hash_sets(paths_to_shelf_name, shelf_path,
shelf->name);
+ }
+ }
+ }
+ }
+ }
+
+ /* Print the results. */
+ array = svn_sort__hash(paths_to_shelf_name,
+ svn_sort_compare_items_as_paths,
+ scratch_pool);
+ for (i = 0; i < array->nelts; i++)
+ {
+ svn_sort__item_t *item = &APR_ARRAY_IDX(array, i, svn_sort__item_t);
+ const char *path = item->key;
+ const char *name = item->value;
+
+ SVN_ERR(svn_cmdline_printf(scratch_pool, "%-20.20s %s\n",
+ name,
+ svn_dirent_local_style(path, scratch_pool)));
+ }
+ return SVN_NO_ERROR;
+}
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__shelf_list_by_paths(apr_getopt_t *os,
+ void *baton,
+ apr_pool_t *pool)
+{
+ svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+ svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+ const char *wc_root_abspath;
+ apr_array_header_t *targets;
+
+ /* Parse the remaining arguments as paths. */
+ SVN_ERR(targets_relative_to_a_wc(&wc_root_abspath, &targets,
+ os, opt_state->targets,
+ ctx, pool, pool));
+
+ SVN_ERR(shelf_list_by_paths(targets, wc_root_abspath, ctx, pool));
+ return SVN_NO_ERROR;
+}
+
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__shelf_diff(apr_getopt_t *os,
Modified: subversion/trunk/subversion/svn/svn.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/svn.c?rev=1825911&r1=1825910&r2=1825911&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/svn.c (original)
+++ subversion/trunk/subversion/svn/svn.c Mon Mar 5 16:32:52 2018
@@ -1723,6 +1723,18 @@ const svn_opt_subcommand_desc2_t svn_cl_
{'q', 'v'}
},
+ { "shelf-list-by-paths", svn_cl__shelf_list_by_paths, {0}, N_
+ ("List which shelf affects each path.\n"
+ "usage: shelf-list-by-paths [PATH...]\n"
+ "\n"
+ " List which shelf most recently affects each path below the given
PATHs.\n"
+ "\n"
+ " The shelving feature is EXPERIMENTAL. This command is likely to
change\n"
+ " in the next release, and there is no promise of backward
compatibility.\n"
+ ),
+ {}
+ },
+
{ "shelf-log", svn_cl__shelf_log, {0}, N_
("Show the versions of a shelf.\n"
"usage: shelf-log NAME\n"
Modified: subversion/trunk/tools/client-side/bash_completion
URL:
http://svn.apache.org/viewvc/subversion/trunk/tools/client-side/bash_completion?rev=1825911&r1=1825910&r2=1825911&view=diff
==============================================================================
--- subversion/trunk/tools/client-side/bash_completion (original)
+++ subversion/trunk/tools/client-side/bash_completion Mon Mar 5 16:32:52 2018
@@ -248,7 +248,7 @@ _svn()
cmds="$cmds patch propdel pdel propedit pedit propget pget proplist"
cmds="$cmds plist propset pset relocate resolve resolved revert status"
cmds="$cmds switch unlock update upgrade"
- cmds="$cmds shelf-diff shelf-drop shelf-list shelf-log shelf-save"
+ cmds="$cmds shelf-list-by-paths shelf-diff shelf-drop shelf-list
shelf-log shelf-save"
cmds="$cmds shelve shelves unshelve"
# help options have a strange command status...
@@ -1024,6 +1024,9 @@ _svn()
upgrade)
cmdOpts="$qOpts $pOpts"
;;
+ shelf-list-by-paths)
+ cmdOpts="$pOpts"
+ ;;
shelf-diff)
cmdOpts="$pOpts"
;;