Make 'svn commit --changelist mychange' work.
At the moment, the changelist associations are removed from entries
during post-commit processing. In a followup change, we'll add a new
option to 'commit' which retains the changelist definition after a
commit.
Note: somehow this change is failing lock_tests.py. I'm
investigating, and will commit a fix soon.
* subversion/include/client.h
(svn_client_commit4): add a 'changelist' argument, rev function to v4.
(svn_client_commit3): deprecate.
* subversion/include/svn_wc.h
(svn_wc_process_committed3): update docstring to describe
changelist interaction.
* subversion/libsvn_wc/log.c, log.h
(SVN_WC__LOG_DELETE_CHANGELIST): new xml command for logfiles.
(log_do_delete_changelist): new utility function for log execution.
(start_handler): process the new xml command.
(svn_wc__loggy_delete_changelist): new function to tweak entry.
* subversion/libsvn_wc/adm_ops.c
(svn_wc_process_committed3): remove any changelist association when
doing post-commit processing on an entry.
* subversion/libsvn_client/client.h
(svn_client__harvest_committables): take a 'changelist_name' arg.
* subversion/libsvn_client/commit_util.c
(harvest_committables): take a 'changelist_name' arg, use it as a filter.
(svn_client_harvest_committables): take a 'changelist_name' arg,
pass it to static func.
(svn_client__get_copy_committables): update caller to pass NULL
changelist_name.
* subversion/libsvn_client/commit.c
(svn_client_commit4): take a 'changelist_name' arg and pass it on.
(svn_client_commit3): become a wrapper around svn_client_commit4().
* subversion/svn/commit-cmd.c
(svn_cl__commit): invoke svn_client_commit4(), not 3.
* subversion/svn/main.c
(svn_cl__cmd_table): allow 'svn commit' to take --changelist option.
* subversion/tests/cmdline/getopt_tests_data/svn_help_stdout, svn--help_stdout
Fix expected output of 'svn help' to show changelist command.
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/changelist-feature@860372 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subversion/include/svn_client.h b/subversion/include/svn_client.h
index abf316c..c7d99f5 100644
--- a/subversion/include/svn_client.h
+++ b/subversion/include/svn_client.h
@@ -1068,6 +1068,10 @@
*
* Unlock paths in the repository, unless @a keep_locks is true.
*
+ * If @a changelist_name is non-NULL, then use it as a restrictive filter
+ * on items that are committed; that is, don't commit anything unless
+ * it's a member of changelist @a changelist_name.
+ *
* Use @a pool for any temporary allocations.
*
* If no error is returned and @a (*commit_info_p)->revision is set to
@@ -1077,6 +1081,22 @@
* @since New in 1.3.
*/
svn_error_t *
+svn_client_commit4(svn_commit_info_t **commit_info_p,
+ const apr_array_header_t *targets,
+ svn_boolean_t recurse,
+ svn_boolean_t keep_locks,
+ const char *changelist_name,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
+
+/** Similar to svn_client_commit4(), but always passes NULL @a
+ * changelist_name.
+ *
+ * @deprecated Provided for backward compatibility with the 1.3 API.
+ *
+ * @since New in 1.3.
+ */
+svn_error_t *
svn_client_commit3(svn_commit_info_t **commit_info_p,
const apr_array_header_t *targets,
svn_boolean_t recurse,
diff --git a/subversion/include/svn_wc.h b/subversion/include/svn_wc.h
index 2bfa204..9397663 100644
--- a/subversion/include/svn_wc.h
+++ b/subversion/include/svn_wc.h
@@ -2292,6 +2292,8 @@
* If @a remove_lock is @c TRUE, any entryprops related to a repository
* lock will be removed.
*
+ * If @a path is a member of a changelist, remove that association.
+ *
* If @a path is a file and @a digest is non-null, use @a digest as
* the checksum for the new text base. Else, calculate the checksum
* if needed.
diff --git a/subversion/libsvn_client/client.h b/subversion/libsvn_client/client.h
index d5ecccf..ecf7ac2 100644
--- a/subversion/libsvn_client/client.h
+++ b/subversion/libsvn_client/client.h
@@ -534,9 +534,9 @@
canonical repository URLs. LOCK_TOKENS will point to a hash table
with const char * lock tokens, keyed on const char * URLs. Also,
LOCKED_DIRS will be an apr_hash_t * hash of svn_wc_adm_access_t *
- keyed
- on const char * working copy path directory names which were locked
- in the process of this crawl. These will need to be unlocked again post-commit.
+ keyed on const char * working copy path directory names which were
+ locked in the process of this crawl. These will need to be
+ unlocked again post-commit.
If NONRECURSIVE is specified, subdirectories of directory targets
found in TARGETS will not be crawled for modifications.
@@ -544,6 +544,10 @@
If JUST_LOCKED is TRUE, treat unmodified items with lock tokens as
commit candidates.
+ If CHANGELIST_NAME is non-NULL, then use it as a restrictive filter
+ when harvesting committables; that is, don't add a path to
+ COMMITTABLES unless it's a member of the changelist.
+
If CTX->CANCEL_FUNC is non-null, it will be called with
CTX->CANCEL_BATON while harvesting to determine if the client has
cancelled the operation. */
@@ -554,6 +558,7 @@
apr_array_header_t *targets,
svn_boolean_t nonrecursive,
svn_boolean_t just_locked,
+ const char *changelist_name,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
diff --git a/subversion/libsvn_client/commit.c b/subversion/libsvn_client/commit.c
index 854d214..4805938 100644
--- a/subversion/libsvn_client/commit.c
+++ b/subversion/libsvn_client/commit.c
@@ -1170,10 +1170,11 @@
svn_error_t *
-svn_client_commit3(svn_commit_info_t **commit_info_p,
+svn_client_commit4(svn_commit_info_t **commit_info_p,
const apr_array_header_t *targets,
svn_boolean_t recurse,
svn_boolean_t keep_locks,
+ const char *changelist_name,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -1430,6 +1431,7 @@
rel_targets,
recurse ? FALSE : TRUE,
! keep_locks,
+ changelist_name,
ctx,
pool)))
goto cleanup;
@@ -1638,6 +1640,18 @@
}
svn_error_t *
+svn_client_commit3(svn_commit_info_t **commit_info_p,
+ const apr_array_header_t *targets,
+ svn_boolean_t recurse,
+ svn_boolean_t keep_locks,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ return svn_client_commit4(commit_info_p, targets, recurse, keep_locks,
+ NULL, ctx, pool);
+}
+
+svn_error_t *
svn_client_commit2(svn_client_commit_info_t **commit_info_p,
const apr_array_header_t *targets,
svn_boolean_t recurse,
diff --git a/subversion/libsvn_client/commit_util.c b/subversion/libsvn_client/commit_util.c
index bd17caf..acee715 100644
--- a/subversion/libsvn_client/commit_util.c
+++ b/subversion/libsvn_client/commit_util.c
@@ -194,6 +194,10 @@
with history as URL, and add 'deleted' entries to COMMITTABLES as
items to delete in the copy destination.
+ If CHANGELIST_NAME is non-NULL, then use it as a restrictive filter
+ when harvesting committables; that is, don't add a path to
+ COMMITTABLES unless it's a member of the changelist.
+
If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to see
if the user has cancelled the operation. */
static svn_error_t *
@@ -209,6 +213,7 @@
svn_boolean_t copy_mode,
svn_boolean_t nonrecursive,
svn_boolean_t just_locked,
+ const char *changelist_name,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -478,16 +483,21 @@
/* Now, if this is something to commit, add it to our list. */
if (state_flags)
{
- /* Finally, add the committable item. */
- add_committable(committables, path, entry->kind, url,
- entry->revision,
- cf_url,
- cf_rev,
- state_flags);
- if (lock_tokens && entry->lock_token)
- apr_hash_set(lock_tokens, apr_pstrdup(token_pool, url),
- APR_HASH_KEY_STRING,
- apr_pstrdup(token_pool, entry->lock_token));
+ if ((changelist_name == NULL)
+ || (entry->changelist
+ && (strcmp(changelist_name, entry->changelist) == 0)))
+ {
+ /* Finally, add the committable item. */
+ add_committable(committables, path, entry->kind, url,
+ entry->revision,
+ cf_url,
+ cf_rev,
+ state_flags);
+ if (lock_tokens && entry->lock_token)
+ apr_hash_set(lock_tokens, apr_pstrdup(token_pool, url),
+ APR_HASH_KEY_STRING,
+ apr_pstrdup(token_pool, entry->lock_token));
+ }
}
/* For directories, recursively handle each of their entries (except
@@ -564,14 +574,20 @@
&& childkind == svn_node_none
&& this_entry->schedule == svn_wc_schedule_delete)
{
- add_committable(committables, full_path,
- this_entry->kind, used_url,
- SVN_INVALID_REVNUM,
- NULL,
- SVN_INVALID_REVNUM,
- SVN_CLIENT_COMMIT_ITEM_DELETE);
- svn_error_clear(lockerr);
- continue; /* don't recurse! */
+ if ((changelist_name == NULL)
+ || (entry->changelist
+ && (strcmp(changelist_name,
+ entry->changelist) == 0)))
+ {
+ add_committable(committables, full_path,
+ this_entry->kind, used_url,
+ SVN_INVALID_REVNUM,
+ NULL,
+ SVN_INVALID_REVNUM,
+ SVN_CLIENT_COMMIT_ITEM_DELETE);
+ svn_error_clear(lockerr);
+ continue; /* don't recurse! */
+ }
}
else
{
@@ -595,6 +611,7 @@
adds_only,
copy_mode,
FALSE, just_locked,
+ changelist_name,
ctx,
loop_pool));
}
@@ -622,6 +639,7 @@
apr_array_header_t *targets,
svn_boolean_t nonrecursive,
svn_boolean_t just_locked,
+ const char *changelist_name,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -750,10 +768,11 @@
? target
: svn_path_dirname(target, subpool)),
subpool));
- SVN_ERR(harvest_committables(*committables, *lock_tokens, target, dir_access,
- entry->url, NULL, entry, NULL, FALSE,
- FALSE, nonrecursive, just_locked, ctx,
- subpool));
+ SVN_ERR(harvest_committables(*committables, *lock_tokens, target,
+ dir_access, entry->url, NULL,
+ entry, NULL, FALSE, FALSE, nonrecursive,
+ just_locked, changelist_name,
+ ctx, subpool));
i++;
}
@@ -819,7 +838,8 @@
/* Handle our TARGET. */
SVN_ERR(harvest_committables(*committables, NULL, target,
adm_access, new_url, entry->url, entry, NULL,
- FALSE, TRUE, FALSE, FALSE, ctx, pool));
+ FALSE, TRUE, FALSE, FALSE,
+ NULL, ctx, pool));
return SVN_NO_ERROR;
}
diff --git a/subversion/libsvn_wc/adm_ops.c b/subversion/libsvn_wc/adm_ops.c
index 2638567..10b71d1 100644
--- a/subversion/libsvn_wc/adm_ops.c
+++ b/subversion/libsvn_wc/adm_ops.c
@@ -432,6 +432,11 @@
SVN_ERR(svn_wc__loggy_delete_lock(&logtags, adm_access,
base_name, pool));
+ /* Also, if the file was part of a changelist, being committed has
+ the effect of *removing* changelist membership. */
+ SVN_ERR(svn_wc__loggy_delete_changelist(&logtags, adm_access,
+ base_name, pool));
+
/* Regardless of whether it's a file or dir, the "main" logfile
contains a command to bump the revision attribute (and
timestamp). */
diff --git a/subversion/libsvn_wc/log.c b/subversion/libsvn_wc/log.c
index 13f3183..bc1d0e8 100644
--- a/subversion/libsvn_wc/log.c
+++ b/subversion/libsvn_wc/log.c
@@ -67,6 +67,9 @@
/* Delete lock related fields from the entry SVN_WC__LOG_ATTR_NAME. */
#define SVN_WC__LOG_DELETE_LOCK "delete-lock"
+/* Delete changelist field from the entry SVN_WC__LOG_ATTR_NAME. */
+#define SVN_WC__LOG_DELETE_CHANGELIST "delete-changelist"
+
/* Delete the entry SVN_WC__LOG_ATTR_NAME. */
#define SVN_WC__LOG_DELETE_ENTRY "delete-entry"
@@ -827,6 +830,29 @@
return SVN_NO_ERROR;
}
+static svn_error_t *
+log_do_delete_changelist(struct log_runner *loggy,
+ const char *name)
+{
+ svn_error_t *err;
+ svn_wc_entry_t entry;
+
+ entry.changelist = NULL;
+
+ /* Now write the new entry out */
+ err = svn_wc__entry_modify(loggy->adm_access, name,
+ &entry,
+ SVN_WC__ENTRY_MODIFY_CHANGELIST,
+ FALSE, loggy->pool);
+ if (err)
+ return svn_error_createf(pick_error_code(loggy), err,
+ _("Error removing changelist from entry '%s'"),
+ name);
+ loggy->entries_modified = TRUE;
+
+ return SVN_NO_ERROR;
+}
+
/* Ben sez: this log command is (at the moment) only executed by the
update editor. It attempts to forcefully remove working data. */
static svn_error_t *
@@ -1507,6 +1533,9 @@
else if (strcmp(eltname, SVN_WC__LOG_DELETE_LOCK) == 0) {
err = log_do_delete_lock(loggy, name);
}
+ else if (strcmp(eltname, SVN_WC__LOG_DELETE_CHANGELIST) == 0) {
+ err = log_do_delete_changelist(loggy, name);
+ }
else if (strcmp(eltname, SVN_WC__LOG_DELETE_ENTRY) == 0) {
err = log_do_delete_entry(loggy, name);
}
@@ -1944,6 +1973,21 @@
svn_error_t *
+svn_wc__loggy_delete_changelist(svn_stringbuf_t **log_accum,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool)
+{
+ svn_xml_make_open_tag(log_accum, pool, svn_xml_self_closing,
+ SVN_WC__LOG_DELETE_CHANGELIST,
+ SVN_WC__LOG_ATTR_NAME, path,
+ NULL);
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
svn_wc__loggy_entry_modify(svn_stringbuf_t **log_accum,
svn_wc_adm_access_t *adm_access,
const char *name,
diff --git a/subversion/libsvn_wc/log.h b/subversion/libsvn_wc/log.h
index 42329ce..58bd784 100644
--- a/subversion/libsvn_wc/log.h
+++ b/subversion/libsvn_wc/log.h
@@ -111,13 +111,20 @@
/* Extend **LOG_ACCUM with log instructions to delete lock related
fields from the entry belonging to PATH.
*/
-
svn_error_t *
svn_wc__loggy_delete_lock(svn_stringbuf_t **log_accum,
svn_wc_adm_access_t *adm_access,
const char *path,
apr_pool_t *pool);
+/* Extend **LOG_ACCUM with log instructions to delete changelist
+ from the entry belonging to PATH.
+*/
+svn_error_t *
+svn_wc__loggy_delete_changelist(svn_stringbuf_t **log_accum,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool);
/* Extend **LOG_ACCUM with commands to modify the entry associated with NAME
according to the flags specified in MODIFY_FLAGS, based on the values
diff --git a/subversion/svn/commit-cmd.c b/subversion/svn/commit-cmd.c
index d9db0e7..11c34ba 100644
--- a/subversion/svn/commit-cmd.c
+++ b/subversion/svn/commit-cmd.c
@@ -92,11 +92,12 @@
/* Commit. */
SVN_ERR(svn_cl__cleanup_log_msg
- (ctx->log_msg_baton2, svn_client_commit3(&commit_info,
+ (ctx->log_msg_baton2, svn_client_commit4(&commit_info,
targets,
opt_state->nonrecursive
? FALSE : TRUE,
no_unlock,
+ opt_state->changelist,
ctx,
pool)));
if (commit_info && ! opt_state->quiet)
diff --git a/subversion/svn/main.c b/subversion/svn/main.c
index 3176bcf..e64083b 100644
--- a/subversion/svn/main.c
+++ b/subversion/svn/main.c
@@ -270,7 +270,8 @@
" successful commit.\n"),
#endif
{'q', 'N', svn_cl__targets_opt, svn_cl__no_unlock_opt,
- SVN_CL__LOG_MSG_OPTIONS, SVN_CL__AUTH_OPTIONS, svn_cl__config_dir_opt} },
+ SVN_CL__LOG_MSG_OPTIONS, SVN_CL__AUTH_OPTIONS,
+ svn_cl__changelist_opt, svn_cl__config_dir_opt} },
{ "copy", svn_cl__copy, {"cp"}, N_
("Duplicate something in working copy or repository, remembering history.\n"
diff --git a/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout b/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout
index 9def574..e2ac3e9 100644
--- a/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout
+++ b/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout
@@ -10,6 +10,7 @@
add
blame (praise, annotate, ann)
cat
+ changelist (cl)
checkout (co)
cleanup
commit (ci)
diff --git a/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout b/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout
index 9def574..e2ac3e9 100644
--- a/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout
+++ b/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout
@@ -10,6 +10,7 @@
add
blame (praise, annotate, ann)
cat
+ changelist (cl)
checkout (co)
cleanup
commit (ci)