subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1826407 [3/6] - in /subversion/branches/better-pristines: ./ subversion/bindings/swig/python/tests/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ subversion/libsvn_fs_fs/ subversion/libs...
Date Sat, 10 Mar 2018 15:27:25 GMT
Modified: subversion/branches/better-pristines/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/cl.h?rev=1826407&r1=1826406&r2=1826407&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/svn/cl.h (original)
+++ subversion/branches/better-pristines/subversion/svn/cl.h Sat Mar 10 15:27:24 2018
@@ -256,7 +256,7 @@ typedef struct svn_cl__opt_state_t
   const char *show_item;           /* print only the given item */
   svn_boolean_t adds_as_modification; /* update 'add vs add' no tree conflict */
   svn_boolean_t vacuum_pristines; /* remove unreferenced pristines */
-  svn_boolean_t list;
+  svn_boolean_t drop;             /* drop shelf after successful unshelve */
   svn_version_t *compatible_version; /* working copy compatibility version */
 } svn_cl__opt_state_t;
 
@@ -308,6 +308,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,
@@ -320,7 +321,7 @@ svn_opt_subcommand_t
 
 
 /* See definition in svn.c for documentation. */
-extern const svn_opt_subcommand_desc2_t svn_cl__cmd_table[];
+extern const svn_opt_subcommand_desc3_t svn_cl__cmd_table[];
 
 /* See definition in svn.c for documentation. */
 extern const int svn_cl__global_options[];

Modified: subversion/branches/better-pristines/subversion/svn/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/help-cmd.c?rev=1826407&r1=1826406&r2=1826407&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/svn/help-cmd.c (original)
+++ subversion/branches/better-pristines/subversion/svn/help-cmd.c Sat Mar 10 15:27:24 2018
@@ -203,7 +203,7 @@ svn_cl__help(apr_getopt_t *os,
   svn_stringbuf_appendcstr(version_footer, "* KWallet (KDE)\n");
 #endif
 
-  return svn_opt_print_help4(os,
+  return svn_opt_print_help5(os,
                              "svn",   /* ### erm, derive somehow? */
                              opt_state ? opt_state->version : FALSE,
                              opt_state ? opt_state->quiet : FALSE,

Modified: subversion/branches/better-pristines/subversion/svn/shelf-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/shelf-cmd.c?rev=1826407&r1=1826406&r2=1826407&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/svn/shelf-cmd.c (original)
+++ subversion/branches/better-pristines/subversion/svn/shelf-cmd.c Sat Mar 10 15:27:24 2018
@@ -28,7 +28,9 @@
 #include "svn_client.h"
 #include "svn_error_codes.h"
 #include "svn_error.h"
+#include "svn_hash.h"
 #include "svn_path.h"
+#include "svn_props.h"
 #include "svn_utf.h"
 
 #include "cl.h"
@@ -53,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 *
@@ -516,8 +591,31 @@ shelve(int *new_version_p,
                                        dry_run, scratch_pool));
     }
 
-  SVN_ERR(svn_client_shelf_set_log_message(shelf, revprop_table,
-                                           dry_run, scratch_pool));
+  /* Fetch the log message and any other revprops */
+  if (ctx->log_msg_func3)
+    {
+      const char *tmp_file;
+      apr_array_header_t *commit_items
+        = apr_array_make(scratch_pool, 1, sizeof(void *));
+      const char *message = "";
+
+      SVN_ERR(ctx->log_msg_func3(&message, &tmp_file, commit_items,
+                                 ctx->log_msg_baton3, scratch_pool));
+      /* Abort the shelving if the log message callback requested so. */
+      if (! message)
+        return SVN_NO_ERROR;
+
+      if (message && !dry_run)
+        {
+          svn_string_t *propval = svn_string_create(message, scratch_pool);
+
+          if (! revprop_table)
+            revprop_table = apr_hash_make(scratch_pool);
+          svn_hash_sets(revprop_table, SVN_PROP_REVISION_LOG, propval);
+        }
+    }
+
+  SVN_ERR(svn_client_shelf_revprop_set_all(shelf, revprop_table, scratch_pool));
 
   if (new_version_p)
     *new_version_p = shelf->max_version;
@@ -583,6 +681,27 @@ check_no_modified_paths(const char *path
   return SVN_NO_ERROR;
 }
 
+/* Intercept patch notifications to detect when there is a conflict */
+struct patch_notify_baton_t
+{
+  svn_wc_notify_func2_t notify_func;
+  void *notify_baton;
+  svn_boolean_t rejects;
+};
+
+/* Intercept patch notifications to detect when there is a conflict */
+static void
+patch_notify(void *baton,
+             const svn_wc_notify_t *notify,
+             apr_pool_t *pool)
+{
+  struct patch_notify_baton_t *b = baton;
+
+  if (notify->action == svn_wc_notify_patch_rejected_hunk)
+    b->rejects = TRUE;
+  b->notify_func(b->notify_baton, notify, pool);
+}
+
 /** Restore/unshelve a given or newest version of changes.
  *
  * Restore local modifications from shelf @a name version @a arg,
@@ -603,6 +722,7 @@ shelf_restore(const char *name,
   apr_time_t time_now = apr_time_now();
   svn_client_shelf_t *shelf;
   svn_client_shelf_version_t *shelf_version;
+  struct patch_notify_baton_t b;
 
   SVN_ERR(svn_client_shelf_open_existing(&shelf, name, local_abspath,
                                          ctx, scratch_pool));
@@ -631,8 +751,22 @@ shelf_restore(const char *name,
   SVN_ERR(check_no_modified_paths(shelf->wc_root_abspath,
                                   shelf_version, quiet, ctx, scratch_pool));
 
+  b.rejects = FALSE;
+  b.notify_func = ctx->notify_func2;
+  b.notify_baton = ctx->notify_baton2;
+  ctx->notify_func2 = patch_notify;
+  ctx->notify_baton2 = &b;
+
   SVN_ERR(svn_client_shelf_apply(shelf_version,
                                  dry_run, scratch_pool));
+  ctx->notify_func2 = b.notify_func;
+  ctx->notify_baton2 = b.notify_baton;
+
+  if (b.rejects)
+    {
+      return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
+                              _("Unshelve/restore failed due to conflicts"));
+    }
 
   if (! dry_run)
     {
@@ -859,6 +993,12 @@ svn_cl__shelf_unshelve(apr_getopt_t *os,
                         opt_state->dry_run, opt_state->quiet,
                         local_abspath, ctx, scratch_pool));
 
+  if (opt_state->drop)
+    {
+      SVN_ERR(shelf_drop(name, local_abspath,
+                         opt_state->dry_run, opt_state->quiet,
+                         ctx, scratch_pool));
+    }
   return SVN_NO_ERROR;
 }
 
@@ -885,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,



Mime
View raw message