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