Author: julianfoad
Date: Thu Jan 11 17:13:34 2018
New Revision: 1820901

URL: http://svn.apache.org/viewvc?rev=1820901&view=rev
Log:
On the 'shelve-checkpoint' branch: 'svn unshelve' prints shelf info and
any conflicting modifications in the WC.

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=1820901&r1=1820900&r2=1820901&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/svn/shelve-cmd.c Thu Jan 
11 17:13:34 2018
@@ -79,7 +79,7 @@ show_diffstat(const svn_client_shelf_ver
 {
 #ifndef WIN32
   int result = system(apr_psprintf(scratch_pool,
-                                   "diffstat -p0 %s 2> /dev/null",
+                                   "diffstat -p0 '%s' 2> /dev/null",
                                    info->patch_abspath));
   if (result == 0)
     SVN_ERR(svn_cmdline_printf(scratch_pool, "\n"));
@@ -118,6 +118,63 @@ list_sorted_by_date(apr_array_header_t *
   return SVN_NO_ERROR;
 }
 
+/*  */
+static svn_error_t *
+stats(svn_client_shelf_t *shelf,
+      int version,
+      apr_time_t time_now,
+      svn_boolean_t with_logmsg,
+      apr_pool_t *scratch_pool)
+{
+  svn_client_shelf_version_info_t *info;
+  char *age_str;
+  char *version_str;
+  apr_hash_t *paths;
+  const char *paths_str = "";
+  char *info_str;
+
+  SVN_ERR(svn_client_shelf_version_get_info(&info,
+                                            shelf, version,
+                                            scratch_pool, scratch_pool));
+
+  age_str = friendly_duration_str(time_now - info->mtime, scratch_pool);
+  if (version == shelf->max_version)
+    version_str = apr_psprintf(scratch_pool,
+                               _("version %d"), version);
+  else
+    version_str = apr_psprintf(scratch_pool,
+                               _("version %d of %d"),
+                               version, shelf->max_version);
+  SVN_ERR(svn_client_shelf_get_paths(&paths,
+                                     shelf, shelf->max_version,
+                                     scratch_pool, scratch_pool));
+  if (paths)
+    paths_str = apr_psprintf(scratch_pool,
+                             _(", %d paths changed"), apr_hash_count(paths));
+  info_str = apr_psprintf(scratch_pool,
+                          _("%s, %s ago%s\n"),
+                          version_str, age_str, paths_str);
+  SVN_ERR(svn_cmdline_printf(scratch_pool,
+                             "%-30s %s",
+                             shelf->name, info_str));
+
+  if (with_logmsg)
+    {
+      char *log_message;
+
+      SVN_ERR(svn_client_shelf_get_log_message(&log_message, shelf,
+                                               scratch_pool));
+      if (log_message)
+        {
+          SVN_ERR(svn_cmdline_printf(scratch_pool,
+                                     _(" %.50s\n"),
+                                     log_message));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Display a list of shelves */
 static svn_error_t *
 shelves_list(const char *local_abspath,
@@ -139,38 +196,14 @@ shelves_list(const char *local_abspath,
       const char *name = item->key;
       svn_client_shelf_t *shelf;
       svn_client_shelf_version_info_t *info;
-      char *age_str;
-      apr_hash_t *paths;
 
       SVN_ERR(svn_client_shelf_open(&shelf,
                                     name, local_abspath, ctx, scratch_pool));
       SVN_ERR(svn_client_shelf_version_get_info(&info,
                                                 shelf, shelf->max_version,
                                                 scratch_pool, scratch_pool));
-      age_str = friendly_duration_str(time_now - info->mtime, scratch_pool);
-
-      SVN_ERR(svn_client_shelf_get_paths(&paths,
-                                         shelf, shelf->max_version,
-                                         scratch_pool, scratch_pool));
-
-      SVN_ERR(svn_cmdline_printf(scratch_pool,
-                                 _("%-30s %s ago,  %d versions,  %d paths 
changed\n"),
-                                 name, age_str, shelf->max_version,
-                                 apr_hash_count(paths)));
-      if (with_logmsg)
-        {
-          char *log_message;
-
-          SVN_ERR(svn_client_shelf_get_log_message(&log_message, shelf,
-                                                   scratch_pool));
-          if (log_message)
-            {
-              SVN_ERR(svn_cmdline_printf(scratch_pool,
-                                         _(" %.50s\n"),
-                                         log_message));
-            }
-        }
-
+      SVN_ERR(stats(shelf, shelf->max_version, time_now,
+                    with_logmsg, scratch_pool));
       if (with_diffstat)
         {
           SVN_ERR(show_diffstat(info, scratch_pool));
@@ -200,17 +233,12 @@ shelf_log(const char *name,
   for (i = 1; i <= shelf->max_version; i++)
     {
       svn_client_shelf_version_info_t *info;
-      char *age_str;
 
       SVN_ERR(svn_client_shelf_version_get_info(&info,
                                                 shelf, i,
                                                 scratch_pool, scratch_pool));
-      age_str = friendly_duration_str(time_now - info->mtime, scratch_pool);
-
-      SVN_ERR(svn_cmdline_printf(scratch_pool,
-                                 _("version %d: %s ago\n"),
-                                 i, age_str));
-
+      SVN_ERR(stats(shelf, i, time_now,
+                    FALSE /*with_logmsg*/, scratch_pool));
       if (with_diffstat)
         {
           SVN_ERR(show_diffstat(info, scratch_pool));
@@ -309,6 +337,42 @@ shelve(int *new_version_p,
   return SVN_NO_ERROR;
 }
 
+struct status_baton
+{
+  /* These fields correspond to the ones in the
+     svn_cl__print_status() interface. */
+  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 */
+
+  svn_client_ctx_t *ctx;
+};
+
+/* A status callback function for printing STATUS for PATH. */
+static svn_error_t *
+print_status(void *baton,
+             const char *path,
+             const svn_client_status_t *status,
+             apr_pool_t *pool)
+{
+  struct status_baton *sb = baton;
+  unsigned int conflicts;
+
+  return svn_cl__print_status(sb->target_abspath, sb->target_path,
+                              path, status,
+                              TRUE /*suppress_externals_placeholders*/,
+                              FALSE /*detailed*/,
+                              FALSE /*show_last_committed*/,
+                              TRUE /*skip_unrecognized*/,
+                              FALSE /*repos_locks*/,
+                              &conflicts, &conflicts, &conflicts,
+                              sb->ctx,
+                              pool);
+}
+
 /* Set *BATON to true if the reported path has any local modification or
  * any status that means we should not attempt to patch it.
  *
@@ -319,14 +383,25 @@ modification_checker(void *baton,
                      const svn_client_status_t *status,
                      apr_pool_t *scratch_pool)
 {
-  svn_boolean_t *modified = baton;
+  struct status_baton *sb = baton;
 
   if (status->conflicted
       || ! (status->node_status == svn_wc_status_none
             || status->node_status == svn_wc_status_unversioned
             || status->node_status == svn_wc_status_normal))
     {
-      *modified = TRUE;
+      if (sb->verbose)
+        {
+          if (!sb->printed_header)
+            {
+              SVN_ERR(svn_cmdline_printf(scratch_pool,
+                                         _("--- Paths modified in shelf and in 
WC:\n")));
+              sb->printed_header = TRUE;
+            }
+          SVN_ERR(print_status(baton, target, status, scratch_pool));
+        }
+
+      *sb->modified = TRUE;
     }
   return SVN_NO_ERROR;
 }
@@ -336,12 +411,20 @@ modification_checker(void *baton,
 static svn_error_t *
 check_no_modified_paths(svn_client_shelf_t *shelf,
                         int version,
+                        svn_boolean_t verbose,
                         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.ctx = ctx;
+
   SVN_ERR(svn_client_shelf_get_paths(&paths,
                                      shelf, version,
                                      scratch_pool, scratch_pool));
@@ -349,8 +432,9 @@ check_no_modified_paths(svn_client_shelf
     {
       const char *path = apr_hash_this_key(hi);
       const char *abspath = svn_path_join(shelf->wc_root_abspath, path, 
scratch_pool);
-      svn_boolean_t modified = FALSE;
 
+      sb.target_abspath = abspath;
+      sb.target_path = abspath;
       SVN_ERR(svn_client_status6(NULL /*result_rev*/,
                                  ctx, abspath,
                                  NULL /*revision*/,
@@ -362,14 +446,14 @@ check_no_modified_paths(svn_client_shelf
                                  TRUE /*ignore_externals*/,
                                  FALSE /*depth_as_sticky*/,
                                  NULL /*changelists*/,
-                                 modification_checker, &modified,
+                                 modification_checker, &sb,
                                  scratch_pool));
-      if (modified)
-        {
-          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                                   _("Shelf affects at least one path that is 
already modified: '%s'"),
-                                   path);
-        }
+    }
+  if (any_modified)
+    {
+      return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
+                              _("Cannot unshelve/restore, as at least one "
+                                "path is modified in shelf and in WC"));
     }
   return SVN_NO_ERROR;
 }
@@ -391,6 +475,7 @@ shelf_restore(const char *name,
               apr_pool_t *scratch_pool)
 {
   int version, old_version;
+  apr_time_t time_now = apr_time_now();
   svn_client_shelf_t *shelf;
 
   SVN_ERR(svn_client_shelf_open(&shelf, name, local_abspath,
@@ -412,7 +497,15 @@ shelf_restore(const char *name,
       version = shelf->max_version;
     }
 
-  SVN_ERR(check_no_modified_paths(shelf, version, ctx, scratch_pool));
+  if (! quiet)
+    {
+      SVN_ERR(svn_cmdline_printf(scratch_pool,
+                                 _("--- Unshelve '%s' in WC root '%s'\n"),
+                                 shelf->name, shelf->wc_root_abspath));
+      SVN_ERR(stats(shelf, version, time_now,
+                    TRUE /*with_logmsg*/, scratch_pool));
+    }
+  SVN_ERR(check_no_modified_paths(shelf, version, !quiet, ctx, scratch_pool));
 
   SVN_ERR(svn_client_shelf_apply(shelf, version,
                                  dry_run, scratch_pool));
@@ -649,7 +742,7 @@ svn_cl__unshelve(apr_getopt_t *os,
       SVN_ERR(name_of_youngest(&name,
                                local_abspath, ctx, scratch_pool, 
scratch_pool));
       SVN_ERR(svn_cmdline_printf(scratch_pool,
-                                 _("unshelving the youngest change, '%s'\n"),
+                                 _("unshelving the youngest shelf, '%s'\n"),
                                  name));
     }
 


Reply via email to