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 2011/10/11 21:52:46 UTC

svn commit: r1182053 [7/30] - in /subversion/branches/svn_mutex: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/hook-scripts/enforcer/ contrib/server-side/ notes/ notes/merge-tr...

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/diff.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/diff.c Tue Oct 11 19:52:34 2011
@@ -69,31 +69,6 @@ static const char under_string[] =
 
 /* Utilities */
 
-/* Wrapper for apr_file_printf(), which see.  FORMAT is a utf8-encoded
-   string after it is formatted, so this function can convert it to
-   ENCODING before printing. */
-static svn_error_t *
-file_printf_from_utf8(apr_file_t *fptr, const char *encoding,
-                      const char *format, ...)
-  __attribute__ ((format(printf, 3, 4)));
-static svn_error_t *
-file_printf_from_utf8(apr_file_t *fptr, const char *encoding,
-                      const char *format, ...)
-{
-  va_list ap;
-  const char *buf, *buf_apr;
-
-  va_start(ap, format);
-  buf = apr_pvsprintf(apr_file_pool_get(fptr), format, ap);
-  va_end(ap);
-
-  SVN_ERR(svn_utf_cstring_from_utf8_ex2(&buf_apr, buf, encoding,
-                                        apr_file_pool_get(fptr)));
-
-  return svn_io_file_write_full(fptr, buf_apr, strlen(buf_apr),
-                                NULL, apr_file_pool_get(fptr));
-}
-
 
 /* A helper function for display_prop_diffs.  Output the differences between
    the mergeinfo stored in ORIG_MERGEINFO_VAL and NEW_MERGEINFO_VAL in a
@@ -103,7 +78,7 @@ static svn_error_t *
 display_mergeinfo_diff(const char *old_mergeinfo_val,
                        const char *new_mergeinfo_val,
                        const char *encoding,
-                       apr_file_t *file,
+                       svn_stream_t *outstream,
                        apr_pool_t *pool)
 {
   apr_hash_t *old_mergeinfo_hash, *new_mergeinfo_hash, *added, *deleted;
@@ -132,10 +107,10 @@ display_mergeinfo_diff(const char *old_m
 
       SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray, pool));
 
-      SVN_ERR(file_printf_from_utf8(file, encoding,
-                                    _("   Reverse-merged %s:r%s%s"),
-                                    from_path, merge_revstr->data,
-                                    APR_EOL_STR));
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool,
+                                          _("   Reverse-merged %s:r%s%s"),
+                                          from_path, merge_revstr->data,
+                                          APR_EOL_STR));
     }
 
   for (hi = apr_hash_first(pool, added);
@@ -147,10 +122,10 @@ display_mergeinfo_diff(const char *old_m
 
       SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray, pool));
 
-      SVN_ERR(file_printf_from_utf8(file, encoding,
-                                    _("   Merged %s:r%s%s"),
-                                    from_path, merge_revstr->data,
-                                    APR_EOL_STR));
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool,
+                                          _("   Merged %s:r%s%s"),
+                                          from_path, merge_revstr->data,
+                                          APR_EOL_STR));
     }
 
   return SVN_NO_ERROR;
@@ -254,7 +229,7 @@ adjust_relative_to_repos_root(const char
   return SVN_NO_ERROR;
 }
 
-/* Adjust PATH, ORIG_PATH_1 and ORIG_PATH_2, representing the changed file
+/* Adjust *PATH, *ORIG_PATH_1 and *ORIG_PATH_2, representing the changed file
  * and the two original targets passed to the diff command, to handle the
  * case when we're dealing with different anchors. RELATIVE_TO_DIR is the
  * directory the diff target should be considered relative to. All
@@ -400,15 +375,22 @@ print_git_diff_header_deleted(svn_stream
  * OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */
 static svn_error_t *
 print_git_diff_header_copied(svn_stream_t *os, const char *header_encoding,
-                             const char *copyfrom_path, const char *path,
+                             const char *copyfrom_path,
+                             svn_revnum_t copyfrom_rev,
+                             const char *path,
                              apr_pool_t *result_pool)
 {
   SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
                                       "diff --git a/%s b/%s%s",
                                       copyfrom_path, path, APR_EOL_STR));
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
-                                      "copy from %s%s", copyfrom_path,
-                                      APR_EOL_STR));
+  if (copyfrom_rev != SVN_INVALID_REVNUM)
+    SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+                                        "copy from %s@%ld%s", copyfrom_path,
+                                        copyfrom_rev, APR_EOL_STR));
+  else
+    SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+                                        "copy from %s%s", copyfrom_path,
+                                        APR_EOL_STR));
   SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
                                       "copy to %s%s", path, APR_EOL_STR));
   return SVN_NO_ERROR;
@@ -450,11 +432,8 @@ print_git_diff_header_modified(svn_strea
  * HEADER_ENCODING. Return suitable diff labels for the git diff in *LABEL1
  * and *LABEL2. REPOS_RELPATH1 and REPOS_RELPATH2 are relative to reposroot.
  * are the paths passed to the original diff command. REV1 and REV2 are
- * revisions being diffed. COPYFROM_PATH indicates where the diffed item
- * was copied from. RA_SESSION and WC_CTX are used to adjust paths in the
- * headers to be relative to the repository root.
- * WC_ROOT_ABSPATH is the absolute path to the root directory of a working
- * copy involved in a repos-wc diff, and may be NULL.
+ * revisions being diffed. COPYFROM_PATH and COPYFROM_REV indicate where the
+ * diffed item was copied from.
  * Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
 print_git_diff_header(svn_stream_t *os,
@@ -465,10 +444,8 @@ print_git_diff_header(svn_stream_t *os,
                       svn_revnum_t rev1,
                       svn_revnum_t rev2,
                       const char *copyfrom_path,
+                      svn_revnum_t copyfrom_rev,
                       const char *header_encoding,
-                      svn_ra_session_t *ra_session,
-                      svn_wc_context_t *wc_ctx,
-                      const char *wc_root_abspath,
                       apr_pool_t *scratch_pool)
 {
   if (operation == svn_diff_op_deleted)
@@ -484,7 +461,8 @@ print_git_diff_header(svn_stream_t *os,
   else if (operation == svn_diff_op_copied)
     {
       SVN_ERR(print_git_diff_header_copied(os, header_encoding,
-                                           copyfrom_path, repos_relpath2,
+                                           copyfrom_path, copyfrom_rev,
+                                           repos_relpath2,
                                            scratch_pool));
       *label1 = diff_label(apr_psprintf(scratch_pool, "a/%s", copyfrom_path),
                            rev1, scratch_pool);
@@ -525,7 +503,7 @@ print_git_diff_header(svn_stream_t *os,
 }
 
 /* A helper func that writes out verbal descriptions of property diffs
-   to FILE.   Of course, the apr_file_t will probably be the 'outfile'
+   to FILE.   Of course, OUTSTREAM will probably be whatever was
    passed to svn_client_diff5, which is probably stdout.
 
    ### FIXME needs proper docstring
@@ -546,7 +524,7 @@ display_prop_diffs(const apr_array_heade
                    svn_revnum_t rev1,
                    svn_revnum_t rev2,
                    const char *encoding,
-                   apr_file_t *file,
+                   svn_stream_t *outstream,
                    const char *relative_to_dir,
                    svn_boolean_t show_diff_header,
                    svn_boolean_t use_git_diff_format,
@@ -556,8 +534,9 @@ display_prop_diffs(const apr_array_heade
                    apr_pool_t *pool)
 {
   int i;
-  const char *path1 = apr_pstrdup(pool, orig_path1);
-  const char *path2 = apr_pstrdup(pool, orig_path2);
+  const char *path1 = orig_path1;
+  const char *path2 = orig_path2;
+  apr_pool_t *iterpool;
 
   if (use_git_diff_format)
     {
@@ -579,8 +558,8 @@ display_prop_diffs(const apr_array_heade
     {
       const char *label1;
       const char *label2;
-      const char *adjusted_path1 = apr_pstrdup(pool, path1);
-      const char *adjusted_path2 = apr_pstrdup(pool, path2);
+      const char *adjusted_path1 = path1;
+      const char *adjusted_path2 = path2;
 
       SVN_ERR(adjust_paths_for_diff_labels(&path, &adjusted_path1,
                                            &adjusted_path2,
@@ -592,40 +571,35 @@ display_prop_diffs(const apr_array_heade
       /* ### 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(svn_stream_printf_from_utf8(outstream, encoding, pool,
+                                          "Index: %s" APR_EOL_STR
+                                          "%s" APR_EOL_STR,
+                                          path, equal_string));
 
       if (use_git_diff_format)
-        {
-          svn_stream_t *os;
+        SVN_ERR(print_git_diff_header(outstream, &label1, &label2,
+                                      svn_diff_op_modified,
+                                      path1, path2, rev1, rev2, NULL,
+                                      SVN_INVALID_REVNUM,
+                                      encoding, pool));
 
-          os = svn_stream_from_aprfile2(file, TRUE, pool);
-          SVN_ERR(print_git_diff_header(os, &label1, &label2,
-                                        svn_diff_op_modified,
-                                        path1, path2, rev1, rev2, NULL,
-                                        encoding, ra_session, wc_ctx,
-                                        wc_root_abspath, pool));
-          SVN_ERR(svn_stream_close(os));
-        }
-
-      SVN_ERR(file_printf_from_utf8(file, encoding,
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool,
                                           "--- %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,
-                                use_git_diff_format ? path1 : path,
-                                APR_EOL_STR));
+  SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool,
+                                      _("%sProperty changes on: %s%s"),
+                                      APR_EOL_STR,
+                                      use_git_diff_format ? path1 : path,
+                                      APR_EOL_STR));
 
-  SVN_ERR(file_printf_from_utf8(file, encoding, "%s" APR_EOL_STR,
-                                under_string));
+  SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool,
+                                      "%s" APR_EOL_STR, under_string));
 
+  iterpool = svn_pool_create(pool);
   for (i = 0; i < propchanges->nelts; i++)
     {
       const char *action;
@@ -646,21 +620,24 @@ display_prop_diffs(const apr_array_heade
               && svn_string_compare(original_value, propchange->value)))
         continue;
 
+      svn_pool_clear(iterpool);
+
       if (! original_value)
         action = "Added";
       else if (! propchange->value)
         action = "Deleted";
       else
         action = "Modified";
-      SVN_ERR(file_printf_from_utf8(file, encoding, "%s: %s%s", action,
-                                    propchange->name, APR_EOL_STR));
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          "%s: %s%s", action,
+                                          propchange->name, APR_EOL_STR));
 
       if (strcmp(propchange->name, SVN_PROP_MERGEINFO) == 0)
         {
           const char *orig = original_value ? original_value->data : NULL;
           const char *val = propchange->value ? propchange->value->data : NULL;
           svn_error_t *err = display_mergeinfo_diff(orig, val, encoding,
-                                                    file, pool);
+                                                    outstream, iterpool);
 
           /* Issue #3896: If we can't pretty-print mergeinfo differences
              because invalid mergeinfo is present, then don't let the diff
@@ -677,7 +654,6 @@ display_prop_diffs(const apr_array_heade
         }
 
       {
-        svn_stream_t *os = svn_stream_from_aprfile2(file, TRUE, pool);
         svn_diff_t *diff;
         svn_diff_file_options_t options = { 0 };
         const svn_string_t *tmp;
@@ -688,14 +664,16 @@ display_prop_diffs(const apr_array_heade
            Since the diff is not useful anyway for patching properties an
            eol character is appended when needed to remove those pescious
            ' \ No newline at end of file' lines. */
-        tmp = original_value ? original_value : svn_string_create("", pool);
-        orig = maybe_append_eol(tmp, pool);
+        tmp = original_value ? original_value : svn_string_create("",
+                                                                  iterpool);
+        orig = maybe_append_eol(tmp, iterpool);
 
         tmp = propchange->value ? propchange->value :
-                                  svn_string_create("", pool);
-        val = maybe_append_eol(tmp, pool);
+                                  svn_string_create("", iterpool);
+        val = maybe_append_eol(tmp, iterpool);
 
-        SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, pool));
+        SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options,
+                                         iterpool));
 
         /* UNIX patch will try to apply a diff even if the diff header
          * is missing. It tries to be helpful by asking the user for a
@@ -704,14 +682,17 @@ display_prop_diffs(const apr_array_heade
          * UNIX patch could apply the property diff to, so we use "##"
          * instead of "@@" as the default hunk delimiter for property diffs.
          * We also supress the diff header. */
-        SVN_ERR(svn_diff_mem_string_output_unified2(os, diff, FALSE, "##",
-                                           svn_dirent_local_style(path, pool),
-                                           svn_dirent_local_style(path, pool),
-                                           encoding, orig, val, pool));
-        SVN_ERR(svn_stream_close(os));
+        SVN_ERR(svn_diff_mem_string_output_unified2(outstream, diff, FALSE,
+                                                    "##",
+                                           svn_dirent_local_style(path,
+                                                                  iterpool),
+                                           svn_dirent_local_style(path,
+                                                                  iterpool),
+                                           encoding, orig, val, iterpool));
 
       }
     }
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -741,8 +722,8 @@ struct diff_cmd_baton {
   } options;
 
   apr_pool_t *pool;
-  apr_file_t *outfile;
-  apr_file_t *errfile;
+  svn_stream_t *outstream;
+  svn_stream_t *errstream;
 
   const char *header_encoding;
 
@@ -778,6 +759,9 @@ struct diff_cmd_baton {
   /* Whether we're producing a git-style diff. */
   svn_boolean_t use_git_diff_format;
 
+  /* Whether deletion of a file is summarized versus showing a full diff. */
+  svn_boolean_t no_diff_deleted;
+
   svn_wc_context_t *wc_ctx;
 
   /* The RA session used during diffs involving the repository. */
@@ -806,10 +790,9 @@ diff_props_changed(svn_wc_notify_state_t
                    svn_boolean_t dir_was_added,
                    const apr_array_header_t *propchanges,
                    apr_hash_t *original_props,
-                   void *diff_baton,
+                   struct diff_cmd_baton *diff_cmd_baton,
                    apr_pool_t *scratch_pool)
 {
-  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
   apr_array_header_t *props;
   svn_boolean_t show_diff_header;
 
@@ -832,7 +815,7 @@ diff_props_changed(svn_wc_notify_state_t
                                  diff_cmd_baton->revnum1,
                                  diff_cmd_baton->revnum2,
                                  diff_cmd_baton->header_encoding,
-                                 diff_cmd_baton->outfile,
+                                 diff_cmd_baton->outstream,
                                  diff_cmd_baton->relative_to_dir,
                                  show_diff_header,
                                  diff_cmd_baton->use_git_diff_format,
@@ -877,7 +860,7 @@ diff_dir_props_changed(svn_wc_notify_sta
                                             dir_was_added,
                                             propchanges,
                                             original_props,
-                                            diff_baton,
+                                            diff_cmd_baton,
                                             scratch_pool));
 }
 
@@ -896,26 +879,20 @@ diff_content_changed(const char *path,
                      const char *mimetype2,
                      svn_diff_operation_kind_t operation,
                      const char *copyfrom_path,
-                     void *diff_baton)
+                     svn_revnum_t copyfrom_rev,
+                     struct diff_cmd_baton *diff_cmd_baton)
 {
-  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
   int exitcode;
   apr_pool_t *subpool = svn_pool_create(diff_cmd_baton->pool);
-  svn_stream_t *os;
   const char *rel_to_dir = diff_cmd_baton->relative_to_dir;
-  apr_file_t *errfile = diff_cmd_baton->errfile;
+  svn_stream_t *errstream = diff_cmd_baton->errstream;
+  svn_stream_t *outstream = diff_cmd_baton->outstream;
   const char *label1, *label2;
   svn_boolean_t mt1_binary = FALSE, mt2_binary = FALSE;
-  const char *path1, *path2;
-
-  /* Get a stream from our output file. */
-  os = svn_stream_from_aprfile2(diff_cmd_baton->outfile, TRUE, subpool);
+  const char *path1 = diff_cmd_baton->orig_path_1;
+  const char *path2 = diff_cmd_baton->orig_path_2;
 
   /* Generate the diff headers. */
-
-  path1 = apr_pstrdup(subpool, diff_cmd_baton->orig_path_1);
-  path2 = apr_pstrdup(subpool, diff_cmd_baton->orig_path_2);
-
   SVN_ERR(adjust_paths_for_diff_labels(&path, &path1, &path2,
                                        rel_to_dir, subpool));
 
@@ -933,35 +910,35 @@ diff_content_changed(const char *path,
   if (! diff_cmd_baton->force_binary && (mt1_binary || mt2_binary))
     {
       /* Print out the diff header. */
-      SVN_ERR(svn_stream_printf_from_utf8
-              (os, diff_cmd_baton->header_encoding, subpool,
+      SVN_ERR(svn_stream_printf_from_utf8(outstream,
+               diff_cmd_baton->header_encoding, subpool,
                "Index: %s" APR_EOL_STR "%s" APR_EOL_STR, path, equal_string));
 
       /* ### Print git diff headers. */
 
-      SVN_ERR(svn_stream_printf_from_utf8
-              (os, diff_cmd_baton->header_encoding, subpool,
+      SVN_ERR(svn_stream_printf_from_utf8(outstream,
+               diff_cmd_baton->header_encoding, subpool,
                _("Cannot display: file marked as a binary type.%s"),
                APR_EOL_STR));
 
       if (mt1_binary && !mt2_binary)
-        SVN_ERR(svn_stream_printf_from_utf8
-                (os, diff_cmd_baton->header_encoding, subpool,
+        SVN_ERR(svn_stream_printf_from_utf8(outstream,
+                 diff_cmd_baton->header_encoding, subpool,
                  "svn:mime-type = %s" APR_EOL_STR, mimetype1));
       else if (mt2_binary && !mt1_binary)
-        SVN_ERR(svn_stream_printf_from_utf8
-                (os, diff_cmd_baton->header_encoding, subpool,
+        SVN_ERR(svn_stream_printf_from_utf8(outstream,
+                 diff_cmd_baton->header_encoding, subpool,
                  "svn:mime-type = %s" APR_EOL_STR, mimetype2));
       else if (mt1_binary && mt2_binary)
         {
           if (strcmp(mimetype1, mimetype2) == 0)
-            SVN_ERR(svn_stream_printf_from_utf8
-                    (os, diff_cmd_baton->header_encoding, subpool,
+            SVN_ERR(svn_stream_printf_from_utf8(outstream,
+                     diff_cmd_baton->header_encoding, subpool,
                      "svn:mime-type = %s" APR_EOL_STR,
                      mimetype1));
           else
-            SVN_ERR(svn_stream_printf_from_utf8
-                    (os, diff_cmd_baton->header_encoding, subpool,
+            SVN_ERR(svn_stream_printf_from_utf8(outstream,
+                     diff_cmd_baton->header_encoding, subpool,
                      "svn:mime-type = (%s, %s)" APR_EOL_STR,
                      mimetype1, mimetype2));
         }
@@ -974,25 +951,52 @@ diff_content_changed(const char *path,
 
   if (diff_cmd_baton->diff_cmd)
     {
+      apr_file_t *outfile;
+      apr_file_t *errfile;
+      const char *outfilename;
+      const char *errfilename;
+      svn_stream_t *stream;
+
       /* Print out the diff header. */
-      SVN_ERR(svn_stream_printf_from_utf8
-              (os, diff_cmd_baton->header_encoding, subpool,
+      SVN_ERR(svn_stream_printf_from_utf8(outstream,
+               diff_cmd_baton->header_encoding, subpool,
                "Index: %s" APR_EOL_STR "%s" APR_EOL_STR, path, equal_string));
-      /* Close the stream (flush) */
-      SVN_ERR(svn_stream_close(os));
 
       /* ### Do we want to add git diff headers here too? I'd say no. The
        * ### 'Index' and '===' line is something subversion has added. The rest
        * ### is up to the external diff application. We may be dealing with
        * ### a non-git compatible diff application.*/
 
+      /* We deal in streams, but svn_io_run_diff2() deals in file handles,
+         unfortunately, so we need to make these temporary files, and then
+         copy the contents to our stream. */
+      SVN_ERR(svn_io_open_unique_file3(&outfile, &outfilename, NULL,
+                                       svn_io_file_del_on_pool_cleanup,
+                                       subpool, subpool));
+      SVN_ERR(svn_io_open_unique_file3(&errfile, &errfilename, NULL,
+                                       svn_io_file_del_on_pool_cleanup,
+                                       subpool, subpool));
+
       SVN_ERR(svn_io_run_diff2(".",
                                diff_cmd_baton->options.for_external.argv,
                                diff_cmd_baton->options.for_external.argc,
                                label1, label2,
                                tmpfile1, tmpfile2,
-                               &exitcode, diff_cmd_baton->outfile, errfile,
+                               &exitcode, outfile, errfile,
                                diff_cmd_baton->diff_cmd, subpool));
+
+      SVN_ERR(svn_io_file_close(outfile, subpool));
+      SVN_ERR(svn_io_file_close(errfile, subpool));
+
+      /* Now, open and copy our files to our output streams. */
+      SVN_ERR(svn_stream_open_readonly(&stream, outfilename,
+                                       subpool, subpool));
+      SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(outstream, subpool),
+                               NULL, NULL, subpool));
+      SVN_ERR(svn_stream_open_readonly(&stream, errfilename,
+                                       subpool, subpool));
+      SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(errstream, subpool),
+                               NULL, NULL, subpool));
     }
   else   /* use libsvn_diff to generate the diff  */
     {
@@ -1006,8 +1010,8 @@ diff_content_changed(const char *path,
           diff_cmd_baton->use_git_diff_format)
         {
           /* Print out the diff header. */
-          SVN_ERR(svn_stream_printf_from_utf8
-                  (os, diff_cmd_baton->header_encoding, subpool,
+          SVN_ERR(svn_stream_printf_from_utf8(outstream,
+                   diff_cmd_baton->header_encoding, subpool,
                    "Index: %s" APR_EOL_STR "%s" APR_EOL_STR,
                    path, equal_string));
 
@@ -1022,20 +1026,19 @@ diff_content_changed(const char *path,
                          &tmp_path2, path, diff_cmd_baton->orig_path_2,
                          diff_cmd_baton->ra_session, diff_cmd_baton->wc_ctx,
                          diff_cmd_baton->wc_root_abspath, subpool));
-              SVN_ERR(print_git_diff_header(os, &label1, &label2, operation,
+              SVN_ERR(print_git_diff_header(outstream, &label1, &label2,
+                                            operation,
                                             tmp_path1, tmp_path2, rev1, rev2,
                                             copyfrom_path,
+                                            copyfrom_rev,
                                             diff_cmd_baton->header_encoding,
-                                            diff_cmd_baton->ra_session,
-                                            diff_cmd_baton->wc_ctx,
-                                            diff_cmd_baton->wc_root_abspath,
                                             subpool));
             }
 
           /* Output the actual diff */
           if (svn_diff_contains_diffs(diff) || diff_cmd_baton->force_empty)
-            SVN_ERR(svn_diff_file_output_unified3
-                    (os, diff, tmpfile1, tmpfile2, label1, label2,
+            SVN_ERR(svn_diff_file_output_unified3(outstream, diff,
+                     tmpfile1, tmpfile2, label1, label2,
                      diff_cmd_baton->header_encoding, rel_to_dir,
                      diff_cmd_baton->options.for_internal->show_c_function,
                      subpool));
@@ -1045,9 +1048,6 @@ diff_content_changed(const char *path,
                        APR_HASH_KEY_STRING, path);
 
         }
-
-      /* Close the stream (flush) */
-      SVN_ERR(svn_stream_close(os));
     }
 
   /* ### todo: someday we'll need to worry about whether we're going
@@ -1089,17 +1089,19 @@ diff_file_changed(svn_wc_notify_state_t 
                   apr_pool_t *scratch_pool)
 {
   struct diff_cmd_baton *diff_cmd_baton = diff_baton;
+
   if (diff_cmd_baton->anchor)
     path = svn_dirent_join(diff_cmd_baton->anchor, path, scratch_pool);
   if (tmpfile1)
     SVN_ERR(diff_content_changed(path,
                                  tmpfile1, tmpfile2, rev1, rev2,
                                  mimetype1, mimetype2,
-                                 svn_diff_op_modified, NULL, diff_baton));
+                                 svn_diff_op_modified, NULL,
+                                 SVN_INVALID_REVNUM, diff_cmd_baton));
   if (prop_changes->nelts > 0)
     SVN_ERR(diff_props_changed(prop_state, tree_conflicted,
                                path, FALSE, prop_changes,
-                               original_props, diff_baton, scratch_pool));
+                               original_props, diff_cmd_baton, scratch_pool));
   if (content_state)
     *content_state = svn_wc_notify_state_unknown;
   if (prop_state)
@@ -1149,16 +1151,17 @@ diff_file_added(svn_wc_notify_state_t *c
                                  tmpfile1, tmpfile2, rev1, rev2,
                                  mimetype1, mimetype2,
                                  svn_diff_op_copied, copyfrom_path,
-                                 diff_baton));
+                                 copyfrom_revision, diff_cmd_baton));
   else if (tmpfile1)
     SVN_ERR(diff_content_changed(path,
                                  tmpfile1, tmpfile2, rev1, rev2,
                                  mimetype1, mimetype2,
-                                 svn_diff_op_added, NULL, diff_baton));
+                                 svn_diff_op_added, NULL, SVN_INVALID_REVNUM,
+                                 diff_cmd_baton));
   if (prop_changes->nelts > 0)
     SVN_ERR(diff_props_changed(prop_state, tree_conflicted,
                                path, FALSE, prop_changes,
-                               original_props, diff_baton, scratch_pool));
+                               original_props, diff_cmd_baton, scratch_pool));
   if (content_state)
     *content_state = svn_wc_notify_state_unknown;
   if (prop_state)
@@ -1173,28 +1176,40 @@ diff_file_added(svn_wc_notify_state_t *c
 
 /* An svn_wc_diff_callbacks4_t function. */
 static svn_error_t *
-diff_file_deleted_with_diff(svn_wc_notify_state_t *state,
-                            svn_boolean_t *tree_conflicted,
-                            const char *path,
-                            const char *tmpfile1,
-                            const char *tmpfile2,
-                            const char *mimetype1,
-                            const char *mimetype2,
-                            apr_hash_t *original_props,
-                            void *diff_baton,
-                            apr_pool_t *scratch_pool)
+diff_file_deleted(svn_wc_notify_state_t *state,
+                  svn_boolean_t *tree_conflicted,
+                  const char *path,
+                  const char *tmpfile1,
+                  const char *tmpfile2,
+                  const char *mimetype1,
+                  const char *mimetype2,
+                  apr_hash_t *original_props,
+                  void *diff_baton,
+                  apr_pool_t *scratch_pool)
 {
   struct diff_cmd_baton *diff_cmd_baton = diff_baton;
 
   if (diff_cmd_baton->anchor)
     path = svn_dirent_join(diff_cmd_baton->anchor, path, scratch_pool);
 
-  if (tmpfile1)
-    SVN_ERR(diff_content_changed(path,
-                                 tmpfile1, tmpfile2, diff_cmd_baton->revnum1,
-                                 diff_cmd_baton->revnum2,
-                                 mimetype1, mimetype2,
-                                 svn_diff_op_deleted, NULL, diff_baton));
+  if (diff_cmd_baton->no_diff_deleted)
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(diff_cmd_baton->outstream,
+                diff_cmd_baton->header_encoding, scratch_pool,
+                "Index: %s (deleted)" APR_EOL_STR "%s" APR_EOL_STR,
+                path, equal_string));
+    }
+  else
+    {
+      if (tmpfile1)
+        SVN_ERR(diff_content_changed(path,
+                                     tmpfile1, tmpfile2,
+                                     diff_cmd_baton->revnum1,
+                                     diff_cmd_baton->revnum2,
+                                     mimetype1, mimetype2,
+                                     svn_diff_op_deleted, NULL,
+                                     SVN_INVALID_REVNUM, diff_cmd_baton));
+    }
 
   /* We don't list all the deleted properties. */
 
@@ -1208,36 +1223,6 @@ diff_file_deleted_with_diff(svn_wc_notif
 
 /* An svn_wc_diff_callbacks4_t function. */
 static svn_error_t *
-diff_file_deleted_no_diff(svn_wc_notify_state_t *state,
-                          svn_boolean_t *tree_conflicted,
-                          const char *path,
-                          const char *tmpfile1,
-                          const char *tmpfile2,
-                          const char *mimetype1,
-                          const char *mimetype2,
-                          apr_hash_t *original_props,
-                          void *diff_baton,
-                          apr_pool_t *scratch_pool)
-{
-  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
-
-  if (diff_cmd_baton->anchor)
-    path = svn_dirent_join(diff_cmd_baton->anchor, path, scratch_pool);
-
-  if (state)
-    *state = svn_wc_notify_state_unknown;
-  if (tree_conflicted)
-    *tree_conflicted = FALSE;
-
-  return file_printf_from_utf8
-          (diff_cmd_baton->outfile,
-           diff_cmd_baton->header_encoding,
-           "Index: %s (deleted)" APR_EOL_STR "%s" APR_EOL_STR,
-           path, equal_string);
-}
-
-/* An svn_wc_diff_callbacks4_t function. */
-static svn_error_t *
 diff_dir_added(svn_wc_notify_state_t *state,
                svn_boolean_t *tree_conflicted,
                svn_boolean_t *skip,
@@ -1313,6 +1298,18 @@ diff_dir_closed(svn_wc_notify_state_t *c
   return SVN_NO_ERROR;
 }
 
+static const svn_wc_diff_callbacks4_t diff_callbacks =
+{
+  diff_file_opened,
+  diff_file_changed,
+  diff_file_added,
+  diff_file_deleted,
+  diff_dir_deleted,
+  diff_dir_opened,
+  diff_dir_added,
+  diff_dir_props_changed,
+  diff_dir_closed    
+};
 
 /*-----------------------------------------------------------------*/
 
@@ -1324,14 +1321,14 @@ diff_dir_closed(svn_wc_notify_state_t *c
    this knowledge has been grokked yet.
 
    There are five cases:
-      1. path is not an URL and start_revision != end_revision
-      2. path is not an URL and start_revision == end_revision
-      3. path is an URL and start_revision != end_revision
-      4. path is an URL and start_revision == end_revision
-      5. path is not an URL and no revisions given
+      1. path is not a URL and start_revision != end_revision
+      2. path is not a URL and start_revision == end_revision
+      3. path is a URL and start_revision != end_revision
+      4. path is a URL and start_revision == end_revision
+      5. path is not a URL and no revisions given
 
    With only one distinct revision the working copy provides the
-   other.  When path is an URL there is no working copy. Thus
+   other.  When path is a URL there is no working copy. Thus
 
      1: compare repository versions for URL coresponding to working copy
      2: compare working copy against repository version
@@ -1739,17 +1736,18 @@ diff_repos_repos(const svn_wc_diff_callb
      Otherwise, we just use "". */
   SVN_ERR(svn_client__get_diff_editor(
                 &diff_editor, &diff_edit_baton,
-                NULL, "", depth,
-                extra_ra_session, rev1, TRUE, FALSE,
+                depth,
+                extra_ra_session, rev1, TRUE /* walk_deleted_dirs */,
+                TRUE /* text_deltas */,
                 callbacks, callback_baton,
                 ctx->cancel_func, ctx->cancel_baton,
                 NULL /* no notify_func */, NULL /* no notify_baton */,
-                pool, pool));
+                pool));
 
   /* We want to switch our txn into URL2 */
   SVN_ERR(svn_ra_do_diff3
           (ra_session, &reporter, &reporter_baton, rev2, target1,
-           depth, ignore_ancestry, TRUE,
+           depth, ignore_ancestry, TRUE /* text_deltas */,
            url2, diff_editor, diff_edit_baton, pool));
 
   /* Drive the reporter; do the diff. */
@@ -1831,17 +1829,13 @@ diff_repos_wc(const char *path1,
      actual URLs will be. */
   if (peg_revision->kind != svn_opt_revision_unspecified)
     {
-      svn_opt_revision_t *start_ignore, *end_ignore, end;
-      const char *url_ignore;
-
-      end.kind = svn_opt_revision_unspecified;
+      svn_opt_revision_t *start_ignore;
 
-      SVN_ERR(svn_client__repos_locations(&url1, &start_ignore,
-                                          &url_ignore, &end_ignore,
+      SVN_ERR(svn_client__repos_locations(&url1, &start_ignore, NULL, NULL,
                                           NULL,
                                           path1,
                                           peg_revision,
-                                          revision1, &end,
+                                          revision1, NULL,
                                           ctx, pool));
       if (!reverse)
         {
@@ -1957,6 +1951,7 @@ do_diff(const svn_wc_diff_callbacks4_t *
     {
       if (is_repos2)
         {
+          /* ### Ignores 'show_copies_as_adds'. */
           SVN_ERR(diff_repos_repos(callbacks, callback_baton, ctx,
                                    path1, path2, revision1, revision2,
                                    peg_revision, depth, ignore_ancestry,
@@ -1993,6 +1988,64 @@ do_diff(const svn_wc_diff_callbacks4_t *
   return SVN_NO_ERROR;
 }
 
+/* Perform a summary diff between two working-copy paths.
+
+   PATH1 and PATH2 are both working copy paths.  REVISION1 and
+   REVISION2 are their respective revisions.
+
+   All other options are the same as those passed to svn_client_diff5(). */
+static svn_error_t *
+diff_summarize_wc_wc(svn_client_diff_summarize_func_t summarize_func,
+                     void *summarize_baton,
+                     const char *path1,
+                     const svn_opt_revision_t *revision1,
+                     const char *path2,
+                     const svn_opt_revision_t *revision2,
+                     svn_depth_t depth,
+                     svn_boolean_t ignore_ancestry,
+                     const apr_array_header_t *changelists,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *pool)
+{
+  svn_wc_diff_callbacks4_t *callbacks;
+  void *callback_baton;
+  const char *abspath1, *target1;
+  svn_node_kind_t kind;
+
+  SVN_ERR_ASSERT(! svn_path_is_url(path1));
+  SVN_ERR_ASSERT(! svn_path_is_url(path2));
+
+  /* Currently we support only the case where path1 and path2 are the
+     same path. */
+  if ((strcmp(path1, path2) != 0)
+      || (! ((revision1->kind == svn_opt_revision_base)
+             && (revision2->kind == svn_opt_revision_working))))
+    return unsupported_diff_error
+      (svn_error_create
+       (SVN_ERR_INCORRECT_PARAMS, NULL,
+        _("Only diffs between a path's text-base "
+          "and its working files are supported at this time")));
+
+  /* Find the node kind of PATH1 so that we know whether the diff drive will
+     be anchored at PATH1 or its parent dir. */
+  SVN_ERR(svn_dirent_get_absolute(&abspath1, path1, pool));
+  SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, abspath1, FALSE, pool));
+  target1 = (kind == svn_node_dir) ? "" : svn_dirent_basename(path1, pool);
+  SVN_ERR(svn_client__get_diff_summarize_callbacks(
+            &callbacks, &callback_baton, target1,
+            summarize_func, summarize_baton, pool));
+
+  SVN_ERR(svn_wc_diff6(ctx->wc_ctx,
+                       abspath1,
+                       callbacks, callback_baton,
+                       depth,
+                       ignore_ancestry, FALSE /* show_copies_as_adds */,
+                       FALSE /* use_git_diff_format */, changelists,
+                       ctx->cancel_func, ctx->cancel_baton,
+                       pool));
+  return SVN_NO_ERROR;
+}
+
 /* Perform a diff summary between two repository paths. */
 static svn_error_t *
 diff_summarize_repos_repos(svn_client_diff_summarize_func_t summarize_func,
@@ -2025,6 +2078,8 @@ diff_summarize_repos_repos(svn_client_di
   const char *target1;
   const char *target2;
   svn_ra_session_t *ra_session;
+  svn_wc_diff_callbacks4_t *callbacks;
+  void *callback_baton;
 
   /* Prepare info for the repos repos diff. */
   SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
@@ -2033,6 +2088,10 @@ diff_summarize_repos_repos(svn_client_di
                                    path1, path2, revision1, revision2,
                                    peg_revision, pool));
 
+  SVN_ERR(svn_client__get_diff_summarize_callbacks(
+            &callbacks, &callback_baton,
+            target1, summarize_func, summarize_baton, pool));
+
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used to get the kind of deleted paths.  */
   SVN_ERR(svn_client__open_ra_session_internal(&extra_ra_session, NULL,
@@ -2040,10 +2099,13 @@ diff_summarize_repos_repos(svn_client_di
                                                TRUE, ctx, pool));
 
   /* Set up the repos_diff editor. */
-  SVN_ERR(svn_client__get_diff_summarize_editor
-          (target2, summarize_func,
-           summarize_baton, extra_ra_session, rev1, ctx->cancel_func,
-           ctx->cancel_baton, &diff_editor, &diff_edit_baton, pool));
+  SVN_ERR(svn_client__get_diff_editor(&diff_editor, &diff_edit_baton,
+            depth,
+            extra_ra_session, rev1, TRUE /* walk_deleted_dirs */,
+            FALSE /* text_deltas */,
+            callbacks, callback_baton,
+            ctx->cancel_func, ctx->cancel_baton,
+            NULL /* notify_func */, NULL /* notify_baton */, pool));
 
   /* We want to switch our txn into URL2 */
   SVN_ERR(svn_ra_do_diff3
@@ -2071,6 +2133,7 @@ do_diff_summarize(svn_client_diff_summar
                   const svn_opt_revision_t *peg_revision,
                   svn_depth_t depth,
                   svn_boolean_t ignore_ancestry,
+                  const apr_array_header_t *changelists,
                   apr_pool_t *pool)
 {
   svn_boolean_t is_repos1;
@@ -2085,10 +2148,16 @@ do_diff_summarize(svn_client_diff_summar
                                       path1, path2, revision1, revision2,
                                       peg_revision, depth, ignore_ancestry,
                                       pool);
+  else if (! is_repos1 && ! is_repos2)
+    return diff_summarize_wc_wc(summarize_func, summarize_baton,
+                                path1, revision1, path2, revision2,
+                                depth, ignore_ancestry,
+                                changelists, ctx, pool);
   else
-    return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                            _("Summarizing diff can only compare repository "
-                              "to repository"));
+   return unsupported_diff_error(
+            svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                             _("Summarizing diff cannot compare repository "
+                               "to WC")));
 }
 
 
@@ -2194,7 +2263,7 @@ set_up_diff_cmd_and_options(struct diff_
       * These cases require server communication.
 */
 svn_error_t *
-svn_client_diff5(const apr_array_header_t *options,
+svn_client_diff6(const apr_array_header_t *options,
                  const char *path1,
                  const svn_opt_revision_t *revision1,
                  const char *path2,
@@ -2207,39 +2276,27 @@ svn_client_diff5(const apr_array_header_
                  svn_boolean_t ignore_content_type,
                  svn_boolean_t use_git_diff_format,
                  const char *header_encoding,
-                 apr_file_t *outfile,
-                 apr_file_t *errfile,
+                 svn_stream_t *outstream,
+                 svn_stream_t *errstream,
                  const apr_array_header_t *changelists,
                  svn_client_ctx_t *ctx,
                  apr_pool_t *pool)
 {
   struct diff_cmd_baton diff_cmd_baton = { 0 };
-  svn_wc_diff_callbacks4_t diff_callbacks;
 
   /* We will never do a pegged diff from here. */
   svn_opt_revision_t peg_revision;
   peg_revision.kind = svn_opt_revision_unspecified;
 
   /* setup callback and baton */
-  diff_callbacks.file_opened = diff_file_opened;
-  diff_callbacks.file_changed = diff_file_changed;
-  diff_callbacks.file_added = diff_file_added;
-  diff_callbacks.file_deleted = no_diff_deleted ? diff_file_deleted_no_diff :
-                                                  diff_file_deleted_with_diff;
-  diff_callbacks.dir_added =  diff_dir_added;
-  diff_callbacks.dir_deleted = diff_dir_deleted;
-  diff_callbacks.dir_props_changed = diff_dir_props_changed;
-  diff_callbacks.dir_opened = diff_dir_opened;
-  diff_callbacks.dir_closed = diff_dir_closed;
-
   diff_cmd_baton.orig_path_1 = path1;
   diff_cmd_baton.orig_path_2 = path2;
 
   SVN_ERR(set_up_diff_cmd_and_options(&diff_cmd_baton, options,
                                       ctx->config, pool));
   diff_cmd_baton.pool = pool;
-  diff_cmd_baton.outfile = outfile;
-  diff_cmd_baton.errfile = errfile;
+  diff_cmd_baton.outstream = outstream;
+  diff_cmd_baton.errstream = errstream;
   diff_cmd_baton.header_encoding = header_encoding;
   diff_cmd_baton.revnum1 = SVN_INVALID_REVNUM;
   diff_cmd_baton.revnum2 = SVN_INVALID_REVNUM;
@@ -2248,6 +2305,7 @@ svn_client_diff5(const apr_array_header_
   diff_cmd_baton.force_binary = ignore_content_type;
   diff_cmd_baton.relative_to_dir = relative_to_dir;
   diff_cmd_baton.use_git_diff_format = use_git_diff_format;
+  diff_cmd_baton.no_diff_deleted = no_diff_deleted;
   diff_cmd_baton.wc_ctx = ctx->wc_ctx;
   diff_cmd_baton.visited_paths = apr_hash_make(pool);
   diff_cmd_baton.ra_session = NULL;
@@ -2261,7 +2319,7 @@ svn_client_diff5(const apr_array_header_
 }
 
 svn_error_t *
-svn_client_diff_peg5(const apr_array_header_t *options,
+svn_client_diff_peg6(const apr_array_header_t *options,
                      const char *path,
                      const svn_opt_revision_t *peg_revision,
                      const svn_opt_revision_t *start_revision,
@@ -2274,35 +2332,23 @@ svn_client_diff_peg5(const apr_array_hea
                      svn_boolean_t ignore_content_type,
                      svn_boolean_t use_git_diff_format,
                      const char *header_encoding,
-                     apr_file_t *outfile,
-                     apr_file_t *errfile,
+                     svn_stream_t *outstream,
+                     svn_stream_t *errstream,
                      const apr_array_header_t *changelists,
                      svn_client_ctx_t *ctx,
                      apr_pool_t *pool)
 {
   struct diff_cmd_baton diff_cmd_baton = { 0 };
-  svn_wc_diff_callbacks4_t diff_callbacks;
 
   /* setup callback and baton */
-  diff_callbacks.file_opened = diff_file_opened;
-  diff_callbacks.file_changed = diff_file_changed;
-  diff_callbacks.file_added = diff_file_added;
-  diff_callbacks.file_deleted = no_diff_deleted ? diff_file_deleted_no_diff :
-                                                  diff_file_deleted_with_diff;
-  diff_callbacks.dir_added =  diff_dir_added;
-  diff_callbacks.dir_deleted = diff_dir_deleted;
-  diff_callbacks.dir_props_changed = diff_dir_props_changed;
-  diff_callbacks.dir_opened = diff_dir_opened;
-  diff_callbacks.dir_closed = diff_dir_closed;
-
   diff_cmd_baton.orig_path_1 = path;
   diff_cmd_baton.orig_path_2 = path;
 
   SVN_ERR(set_up_diff_cmd_and_options(&diff_cmd_baton, options,
                                       ctx->config, pool));
   diff_cmd_baton.pool = pool;
-  diff_cmd_baton.outfile = outfile;
-  diff_cmd_baton.errfile = errfile;
+  diff_cmd_baton.outstream = outstream;
+  diff_cmd_baton.errstream = errstream;
   diff_cmd_baton.header_encoding = header_encoding;
   diff_cmd_baton.revnum1 = SVN_INVALID_REVNUM;
   diff_cmd_baton.revnum2 = SVN_INVALID_REVNUM;
@@ -2311,6 +2357,7 @@ svn_client_diff_peg5(const apr_array_hea
   diff_cmd_baton.force_binary = ignore_content_type;
   diff_cmd_baton.relative_to_dir = relative_to_dir;
   diff_cmd_baton.use_git_diff_format = use_git_diff_format;
+  diff_cmd_baton.no_diff_deleted = no_diff_deleted;
   diff_cmd_baton.wc_ctx = ctx->wc_ctx;
   diff_cmd_baton.visited_paths = apr_hash_make(pool);
   diff_cmd_baton.ra_session = NULL;
@@ -2340,10 +2387,9 @@ svn_client_diff_summarize2(const char *p
   svn_opt_revision_t peg_revision;
   peg_revision.kind = svn_opt_revision_unspecified;
 
-  /* ### CHANGELISTS parameter isn't used */
   return do_diff_summarize(summarize_func, summarize_baton, ctx,
                            path1, path2, revision1, revision2, &peg_revision,
-                           depth, ignore_ancestry, pool);
+                           depth, ignore_ancestry, changelists, pool);
 }
 
 svn_error_t *
@@ -2359,10 +2405,10 @@ svn_client_diff_summarize_peg2(const cha
                                svn_client_ctx_t *ctx,
                                apr_pool_t *pool)
 {
-  /* ### CHANGELISTS parameter isn't used */
   return do_diff_summarize(summarize_func, summarize_baton, ctx,
                            path, path, start_revision, end_revision,
-                           peg_revision, depth, ignore_ancestry, pool);
+                           peg_revision,
+                           depth, ignore_ancestry, changelists, pool);
 }
 
 svn_client_diff_summarize_t *

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/export.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/export.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/export.c Tue Oct 11 19:52:34 2011
@@ -1039,7 +1039,6 @@ svn_client_export5(svn_revnum_t *result_
                    apr_pool_t *pool)
 {
   svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
-  const char *url;
   svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url);
 
   SVN_ERR_ASSERT(peg_revision != NULL);
@@ -1056,10 +1055,10 @@ svn_client_export5(svn_revnum_t *result_
   if (from_is_url || ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
     {
       svn_revnum_t revnum;
+      const char *url;
       svn_ra_session_t *ra_session;
       svn_node_kind_t kind;
       struct edit_baton *eb = apr_pcalloc(pool, sizeof(*eb));
-      const char *repos_root_url;
 
       /* Get the RA connection. */
       SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
@@ -1067,9 +1066,6 @@ svn_client_export5(svn_revnum_t *result_
                                                peg_revision,
                                                revision, ctx, pool));
 
-      /* Get the repository root. */
-      SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
-
       eb->root_path = to_path;
       eb->root_url = url;
       eb->force = overwrite;
@@ -1182,6 +1178,10 @@ svn_client_export5(svn_revnum_t *result_
                                                     &edit_baton,
                                                     pool));
 
+          SVN_ERR(svn_editor__insert_shims(&export_editor, &edit_baton,
+                                           export_editor, edit_baton,
+                                           NULL, NULL, NULL, NULL,
+                                           pool, pool));
 
           /* Manufacture a basic 'report' to the update reporter. */
           SVN_ERR(svn_ra_do_update2(ra_session,
@@ -1219,8 +1219,10 @@ svn_client_export5(svn_revnum_t *result_
 
           if (! ignore_externals && depth == svn_depth_infinity)
             {
+              const char *repos_root_url;
               const char *to_abspath;
 
+              SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
               SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, pool));
               SVN_ERR(svn_client__export_externals(eb->externals,
                                                    from_path_or_url,

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/externals.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/externals.c Tue Oct 11 19:52:34 2011
@@ -126,8 +126,8 @@ relegate_dir_external(svn_wc_context_t *
 static svn_error_t *
 switch_dir_external(const char *local_abspath,
                     const char *url,
-                    const svn_opt_revision_t *revision,
                     const svn_opt_revision_t *peg_revision,
+                    const svn_opt_revision_t *revision,
                     const char *defining_abspath,
                     svn_boolean_t *timestamp_sleep,
                     svn_client_ctx_t *ctx,
@@ -135,10 +135,18 @@ switch_dir_external(const char *local_ab
 {
   svn_node_kind_t kind;
   svn_error_t *err;
+  svn_revnum_t external_peg_rev = SVN_INVALID_REVNUM;
+  svn_revnum_t external_rev = SVN_INVALID_REVNUM;
   apr_pool_t *subpool = svn_pool_create(pool);
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
+  if (peg_revision->kind == svn_opt_revision_number)
+    external_peg_rev = peg_revision->value.number;
+
+  if (revision->kind == svn_opt_revision_number)
+    external_rev = revision->value.number;
+
   /* If path is a directory, try to update/switch to the correct URL
      and revision. */
   SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
@@ -230,8 +238,8 @@ switch_dir_external(const char *local_ab
                                                 svn_uri_skip_ancestor(
                                                             repos_root_url,
                                                             url, subpool),
-                                                SVN_INVALID_REVNUM,
-                                                SVN_INVALID_REVNUM,
+                                                external_peg_rev,
+                                                external_rev,
                                                 subpool));
 
               svn_pool_destroy(subpool);
@@ -288,8 +296,8 @@ switch_dir_external(const char *local_ab
                                       repos_root_url, repos_uuid,
                                       svn_uri_skip_ancestor(repos_root_url,
                                                             url, pool),
-                                      SVN_INVALID_REVNUM,
-                                      SVN_INVALID_REVNUM,
+                                      external_peg_rev,
+                                      external_rev,
                                       pool));
   }
 
@@ -504,219 +512,6 @@ cleanup:
   return svn_error_trace(err);
 }
 
-/* Return the scheme of @a uri in @a scheme allocated from @a pool.
-   If @a uri does not appear to be a valid URI, then @a scheme will
-   not be updated.  */
-static svn_error_t *
-uri_scheme(const char **scheme, const char *uri, apr_pool_t *pool)
-{
-  apr_size_t i;
-
-  for (i = 0; uri[i] && uri[i] != ':'; ++i)
-    if (uri[i] == '/')
-      goto error;
-
-  if (i > 0 && uri[i] == ':' && uri[i+1] == '/' && uri[i+2] == '/')
-    {
-      *scheme = apr_pstrmemdup(pool, uri, i);
-      return SVN_NO_ERROR;
-    }
-
-error:
-  return svn_error_createf(SVN_ERR_BAD_URL, 0,
-                           _("URL '%s' does not begin with a scheme"),
-                           uri);
-}
-
-/* If the URL for @a item is relative, then using the repository root
-   URL @a repos_root_url and the parent directory URL @parent_dir_url,
-   resolve it into an absolute URL and save it in @a item.
-
-   Regardless if the URL is absolute or not, if there are no errors,
-   the URL in @a item will be canonicalized.
-
-   The following relative URL formats are supported:
-
-     ../    relative to the parent directory of the external
-     ^/     relative to the repository root
-     //     relative to the scheme
-     /      relative to the server's hostname
-
-   The ../ and ^/ relative URLs may use .. to remove path elements up
-   to the server root.
-
-   The external URL should not be canonicalized before calling this function,
-   as otherwise the scheme relative URL '//host/some/path' would have been
-   canonicalized to '/host/some/path' and we would not be able to match on
-   the leading '//'. */
-static svn_error_t *
-resolve_relative_external_url(const char **resolved_url,
-                              const svn_wc_external_item2_t *item,
-                              const char *repos_root_url,
-                              const char *parent_dir_url,
-                              apr_pool_t *result_pool,
-                              apr_pool_t *scratch_pool)
-{
-  const char *url = item->url;
-  apr_uri_t parent_dir_uri;
-  apr_status_t status;
-
-  *resolved_url = item->url;
-
-  /* If the URL is already absolute, there is nothing to do. */
-  if (svn_path_is_url(url))
-    {
-      /* "http://server/path" */
-      *resolved_url = svn_uri_canonicalize(url, result_pool);
-      return SVN_NO_ERROR;
-    }
-
-  if (url[0] == '/')
-    {
-      /* "/path", "//path", and "///path" */
-      int num_leading_slashes = 1;
-      if (url[1] == '/')
-        {
-          num_leading_slashes++;
-          if (url[2] == '/')
-            num_leading_slashes++;
-        }
-
-      /* "//schema-relative" and in some cases "///schema-relative".
-         This last format is supported on file:// schema relative. */
-      url = apr_pstrcat(scratch_pool,
-                        apr_pstrndup(scratch_pool, url, num_leading_slashes),
-                        svn_relpath_canonicalize(url + num_leading_slashes,
-                                                 scratch_pool),
-                        (char*)NULL);
-    }
-  else
-    {
-      /* "^/path" and "../path" */
-      url = svn_relpath_canonicalize(url, scratch_pool);
-    }
-
-  /* Parse the parent directory URL into its parts. */
-  status = apr_uri_parse(scratch_pool, parent_dir_url, &parent_dir_uri);
-  if (status)
-    return svn_error_createf(SVN_ERR_BAD_URL, 0,
-                             _("Illegal parent directory URL '%s'"),
-                             parent_dir_url);
-
-  /* If the parent directory URL is at the server root, then the URL
-     may have no / after the hostname so apr_uri_parse() will leave
-     the URL's path as NULL. */
-  if (! parent_dir_uri.path)
-    parent_dir_uri.path = apr_pstrmemdup(scratch_pool, "/", 1);
-  parent_dir_uri.query = NULL;
-  parent_dir_uri.fragment = NULL;
-
-  /* Handle URLs relative to the current directory or to the
-     repository root.  The backpaths may only remove path elements,
-     not the hostname.  This allows an external to refer to another
-     repository in the same server relative to the location of this
-     repository, say using SVNParentPath. */
-  if ((0 == strncmp("../", url, 3)) ||
-      (0 == strncmp("^/", url, 2)))
-    {
-      apr_array_header_t *base_components;
-      apr_array_header_t *relative_components;
-      int i;
-
-      /* Decompose either the parent directory's URL path or the
-         repository root's URL path into components.  */
-      if (0 == strncmp("../", url, 3))
-        {
-          base_components = svn_path_decompose(parent_dir_uri.path,
-                                               scratch_pool);
-          relative_components = svn_path_decompose(url, scratch_pool);
-        }
-      else
-        {
-          apr_uri_t repos_root_uri;
-
-          status = apr_uri_parse(scratch_pool, repos_root_url,
-                                 &repos_root_uri);
-          if (status)
-            return svn_error_createf(SVN_ERR_BAD_URL, 0,
-                                     _("Illegal repository root URL '%s'"),
-                                     repos_root_url);
-
-          /* If the repository root URL is at the server root, then
-             the URL may have no / after the hostname so
-             apr_uri_parse() will leave the URL's path as NULL. */
-          if (! repos_root_uri.path)
-            repos_root_uri.path = apr_pstrmemdup(scratch_pool, "/", 1);
-
-          base_components = svn_path_decompose(repos_root_uri.path,
-                                               scratch_pool);
-          relative_components = svn_path_decompose(url + 2, scratch_pool);
-        }
-
-      for (i = 0; i < relative_components->nelts; ++i)
-        {
-          const char *component = APR_ARRAY_IDX(relative_components,
-                                                i,
-                                                const char *);
-          if (0 == strcmp("..", component))
-            {
-              /* Constructing the final absolute URL together with
-                 apr_uri_unparse() requires that the path be absolute,
-                 so only pop a component if the component being popped
-                 is not the component for the root directory. */
-              if (base_components->nelts > 1)
-                apr_array_pop(base_components);
-            }
-          else
-            APR_ARRAY_PUSH(base_components, const char *) = component;
-        }
-
-      parent_dir_uri.path = (char *)svn_path_compose(base_components,
-                                                     scratch_pool);
-      *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool,
-                                                           &parent_dir_uri, 0),
-                                       result_pool);
-      return SVN_NO_ERROR;
-    }
-
-  /* The remaining URLs are relative to the either the scheme or
-     server root and can only refer to locations inside that scope, so
-     backpaths are not allowed. */
-  if (svn_path_is_backpath_present(url + 2))
-    return svn_error_createf(SVN_ERR_BAD_URL, 0,
-                             _("The external relative URL '%s' cannot have "
-                               "backpaths, i.e. '..'"),
-                             item->url);
-
-  /* Relative to the scheme: Build a new URL from the parts we know.  */
-  if (0 == strncmp("//", url, 2))
-    {
-      const char *scheme;
-
-      SVN_ERR(uri_scheme(&scheme, repos_root_url, scratch_pool));
-      *resolved_url = svn_uri_canonicalize(apr_pstrcat(scratch_pool, scheme,
-                                                       ":", url, (char *)NULL),
-                                           result_pool);
-      return SVN_NO_ERROR;
-    }
-
-  /* Relative to the server root: Just replace the path portion of the
-     parent's URL.  */
-  if (url[0] == '/')
-    {
-      parent_dir_uri.path = (char *)url;
-      *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool,
-                                                           &parent_dir_uri, 0),
-                                           result_pool);
-      return SVN_NO_ERROR;
-    }
-
-  return svn_error_createf(SVN_ERR_BAD_URL, 0,
-                           _("Unrecognized format for the relative external "
-                             "URL '%s'"),
-                           item->url);
-}
-
 static svn_error_t *
 handle_external_item_removal(const struct external_change_baton_t *eb,
                              const char *defining_abspath,
@@ -824,10 +619,10 @@ handle_external_item_change(const struct
      iterpool, since the hash table values outlive the iterpool and
      any pointers they have should also outlive the iterpool.  */
 
-   SVN_ERR(resolve_relative_external_url(&new_url,
-                                         new_item, eb->repos_root_url,
-                                         parent_dir_url,
-                                         scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__resolve_relative_external_url(&new_url,
+                                                new_item, eb->repos_root_url,
+                                                parent_dir_url,
+                                                scratch_pool, scratch_pool));
 
   /* If the external is being checked out, exported or updated,
      determine if the external is a file or directory. */
@@ -871,17 +666,21 @@ handle_external_item_change(const struct
      the global case is hard, and it should be pretty obvious to a
      user when it happens.  Worst case: your disk fills up :-). */
 
+  /* First notify that we're about to handle an external. */
+  if (eb->ctx->notify_func2)
+    {
+      (*eb->ctx->notify_func2)(
+         eb->ctx->notify_baton2,
+         svn_wc_create_notify(local_abspath,
+                              svn_wc_notify_update_external,
+                              scratch_pool),
+         scratch_pool);
+    }
+
   if (! old_defining_abspath)
     {
       /* This branch is only used during a checkout or an export. */
 
-      /* First notify that we're about to handle an external. */
-      if (eb->ctx->notify_func2)
-        (*eb->ctx->notify_func2)(
-           eb->ctx->notify_baton2,
-           svn_wc_create_notify(local_abspath, svn_wc_notify_update_external,
-                                scratch_pool), scratch_pool);
-
       switch (ra_cache.kind)
         {
         case svn_node_dir:
@@ -898,6 +697,11 @@ handle_external_item_change(const struct
                    scratch_pool));
           break;
         case svn_node_file:
+          if (strcmp(eb->repos_root_url, ra_cache.repos_root_url))
+            return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                      _("Unsupported external: "
+                        "url of file external '%s' is not in repository '%s'"),
+                      new_url, eb->repos_root_url);
           SVN_ERR(switch_file_external(local_abspath,
                                        new_url,
                                        &new_item->peg_revision,
@@ -919,18 +723,6 @@ handle_external_item_change(const struct
     {
       /* This branch handles a definition change or simple update. */
 
-      /* First notify that we're about to handle an external. */
-      if (eb->ctx->notify_func2)
-        {
-          svn_wc_notify_t *nt;
-
-          nt = svn_wc_create_notify(local_abspath,
-                                    svn_wc_notify_update_external,
-                                    scratch_pool);
-
-          eb->ctx->notify_func2(eb->ctx->notify_baton2, nt, scratch_pool);
-        }
-
       /* Either the URL changed, or the exact same item is present in
          both hashes, and caller wants to update such unchanged items.
          In the latter case, the call below will try to make sure that
@@ -940,13 +732,18 @@ handle_external_item_change(const struct
         {
         case svn_node_dir:
           SVN_ERR(switch_dir_external(local_abspath, new_url,
-                                      &(new_item->revision),
                                       &(new_item->peg_revision),
+                                      &(new_item->revision),
                                       parent_dir_abspath,
                                       eb->timestamp_sleep, eb->ctx,
                                       scratch_pool));
           break;
         case svn_node_file:
+          if (strcmp(eb->repos_root_url, ra_cache.repos_root_url))
+            return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                      _("Unsupported external: "
+                        "url of file external '%s' is not in repository '%s'"),
+                      new_url, eb->repos_root_url);
           SVN_ERR(switch_file_external(local_abspath,
                                        new_url,
                                        &new_item->peg_revision,
@@ -1044,6 +841,9 @@ handle_externals_change(const struct ext
 
       svn_pool_clear(iterpool);
 
+      if (eb->ctx->cancel_func)
+        SVN_ERR(eb->ctx->cancel_func(eb->ctx->cancel_baton));
+
       target_abspath = svn_dirent_join(local_abspath, new_item->target_dir,
                                        iterpool);
 
@@ -1219,9 +1019,10 @@ svn_client__export_externals(apr_hash_t 
           item_abspath = svn_dirent_join(local_abspath, item->target_dir,
                                          sub_iterpool);
 
-          SVN_ERR(resolve_relative_external_url(&new_url, item,
-                                                repos_root_url, dir_url,
-                                                sub_iterpool, sub_iterpool));
+          SVN_ERR(svn_wc__resolve_relative_external_url(&new_url, item,
+                                                        repos_root_url,
+                                                        dir_url, sub_iterpool,
+                                                        sub_iterpool));
 
           /* The target dir might have multiple components.  Guarantee
              the path leading down to the last component. */

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/info.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/info.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/info.c Tue Oct 11 19:52:34 2011
@@ -186,20 +186,18 @@ same_resource_in_head(svn_boolean_t *sam
                       apr_pool_t *pool)
 {
   svn_error_t *err;
-  svn_opt_revision_t start_rev, end_rev, peg_rev;
+  svn_opt_revision_t start_rev, peg_rev;
   svn_opt_revision_t *ignored_rev;
-  const char *head_url, *ignored_url;
+  const char *head_url;
 
   start_rev.kind = svn_opt_revision_head;
   peg_rev.kind = svn_opt_revision_number;
   peg_rev.value.number = rev;
-  end_rev.kind = svn_opt_revision_unspecified;
 
-  err = svn_client__repos_locations(&head_url, &ignored_rev,
-                                    &ignored_url, &ignored_rev,
+  err = svn_client__repos_locations(&head_url, &ignored_rev, NULL, NULL,
                                     ra_session,
                                     url, &peg_rev,
-                                    &start_rev, &end_rev,
+                                    &start_rev, NULL,
                                     ctx, pool);
   if (err &&
       ((err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES) ||
@@ -262,10 +260,12 @@ svn_error_t *
 svn_client_info3(const char *abspath_or_url,
                  const svn_opt_revision_t *peg_revision,
                  const svn_opt_revision_t *revision,
-                 svn_client_info_receiver2_t receiver,
-                 void *receiver_baton,
                  svn_depth_t depth,
+                 svn_boolean_t fetch_excluded,
+                 svn_boolean_t fetch_actual_only,
                  const apr_array_header_t *changelists,
+                 svn_client_info_receiver2_t receiver,
+                 void *receiver_baton,
                  svn_client_ctx_t *ctx,
                  apr_pool_t *pool)
 {
@@ -294,7 +294,8 @@ svn_client_info3(const char *abspath_or_
       wc_info_receiver_baton_t b = { receiver, receiver_baton };
       return svn_error_trace(
         svn_wc__get_info(ctx->wc_ctx, abspath_or_url, depth,
-                         wc_info_receiver, &b, changelists,
+                        fetch_excluded, fetch_actual_only, changelists,
+                         wc_info_receiver, &b,
                          ctx->cancel_func, ctx->cancel_baton, pool));
     }
 

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/locking_commands.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/locking_commands.c Tue Oct 11 19:52:34 2011
@@ -60,6 +60,8 @@ struct lock_baton
  * (depending on whether DO_LOCK is true or false respectively), but
  * only if RA_ERR is null, or (in the unlock case) is something other
  * than SVN_ERR_FS_LOCK_OWNER_MISMATCH.
+ *
+ * Implements svn_ra_lock_callback_t.
  */
 static svn_error_t *
 store_locks_callback(void *baton,

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/log.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/log.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/log.c Tue Oct 11 19:52:34 2011
@@ -211,8 +211,7 @@ pre_15_receiver(void *baton, svn_log_ent
                                   name, &value, pool));
           if (log_entry->revprops == NULL)
             log_entry->revprops = apr_hash_make(pool);
-          apr_hash_set(log_entry->revprops, (const void *)name,
-                       APR_HASH_KEY_STRING, (const void *)value);
+          apr_hash_set(log_entry->revprops, name, APR_HASH_KEY_STRING, value);
         }
       if (log_entry->revprops)
         {
@@ -330,7 +329,7 @@ svn_client_log5(const apr_array_header_t
       else if (range->start.kind == svn_opt_revision_unspecified)
         {
           /* Default to any specified peg revision.  Otherwise, if the
-           * first target is an URL, then we default to HEAD:0.  Lastly,
+           * first target is a URL, then we default to HEAD:0.  Lastly,
            * the default is BASE:0 since WC@HEAD may not exist. */
           if (peg_rev.kind == svn_opt_revision_unspecified)
             {