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/06/07 18:17:53 UTC
svn commit: r1833135 - in /subversion/trunk/subversion: include/svn_client.h
libsvn_client/shelf.c svn/shelf-cmd.c
Author: julianfoad
Date: Thu Jun 7 18:17:53 2018
New Revision: 1833135
URL: http://svn.apache.org/viewvc?rev=1833135&view=rev
Log:
Shelving: better reporting of shelved and not-shelved changes.
* subversion/include/svn_client.h,
subversion/libsvn_client/shelf.c
(svn_client_shelf_save_new_version3): New.
(svn_client_shelf_save_new_version2): Deprecate.
* subversion/svn/shelf-cmd.c
Use callbacks to report shelved and not-shelved paths.
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=1833135&r1=1833134&r2=1833135&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Thu Jun 7 18:17:53 2018
@@ -6954,21 +6954,51 @@ 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.
+ * If any paths are shelved, create a new shelf-version and return the new
+ * shelf-version in @a *new_version_p, else set @a *new_version_p to null.
+ * @a new_version_p may be null if that output is not wanted; a new shelf-
+ * version is still saved and may be found through @a shelf.
*
* @a paths are relative to the CWD, or absolute.
*
+ * For each successfully shelved path: call @a shelved_func (if not null)
+ * with @a shelved_baton.
+ *
+ * If any paths cannot be shelved: if @a not_shelved_func is given, call
+ * it with @a not_shelved_baton for each such path, and still create a new
+ * shelf-version if any paths are shelved.
+ *
+ * This function does not revert the changes from the WC; use
+ * svn_client_shelf_unapply() for that.
+ *
+ * @since New in 1.X.
+ * @warning EXPERIMENTAL.
+ */
+SVN_EXPERIMENTAL
+svn_error_t *
+svn_client_shelf_save_new_version3(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,
+ svn_client_status_func_t shelved_func,
+ void *shelved_baton,
+ svn_client_status_func_t not_shelved_func,
+ void *not_shelved_baton,
+ apr_pool_t *scratch_pool);
+
+/** @deprecated Use svn_client_shelf_save_new_version3() instead.
+ *
+ * If any paths cannot be shelved, throw an error.
+ *
* If there are no local modifications in the specified locations, do not
* 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_DEPRECATED
svn_error_t *
svn_client_shelf_save_new_version2(svn_client_shelf_version_t **new_version_p,
svn_client_shelf_t *shelf,
Modified: subversion/trunk/subversion/libsvn_client/shelf.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/shelf.c?rev=1833135&r1=1833134&r2=1833135&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/shelf.c (original)
+++ subversion/trunk/subversion/libsvn_client/shelf.c Thu Jun 7 18:17:53 2018
@@ -728,23 +728,61 @@ svn_client_shelf_version_status_walk(svn
return SVN_NO_ERROR;
}
-/* A baton for use with walk_callback(). */
+/* A baton for use with write_changes_visitor(). */
typedef struct write_changes_baton_t {
const char *wc_root_abspath;
svn_client_shelf_version_t *shelf_version;
svn_client_ctx_t *ctx;
svn_boolean_t any_shelved; /* were any paths successfully shelved? */
- apr_array_header_t *unshelvable; /* paths unshelvable */
+ svn_client_status_func_t was_shelved_func;
+ void *was_shelved_baton;
+ svn_client_status_func_t was_not_shelved_func;
+ void *was_not_shelved_baton;
apr_pool_t *pool; /* pool for data in 'unshelvable', etc. */
} write_changes_baton_t;
/* */
static svn_error_t *
-note_shelved(apr_array_header_t *shelved,
- const char *relpath,
- apr_pool_t *pool)
+notify_shelved(write_changes_baton_t *wb,
+ const char *wc_relpath,
+ const char *local_abspath,
+ const svn_wc_status3_t *wc_status,
+ apr_pool_t *scratch_pool)
+{
+ if (wb->was_shelved_func)
+ {
+ svn_client_status_t *cst;
+
+ SVN_ERR(svn_client__create_status(&cst, wb->ctx->wc_ctx, local_abspath,
+ wc_status,
+ scratch_pool, scratch_pool));
+ SVN_ERR(wb->was_shelved_func(wb->was_shelved_baton,
+ wc_relpath, cst, scratch_pool));
+ }
+
+ wb->any_shelved = TRUE;
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+notify_not_shelved(write_changes_baton_t *wb,
+ const char *wc_relpath,
+ const char *local_abspath,
+ const svn_wc_status3_t *wc_status,
+ apr_pool_t *scratch_pool)
{
- APR_ARRAY_PUSH(shelved, const char *) = apr_pstrdup(pool, relpath);
+ if (wb->was_not_shelved_func)
+ {
+ svn_client_status_t *cst;
+
+ SVN_ERR(svn_client__create_status(&cst, wb->ctx->wc_ctx, local_abspath,
+ wc_status,
+ scratch_pool, scratch_pool));
+ SVN_ERR(wb->was_not_shelved_func(wb->was_not_shelved_baton,
+ wc_relpath, cst, scratch_pool));
+ }
+
return SVN_NO_ERROR;
}
@@ -944,7 +982,8 @@ write_changes_visitor(void *baton,
if (status->kind != svn_node_file
|| status->copied)
{
- SVN_ERR(note_shelved(wb->unshelvable, wc_relpath, wb->pool));
+ SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
+ status, scratch_pool));
break;
}
/* fall through */
@@ -953,7 +992,8 @@ write_changes_visitor(void *baton,
/* Store metadata, and base and working versions if it's a file */
SVN_ERR(store_file(local_abspath, wc_relpath, wb->shelf_version,
status, wb->ctx, scratch_pool));
- wb->any_shelved = TRUE;
+ SVN_ERR(notify_shelved(wb, wc_relpath, local_abspath,
+ status, scratch_pool));
break;
}
@@ -964,14 +1004,16 @@ write_changes_visitor(void *baton,
&& status->prop_status != svn_wc_status_none))
{
/* Incomplete, but local modifications */
- SVN_ERR(note_shelved(wb->unshelvable, wc_relpath, wb->pool));
+ SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
+ status, scratch_pool));
}
break;
case svn_wc_status_conflicted:
case svn_wc_status_missing:
case svn_wc_status_obstructed:
- SVN_ERR(note_shelved(wb->unshelvable, wc_relpath, wb->pool));
+ SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
+ status, scratch_pool));
break;
case svn_wc_status_normal:
@@ -1070,11 +1112,14 @@ wc_walk_status_multi(const apr_array_hea
*/
static svn_error_t *
shelf_write_changes(svn_boolean_t *any_shelved,
- apr_array_header_t **unshelvable,
svn_client_shelf_version_t *shelf_version,
const apr_array_header_t *paths,
svn_depth_t depth,
const apr_array_header_t *changelists,
+ svn_client_status_func_t shelved_func,
+ void *shelved_baton,
+ svn_client_status_func_t not_shelved_func,
+ void *not_shelved_baton,
const char *wc_root_abspath,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
@@ -1086,7 +1131,10 @@ shelf_write_changes(svn_boolean_t *any_s
wb.shelf_version = shelf_version;
wb.ctx = ctx;
wb.any_shelved = FALSE;
- wb.unshelvable = apr_array_make(result_pool, 0, sizeof(char *));
+ wb.was_shelved_func = shelved_func;
+ wb.was_shelved_baton = shelved_baton;
+ wb.was_not_shelved_func = not_shelved_func;
+ wb.was_not_shelved_baton = not_shelved_baton;
wb.pool = result_pool;
/* Walk the WC */
@@ -1095,7 +1143,6 @@ shelf_write_changes(svn_boolean_t *any_s
ctx, scratch_pool));
*any_shelved = wb.any_shelved;
- *unshelvable = wb.unshelvable;
return SVN_NO_ERROR;
}
@@ -1682,35 +1729,31 @@ svn_client_shelf_export_patch(svn_client
}
svn_error_t *
-svn_client_shelf_save_new_version2(svn_client_shelf_version_t **new_version_p,
+svn_client_shelf_save_new_version3(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,
+ svn_client_status_func_t shelved_func,
+ void *shelved_baton,
+ svn_client_status_func_t not_shelved_func,
+ void *not_shelved_baton,
apr_pool_t *scratch_pool)
{
int next_version = shelf->max_version + 1;
svn_client_shelf_version_t *new_shelf_version;
svn_boolean_t any_shelved;
- apr_array_header_t *unshelvable;
SVN_ERR(shelf_version_create(&new_shelf_version,
shelf, next_version, scratch_pool));
- SVN_ERR(shelf_write_changes(&any_shelved, &unshelvable,
+ SVN_ERR(shelf_write_changes(&any_shelved,
new_shelf_version,
paths, depth, changelists,
+ shelved_func, shelved_baton,
+ not_shelved_func, not_shelved_baton,
shelf->wc_root_abspath,
shelf->ctx, scratch_pool, scratch_pool));
- if (unshelvable->nelts > 0)
- {
- return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
- Q_("%d path could not be shelved",
- "%d paths could not be shelved",
- unshelvable->nelts),
- unshelvable->nelts);
- }
-
if (any_shelved)
{
shelf->max_version = next_version;
@@ -1728,6 +1771,66 @@ svn_client_shelf_save_new_version2(svn_c
return SVN_NO_ERROR;
}
+/* A compatibility callback for counting not-shelved paths. */
+static svn_error_t *
+was_not_shelved(void *baton,
+ const char *path,
+ const svn_client_status_t *status,
+ apr_pool_t *scratch_pool)
+{
+ int *num_paths_not_shelved = baton;
+
+ ++(*num_paths_not_shelved);
+ return SVN_NO_ERROR;
+}
+
+/* A compatibility wrapper. */
+static svn_error_t *
+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)
+{
+ svn_client_shelf_version_t *previous_version;
+ int num_paths_not_shelved = 0;
+
+ SVN_ERR(svn_client_shelf_get_newest_version(&previous_version, shelf,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_client_shelf_save_new_version3(new_version_p, shelf,
+ paths, depth, changelists,
+ NULL, NULL,
+ was_not_shelved, &num_paths_not_shelved,
+ scratch_pool));
+ if (num_paths_not_shelved)
+ {
+ SVN_ERR(svn_client_shelf_delete_newer_versions(shelf, previous_version,
+ scratch_pool));
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ Q_("%d path could not be shelved",
+ "%d paths could not be shelved",
+ num_paths_not_shelved),
+ num_paths_not_shelved);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+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)
+{
+ SVN_ERR(save_new_version2(new_version_p, shelf,
+ paths, depth, changelists,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_shelf_save_new_version(svn_client_shelf_t *shelf,
const apr_array_header_t *paths,
@@ -1735,9 +1838,9 @@ svn_client_shelf_save_new_version(svn_cl
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));
+ SVN_ERR(save_new_version2(NULL, shelf,
+ paths, depth, changelists,
+ scratch_pool));
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/svn/shelf-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/shelf-cmd.c?rev=1833135&r1=1833134&r2=1833135&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/shelf-cmd.c (original)
+++ subversion/trunk/subversion/svn/shelf-cmd.c Thu Jun 7 18:17:53 2018
@@ -331,45 +331,6 @@ name_of_youngest(const char **name_p,
return SVN_NO_ERROR;
}
-/*
- * PATHS are relative to WC_ROOT_ABSPATH.
- */
-static svn_error_t *
-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)
-{
- int i;
-
- for (i = 0; i < paths->nelts; i++)
- {
- const char *path = APR_ARRAY_IDX(paths, i, const char *);
- const char *abspath = svn_dirent_join(paths_base_abspath, path,
- 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));
- }
-
- return SVN_NO_ERROR;
-}
-
struct status_baton
{
/* These fields correspond to the ones in the
@@ -377,9 +338,9 @@ struct status_baton
const char *target_abspath;
const char *target_path;
- 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_boolean_t quiet; /* don't display statuses while shelving them */
+ int num_paths_shelved;
+ int num_paths_not_shelved;
svn_client_ctx_t *ctx;
};
@@ -388,7 +349,7 @@ static svn_error_t *
print_status(void *baton,
const char *path,
const svn_client_status_t *status,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
struct status_baton *sb = baton;
unsigned int conflicts;
@@ -402,37 +363,39 @@ print_status(void *baton,
FALSE /*repos_locks*/,
&conflicts, &conflicts, &conflicts,
sb->ctx,
- pool);
+ scratch_pool);
}
-/* Set BATON->modified to true if TARGET has any local modification or
- * any status that means we should not attempt to apply changes to it.
- *
- * A callback of type svn_client_status_func_t. */
+/* A callback function for shelved paths. */
static svn_error_t *
-modification_checker(void *baton,
- const char *target,
- const svn_client_status_t *status,
- apr_pool_t *scratch_pool)
+was_shelved(void *baton,
+ const char *path,
+ const svn_client_status_t *status,
+ apr_pool_t *scratch_pool)
{
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))
+ if (!sb->quiet)
{
- if (!sb->quiet)
- {
- if (!sb->modified) /* print the header only once */
- {
- SVN_ERR(svn_cmdline_printf(scratch_pool, "%s", sb->header));
- }
- SVN_ERR(print_status(baton, target, status, scratch_pool));
- }
-
- sb->modified = TRUE;
+ SVN_ERR(print_status(baton, path, status, scratch_pool));
}
+
+ ++sb->num_paths_shelved;
+ return SVN_NO_ERROR;
+}
+
+/* A callback function for not-shelved paths. */
+static svn_error_t *
+was_not_shelved(void *baton,
+ const char *path,
+ const svn_client_status_t *status,
+ apr_pool_t *scratch_pool)
+{
+ struct status_baton *sb = baton;
+
+ SVN_ERR(print_status(baton, path, status, scratch_pool));
+ SVN_ERR(svn_cmdline_printf(scratch_pool, " > not shelved\n"));
+ ++sb->num_paths_not_shelved;
return SVN_NO_ERROR;
}
@@ -466,7 +429,6 @@ shelve(int *new_version_p,
svn_client_shelf_t *shelf;
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,
@@ -485,37 +447,40 @@ shelve(int *new_version_p,
TRUE /*with_logmsg*/, scratch_pool));
}
- sb.header = (keep_local
- ? _("--- Modifications to save:\n")
- : _("--- Modifications to shelve:\n"));
+ sb.target_abspath = shelf->wc_root_abspath;
+ sb.target_path = "";
sb.quiet = quiet;
- sb.modified = FALSE;
+ sb.num_paths_shelved = 0;
+ sb.num_paths_not_shelved = 0;
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_version2(&new_version, shelf,
+ SVN_ERR(svn_client_shelf_save_new_version3(&new_version, shelf,
paths, depth, changelists,
+ was_shelved, &sb,
+ was_not_shelved, &sb,
scratch_pool));
- if (! new_version)
+ if (sb.num_paths_not_shelved > 0)
+ {
+ SVN_ERR(svn_client_shelf_delete_newer_versions(shelf, previous_version,
+ scratch_pool));
+ SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ Q_("%d path could not be shelved",
+ "%d paths could not be shelved",
+ sb.num_paths_not_shelved),
+ sb.num_paths_not_shelved);
+ }
+ if (sb.num_paths_shelved == 0
+ || ! new_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"));
+ keep_local ? _("No local modifications could be saved")
+ : _("No local modifications could be shelved"));
}
/* Un-apply the changes, if required. */