[PATCH] Extend 'svn diff URL URL' to 'svn diff URL URL [WC]'

Philip Martin <[email protected]> Thu, 03 Dec 2009 11:00:52 +0000
Newsgroups gmane.comp.version-control.subversion.devel,gmane.comp.version-control.subversion.rapidsvn.devel
Message-ID <[email protected]>
It's possible to compare branches in the repository using

$ svn diff ^/repo/branches/foo ^/repo/branches/bar

but that only works if the current directory is a working copy because
libsvn_client/cmdline.c:svn_client_args_to_target_array converts
relative URLs to full URLs using the hardcoded path "".  Since I
regularly have my current working directory outside a working copy
this is inconvenient.

I'd like to be able to do

$ svn diff ^/repo/branches/foo ^/repo/branches/bar path/to/wc

and it turns out to be quite simple from a code point of view.  It is,
of course, an extension to our rather complex diff UI.  What do people
think?


Add 'svn diff URL URL [WC]' as an extension to 'svn diff URL URL'.

* subversion/svn/diff-cmd.c:
  (svn_cl_diff): Recognise 'svn diff URL URL [WC]'.

* subversion/svn/main.c
  (svn_cl__cmd_table): Extend diff help text.

* subversion/include/svn_client.h
  (svn_client_args_to_target_array): Tweak doc string.

* subversion/libsvn_client/cmdline.c
  (svn_client_args_to_target_array): Convert relative urls using the first
    path given and only use "" if there are no paths.
  
Index: subversion/svn/diff-cmd.c
===================================================================
--- subversion/svn/diff-cmd.c	(revision 886136)
+++ subversion/svn/diff-cmd.c	(working copy)
@@ -196,13 +196,20 @@
                                                       ctx, pool));
 
   if (! opt_state->old_target && ! opt_state->new_target
-      && (targets->nelts == 2)
-      && svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *))
-      && svn_path_is_url(APR_ARRAY_IDX(targets, 1, const char *))
+      && ((targets->nelts == 2
+           && svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *))
+           && svn_path_is_url(APR_ARRAY_IDX(targets, 1, const char *)))
+          ||
+          (targets->nelts == 3
+           && svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *))
+           && svn_path_is_url(APR_ARRAY_IDX(targets, 1, const char *))
+           && !svn_path_is_url(APR_ARRAY_IDX(targets, 2, const char *))))
       && opt_state->start_revision.kind == svn_opt_revision_unspecified
       && opt_state->end_revision.kind == svn_opt_revision_unspecified)
     {
-      /* The 'svn diff OLD_URL[@OLDREV] NEW_URL[@NEWREV]' case matches. */
+      /* Either 'svn diff OLD_URL[@OLDREV] NEW_URL[@NEWREV]'
+         or     'svn diff OLD_URL[@OLDREV] NEW_URL[@NEWREV] wc'
+         matches. */
 
       SVN_ERR(svn_opt_parse_path(&opt_state->start_revision, &old_target,
                                  APR_ARRAY_IDX(targets, 0, const char *),
@@ -222,8 +229,8 @@
       apr_array_header_t *tmp, *tmp2;
       svn_opt_revision_t old_rev, new_rev;
 
-      /* The 'svn diff --old=OLD[@OLDREV] [--new=NEW[@NEWREV]]
-         [PATH...]' case matches. */
+      /* The 'svn diff --old=OLD[@OLDREV] [--new=NEW[@NEWREV]] [PATH...]'
+         case matches. */
 
       tmp = apr_array_make(pool, 2, sizeof(const char *));
       APR_ARRAY_PUSH(tmp, const char *) = (opt_state->old_target);
Index: subversion/svn/main.c
===================================================================
--- subversion/svn/main.c	(revision 886136)
+++ subversion/svn/main.c	(working copy)
@@ -473,7 +473,7 @@
      "usage: 1. diff [-c M | -r N[:M]] [TARGET[@REV]...]\n"
      "       2. diff [-r N[:M]] --old=OLD-TGT[@OLDREV] [--new=NEW-TGT[@NEWREV]] \\\n"
      "               [PATH...]\n"
-     "       3. diff OLD-URL[@OLDREV] NEW-URL[@NEWREV]\n"
+     "       3. diff OLD-URL[@OLDREV] NEW-URL[@NEWREV] [PATH]\n"
      "\n"
      "  1. Display the changes made to TARGETs as they are seen in REV between\n"
      "     two revisions.  TARGETs may be all working copy paths or all URLs.\n"
@@ -490,6 +490,8 @@
      "     to N, -r N:M makes OLDREV default to N and NEWREV default to M.\n"
      "\n"
      "  3. Shorthand for 'svn diff --old=OLD-URL[@OLDREV] --new=NEW-URL[@NEWREV]'\n"
+     "     Relative URLs are converted to full URLs using either PATH, if given,\n"
+     "     or the current directory.\n"
      "\n"
      "  Use just 'svn diff' to display local modifications in a working copy.\n"),
     {'r', 'c', opt_old_cmd, opt_new_cmd, 'N', opt_depth, opt_diff_cmd, 'x',
Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h	(revision 886136)
+++ subversion/include/svn_client.h	(working copy)
@@ -994,6 +994,8 @@
  * (which might come from, for example, the "--targets" command line option).
  *
  * On each URL target, do some IRI-to-URI encoding and some auto-escaping.
+ * Relative URLs are converted to full URLs using the first non-URL path,
+ * or the current directory if only URLs are supplied.
  * On each local path, canonicalize case and path separators.
  *
  * Allocate @a *targets_p and its elements in @a pool.
Index: subversion/libsvn_client/cmdline.c
===================================================================
--- subversion/libsvn_client/cmdline.c	(revision 886136)
+++ subversion/libsvn_client/cmdline.c	(working copy)
@@ -281,7 +281,21 @@
        * arguments.
        */
       if (root_url == NULL)
-        SVN_ERR(svn_client_root_url_from_path(&root_url, "", ctx, pool));
+        {
+          const char *path_for_root_url = "";
+          for (i = 0; i < output_targets->nelts; i++)
+            {
+              const char *target = APR_ARRAY_IDX(output_targets, i,
+                                                 const char *);
+              if (!arg_is_repos_relative_url(target))
+                {
+                  path_for_root_url = target;
+                  break;
+                }
+            }
+          SVN_ERR(svn_client_root_url_from_path(&root_url, path_for_root_url,
+                                                ctx, pool));
+        }
 
       *targets_p = apr_array_make(pool, output_targets->nelts,
                                   sizeof(const char *));
-- 
Philip

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2426641

Please start new threads on the <[email protected]> mailing list.
To subscribe to the new list, send an empty e-mail to <[email protected]>.