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


Reply via email to