You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/08/27 17:23:00 UTC

svn commit: r990172 - in /subversion/trunk/subversion: libsvn_client/diff.c tests/cmdline/diff_tests.py

Author: stsp
Date: Fri Aug 27 15:22:59 2010
New Revision: 990172

URL: http://svn.apache.org/viewvc?rev=990172&view=rev
Log:
Make property diffs show git-style diff headers in git diff mode.

* subversion/tests/cmdline/diff_tests.py
  (diff_git_with_props, test_list): New test.

* subversion/libsvn_client/diff.c
  (print_git_diff_header): Needs forward declaration so it can be used in ...
  (display_prop_diffs): ... this function, without having to move it around.
   Add new arguments USE_GIT_DIFF_FORMAT, RA_SESSION, and WC_CTX, for use
   in git diff mode. In which, show git diff headers, with paths relative
   to the repository root.
  (diff_props_changed): Update caller.

Modified:
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/tests/cmdline/diff_tests.py

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=990172&r1=990171&r2=990172&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Fri Aug 27 15:22:59 2010
@@ -433,12 +433,32 @@ diff_label(const char *path,
   return label;
 }
 
-
-
+/* ### forward declaration */
+static svn_error_t *
+print_git_diff_header(svn_stream_t *os,
+                      const char **label1, const char **label2,
+                      svn_diff_operation_kind_t operation,
+                      const char *path,
+                      const char *path1,
+                      const char *path2,
+                      svn_revnum_t rev1,
+                      svn_revnum_t rev2,
+                      const char *copyfrom_path,
+                      const char *header_encoding,
+                      svn_ra_session_t *ra_session,
+                      svn_wc_context_t *wc_ctx,
+                      apr_pool_t *scratch_pool);
 
 /* A helper func that writes out verbal descriptions of property diffs
    to FILE.   Of course, the apr_file_t will probably be the 'outfile'
-   passed to svn_client_diff5, which is probably stdout. */
+   passed to svn_client_diff5, which is probably stdout.
+
+   ### FIXME needs proper docstring
+   
+   If USE_GIT_DIFF_FORMAT is TRUE, pring git diff headers, which always
+   show paths relative to the repository root. RA_SESSION and WC_CTX are
+   needed to normalize paths relative the repository root, and are ignored
+   if USE_GIT_DIFF_FORMAT is FALSE. */
 static svn_error_t *
 display_prop_diffs(const apr_array_header_t *propchanges,
                    apr_hash_t *original_props,
@@ -451,47 +471,83 @@ display_prop_diffs(const apr_array_heade
                    apr_file_t *file,
                    const char *relative_to_dir,
                    svn_boolean_t show_diff_header,
+                   svn_boolean_t use_git_diff_format,
+                   svn_ra_session_t *ra_session,
+                   svn_wc_context_t *wc_ctx,
                    apr_pool_t *pool)
 {
   int i;
+  const char *path1 = apr_pstrdup(pool, orig_path1);
+  const char *path2 = apr_pstrdup(pool, orig_path2);
 
   /* If we're creating a diff on the wc root, path would be empty. */
   if (path[0] == '\0')
     path = apr_psprintf(pool, ".");
 
-    if (show_diff_header)
-      {
-        const char *path1 = orig_path1;
-        const char *path2 = orig_path2;
-        const char *label1;
-        const char *label2;
-
-        SVN_ERR(adjust_paths_for_diff_labels(&path, &path1, &path2,
-                                             relative_to_dir, pool));
-
-        label1 = diff_label(path1, rev1, pool);
-        label2 = diff_label(path2, rev2, pool);
-
-        /* ### Should we show the paths in platform specific format,
-         * ### diff_content_changed() does not! */
-
-        SVN_ERR(file_printf_from_utf8 (file, encoding,
-                                       "Index: %s" APR_EOL_STR 
-                                       "%s" APR_EOL_STR, 
-                                       path,
-                                       equal_string));
-
-        SVN_ERR(file_printf_from_utf8(file, encoding,
-                                            "--- %s" APR_EOL_STR
-                                            "+++ %s" APR_EOL_STR,
-                                            label1,
-                                            label2));
-      }
+  if (show_diff_header)
+    SVN_ERR(adjust_paths_for_diff_labels(&path, &path1, &path2,
+                                         relative_to_dir, pool));
+
+  if (use_git_diff_format)
+    {
+      SVN_ERR(adjust_relative_to_repos_root(&path1, path, orig_path1,
+                                            ra_session, wc_ctx,
+                                            svn_path_is_url(path1) &&
+                                              svn_path_is_url(path2),
+                                            pool));
+      SVN_ERR(adjust_relative_to_repos_root(&path2, path, orig_path2,
+                                            ra_session, wc_ctx,
+                                            svn_path_is_url(path1) &&
+                                              svn_path_is_url(path2),
+                                            pool));
+    }
+
+  if (show_diff_header)
+    {
+      const char *label1;
+      const char *label2;
+      const char *adjusted_path1 = apr_pstrdup(pool, path1);
+      const char *adjusted_path2 = apr_pstrdup(pool, path2);
+
+      SVN_ERR(adjust_paths_for_diff_labels(&path, &adjusted_path1,
+                                           &adjusted_path2,
+                                           relative_to_dir, pool));
+
+      label1 = diff_label(adjusted_path1, rev1, pool);
+      label2 = diff_label(adjusted_path2, rev2, pool);
+
+      /* ### Should we show the paths in platform specific format,
+       * ### diff_content_changed() does not! */
+
+      SVN_ERR(file_printf_from_utf8(file, encoding,
+                                    "Index: %s" APR_EOL_STR 
+                                    "%s" APR_EOL_STR, 
+                                    path, equal_string));
+
+      if (use_git_diff_format)
+        {
+          svn_stream_t *os;
+
+          os = svn_stream_from_aprfile2(file, TRUE, pool);
+          SVN_ERR(print_git_diff_header(os, &label1, &label2,
+                                        svn_diff_op_modified, path,
+                                        orig_path1, orig_path2,
+                                        rev1, rev2, NULL,
+                                        encoding, ra_session, wc_ctx, pool));
+          SVN_ERR(svn_stream_close(os));
+        }
+
+      SVN_ERR(file_printf_from_utf8(file, encoding,
+                                          "--- %s" APR_EOL_STR
+                                          "+++ %s" APR_EOL_STR,
+                                          label1,
+                                          label2));
+    }
 
   SVN_ERR(file_printf_from_utf8(file, encoding,
                                 _("%sProperty changes on: %s%s"),
                                 APR_EOL_STR,
-                                path,
+                                use_git_diff_format ? path1 : path,
                                 APR_EOL_STR));
 
   SVN_ERR(file_printf_from_utf8(file, encoding, "%s" APR_EOL_STR,
@@ -861,6 +917,9 @@ diff_props_changed(const char *local_dir
                                  diff_cmd_baton->outfile,
                                  diff_cmd_baton->relative_to_dir,
                                  show_diff_header,
+                                 diff_cmd_baton->use_git_diff_format,
+                                 diff_cmd_baton->ra_session,
+                                 diff_cmd_baton->wc_ctx,
                                  subpool));
 
       /* We've printed the diff header so now we can mark the path as

Modified: subversion/trunk/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/diff_tests.py?rev=990172&r1=990171&r2=990172&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/diff_tests.py Fri Aug 27 15:22:59 2010
@@ -3645,7 +3645,53 @@ def diff_git_empty_files(sbox):
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', 
                                      '--git', wc_dir)
 
+def diff_git_with_props(sbox):
+  "create a diff in git format showing prop changes"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  iota_path = os.path.join(wc_dir, 'iota')
+  new_path = os.path.join(wc_dir, 'new')
+  svntest.main.file_write(iota_path, "")
+
+  # Now commit the local mod, creating rev 2.
+  expected_output = svntest.wc.State(wc_dir, {
+    'iota' : Item(verb='Sending'),
+    })
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'iota' : Item(status='  ', wc_rev=2),
+    })
+
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  svntest.main.file_write(new_path, "")
+  svntest.main.run_svn(None, 'add', new_path)
+  svntest.main.run_svn(None, 'propset', 'svn:eol-style', 'native', new_path)
+  svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Id', iota_path)
+
+  expected_output = make_git_diff_header(new_path, "new", "revision 0", 
+                                         "working copy", 
+                                         add=True, text_changes=False) + [
+      "\n",
+      "Property changes on: new\n",
+      "___________________________________________________________________\n",
+      "Added: svn:eol-style\n",
+      "## -0,0 +1 ##\n",
+      "+native\n",
+  ] + make_git_diff_header(iota_path, "iota", "revision 1", "working copy", 
+                           text_changes=False) + [
+      "\n",
+      "Property changes on: iota\n",
+      "___________________________________________________________________\n",
+      "Added: svn:keywords\n",
+      "## -0,0 +1 ##\n",
+      "+Id\n",
+  ]
 
+  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', 
+                                     '--git', wc_dir)
 ########################################################################
 #Run the tests
 
@@ -3708,6 +3754,7 @@ test_list = [ None,
               diff_prop_missing_context,
               diff_prop_multiple_hunks,
               diff_git_empty_files,
+              diff_git_with_props,
               ]
 
 if __name__ == '__main__':