Author: julianfoad
Date: Mon Mar 12 16:05:20 2018
New Revision: 1826559

URL: http://svn.apache.org/viewvc?rev=1826559&view=rev
Log:
Shelving: reduce the API's reliance on integer version numbers.

* subversion/include/svn_client.h,
  subversion/libsvn_client/shelf.c
  (svn_client_shelf_t): Deprecate 'max_version'.
  (svn_client_shelf_version_t): Add the version number as a private member.
  (svn_client_shelf_save_new_version2): New.
  (svn_client_shelf_save_new_version): Deprecate.
  (svn_client_shelf_delete_newer_versions): New.
  (svn_client_shelf_set_current_version): Deprecate.
  (svn_client_shelf_version_open): Tweak docs and parameter name.
  (svn_client_shelf_get_newest_version): New.
  (svn_client_shelf_get_all_versions): New.

* subversion/svn/shelf-cmd.c
  Update accordingly.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/shelf.c
    subversion/trunk/subversion/svn/shelf-cmd.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1826559&r1=1826558&r2=1826559&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Mon Mar 12 16:05:20 2018
@@ -6828,7 +6828,7 @@ typedef struct svn_client_shelf_t
 {
     /* Public fields (read-only for public use) */
     const char *name;
-    int max_version;
+    int max_version;  /** @deprecated */
 
     /* Private fields */
     const char *wc_root_abspath;
@@ -6849,8 +6849,9 @@ typedef struct svn_client_shelf_version_
   svn_client_shelf_t *shelf;
   apr_time_t mtime;  /** time-stamp of this version */
 
-  /* TODO: these should be Private fields */
+  /* Private fields */
   const char *patch_abspath;  /** abspath of the patch file */
+  int version_number;  /** version number starting from 1 */
 } svn_client_shelf_version_t;
 
 /** Open an existing shelf or create a new shelf.
@@ -6920,37 +6921,70 @@ svn_client_shelf_delete(const char *name
 /** Save the local modifications found by @a paths, @a depth,
  * @a changelists as a new version of @a shelf.
  *
+ * Return the new shelf-version in @a *new_version_p.
+ *
  * @a paths are relative to the CWD, or absolute.
  *
  * If there are no local modifications in the specified locations, do not
- * create a new version of @a shelf, and return SVN_NO_ERROR. In this case
- * @a shelf->max_version after the call is the same as before the call.
+ * create a new version of @a shelf; set @a *new_version_p to null and
+ * return SVN_NO_ERROR. In this case @a shelf->max_version after the call
+ * is the same as before the call.
+ *
+ * @a *new_version_p may be null if that output is not wanted.
  *
  * @since New in 1.X.
  * @warning EXPERIMENTAL.
  */
 SVN_EXPERIMENTAL
 svn_error_t *
+svn_client_shelf_save_new_version2(svn_client_shelf_version_t **new_version_p,
+                                   svn_client_shelf_t *shelf,
+                                   const apr_array_header_t *paths,
+                                   svn_depth_t depth,
+                                   const apr_array_header_t *changelists,
+                                   apr_pool_t *scratch_pool);
+
+/** @deprecated Use svn_client_shelf_save_new_version2() instead.
+ * @warning EXPERIMENTAL.
+ */
+SVN_DEPRECATED
+svn_error_t *
 svn_client_shelf_save_new_version(svn_client_shelf_t *shelf,
                                   const apr_array_header_t *paths,
                                   svn_depth_t depth,
                                   const apr_array_header_t *changelists,
                                   apr_pool_t *scratch_pool);
 
-/** Set the newest version of @a shelf to @a version.
+/** Delete all newer versions of @a shelf newer than @a shelf_version.
+ *
+ * If @a shelf_version is null, delete all versions of @a shelf.
+ *
+ * Leave the shelf's log message and other revprops unchanged.
  *
- * Delete all newer versions.
+ * Any #svn_client_shelf_version_t object that refers to a deleted version
+ * will become invalid: attempting to use it will give undefined behaviour.
+ * The given @a shelf_version will remain valid.
  *
  * @since New in 1.X.
  * @warning EXPERIMENTAL.
  */
 SVN_EXPERIMENTAL
 svn_error_t *
+svn_client_shelf_delete_newer_versions(svn_client_shelf_t *shelf,
+                                       svn_client_shelf_version_t 
*shelf_version,
+                                       apr_pool_t *scratch_pool);
+
+/** @deprecated Use svn_client_shelf_delete_newer_versions() instead.
+ * @warning EXPERIMENTAL.
+ */
+SVN_DEPRECATED
+svn_error_t *
 svn_client_shelf_set_current_version(svn_client_shelf_t *shelf,
-                                     int version,
+                                     int version_number,
                                      apr_pool_t *scratch_pool);
 
-/** Open an existing @a shelf_version, or error if it doesn't exist.
+/** Return in @a shelf_version an existing version of @a shelf, given its
+ * @a version_number. Error if that version doesn't exist.
  *
  * There is no need to "close" it after use.
  *
@@ -6961,10 +6995,39 @@ SVN_EXPERIMENTAL
 svn_error_t *
 svn_client_shelf_version_open(svn_client_shelf_version_t **shelf_version_p,
                               svn_client_shelf_t *shelf,
-                              int version,
+                              int version_number,
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
 
+/** Return in @a shelf_version the newest version of @a shelf.
+ *
+ * Set @a shelf_version to null if no versions exist.
+ *
+ * @since New in 1.X.
+ * @warning EXPERIMENTAL.
+ */
+SVN_EXPERIMENTAL
+svn_error_t *
+svn_client_shelf_get_newest_version(svn_client_shelf_version_t 
**shelf_version_p,
+                                    svn_client_shelf_t *shelf,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool);
+
+/** Return in @a versions_p an array of (#svn_client_shelf_version_t *)
+ * containing all versions of @a shelf.
+ *
+ * The versions will be in chronological order, oldest to newest.
+ *
+ * @since New in 1.X.
+ * @warning EXPERIMENTAL.
+ */
+SVN_EXPERIMENTAL
+svn_error_t *
+svn_client_shelf_get_all_versions(apr_array_header_t **versions_p,
+                                  svn_client_shelf_t *shelf,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
+
 /** Apply @a shelf_version to the WC.
  *
  * @since New in 1.X.

Modified: subversion/trunk/subversion/libsvn_client/shelf.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/shelf.c?rev=1826559&r1=1826558&r2=1826559&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/shelf.c (original)
+++ subversion/trunk/subversion/libsvn_client/shelf.c Mon Mar 12 16:05:20 2018
@@ -620,18 +620,33 @@ svn_client_shelf_unapply(svn_client_shel
 
 svn_error_t *
 svn_client_shelf_set_current_version(svn_client_shelf_t *shelf,
-                                     int version,
+                                     int version_number,
                                      apr_pool_t *scratch_pool)
 {
+  svn_client_shelf_version_t *shelf_version;
+
+  SVN_ERR(svn_client_shelf_version_open(&shelf_version, shelf, version_number,
+                                        scratch_pool, scratch_pool));
+  SVN_ERR(svn_client_shelf_delete_newer_versions(shelf, shelf_version,
+                                                 scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_shelf_delete_newer_versions(svn_client_shelf_t *shelf,
+                                       svn_client_shelf_version_t 
*shelf_version,
+                                       apr_pool_t *scratch_pool)
+{
+  int previous_version = shelf_version ? shelf_version->version_number : 0;
   int i;
 
   /* Delete any newer checkpoints */
-  for (i = shelf->max_version; i > version; i--)
+  for (i = shelf->max_version; i > previous_version; i--)
     {
       SVN_ERR(shelf_delete_patch_file(shelf, i, scratch_pool));
     }
 
-  shelf->max_version = version;
+  shelf->max_version = previous_version;
   SVN_ERR(shelf_write_current(shelf, scratch_pool));
   return SVN_NO_ERROR;
 }
@@ -661,11 +676,12 @@ svn_client_shelf_export_patch(svn_client
 }
 
 svn_error_t *
-svn_client_shelf_save_new_version(svn_client_shelf_t *shelf,
-                                  const apr_array_header_t *paths,
-                                  svn_depth_t depth,
-                                  const apr_array_header_t *changelists,
-                                  apr_pool_t *scratch_pool)
+svn_client_shelf_save_new_version2(svn_client_shelf_version_t **new_version_p,
+                                   svn_client_shelf_t *shelf,
+                                   const apr_array_header_t *paths,
+                                   svn_depth_t depth,
+                                   const apr_array_header_t *changelists,
+                                   apr_pool_t *scratch_pool)
 {
   int next_version = shelf->max_version + 1;
   const char *patch_abspath;
@@ -681,13 +697,35 @@ svn_client_shelf_save_new_version(svn_cl
   SVN_ERR(svn_io_stat(&file_info, patch_abspath, APR_FINFO_MTIME, 
scratch_pool));
   if (file_info.size > 0)
     {
-      SVN_ERR(svn_client_shelf_set_current_version(shelf, next_version,
-                                                   scratch_pool));
+      shelf->max_version = next_version;
+      SVN_ERR(shelf_write_current(shelf, scratch_pool));
+
+      if (new_version_p)
+        SVN_ERR(svn_client_shelf_version_open(new_version_p, shelf, 
next_version,
+                                              scratch_pool, scratch_pool));
+    }
+  else
+    {
+      if (new_version_p)
+        *new_version_p = NULL;
     }
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
+svn_client_shelf_save_new_version(svn_client_shelf_t *shelf,
+                                  const apr_array_header_t *paths,
+                                  svn_depth_t depth,
+                                  const apr_array_header_t *changelists,
+                                  apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_client_shelf_save_new_version2(NULL, shelf,
+                                             paths, depth, changelists,
+                                             scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_client_shelf_get_log_message(char **log_message,
                                  svn_client_shelf_t *shelf,
                                  apr_pool_t *result_pool)
@@ -759,7 +797,7 @@ svn_client_shelf_list(apr_hash_t **shelf
 svn_error_t *
 svn_client_shelf_version_open(svn_client_shelf_version_t **shelf_version_p,
                               svn_client_shelf_t *shelf,
-                              int version,
+                              int version_number,
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool)
 {
@@ -769,7 +807,7 @@ svn_client_shelf_version_open(svn_client
 
   shelf_version->shelf = shelf;
   SVN_ERR(get_existing_patch_abspath(&shelf_version->patch_abspath,
-                                     shelf, version,
+                                     shelf, version_number,
                                      result_pool, scratch_pool));
   SVN_ERR(svn_io_stat_dirent2(&dirent,
                               shelf_version->patch_abspath,
@@ -777,6 +815,48 @@ svn_client_shelf_version_open(svn_client
                               TRUE /*ignore_enoent*/,
                               result_pool, scratch_pool));
   shelf_version->mtime = dirent->mtime;
+  shelf_version->version_number = version_number;
   *shelf_version_p = shelf_version;
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_client_shelf_get_newest_version(svn_client_shelf_version_t 
**shelf_version_p,
+                                    svn_client_shelf_t *shelf,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool)
+{
+  if (shelf->max_version == 0)
+    {
+      *shelf_version_p = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_client_shelf_version_open(shelf_version_p,
+                                        shelf, shelf->max_version,
+                                        result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_shelf_get_all_versions(apr_array_header_t **versions_p,
+                                  svn_client_shelf_t *shelf,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
+{
+  int i;
+
+  *versions_p = apr_array_make(result_pool, shelf->max_version - 1,
+                               sizeof(svn_client_shelf_version_t *));
+
+  for (i = 1; i <= shelf->max_version; i++)
+    {
+      svn_client_shelf_version_t *shelf_version;
+
+      SVN_ERR(svn_client_shelf_version_open(&shelf_version,
+                                            shelf, i,
+                                            result_pool, scratch_pool));
+      APR_ARRAY_PUSH(*versions_p, svn_client_shelf_version_t *) = 
shelf_version;
+    }
+  return SVN_NO_ERROR;
+}
\ No newline at end of file

Modified: subversion/trunk/subversion/svn/shelf-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/shelf-cmd.c?rev=1826559&r1=1826558&r2=1826559&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/shelf-cmd.c (original)
+++ subversion/trunk/subversion/svn/shelf-cmd.c Mon Mar 12 16:05:20 2018
@@ -237,26 +237,22 @@ list_sorted_by_date(apr_array_header_t *
 static svn_error_t *
 stats(svn_client_shelf_t *shelf,
       int version,
+      svn_client_shelf_version_t *shelf_version,
       apr_time_t time_now,
       svn_boolean_t with_logmsg,
       apr_pool_t *scratch_pool)
 {
-  svn_client_shelf_version_t *shelf_version;
   char *age_str;
   char *version_str;
   apr_hash_t *paths;
   const char *paths_str = "";
   char *info_str;
 
-  if (version == 0)
+  if (! shelf_version)
     {
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_client_shelf_version_open(&shelf_version,
-                                        shelf, version,
-                                        scratch_pool, scratch_pool));
-
   age_str = friendly_duration_str(time_now - shelf_version->mtime, 
scratch_pool);
   if (version == shelf->max_version)
     version_str = apr_psprintf(scratch_pool,
@@ -318,15 +314,14 @@ shelves_list(const char *local_abspath,
 
       SVN_ERR(svn_client_shelf_open_existing(&shelf, name, local_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_get_newest_version(&shelf_version, shelf,
+                                                  scratch_pool, scratch_pool));
       if (quiet)
         SVN_ERR(svn_cmdline_printf(scratch_pool, "%s\n", shelf->name));
       else
-        SVN_ERR(stats(shelf, shelf->max_version, time_now,
+        SVN_ERR(stats(shelf, shelf->max_version, shelf_version, time_now,
                       TRUE /*with_logmsg*/, scratch_pool));
-      if (with_diffstat)
+      if (with_diffstat && shelf_version)
         {
           SVN_ERR(show_diffstat(shelf_version, scratch_pool));
         }
@@ -347,19 +342,19 @@ shelf_log(const char *name,
 {
   apr_time_t time_now = apr_time_now();
   svn_client_shelf_t *shelf;
+  apr_array_header_t *versions;
   int i;
 
   SVN_ERR(svn_client_shelf_open_existing(&shelf, name, local_abspath,
                                          ctx, scratch_pool));
-
-  for (i = 1; i <= shelf->max_version; i++)
+  SVN_ERR(svn_client_shelf_get_all_versions(&versions, shelf,
+                                        scratch_pool, scratch_pool));
+  for (i = 0; i < versions->nelts; i++)
     {
-      svn_client_shelf_version_t *shelf_version;
+      svn_client_shelf_version_t *shelf_version
+        = APR_ARRAY_IDX(versions, i, void *);
 
-      SVN_ERR(svn_client_shelf_version_open(&shelf_version,
-                                            shelf, i,
-                                            scratch_pool, scratch_pool));
-      SVN_ERR(stats(shelf, i, time_now,
+      SVN_ERR(stats(shelf, i + 1, shelf_version, time_now,
                     FALSE /*with_logmsg*/, scratch_pool));
       if (with_diffstat)
         {
@@ -527,14 +522,16 @@ shelve(int *new_version_p,
        apr_pool_t *scratch_pool)
 {
   svn_client_shelf_t *shelf;
-  int previous_version;
+  svn_client_shelf_version_t *previous_version;
+  svn_client_shelf_version_t *new_version;
   const char *cwd_abspath;
   struct status_baton sb;
 
   SVN_ERR(svn_client_shelf_open_or_create(&shelf,
                                           name, local_abspath,
                                           ctx, scratch_pool));
-  previous_version = shelf->max_version;
+  SVN_ERR(svn_client_shelf_get_newest_version(&previous_version, shelf,
+                                              scratch_pool, scratch_pool));
 
   if (! quiet)
     {
@@ -542,7 +539,7 @@ shelve(int *new_version_p,
         ? _("--- 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(),
+      SVN_ERR(stats(shelf, shelf->max_version, previous_version, 
apr_time_now(),
                     TRUE /*with_logmsg*/, scratch_pool));
     }
 
@@ -568,10 +565,10 @@ shelve(int *new_version_p,
     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_save_new_version2(&new_version, shelf,
+                                             paths, depth, changelists,
+                                             scratch_pool));
+  if (! new_version)
     {
       SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
       return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -582,12 +579,7 @@ shelve(int *new_version_p,
   /* Un-apply the patch, if required. */
   if (!keep_local)
     {
-      svn_client_shelf_version_t *shelf_version;
-
-      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,
+      SVN_ERR(svn_client_shelf_unapply(new_version,
                                        dry_run, scratch_pool));
     }
 
@@ -622,8 +614,8 @@ shelve(int *new_version_p,
 
   if (dry_run)
     {
-      SVN_ERR(svn_client_shelf_set_current_version(shelf, previous_version,
-                                                   scratch_pool));
+      SVN_ERR(svn_client_shelf_delete_newer_versions(shelf, previous_version,
+                                                     scratch_pool));
     }
 
   SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
@@ -731,10 +723,15 @@ shelf_restore(const char *name,
   if (arg)
     {
       SVN_ERR(svn_cstring_atoi(&version, arg));
+      SVN_ERR(svn_client_shelf_version_open(&shelf_version,
+                                            shelf, version,
+                                            scratch_pool, scratch_pool));
     }
   else
     {
       version = shelf->max_version;
+      SVN_ERR(svn_client_shelf_get_newest_version(&shelf_version, shelf,
+                                                  scratch_pool, scratch_pool));
     }
 
   if (! quiet)
@@ -742,12 +739,9 @@ shelf_restore(const char *name,
       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,
+      SVN_ERR(stats(shelf, version, shelf_version, time_now,
                     TRUE /*with_logmsg*/, scratch_pool));
     }
-  SVN_ERR(svn_client_shelf_version_open(&shelf_version,
-                                        shelf, version,
-                                        scratch_pool, scratch_pool));
   SVN_ERR(check_no_modified_paths(shelf->wc_root_abspath,
                                   shelf_version, quiet, ctx, scratch_pool));
 
@@ -770,8 +764,8 @@ shelf_restore(const char *name,
 
   if (! dry_run)
     {
-      SVN_ERR(svn_client_shelf_set_current_version(shelf, version,
-                                                   scratch_pool));
+      SVN_ERR(svn_client_shelf_delete_newer_versions(shelf, shelf_version,
+                                                     scratch_pool));
     }
 
   if (!quiet)
@@ -797,7 +791,6 @@ shelf_diff(const char *name,
            svn_client_ctx_t *ctx,
            apr_pool_t *scratch_pool)
 {
-  int version;
   svn_client_shelf_t *shelf;
   svn_client_shelf_version_t *shelf_version;
   svn_stream_t *stream;
@@ -807,15 +800,18 @@ shelf_diff(const char *name,
 
   if (arg)
     {
+      int version;
+
       SVN_ERR(svn_cstring_atoi(&version, arg));
+      SVN_ERR(svn_client_shelf_version_open(&shelf_version,
+                                            shelf, version,
+                                            scratch_pool, scratch_pool));
     }
   else
     {
-      version = shelf->max_version;
+      SVN_ERR(svn_client_shelf_get_newest_version(&shelf_version, shelf,
+                                                  scratch_pool, scratch_pool));
     }
-  SVN_ERR(svn_client_shelf_version_open(&shelf_version,
-                                        shelf, version,
-                                        scratch_pool, scratch_pool));
 
   SVN_ERR(svn_stream_for_stdout(&stream, scratch_pool));
   SVN_ERR(svn_client_shelf_export_patch(shelf_version, stream,
@@ -1067,9 +1063,8 @@ shelf_list_by_paths(apr_array_header_t *
       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_get_newest_version(&shelf_version, shelf,
+                                                  scratch_pool, scratch_pool));
       SVN_ERR(svn_client_shelf_paths_changed(&shelf_paths,
                                              shelf_version,
                                              scratch_pool, scratch_pool));


Reply via email to