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"
                ;;


Reply via email to