Author: julianfoad
Date: Thu Oct 6 09:12:57 2011
New Revision: 1179544
URL: http://svn.apache.org/viewvc?rev=1179544&view=rev
Log:
On the 'showing-merge-info' branch: introduce a more focusses API for
getting merge info; improve the 'target_t' API; tweaks to the output.
*** Experimental work, in flux, not for in-depth review, not intended to be
merged to trunk in its current state. ***
* subversion/include/svn_client.h,
subversion/libsvn_client/url.c
(svn_client__target): Take a 'peg_revision' parameter.
(svn_client__parse_target): New function.
* subversion/include/svn_client.h
(svn_client_merged_rev_t, svn_mergeinfo_receiver_t): New types.
(svn_client_mergeinfo_log2): New revision of svn_client_mergeinfo_log().
* subversion/libsvn_client/mergeinfo.c
(baton, mergeinfo_log_receiver): New type and function.
(svn_client_mergeinfo_log2): Implement.
* subversion/svn/mergeinfo-cmd.c
(has_merge_prop_change): Delete.
(print_log_rev_baton_t): New struct.
(print_log_rev): Stop and print "..." after 5 lines. Simplify by using the
new and revised APIs above.
(target_for_display): Tweak output.
(find_source_branch, svn_cl__mergeinfo): Simplify by using the new and
revised APIs above.
Modified:
subversion/branches/showing-merge-info/subversion/include/svn_client.h
subversion/branches/showing-merge-info/subversion/libsvn_client/mergeinfo.c
subversion/branches/showing-merge-info/subversion/libsvn_client/url.c
subversion/branches/showing-merge-info/subversion/svn/mergeinfo-cmd.c
Modified: subversion/branches/showing-merge-info/subversion/include/svn_client.h
URL:
http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/svn_client.h?rev=1179544&r1=1179543&r2=1179544&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/svn_client.h
(original)
+++ subversion/branches/showing-merge-info/subversion/include/svn_client.h Thu
Oct 6 09:12:57 2011
@@ -1033,8 +1033,15 @@ typedef struct svn_client_target_t
svn_error_t *
svn_client__target(svn_client_target_t **target,
const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
apr_pool_t *pool);
+/* Like svn_opt_parse_path(). */
+svn_error_t *
+svn_client__parse_target(svn_client_target_t **target,
+ const char *target_string,
+ apr_pool_t *pool);
+
/* */
svn_error_t *
svn_client__resolve_location(const char **repo_root_url_p,
@@ -3604,6 +3611,21 @@ svn_client_mergeinfo_get_merged(apr_hash
apr_pool_t *pool);
+/* */
+typedef struct svn_client_merged_rev_t
+{
+ svn_revnum_t revnum;
+ svn_boolean_t is_merge;
+ svn_boolean_t content_modified;
+ const char *misc;
+} svn_client_merged_rev_t;
+
+/* */
+typedef svn_error_t *
+ svn_mergeinfo_receiver_t(const svn_client_merged_rev_t *merged,
+ void *baton,
+ apr_pool_t *pool);
+
/**
* If @a finding_merged is TRUE, then drive log entry callbacks
* @a receiver / @a receiver_baton with the revisions merged from
@@ -3619,15 +3641,30 @@ svn_client_mergeinfo_get_merged(apr_hash
* If a depth other than #svn_depth_empty or #svn_depth_infinity is
* requested then return a #SVN_ERR_UNSUPPORTED_FEATURE error.
*
- * @a discover_changed_paths and @a revprops are the same as for
- * svn_client_log5(). Use @a scratch_pool for all temporary allocations.
+ * @a revprops is the same as for svn_client_log5().
*
+ * Use @a scratch_pool for all temporary allocations.
+ *
* @a ctx is a context used for authentication.
*
* If the server doesn't support retrieval of mergeinfo, return an
* #SVN_ERR_UNSUPPORTED_FEATURE error.
*
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
+ svn_client_target_t *target,
+ svn_client_target_t *source,
+ svn_mergeinfo_receiver_t receiver,
+ void *receiver_baton,
+ const apr_array_header_t *revprops,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool);
+
+/*
* @since New in 1.7.
+ * @deprecated Provided for backwards compatibility with the 1.6 API.
*/
svn_error_t *
svn_client_mergeinfo_log(svn_boolean_t finding_merged,
Modified:
subversion/branches/showing-merge-info/subversion/libsvn_client/mergeinfo.c
URL:
http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/mergeinfo.c?rev=1179544&r1=1179543&r2=1179544&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/mergeinfo.c
(original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/mergeinfo.c
Thu Oct 6 09:12:57 2011
@@ -2155,6 +2155,74 @@ svn_client_mergeinfo_log(svn_boolean_t f
return SVN_NO_ERROR;
}
+struct baton
+{
+ svn_mergeinfo_receiver_t *receiver_func;
+ void *receiver_baton;
+};
+
+static svn_error_t *
+mergeinfo_log_receiver(void *baton,
+ svn_log_entry_t *log_entry,
+ apr_pool_t *pool)
+{
+ struct baton *b = baton;
+ svn_client_merged_rev_t info = { log_entry->revision, FALSE, FALSE, NULL };
+
+ /* Identify this source-rev as "original change" or "no-op" or "a merge" */
+ /* ### Fake: say it's a merge if log msg contains "erge". */
+ {
+ const svn_string_t *log = apr_hash_get(log_entry->revprops, "svn:log",
+ APR_HASH_KEY_STRING);
+
+ info.is_merge = strstr(log->data, "erge") != NULL;
+ }
+ /* ### Fake: say it's operative if (rev % 10 != 0). */
+ info.content_modified = (log_entry->revision % 10 != 0);
+
+ info.misc = apr_psprintf(pool, "%s%s%s",
+ log_entry->non_inheritable ? "*" : " ",
+ log_entry->subtractive_merge ? " (reverse)" : "",
+ log_entry->has_children ? " (has children)" : "");
+
+ b->receiver_func(&info, b->receiver_baton, pool);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
+ svn_client_target_t *target,
+ svn_client_target_t *source,
+ svn_mergeinfo_receiver_t receiver,
+ void *receiver_baton,
+ const apr_array_header_t *revprops,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ struct baton b;
+
+ b.receiver_func = receiver;
+ b.receiver_baton = receiver_baton;
+
+ /* ### Request 'svn:log' revprop in order to discover whether it's a
+ merge by scanning the text for "erge". */
+ if (revprops)
+ {
+ apr_array_header_t *revprops2 = apr_array_copy(scratch_pool, revprops);
+ APR_ARRAY_PUSH(revprops2, const char *) = "svn:log";
+ revprops = revprops2;
+ }
+
+ SVN_ERR(svn_client_mergeinfo_log(finding_merged,
+ target->path_or_url, &target->peg_revision,
+ source->path_or_url, &source->peg_revision,
+ mergeinfo_log_receiver, &b,
+ FALSE /* discover_changed_paths */,
+ svn_depth_infinity, revprops,
+ ctx, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_suggest_merge_sources(apr_array_header_t **suggestions,
const char *path_or_url,
Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/url.c
URL:
http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/url.c?rev=1179544&r1=1179543&r2=1179544&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/url.c
(original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/url.c Thu
Oct 6 09:12:57 2011
@@ -81,6 +81,7 @@ svn_client_root_url_from_path(const char
svn_error_t *
svn_client__target(svn_client_target_t **target_p,
const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
apr_pool_t *pool)
{
*target_p = apr_pcalloc(pool, sizeof(**target_p));
@@ -92,6 +93,21 @@ svn_client__target(svn_client_target_t *
else
svn_error_clear(svn_dirent_get_absolute(&(*target_p)->abspath_or_url,
path_or_url, pool));
+ (*target_p)->peg_revision = *peg_revision;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__parse_target(svn_client_target_t **target,
+ const char *target_string,
+ apr_pool_t *pool)
+{
+ svn_opt_revision_t peg_revision;
+ const char *path_or_url;
+
+ SVN_ERR(svn_opt_parse_path(&peg_revision, &path_or_url, target_string,
+ pool));
+ SVN_ERR(svn_client__target(target, path_or_url, &peg_revision, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/showing-merge-info/subversion/svn/mergeinfo-cmd.c
URL:
http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/mergeinfo-cmd.c?rev=1179544&r1=1179543&r2=1179544&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/mergeinfo-cmd.c
(original)
+++ subversion/branches/showing-merge-info/subversion/svn/mergeinfo-cmd.c Thu
Oct 6 09:12:57 2011
@@ -43,67 +43,45 @@
/*** Code. ***/
-/* Set *CONTENT_MODIFIED if so, else set *MERGEINFO_CHANGED if so, else set
- * both to FALSE. */
-static svn_error_t *
-has_merge_prop_change(svn_boolean_t *content_modified,
- svn_boolean_t *mergeinfo_changed,
- apr_hash_t *changed_paths,
- apr_pool_t *pool)
-{
- apr_hash_index_t *hi;
-
- *content_modified = FALSE;
- *mergeinfo_changed = FALSE;
-
- for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi))
- {
- const char *path = svn__apr_hash_index_key(hi);
- svn_log_changed_path2_t *cp = svn__apr_hash_index_val(hi);
-
- SVN_DBG(("%c %s%s %c %s\n", cp->action,
svn_tristate__to_word(cp->text_modified),
svn_tristate__to_word(cp->props_modified), cp->node_kind == svn_node_dir ? 'D'
: 'f', path));
- if (cp->action == 'A' || cp->action == 'D'
- || cp->text_modified == svn_tristate_true)
- {
- *content_modified = TRUE;
- return SVN_NO_ERROR;
- }
- }
- return SVN_NO_ERROR;
-}
+struct print_log_rev_baton_t
+{
+ int count;
+};
-/* Implements the svn_log_entry_receiver_t interface. */
+/* Implements the svn_mergeinfo_receiver_t interface. */
static svn_error_t *
-print_log_rev(void *baton,
- svn_log_entry_t *log_entry,
+print_log_rev(const svn_client_merged_rev_t *info,
+ void *baton,
apr_pool_t *pool)
{
- svn_boolean_t content_modified;
- svn_boolean_t mergeinfo_changed;
+ struct print_log_rev_baton_t *b = baton;
const char *kind;
- /* Identify this source-rev as "original change" or "no-op" or "a merge" */
- SVN_ERR(has_merge_prop_change(&content_modified, &mergeinfo_changed,
- log_entry->changed_paths2, pool));
- if (content_modified)
+ /* Don't print too much unless the user wants a verbose listing */
+ if (++b->count >= 5)
{
- kind = "operative (at least on some paths)";
+ if (b->count == 5)
+ SVN_ERR(svn_cmdline_printf(pool, " ...\n"));
+ return SVN_NO_ERROR;
}
- else if (mergeinfo_changed)
+
+ /* Identify this source-rev as "original change" or "no-op" or "a merge" */
+ if (info->is_merge)
{
kind = "merge";
}
+ else if (info->content_modified)
+ {
+ kind = "operative (at least on some paths)";
+ }
else
{
/* ### No-op revs aren't currently sent to this callback function at
* all, but later we may use this function on such revs. */
kind = "no-op";
}
- SVN_ERR(svn_cmdline_printf(pool, "r%ld%s%s%s -- %s\n", log_entry->revision,
- log_entry->non_inheritable ? "*" : " ",
- log_entry->subtractive_merge ? " (reverse)" : "",
- log_entry->has_children ? " (has children)" : "",
- kind));
+ SVN_ERR(svn_cmdline_printf(pool, " r%ld -- %s %s\n", info->revnum,
+ kind, info->misc));
return SVN_NO_ERROR;
}
@@ -129,8 +107,8 @@ target_for_display(const svn_client_targ
if (target->revision.kind == svn_opt_revision_base)
{
SVN_ERR_ASSERT_NO_RETURN(target->peg_revision.kind ==
svn_opt_revision_base);
- return apr_psprintf(pool, "^/%s (wc base = r%ld)",
- target->repos_relpath, target->repos_revnum);
+ return apr_psprintf(pool, "^/%s (wc base)",
+ target->repos_relpath);
}
return apr_psprintf(pool, "^/%s (r%ld)",
target->repos_relpath, target->repos_revnum);
@@ -155,6 +133,7 @@ find_source_branch(svn_client_target_t *
{
apr_array_header_t *suggestions;
const char *copyfrom_url;
+ svn_opt_revision_t peg_revision = { svn_opt_revision_number, { 1170000 } };
/* This isn't properly doc'd, but the first result it gives is the
* copyfrom source URL. */
@@ -164,9 +143,7 @@ find_source_branch(svn_client_target_t *
ctx, pool));
copyfrom_url = APR_ARRAY_IDX(suggestions, 0, const char *);
- SVN_ERR(svn_client__target(source_p, copyfrom_url, pool));
- (*source_p)->peg_revision.kind = svn_opt_revision_number;
- (*source_p)->peg_revision.value.number = 1170000;
+ SVN_ERR(svn_client__target(source_p, copyfrom_url, &peg_revision, pool));
(*source_p)->revision.kind = svn_opt_revision_unspecified;
return SVN_NO_ERROR;
@@ -187,6 +164,7 @@ svn_cl__mergeinfo(apr_getopt_t *os,
/* Default to depth empty. */
svn_depth_t depth = opt_state->depth == svn_depth_unknown
? svn_depth_infinity : opt_state->depth;
+ struct print_log_rev_baton_t log_rev_baton;
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -199,16 +177,16 @@ svn_cl__mergeinfo(apr_getopt_t *os,
/* Locate the target branch: the second argument or this dir. */
if (targets->nelts == 2)
{
- SVN_ERR(svn_client__target(&target, "", pool));
- SVN_ERR(svn_opt_parse_path(&target->peg_revision, &target->path_or_url,
- APR_ARRAY_IDX(targets, 1, const char *),
- pool));
+ SVN_ERR(svn_client__parse_target(&target,
+ APR_ARRAY_IDX(targets, 1, const char *),
+ pool));
target->revision.kind = svn_opt_revision_unspecified;
}
else
{
- SVN_ERR(svn_client__target(&target, "", pool));
- target->peg_revision.kind = svn_opt_revision_working;
+ svn_opt_revision_t peg_revision = { svn_opt_revision_working, { 0 } };
+
+ SVN_ERR(svn_client__target(&target, "", &peg_revision, pool));
target->revision.kind = svn_opt_revision_working;
}
@@ -217,13 +195,9 @@ svn_cl__mergeinfo(apr_getopt_t *os,
/* Locate the source branch: the first argument or automatic. */
if (targets->nelts >= 1)
{
- const char *path_or_url;
- svn_opt_revision_t peg_revision;
-
- SVN_ERR(svn_opt_parse_path(&peg_revision, &path_or_url,
- APR_ARRAY_IDX(targets, 0, const char *),
pool));
- SVN_ERR(svn_client__target(&source, path_or_url, pool));
- source->peg_revision = peg_revision;
+ SVN_ERR(svn_client__parse_target(&source,
+ APR_ARRAY_IDX(targets, 0, const char *),
+ pool));
source->revision.kind = svn_opt_revision_unspecified;
/* If no peg-rev was attached to the source URL, assume HEAD. */
@@ -268,24 +242,18 @@ svn_cl__mergeinfo(apr_getopt_t *os,
}
printf(_("Merged revisions:\n"));
- SVN_ERR(svn_client_mergeinfo_log(TRUE /* finding_merged */,
- target->path_or_url,
- &target->peg_revision,
- source->path_or_url,
- &source->peg_revision,
- print_log_rev, NULL,
- TRUE, depth, NULL, ctx,
- pool));
+ log_rev_baton.count = 0;
+ SVN_ERR(svn_client_mergeinfo_log2(TRUE /* finding_merged */,
+ target, source,
+ print_log_rev, &log_rev_baton,
+ NULL, ctx, pool));
printf(_("Eligible revisions:\n"));
- SVN_ERR(svn_client_mergeinfo_log(FALSE /* finding_merged */,
- target->path_or_url,
- &target->peg_revision,
- source->path_or_url,
- &source->peg_revision,
- print_log_rev, NULL,
- TRUE, depth, NULL, ctx,
- pool));
+ log_rev_baton.count = 0;
+ SVN_ERR(svn_client_mergeinfo_log2(FALSE /* finding_merged */,
+ target, source,
+ print_log_rev, &log_rev_baton,
+ NULL, ctx, pool));
return SVN_NO_ERROR;
}