You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2018/01/12 21:12:15 UTC

svn commit: r1821034 - /subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c

Author: julianfoad
Date: Fri Jan 12 21:12:15 2018
New Revision: 1821034

URL: http://svn.apache.org/viewvc?rev=1821034&view=rev
Log:
On the 'shelve-checkpoint' branch: let 'shelve' say what it's going to do.

Modified:
    subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c

Modified: subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c?rev=1821034&r1=1821033&r2=1821034&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c Fri Jan 12 21:12:15 2018
@@ -138,6 +138,11 @@ stats(svn_client_shelf_t *shelf,
   const char *paths_str = "";
   char *info_str;
 
+  if (version == 0)
+    {
+      return SVN_NO_ERROR;
+    }
+
   SVN_ERR(svn_client_shelf_version_open(&shelf_version,
                                         shelf, version,
                                         scratch_pool, scratch_pool));
@@ -276,73 +281,42 @@ name_of_youngest(const char **name_p,
   return SVN_NO_ERROR;
 }
 
-/** Shelve/save a new version of changes.
- *
- * Shelve in shelf @a name the local modifications found by @a paths,
- * @a depth, @a changelists. Revert the shelved changes from the WC
- * unless @a keep_local is true.
- *
- * If no local modifications are found, throw an error.
- *
- * If @a dry_run is true, don't actually do it.
- *
- * Report in @a *new_version_p the new version number (or, with dry run,
- * what it would be).
+/*
+ * PATHS are relative to WC_ROOT_ABSPATH.
  */
 static svn_error_t *
-shelve(int *new_version_p,
-       const char *name,
-       const apr_array_header_t *paths,
-       svn_depth_t depth,
-       const apr_array_header_t *changelists,
-       svn_boolean_t keep_local,
-       svn_boolean_t dry_run,
-       const char *local_abspath,
-       svn_client_ctx_t *ctx,
-       apr_pool_t *scratch_pool)
+run_status_on_wc_paths(const char *paths_base_abspath,
+                       const apr_array_header_t *paths,
+                       svn_depth_t depth,
+                       const apr_array_header_t *changelists,
+                       svn_client_status_func_t status_func,
+                       void *status_baton,
+                       svn_client_ctx_t *ctx,
+                       apr_pool_t *scratch_pool)
 {
-  svn_client_shelf_t *shelf;
-  int previous_version;
-
-  SVN_ERR(svn_client_shelf_open(&shelf,
-                                name, local_abspath, ctx, scratch_pool));
-  previous_version = shelf->max_version;
-
-  SVN_ERR(svn_client_shelf_save_new_version(shelf,
-                                            paths, depth, changelists,
-                                            scratch_pool));
-  if (shelf->max_version == previous_version)
-    {
-      SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
-      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                               _("No local modifications found"));
-    }
+  int i;
 
-  if (!keep_local)
+  for (i = 0; i < paths->nelts; i++)
     {
-      svn_client_shelf_version_t *shelf_version;
-
-      /* Reverse-apply the patch. This should be a safer way to remove those
-         changes from the WC than running a 'revert' operation. */
-      SVN_ERR(svn_client_shelf_version_open(&shelf_version,
-                                            shelf, shelf->max_version,
-                                            scratch_pool, scratch_pool));
-      SVN_ERR(svn_client_shelf_unapply(shelf_version,
-                                       dry_run, scratch_pool));
-    }
-
-  SVN_ERR(svn_client_shelf_set_log_message(shelf, dry_run, scratch_pool));
+      const char *path = APR_ARRAY_IDX(paths, i, const char *);
+      const char *abspath = svn_path_join(paths_base_abspath, path,
+                                          scratch_pool);
 
-  if (new_version_p)
-    *new_version_p = shelf->max_version;
-
-  if (dry_run)
-    {
-      SVN_ERR(svn_client_shelf_set_current_version(shelf, previous_version,
-                                                   scratch_pool));
+      SVN_ERR(svn_client_status6(NULL /*result_rev*/,
+                                 ctx, abspath,
+                                 NULL /*revision*/,
+                                 depth,
+                                 FALSE /*get_all*/,
+                                 FALSE /*check_out_of_date*/,
+                                 TRUE /*check_working_copy*/,
+                                 TRUE /*no_ignore*/,
+                                 TRUE /*ignore_externals*/,
+                                 FALSE /*depth_as_sticky*/,
+                                 changelists,
+                                 status_func, status_baton,
+                                 scratch_pool));
     }
 
-  SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -353,10 +327,9 @@ struct status_baton
   const char *target_abspath;
   const char *target_path;
 
-  svn_boolean_t verbose;  /* display all statuses while checking them */
-  svn_boolean_t printed_header;
-  svn_boolean_t *modified;  /* set to TRUE when any modification is found */
-
+  const char *header;
+  svn_boolean_t quiet;  /* don't display statuses while checking them */
+  svn_boolean_t modified;  /* set to TRUE when any modification is found */
   svn_client_ctx_t *ctx;
 };
 
@@ -382,7 +355,7 @@ print_status(void *baton,
                               pool);
 }
 
-/* Set *BATON to true if the reported path has any local modification or
+/* Set BATON->modified to true if TARGET has any local modification or
  * any status that means we should not attempt to patch it.
  *
  * A callback of type svn_client_status_func_t. */
@@ -399,38 +372,144 @@ modification_checker(void *baton,
             || status->node_status == svn_wc_status_unversioned
             || status->node_status == svn_wc_status_normal))
     {
-      if (sb->verbose)
+      if (!sb->quiet)
         {
-          if (!sb->printed_header)
+          if (!sb->modified)  /* print the header only once */
             {
-              SVN_ERR(svn_cmdline_printf(scratch_pool,
-                                         _("--- Paths modified in shelf and in WC:\n")));
-              sb->printed_header = TRUE;
+              SVN_ERR(svn_cmdline_printf(scratch_pool, "%s", sb->header));
             }
           SVN_ERR(print_status(baton, target, status, scratch_pool));
         }
 
-      *sb->modified = TRUE;
+      sb->modified = TRUE;
+    }
+  return SVN_NO_ERROR;
+}
+
+/** Shelve/save a new version of changes.
+ *
+ * Shelve in shelf @a name the local modifications found by @a paths,
+ * @a depth, @a changelists. Revert the shelved changes from the WC
+ * unless @a keep_local is true.
+ *
+ * If no local modifications are found, throw an error.
+ *
+ * If @a dry_run is true, don't actually do it.
+ *
+ * Report in @a *new_version_p the new version number (or, with dry run,
+ * what it would be).
+ */
+static svn_error_t *
+shelve(int *new_version_p,
+       const char *name,
+       const apr_array_header_t *paths,
+       svn_depth_t depth,
+       const apr_array_header_t *changelists,
+       svn_boolean_t keep_local,
+       svn_boolean_t dry_run,
+       svn_boolean_t quiet,
+       const char *local_abspath,
+       svn_client_ctx_t *ctx,
+       apr_pool_t *scratch_pool)
+{
+  svn_client_shelf_t *shelf;
+  int previous_version;
+  const char *cwd_abspath;
+  struct status_baton sb;
+
+  SVN_ERR(svn_client_shelf_open(&shelf,
+                                name, local_abspath, ctx, scratch_pool));
+  previous_version = shelf->max_version;
+
+  if (! quiet)
+    {
+      SVN_ERR(svn_cmdline_printf(scratch_pool, keep_local
+        ? _("--- Save a new version of '%s' in WC root '%s'\n")
+        : _("--- Shelve '%s' in WC root '%s'\n"),
+        shelf->name, shelf->wc_root_abspath));
+      SVN_ERR(stats(shelf, previous_version, apr_time_now(),
+                    TRUE /*with_logmsg*/, scratch_pool));
+    }
+
+  sb.header = (keep_local
+               ? _("--- Modifications to save:\n")
+               : _("--- Modifications to shelve:\n"));
+  sb.quiet = quiet;
+  sb.modified = FALSE;
+  sb.ctx = ctx;
+  SVN_ERR(svn_dirent_get_absolute(&cwd_abspath, "", scratch_pool));
+  SVN_ERR(run_status_on_wc_paths(cwd_abspath, paths, depth, changelists,
+                                 modification_checker, &sb,
+                                 ctx, scratch_pool));
+
+  if (!sb.modified)
+    {
+      SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
+      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                               _("No local modifications found"));
+    }
+
+  if (! quiet)
+    SVN_ERR(svn_cmdline_printf(scratch_pool,
+                               keep_local ? _("--- Saving...\n")
+                                          : _("--- Shelving...\n")));
+  SVN_ERR(svn_client_shelf_save_new_version(shelf,
+                                            paths, depth, changelists,
+                                            scratch_pool));
+  if (shelf->max_version == previous_version)
+    {
+      SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
+      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+        keep_local ? _("None of the local modifications could be saved")
+                   : _("None of the local modifications could be shelved"));
+    }
+
+  if (!keep_local)
+    {
+      svn_client_shelf_version_t *shelf_version;
+
+      /* Reverse-apply the patch. This should be a safer way to remove those
+         changes from the WC than running a 'revert' operation. */
+      SVN_ERR(svn_client_shelf_version_open(&shelf_version,
+                                            shelf, shelf->max_version,
+                                            scratch_pool, scratch_pool));
+      SVN_ERR(svn_client_shelf_unapply(shelf_version,
+                                       dry_run, scratch_pool));
+    }
+
+  SVN_ERR(svn_client_shelf_set_log_message(shelf, dry_run, scratch_pool));
+
+  if (new_version_p)
+    *new_version_p = shelf->max_version;
+
+  if (dry_run)
+    {
+      SVN_ERR(svn_client_shelf_set_current_version(shelf, previous_version,
+                                                   scratch_pool));
     }
+
+  SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
   return SVN_NO_ERROR;
 }
 
 /* Throw an error if any paths affected by SHELF:VERSION are currently
  * modified in the WC. */
 static svn_error_t *
-check_no_modified_paths(svn_client_shelf_version_t *shelf_version,
-                        svn_boolean_t verbose,
+check_no_modified_paths(const char *paths_base_abspath,
+                        svn_client_shelf_version_t *shelf_version,
+                        svn_boolean_t quiet,
                         svn_client_ctx_t *ctx,
                         apr_pool_t *scratch_pool)
 {
   apr_hash_t *paths;
   struct status_baton sb;
-  svn_boolean_t any_modified = FALSE;
   apr_hash_index_t *hi;
 
-  sb.verbose = verbose;
-  sb.printed_header = FALSE;
-  sb.modified = &any_modified;
+  sb.target_abspath = shelf_version->shelf->wc_root_abspath;
+  sb.target_path = "";
+  sb.header = _("--- Paths modified in shelf and in WC:\n");
+  sb.quiet = quiet;
+  sb.modified = FALSE;
   sb.ctx = ctx;
 
   SVN_ERR(svn_client_shelf_get_paths(&paths, shelf_version,
@@ -438,11 +517,9 @@ check_no_modified_paths(svn_client_shelf
   for (hi = apr_hash_first(scratch_pool, paths); hi; hi = apr_hash_next(hi))
     {
       const char *path = apr_hash_this_key(hi);
-      const char *abspath = svn_path_join(shelf_version->shelf->wc_root_abspath,
-                                          path, scratch_pool);
+      const char *abspath = svn_path_join(paths_base_abspath, path,
+                                          scratch_pool);
 
-      sb.target_abspath = abspath;
-      sb.target_path = abspath;
       SVN_ERR(svn_client_status6(NULL /*result_rev*/,
                                  ctx, abspath,
                                  NULL /*revision*/,
@@ -457,7 +534,7 @@ check_no_modified_paths(svn_client_shelf
                                  modification_checker, &sb,
                                  scratch_pool));
     }
-  if (any_modified)
+  if (sb.modified)
     {
       return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
                               _("Cannot unshelve/restore, as at least one "
@@ -517,7 +594,8 @@ shelf_restore(const char *name,
   SVN_ERR(svn_client_shelf_version_open(&shelf_version,
                                         shelf, version,
                                         scratch_pool, scratch_pool));
-  SVN_ERR(check_no_modified_paths(shelf_version, !quiet, ctx, scratch_pool));
+  SVN_ERR(check_no_modified_paths(shelf->wc_root_abspath,
+                                  shelf_version, quiet, ctx, scratch_pool));
 
   SVN_ERR(svn_client_shelf_apply(shelf_version,
                                  dry_run, scratch_pool));
@@ -613,6 +691,7 @@ shelf_shelve(int *new_version,
              apr_array_header_t *changelists,
              svn_boolean_t keep_local,
              svn_boolean_t dry_run,
+             svn_boolean_t quiet,
              svn_client_ctx_t *ctx,
              apr_pool_t *scratch_pool)
 {
@@ -634,7 +713,7 @@ shelf_shelve(int *new_version,
 
   SVN_ERR(shelve(new_version, name,
                  targets, depth, changelists,
-                 keep_local, dry_run,
+                 keep_local, dry_run, quiet,
                  local_abspath, ctx, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -684,7 +763,7 @@ svn_cl__shelve(apr_getopt_t *os,
       err = shelf_shelve(&new_version, name,
                          targets, opt_state->depth, opt_state->changelists,
                          opt_state->keep_local, opt_state->dry_run,
-                         ctx, pool);
+                         opt_state->quiet, ctx, pool);
       if (ctx->log_msg_func3)
         SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3,
                                         err, pool));