subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cmpil...@apache.org
Subject svn commit: r1325461 [1/3] - in /subversion/branches/master-passphrase: ./ contrib/client-side/emacs/ contrib/client-side/vim/ notes/ subversion/bindings/swig/ruby/test/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversi...
Date Thu, 12 Apr 2012 19:37:47 GMT
Author: cmpilato
Date: Thu Apr 12 19:37:45 2012
New Revision: 1325461

URL: http://svn.apache.org/viewvc?rev=1325461&view=rev
Log:
Sync the 'master-passphrase' branch with recent trunk changes.
(Merged ^/subversion/trunk:r1310042-1325453)

Removed:
    subversion/branches/master-passphrase/contrib/client-side/vim/svn.vim
Modified:
    subversion/branches/master-passphrase/   (props changed)
    subversion/branches/master-passphrase/CHANGES
    subversion/branches/master-passphrase/COMMITTERS
    subversion/branches/master-passphrase/contrib/client-side/emacs/dsvn.el
    subversion/branches/master-passphrase/notes/knobs
    subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_client.rb
    subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_wc.rb
    subversion/branches/master-passphrase/subversion/include/private/svn_temp_serializer.h
    subversion/branches/master-passphrase/subversion/include/svn_config.h
    subversion/branches/master-passphrase/subversion/include/svn_delta.h
    subversion/branches/master-passphrase/subversion/include/svn_editor.h
    subversion/branches/master-passphrase/subversion/libsvn_client/copy.c
    subversion/branches/master-passphrase/subversion/libsvn_client/diff.c
    subversion/branches/master-passphrase/subversion/libsvn_client/export.c
    subversion/branches/master-passphrase/subversion/libsvn_client/merge.c
    subversion/branches/master-passphrase/subversion/libsvn_client/prop_commands.c
    subversion/branches/master-passphrase/subversion/libsvn_client/repos_diff.c
    subversion/branches/master-passphrase/subversion/libsvn_delta/compat.c
    subversion/branches/master-passphrase/subversion/libsvn_delta/editor.c
    subversion/branches/master-passphrase/subversion/libsvn_delta/xdelta.c
    subversion/branches/master-passphrase/subversion/libsvn_fs_fs/fs.h
    subversion/branches/master-passphrase/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/master-passphrase/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/branches/master-passphrase/subversion/libsvn_ra/compat.c
    subversion/branches/master-passphrase/subversion/libsvn_ra_neon/commit.c
    subversion/branches/master-passphrase/subversion/libsvn_ra_serf/commit.c
    subversion/branches/master-passphrase/subversion/libsvn_ra_serf/ra_serf.h
    subversion/branches/master-passphrase/subversion/libsvn_ra_serf/serf.c
    subversion/branches/master-passphrase/subversion/libsvn_ra_svn/cyrus_auth.c
    subversion/branches/master-passphrase/subversion/libsvn_ra_svn/editorp.c
    subversion/branches/master-passphrase/subversion/libsvn_repos/commit.c
    subversion/branches/master-passphrase/subversion/libsvn_repos/dump.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/config.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/crypto.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/crypto.h
    subversion/branches/master-passphrase/subversion/libsvn_subr/svn_temp_serializer.c
    subversion/branches/master-passphrase/subversion/libsvn_wc/diff_editor.c
    subversion/branches/master-passphrase/subversion/libsvn_wc/node.c
    subversion/branches/master-passphrase/subversion/libsvn_wc/status.c
    subversion/branches/master-passphrase/subversion/libsvn_wc/update_editor.c
    subversion/branches/master-passphrase/subversion/libsvn_wc/wc_db.c
    subversion/branches/master-passphrase/subversion/libsvn_wc/wc_db.h
    subversion/branches/master-passphrase/subversion/svn/diff-cmd.c
    subversion/branches/master-passphrase/subversion/svnrdump/dump_editor.c
    subversion/branches/master-passphrase/subversion/tests/cmdline/basic_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/diff_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/info_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/stat_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/svnadmin_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/svnlook_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/trans_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/update_tests.py
    subversion/branches/master-passphrase/subversion/tests/cmdline/upgrade_tests.py
    subversion/branches/master-passphrase/subversion/tests/libsvn_fs/fs-test.c
    subversion/branches/master-passphrase/subversion/tests/libsvn_subr/crypto-test.c
    subversion/branches/master-passphrase/subversion/tests/libsvn_wc/op-depth-test.c
    subversion/branches/master-passphrase/subversion/tests/svn_test_main.c
    subversion/branches/master-passphrase/tools/dev/merge-graph.py
    subversion/branches/master-passphrase/tools/dev/mergegraph/mergegraph.py

Propchange: subversion/branches/master-passphrase/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1310042-1325453

Modified: subversion/branches/master-passphrase/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/CHANGES?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/CHANGES (original)
+++ subversion/branches/master-passphrase/CHANGES Thu Apr 12 19:37:45 2012
@@ -21,6 +21,7 @@ http://svn.apache.org/repos/asf/subversi
     * new --ignore-properties option for 'svn diff' (r1239553. -617)
     * new --patch-compatible option for 'svn diff' (r1239561)
     * new SvnPubSub distributed commit hooks (tools/server-side/svnpubsub)
+    * 'svn diff' can compare arbitrary files and directories (r1310291, et al)
 
   - Client-side bugfixes:
     *
@@ -42,6 +43,24 @@ http://svn.apache.org/repos/asf/subversi
     *
 
 
+Version 1.7.5
+(26 Apr 2012, from /branches/1.7.x)
+http://svn.apache.org/repos/asf/subversion/tags/1.7.5
+
+  User-visible changes:
+    * avoid potential segfault when canonicalizing properties (r1296369)
+    * fix non-fatal FSFS corruption bug with concurrent commits (issue #4129)
+    * improve memory and file-handle management with externals (issue #4130)
+    * ra_serf: convert assertions to errors: MERGE fails (r1302417)
+    * mod_dav_svn: error on MERGE of non-existent resource (r1298343)
+    * fix undefined behaviour during multi-segment reverse merges (issue #4144)
+    * fix potential pool lifetime problem in the diff code (r1311935)
+
+  Developer-visible changes:
+    * swig-py tests: avoid FAILs on APR hash order (r1296137, r1292248)
+    * swig-rb tests: avoid FAILs on APR hash order (r1310535, r1310594)
+
+
 Version 1.7.4
 (08 Mar 2012, from /branches/1.7.x)
 http://svn.apache.org/repos/asf/subversion/tags/1.7.4

Modified: subversion/branches/master-passphrase/COMMITTERS
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/COMMITTERS?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/COMMITTERS [UTF-8] (original)
+++ subversion/branches/master-passphrase/COMMITTERS [UTF-8] Thu Apr 12 19:37:45 2012
@@ -187,6 +187,8 @@ giorgio_valoti   Giorgio Valoti <giorgio
 
   Experimental branches:
 
+         ashod   Ashod Nakashian <ashod@apache.org>          (compressed-
+                                                                 pristines br.)
      gthompson   Glenn A. Thompson <gthompson@cdr.net>       (pluggable-db br.)
        sigfred   Sigfred HÃ¥versen <bsdlist@mumak.com>        (svnserve-ssl br.)
                                                              [EMAIL IS BOUNCING]

Modified: subversion/branches/master-passphrase/contrib/client-side/emacs/dsvn.el
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/contrib/client-side/emacs/dsvn.el?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/contrib/client-side/emacs/dsvn.el (original)
+++ subversion/branches/master-passphrase/contrib/client-side/emacs/dsvn.el Thu Apr 12 19:37:45 2012
@@ -137,12 +137,34 @@
 (setq svn-process-file
   (if (fboundp 'process-file) 'process-file 'call-process))
 
-(defun svn-call-process (program buffer &rest args)
+;; Run svn with default (US-English) messages, since we are going to
+;; parse them.
+(setq svn-process-environment '("LC_MESSAGES=C"))
+
+(defun svn-call-in-svn-environment (func)
+  ;; Dynamic rebinding of process-environment
+  (let ((process-environment
+         (append svn-process-environment process-environment)))
+    (funcall func)))
+
+(defun svn-start-svn-process (buffer args)
+  "Start an svn process associated to BUFFER, with command-line
+arguments ARGS. Return the process object for it."
+  (svn-call-in-svn-environment
+   (lambda ()
+     (apply svn-start-file-process "svn" buffer svn-program args))))
+
+(defun svn-call-svn (infile buffer display args)
+  "Call svn synchronously. Arguments are like process-file."
+  (svn-call-in-svn-environment
+   (lambda ()
+     (apply svn-process-file svn-program infile buffer display args))))
+
+(defun svn-call-process (buffer &rest args)
   "Run svn and wait for it to finish.
-Argument PROGRAM is the svn binary to run.
 Argument BUFFER is the buffer in which to insert output.
 Optional argument ARGS are the arguments to svn."
-  (let ((proc (apply svn-start-file-process "svn" buffer program args)))
+  (let ((proc (svn-start-svn-process buffer args)))
     (set-process-coding-system proc 'utf-8)
     (set-process-filter proc 'svn-output-filter)
     (while (eq (process-status proc) 'run)
@@ -166,9 +188,7 @@ Return non-NIL if there was any output."
         (fundamental-mode))
       (setq default-directory dir)
       (setq buffer-read-only t)
-      (let ((cmd `(,svn-program ,subcommand ,@args))
-            proc)
-        (setq proc (apply svn-start-file-process "svn" buf cmd))
+      (let ((proc (svn-start-svn-process buf (cons subcommand args))))
         (set-process-coding-system proc 'utf-8)
         (set-process-filter proc 'svn-output-filter)
         (while (eq (process-status proc) 'run)
@@ -191,7 +211,7 @@ Returns the buffer that holds the output
     (with-current-buffer buf
       (erase-buffer)
       (setq default-directory dir))
-    (apply svn-process-file svn-program nil buf nil (symbol-name command) args)
+    (svn-call-svn nil buf nil (cons (symbol-name command) args))
     buf))
 
 (defun svn-run-for-stdout (command args)
@@ -199,8 +219,8 @@ Returns the buffer that holds the output
 Argument COMMAND is the svn subcommand to run.
 Optional argument ARGS is a list of arguments."
   (let ((output-buffer (generate-new-buffer "*svn-stdout*")))
-    (apply svn-process-file svn-program nil (list output-buffer nil) nil
-	   (symbol-name command) args)
+    (svn-call-svn nil (list output-buffer nil) nil
+                  (cons (symbol-name command) args))
     (let ((stdout (with-current-buffer output-buffer (buffer-string))))
       (kill-buffer output-buffer)
       stdout)))
@@ -262,8 +282,7 @@ buffer to describe what is going on."
             args (cons "-v" args)))
     (unless (memq command svn-noninteractive-blacklist)
       (setq args (cons "--non-interactive" args)))
-    (setq proc (apply svn-start-file-process "svn" (current-buffer)
-                      svn-program command-s args))
+    (setq proc (svn-start-svn-process (current-buffer) (cons command-s args)))
     (if (fboundp filter-func)
         (set-process-filter proc filter-func)
       (set-process-filter proc 'svn-default-filter))
@@ -553,7 +572,7 @@ VERBOSE-P."
       (setq buffer-read-only t)
       (erase-buffer)
       (setq default-directory dir)
-      (svn-call-process svn-program diff-buf
+      (svn-call-process diff-buf
                         "diff" "-r"
                         (format "%d:%d" (1- commit-id) commit-id)))))
 
@@ -1219,6 +1238,8 @@ With prefix arg, prompt for REVISION."
               ((looking-at "At revision \\([0-9]+\\)\\.\n")
                (svn-update-label svn-revision-label (match-string 1))
                (forward-line 1))
+              ((looking-at "Updating '.*':\n")
+               (delete-region (match-beginning 0) (match-end 0)))
               ((and (not svn-merging)
                     (looking-at "Updated to revision \\([0-9]+\\)\\.\n"))
                (svn-update-label svn-revision-label (match-string 1))

Modified: subversion/branches/master-passphrase/notes/knobs
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/notes/knobs?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/notes/knobs (original)
+++ subversion/branches/master-passphrase/notes/knobs Thu Apr 12 19:37:45 2012
@@ -134,20 +134,23 @@ SVN_I_LIKE_LATENCY_SO_IGNORE_HTTPV2
 3.6 SVN_FS_FS_MAX_LINEAR_DELTIFICATION
 
   Scope:     libsvn_fs_fs
-  Purpose:   max length + 1 of the linear deltification history
-             before skip-deltification kicks in
+  Purpose:   Controls the space efficiency vs. reconstruction costs tradeoff
+             of rep deltification.  Defines the max length of the linear
+             deltification history before skip-deltification kicks in.
+             Values < 2 result in skip-delta-only behavior.
   Default:   16
-  Range:     natural integers
-  Suggested: 2, 4, 8, 16, 32, 64
+  Range:     natural integers; should be a power of 2
+  Suggested: 1, 4, 8, 16, 32, 64
 
 3.7 SVN_FS_FS_MAX_DELTIFICATION_WALK
 
   Scope:     libsvn_fs_fs
-  Purpose:   max skip deltification range. Change histories
-             longer than that will be restarted with a fulltext.
+  Purpose:   Limits the skip deltification range to provide commit runtime
+             guarantees. Change histories longer than that will be restarted
+             with a fulltext.  Values < 1 disable deltification.
   Default:   1023
-  Range:     natural integers
-  Suggested: 1, 2, 3, 4, 5, 7, 11
+  Range:     natural integers; should be a power of 2 minus one
+  Suggested: 0, 63, 1023, 4095, 16383
 
 3.8 SVN_UNALIGNED_ACCESS_IS_OK
 

Modified: subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_client.rb
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_client.rb?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_client.rb (original)
+++ subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_client.rb Thu Apr 12 19:37:45 2012
@@ -2341,7 +2341,9 @@ class SvnClientTest < Test::Unit::TestCa
 
   def test_changelists_get_without_block
     assert_changelists do |ctx, changelist_name|
-      ctx.changelists(changelist_name, @wc_path)
+      changelists = ctx.changelists(changelist_name, @wc_path)
+      changelists.each_value { |v| v.sort! }
+      changelists
     end
   end
 
@@ -2351,6 +2353,7 @@ class SvnClientTest < Test::Unit::TestCa
       ctx.changelists(changelist_name, @wc_path) do |path,cl_name|
         changelists[cl_name] << path
       end
+      changelists.each_value { |v| v.sort! }
       changelists
     end
   end

Modified: subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_wc.rb
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_wc.rb?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_wc.rb (original)
+++ subversion/branches/master-passphrase/subversion/bindings/swig/ruby/test/test_wc.rb Thu Apr 12 19:37:45 2012
@@ -747,14 +747,15 @@ EOE
             :file_changed_prop_name => prop_name,
             :file_changed_prop_value => prop_value,
           }
-          expected_props, actual_result = yield(property_info, callbacks.result)
+          sorted_result = callbacks.result.sort_by {|r| r.first.to_s}
+          expected_props, actual_result = yield(property_info, sorted_result)
           dir_changed_props, file_changed_props, empty_changed_props = expected_props
           assert_equal([
                         [:dir_props_changed, @wc_path, dir_changed_props],
-                        [:file_changed, path1, file_changed_props],
                         [:file_added, path2, empty_changed_props],
+                        [:file_changed, path1, file_changed_props],
                        ],
-                       callbacks.result)
+                       sorted_result)
         end
       end
     end

Modified: subversion/branches/master-passphrase/subversion/include/private/svn_temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/private/svn_temp_serializer.h?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/private/svn_temp_serializer.h (original)
+++ subversion/branches/master-passphrase/subversion/include/private/svn_temp_serializer.h Thu Apr 12 19:37:45 2012
@@ -188,10 +188,10 @@ svn_temp_deserializer__resolve(void *buf
 /**
  * Similar to svn_temp_deserializer__resolve() but instead of modifying
  * the buffer content, the resulting pointer is passed back to the caller
- * a the return value.
+ * as the return value.
  */
 const void *
-svn_temp_deserializer__ptr(const void *buffer, const void **ptr);
+svn_temp_deserializer__ptr(const void *buffer, const void *const *ptr);
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/master-passphrase/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/svn_config.h?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_config.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_config.h Thu Apr 12 19:37:45 2012
@@ -303,6 +303,32 @@ svn_config_set_bool(svn_config_t *cfg,
                     const char *option,
                     svn_boolean_t value);
 
+/** Like svn_config_get(), but for 64 bit signed integers.
+ *
+ * Parses the option as an integer value. Returns an error if the option
+ * could not be converted to an integer.
+ *
+ * @since New in 1.8
+ */
+svn_error_t *
+svn_config_get_int64(svn_config_t *cfg,
+                     apr_int64_t *valuep,
+                     const char *section,
+                     const char *option,
+                     apr_int64_t default_value);
+
+/** Like svn_config_set(), but for 64 bit signed integers.
+ *
+ * Sets the option to the signed decimal @a value.
+ *
+ * @since New in 1.8
+ */
+void
+svn_config_set_int64(svn_config_t *cfg,
+                     const char *section,
+                     const char *option,
+                     apr_int64_t value);
+
 /** Like svn_config_get(), but only for yes/no/ask values.
  *
  * Parse @a option in @a section and set @a *valuep to one of

Modified: subversion/branches/master-passphrase/subversion/include/svn_delta.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/svn_delta.h?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_delta.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_delta.h Thu Apr 12 19:37:45 2012
@@ -1170,6 +1170,8 @@ svn_editor__insert_shims(const svn_delta
                          void **dedit_baton_out,
                          const svn_delta_editor_t *deditor_in,
                          void *dedit_baton_in,
+                         const char *repos_root,
+                         const char *base_dir,
                          svn_delta_shim_callbacks_t *shim_callbacks,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);

Modified: subversion/branches/master-passphrase/subversion/include/svn_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/svn_editor.h?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_editor.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_editor.h Thu Apr 12 19:37:45 2012
@@ -153,12 +153,14 @@ extern "C" {
  * "should", "should not", "recommended", "may", and "optional" in this
  * document are to be interpreted as described in RFC 2119.
  *
- * @note The editor is *not* reentrant. The receiver should not directly
- * or indirectly invoke an editor API unless it has been marked as
- * explicitly supporting reentrancy during a receiver's callback. This
- * limitation extends to the cancellation callback, too. (This limitation
- * is due to the scratch_pool shared by all callbacks, and cleared after
- * each callback; a reentrant call could clear the outer call's pool)
+ * @note The editor objects are *not* reentrant. The receiver should not
+ * directly or indirectly invoke an editor API with the same object unless
+ * it has been marked as explicitly supporting reentrancy during a
+ * receiver's callback. This limitation extends to the cancellation
+ * callback, too. (This limitation is due to the scratch_pool shared by
+ * all callbacks, and cleared after each callback; a reentrant call could
+ * clear the outer call's pool). Note that the code itself is reentrant, so
+ * there is no problem using the APIs on different editor objects.
  *
  * \n
  * <h3>Life-Cycle</h3>
@@ -254,9 +256,8 @@ extern "C" {
  *   This allows the parent directory to properly mark the child as
  *   "incomplete" until the child's add_* call arrives.
  *
- * - A path should
- *   never be referenced more than once by the add_*, alter_*, and
- *   delete operations (the "Once Rule"). The source path of a copy (and
+ * - A path should never be referenced more than once by the add_*, alter_*,
+ *   and delete operations (the "Once Rule"). The source path of a copy (and
  *   its children, if a directory) may be copied many times, and are
  *   otherwise subject to the Once Rule. The destination path of a copy
  *   or move may have alter_* operations applied, but not add_* or delete.
@@ -340,14 +341,19 @@ extern "C" {
  *
  * <h3>Paths</h3>
  * Each driver/receiver implementation of this editor interface must
- * establish the expected root path for the paths sent and received via the
- * callbacks' @a relpath arguments.
+ * establish the expected root for all the paths sent and received via
+ * the callbacks' @a relpath arguments.
  *
- * For example, during an "update", the driver has a working copy checked
- * out at a specific repository URL. The receiver sees the repository as a
- * whole. Here, the receiver could tell the driver which repository
- * URL the working copy refers to, and thus the driver could send
- * @a relpath arguments that are relative to the receiver's working copy.
+ * For example, during an "update", the driver is the repository, as a
+ * whole. The receiver may have just a portion of that repository. Here,
+ * the receiver could tell the driver which repository URL the working
+ * copy refers to, and thus the driver could send @a relpath arguments
+ * that are relative to the receiver's working copy.
+ *
+ * @note Because the source of a copy may be located *anywhere* in the
+ * repository, editor drives should typically use the repository root
+ * as the negotiated root. This allows the @a src_relpath argument in
+ * svn_editor_copy() to specify any possible source.
  * \n\n
  *
  * <h3>Pool Usage</h3>
@@ -860,9 +866,10 @@ svn_editor_add_absent(svn_editor_t *edit
 
 /** Drive @a editor's #svn_editor_cb_alter_directory_t callback.
  *
- * Alter the properties of the directory at @a relpath. @a revision
- * specifies the expected revision of the directory. This is used to
- * catched attempts at altering out-of-date directories. If the
+ * Alter the properties of the directory at @a relpath.
+ *
+ * @a revision specifies the expected revision of the directory and is
+ * used to catch attempts at altering out-of-date directories. If the
  * directory does not have a corresponding revision in the repository
  * (e.g. it has not yet been committed), then @a revision should be
  * #SVN_INVALID_REVNUM.
@@ -955,6 +962,11 @@ svn_editor_delete(svn_editor_t *editor,
  *
  * For a description of @a replaces_rev, see svn_editor_add_file().
  *
+ * @note See the general instructions on paths for this API. Since the
+ * @a src_relpath argument must generally be able to reference any node
+ * in the repository, the implication is that the editor's root must be
+ * the repository root.
+ *
  * For all restrictions on driving the editor, see #svn_editor_t.
  * @since New in 1.8.
  */
@@ -971,6 +983,9 @@ svn_editor_copy(svn_editor_t *editor,
  *
  * For a description of @a replaces_rev, see svn_editor_add_file().
  *
+ * ### what happens if one side of this move is not "within" the receiver's
+ * ### set of paths?
+ *
  * For all restrictions on driving the editor, see #svn_editor_t.
  * @since New in 1.8.
  */
@@ -1000,6 +1015,9 @@ svn_editor_move(svn_editor_t *editor,
  * restrictions against multiple moves of a single node, the rotation
  * operation is needed for certain types of tree edits.
  *
+ * ### what happens if one of the paths of the rotation is not "within" the
+ * ### receiver's set of paths?
+ *
  * For all restrictions on driving the editor, see #svn_editor_t.
  * @since New in 1.8.
  */

Modified: subversion/branches/master-passphrase/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_client/copy.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_client/copy.c Thu Apr 12 19:37:45 2012
@@ -374,7 +374,8 @@ do_wc_to_wc_moves(const apr_array_header
           lock_src = TRUE;
           lock_dst = FALSE;
         }
-      else if (svn_dirent_is_child(pair->dst_parent_abspath, src_parent_abspath,
+      else if (svn_dirent_is_child(pair->dst_parent_abspath,
+                                   src_parent_abspath,
                                    iterpool))
         {
           lock_src = FALSE;
@@ -395,7 +396,8 @@ do_wc_to_wc_moves(const apr_array_header
           FALSE, iterpool);
       else
         SVN_ERR(do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
-                                              lock_src, lock_dst, ctx, iterpool));
+                                              lock_src, lock_dst, ctx,
+                                              iterpool));
 
     }
   svn_pool_destroy(iterpool);
@@ -1163,7 +1165,8 @@ check_url_kind(void *baton,
 
 /* ### Copy ...
  * COMMIT_INFO_P is ...
- * COPY_PAIRS is ...
+ * COPY_PAIRS is ... such that each 'src_abspath_or_url' is a local abspath
+ * and each 'dst_abspath_or_url' is a URL.
  * MAKE_PARENTS is ...
  * REVPROP_TABLE is ...
  * CTX is ... */
@@ -1203,7 +1206,9 @@ wc_to_repos_copy(const apr_array_header_
 
   /* Verify that all the source paths exist, are versioned, etc.
      We'll do so by querying the base revisions of those things (which
-     we'll need to know later anyway). */
+     we'll need to know later anyway).
+     ### Should we use the 'origin' revision instead of 'base'?
+    */
   for (i = 0; i < copy_pairs->nelts; i++)
     {
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
@@ -1407,7 +1412,7 @@ wc_to_repos_copy(const apr_array_header_
   SVN_ERR(svn_client__condense_commit_items(&top_dst_url,
                                             commit_items, pool));
 
-#if ENABLE_EV2_SHIMS
+#ifdef ENABLE_EV2_SHIMS
   for (i = 0; !common_wc_abspath && i < commit_items->nelts; i++)
     {
       common_wc_abspath = APR_ARRAY_IDX(commit_items, i,

Modified: subversion/branches/master-passphrase/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_client/diff.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_client/diff.c Thu Apr 12 19:37:45 2012
@@ -805,6 +805,17 @@ struct diff_cmd_baton {
 };
 
 
+/* A helper function that marks a path as visited. It copies PATH
+ * into the correct pool before referencing it from the hash table. */
+static void
+mark_path_as_visited(struct diff_cmd_baton *diff_cmd_baton, const char *path)
+{
+  const char *p;
+
+  p = apr_pstrdup(apr_hash_pool_get(diff_cmd_baton->visited_paths), path);
+  apr_hash_set(diff_cmd_baton->visited_paths, p, APR_HASH_KEY_STRING, p);
+}
+
 /* An helper for diff_dir_props_changed, diff_file_changed and diff_file_added
  */
 static svn_error_t *
@@ -855,8 +866,7 @@ diff_props_changed(svn_wc_notify_state_t
       /* We've printed the diff header so now we can mark the path as
        * visited. */
       if (show_diff_header)
-        apr_hash_set(diff_cmd_baton->visited_paths, path,
-                     APR_HASH_KEY_STRING, path);
+        mark_path_as_visited(diff_cmd_baton, path);
     }
 
   if (state)
@@ -1072,9 +1082,7 @@ diff_content_changed(const char *path,
                      subpool));
 
           /* We have a printed a diff for this path, mark it as visited. */
-          apr_hash_set(diff_cmd_baton->visited_paths, path,
-                       APR_HASH_KEY_STRING, path);
-
+          mark_path_as_visited(diff_cmd_baton, path);
         }
     }
 
@@ -1773,6 +1781,478 @@ unsupported_diff_error(svn_error_t *chil
                             "that is not yet supported"));
 }
 
+/* Try to get properties for LOCAL_ABSPATH and return them in the property
+ * hash *PROPS. If there are no properties because LOCAL_ABSPATH is not
+ * versioned, return an empty property hash. */
+static svn_error_t *
+get_props(apr_hash_t **props,
+          const char *local_abspath,
+          svn_wc_context_t *wc_ctx,
+          apr_pool_t *result_pool,
+          apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+
+  err = svn_wc_prop_list2(props, wc_ctx, local_abspath, result_pool,
+                          scratch_pool);
+  if (err)
+    {
+      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
+          err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY ||
+          err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+        {
+          svn_error_clear(err);
+          *props = apr_hash_make(result_pool);
+        }
+      else
+        return svn_error_trace(err);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Produce a diff between two arbitrary files at LOCAL_ABSPATH1 and
+ * LOCAL_ABSPATH2, using the diff callbacks from CALLBACKS.
+ * Use PATH as the name passed to diff callbacks.
+ * FILE1_IS_EMPTY and FILE2_IS_EMPTY are used as hints which diff callback
+ * function to use to compare the files (added/deleted/changed).
+ *
+ * If ORIGINAL_PROPS_OVERRIDE is not NULL, use it as original properties
+ * instead of reading properties from LOCAL_ABSPATH1. This is required when
+ * a file replaces a directory, where LOCAL_ABSPATH1 is an empty file that
+ * file content must be diffed against, but properties to diff against come
+ * from the replaced directory. */
+static svn_error_t *
+do_arbitrary_files_diff(const char *local_abspath1,
+                        const char *local_abspath2,
+                        const char *path,
+                        svn_boolean_t file1_is_empty,
+                        svn_boolean_t file2_is_empty,
+                        apr_hash_t *original_props_override,
+                        const svn_wc_diff_callbacks4_t *callbacks,
+                        struct diff_cmd_baton *diff_cmd_baton,
+                        svn_client_ctx_t *ctx,
+                        apr_pool_t *scratch_pool)
+{
+  apr_hash_t *original_props;
+  apr_hash_t *modified_props;
+  apr_array_header_t *prop_changes;
+  svn_string_t *original_mime_type = NULL;
+  svn_string_t *modified_mime_type = NULL;
+
+  if (ctx->cancel_func)
+    SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
+  if (diff_cmd_baton->ignore_prop_diff)
+    {
+      original_props = apr_hash_make(scratch_pool);
+      modified_props = apr_hash_make(scratch_pool);
+    }
+  else
+    {
+      /* Try to get properties from either file. It's OK if the files do not
+       * have properties, or if they are unversioned. */
+      if (original_props_override)
+        original_props = original_props_override;
+      else
+        SVN_ERR(get_props(&original_props, local_abspath1, ctx->wc_ctx,
+                          scratch_pool, scratch_pool));
+      SVN_ERR(get_props(&modified_props, local_abspath2, ctx->wc_ctx,
+                        scratch_pool, scratch_pool));
+    }
+
+  SVN_ERR(svn_prop_diffs(&prop_changes, modified_props, original_props,
+                         scratch_pool));
+
+  if (!diff_cmd_baton->force_binary)
+    {
+      /* Try to determine the mime-type of each file. */
+      original_mime_type = apr_hash_get(original_props, SVN_PROP_MIME_TYPE,
+                                        APR_HASH_KEY_STRING);
+      if (!file1_is_empty && !original_mime_type)
+        {
+          const char *mime_type;
+          SVN_ERR(svn_io_detect_mimetype2(&mime_type, local_abspath1,
+                                          ctx->mimetypes_map, scratch_pool));
+
+          if (mime_type)
+            original_mime_type = svn_string_create(mime_type, scratch_pool);
+        }
+
+      modified_mime_type = apr_hash_get(modified_props, SVN_PROP_MIME_TYPE,
+                                        APR_HASH_KEY_STRING);
+      if (!file2_is_empty && !modified_mime_type)
+        {
+          const char *mime_type;
+          SVN_ERR(svn_io_detect_mimetype2(&mime_type, local_abspath1,
+                                          ctx->mimetypes_map, scratch_pool));
+
+          if (mime_type)
+            modified_mime_type = svn_string_create(mime_type, scratch_pool);
+        }
+    }
+
+  /* Produce the diff. */
+  if (file1_is_empty && !file2_is_empty)
+    SVN_ERR(callbacks->file_added(NULL, NULL, NULL, path,
+                                  local_abspath1, local_abspath2,
+                                  /* ### TODO get real revision info
+                                   * for versioned files? */
+                                  SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+                                  original_mime_type ?
+                                    original_mime_type->data : NULL,
+                                  modified_mime_type ?
+                                    modified_mime_type->data : NULL,
+                                  /* ### TODO get copyfrom? */
+                                  NULL, SVN_INVALID_REVNUM,
+                                  prop_changes, original_props,
+                                  diff_cmd_baton, scratch_pool));
+  else if (!file1_is_empty && file2_is_empty)
+    SVN_ERR(callbacks->file_deleted(NULL, NULL, path,
+                                    local_abspath1, local_abspath2,
+                                    original_mime_type ?
+                                      original_mime_type->data : NULL,
+                                    modified_mime_type ?
+                                      modified_mime_type->data : NULL,
+                                    original_props,
+                                    diff_cmd_baton, scratch_pool));
+  else
+    SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, path,
+                                    local_abspath1, local_abspath2,
+                                    /* ### TODO get real revision info
+                                     * for versioned files? */
+                                    SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+                                    original_mime_type ?
+                                      original_mime_type->data : NULL,
+                                    modified_mime_type ?
+                                      modified_mime_type->data : NULL,
+                                    prop_changes, original_props,
+                                    diff_cmd_baton, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+struct arbitrary_diff_walker_baton {
+  /* The root directories of the trees being compared. */
+  const char *root1_abspath;
+  const char *root2_abspath;
+
+  /* TRUE if recursing within an added subtree of root2_abspath that
+   * does not exist in root1_abspath. */
+  svn_boolean_t recursing_within_added_subtree;
+
+  /* TRUE if recursing within an administrative (.i.e. .svn) directory. */
+  svn_boolean_t recursing_within_adm_dir;
+
+  /* The absolute path of the adm dir if RECURSING_WITHIN_ADM_DIR is TRUE.
+   * Else this is NULL.*/
+  const char *adm_dir_abspath;
+
+  /* A path to an empty file used for diffs that add/delete files. */
+  const char *empty_file_abspath;
+
+  const svn_wc_diff_callbacks4_t *callbacks;
+  struct diff_cmd_baton *callback_baton;
+  svn_client_ctx_t *ctx;
+  apr_pool_t *pool;
+} arbitrary_diff_walker_baton;
+
+/* Forward declaration needed because this function has a cyclic
+ * dependency with do_arbitrary_dirs_diff(). */
+static svn_error_t *
+arbitrary_diff_walker(void *baton, const char *local_abspath,
+                      const apr_finfo_t *finfo,
+                      apr_pool_t *scratch_pool);
+
+/* Produce a diff between two arbitrary directories at LOCAL_ABSPATH1 and
+ * LOCAL_ABSPATH2, using the provided diff callbacks to show file changes
+ * and, for versioned nodes, property changes.
+ *
+ * If ROOT_ABSPATH1 and ROOT_ABSPATH2 are not NULL, show paths in diffs
+ * relative to these roots, rather than relative to LOCAL_ABSPATH1 and
+ * LOCAL_ABSPATH2. This is needed when crawling a subtree that exists
+ * only within LOCAL_ABSPATH2. */
+static svn_error_t *
+do_arbitrary_dirs_diff(const char *local_abspath1,
+                       const char *local_abspath2,
+                       const char *root_abspath1,
+                       const char *root_abspath2,
+                       const svn_wc_diff_callbacks4_t *callbacks,
+                       struct diff_cmd_baton *callback_baton,
+                       svn_client_ctx_t *ctx,
+                       apr_pool_t *scratch_pool)
+{
+  apr_file_t *empty_file;
+  svn_node_kind_t kind1;
+
+  struct arbitrary_diff_walker_baton b;
+
+  /* If LOCAL_ABSPATH1 is not a directory, crawl LOCAL_ABSPATH2 instead
+   * and compare it to LOCAL_ABSPATH1, showing only additions.
+   * This case can only happen during recursion from arbitrary_diff_walker(),
+   * because do_arbitrary_nodes_diff() prevents this from happening at
+   * the root of the comparison. */
+  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
+  b.recursing_within_added_subtree = (kind1 != svn_node_dir);
+
+  b.root1_abspath = root_abspath1 ? root_abspath1 : local_abspath1;
+  b.root2_abspath = root_abspath2 ? root_abspath2 : local_abspath2;
+  b.recursing_within_adm_dir = FALSE;
+  b.adm_dir_abspath = NULL;
+  b.callbacks = callbacks;
+  b.callback_baton = callback_baton;
+  b.ctx = ctx;
+  b.pool = scratch_pool;
+
+  SVN_ERR(svn_io_open_unique_file3(&empty_file, &b.empty_file_abspath,
+                                   NULL, svn_io_file_del_on_pool_cleanup,
+                                   scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
+                                                            : local_abspath1,
+                           0, arbitrary_diff_walker, &b, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* An implementation of svn_io_walk_func_t.
+ * Note: LOCAL_ABSPATH is the path being crawled and can be on either side
+ * of the diff depending on baton->recursing_within_added_subtree. */
+static svn_error_t *
+arbitrary_diff_walker(void *baton, const char *local_abspath,
+                      const apr_finfo_t *finfo,
+                      apr_pool_t *scratch_pool)
+{
+  struct arbitrary_diff_walker_baton *b = baton;
+  const char *local_abspath1;
+  const char *local_abspath2;
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
+  const char *child_relpath;
+  apr_hash_t *dirents1;
+  apr_hash_t *dirents2;
+  apr_hash_t *merged_dirents;
+  apr_array_header_t *sorted_dirents;
+  int i;
+  apr_pool_t *iterpool;
+
+  if (b->ctx->cancel_func)
+    SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
+
+  if (finfo->filetype != APR_DIR)
+    return SVN_NO_ERROR;
+
+  if (b->recursing_within_adm_dir)
+    {
+      if (svn_dirent_skip_ancestor(b->adm_dir_abspath, local_abspath))
+        return SVN_NO_ERROR;
+      else
+        {
+          b->recursing_within_adm_dir = FALSE;
+          b->adm_dir_abspath = NULL;
+        }
+    }
+  else if (strcmp(svn_dirent_basename(local_abspath, scratch_pool),
+                  SVN_WC_ADM_DIR_NAME) == 0)
+    {
+      b->recursing_within_adm_dir = TRUE;
+      b->adm_dir_abspath = apr_pstrdup(b->pool, local_abspath);
+      return SVN_NO_ERROR;
+    }
+
+  if (b->recursing_within_added_subtree)
+    child_relpath = svn_dirent_skip_ancestor(b->root2_abspath, local_abspath);
+  else
+    child_relpath = svn_dirent_skip_ancestor(b->root1_abspath, local_abspath);
+  if (!child_relpath)
+    return SVN_NO_ERROR;
+
+  local_abspath1 = svn_dirent_join(b->root1_abspath, child_relpath,
+                                   scratch_pool);
+  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
+
+  local_abspath2 = svn_dirent_join(b->root2_abspath, child_relpath,
+                                   scratch_pool);
+  SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool));
+
+  if (kind1 == svn_node_dir)
+    SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1,
+                                TRUE, /* only_check_type */
+                                scratch_pool, scratch_pool));
+  else
+    dirents1 = apr_hash_make(scratch_pool);
+
+  if (kind2 == svn_node_dir)
+    {
+      apr_hash_t *original_props;
+      apr_hash_t *modified_props;
+      apr_array_header_t *prop_changes;
+
+      /* Show any property changes for this directory. */
+      SVN_ERR(get_props(&original_props, local_abspath1, b->ctx->wc_ctx,
+                        scratch_pool, scratch_pool));
+      SVN_ERR(get_props(&modified_props, local_abspath2, b->ctx->wc_ctx,
+                        scratch_pool, scratch_pool));
+      SVN_ERR(svn_prop_diffs(&prop_changes, modified_props, original_props,
+                             scratch_pool));
+      if (prop_changes->nelts > 0)
+        SVN_ERR(diff_props_changed(NULL, NULL, child_relpath,
+                                   b->recursing_within_added_subtree,
+                                   prop_changes, original_props,
+                                   b->callback_baton, scratch_pool));
+
+      /* Read directory entries. */
+      SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2,
+                                  TRUE, /* only_check_type */
+                                  scratch_pool, scratch_pool));
+    }
+  else
+    dirents2 = apr_hash_make(scratch_pool);
+
+  /* Compare dirents1 to dirents2 and show added/deleted/changed files. */
+  merged_dirents = apr_hash_merge(scratch_pool, dirents1, dirents2,
+                                  NULL, NULL);
+  sorted_dirents = svn_sort__hash(merged_dirents,
+                                  svn_sort_compare_items_as_paths,
+                                  scratch_pool);
+  iterpool = svn_pool_create(scratch_pool);
+  for (i = 0; i < sorted_dirents->nelts; i++)
+    {
+      svn_sort__item_t elt = APR_ARRAY_IDX(sorted_dirents, i, svn_sort__item_t);
+      const char *name = elt.key;
+      svn_io_dirent2_t *dirent1;
+      svn_io_dirent2_t *dirent2;
+      const char *child1_abspath;
+      const char *child2_abspath;
+
+      svn_pool_clear(iterpool);
+
+      if (b->ctx->cancel_func)
+        SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
+
+      if (strcmp(name, SVN_WC_ADM_DIR_NAME) == 0)
+        continue;
+
+      dirent1 = apr_hash_get(dirents1, name, APR_HASH_KEY_STRING);
+      if (!dirent1)
+        {
+          dirent1 = svn_io_dirent2_create(iterpool);
+          dirent1->kind = svn_node_none;
+        }
+      dirent2 = apr_hash_get(dirents2, name, APR_HASH_KEY_STRING);
+      if (!dirent2)
+        {
+          dirent2 = svn_io_dirent2_create(iterpool);
+          dirent2->kind = svn_node_none;
+        }
+
+      child1_abspath = svn_dirent_join(local_abspath1, name, iterpool);
+      child2_abspath = svn_dirent_join(local_abspath2, name, iterpool);
+
+      if (dirent1->special)
+        SVN_ERR(svn_io_check_resolved_path(child1_abspath, &dirent1->kind,
+                                           iterpool));
+      if (dirent2->special)
+        SVN_ERR(svn_io_check_resolved_path(child1_abspath, &dirent2->kind,
+                                           iterpool));
+
+      if (dirent1->kind == svn_node_dir &&
+          dirent2->kind == svn_node_dir)
+        continue;
+
+      /* Files that exist only in dirents1. */
+      if (dirent1->kind == svn_node_file &&
+          (dirent2->kind == svn_node_dir || dirent2->kind == svn_node_none))
+        SVN_ERR(do_arbitrary_files_diff(child1_abspath, b->empty_file_abspath,
+                                        svn_relpath_join(child_relpath, name,
+                                                         iterpool),
+                                        FALSE, TRUE, NULL,
+                                        b->callbacks, b->callback_baton,
+                                        b->ctx, iterpool));
+
+      /* Files that exist only in dirents2. */
+      if (dirent2->kind == svn_node_file &&
+          (dirent1->kind == svn_node_dir || dirent1->kind == svn_node_none))
+        {
+          apr_hash_t *original_props;
+
+          SVN_ERR(get_props(&original_props, child1_abspath, b->ctx->wc_ctx,
+                            scratch_pool, scratch_pool));
+          SVN_ERR(do_arbitrary_files_diff(b->empty_file_abspath, child2_abspath,
+                                          svn_relpath_join(child_relpath, name,
+                                                           iterpool),
+                                          TRUE, FALSE, original_props,
+                                          b->callbacks, b->callback_baton,
+                                          b->ctx, iterpool));
+        }
+
+      /* Files that exist in dirents1 and dirents2. */
+      if (dirent1->kind == svn_node_file && dirent2->kind == svn_node_file)
+        SVN_ERR(do_arbitrary_files_diff(child1_abspath, child2_abspath,
+                                        svn_relpath_join(child_relpath, name,
+                                                         iterpool),
+                                        FALSE, FALSE, NULL,
+                                        b->callbacks, b->callback_baton,
+                                        b->ctx, scratch_pool));
+
+      /* Directories that only exist in dirents2. These aren't crawled
+       * by this walker so we have to crawl them separately. */
+      if (dirent2->kind == svn_node_dir &&
+          (dirent1->kind == svn_node_file || dirent1->kind == svn_node_none))
+        SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath,
+                                       b->root1_abspath, b->root2_abspath,
+                                       b->callbacks, b->callback_baton,
+                                       b->ctx, iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* Produce a diff between two files or two directories at LOCAL_ABSPATH1
+ * and LOCAL_ABSPATH2, using the provided diff callbacks to show changes
+ * in files. The files and directories involved may be part of a working
+ * copy or they may be unversioned. For versioned files, show property
+ * changes, too. */ 
+static svn_error_t *
+do_arbitrary_nodes_diff(const char *local_abspath1,
+                        const char *local_abspath2,
+                        const svn_wc_diff_callbacks4_t *callbacks,
+                        struct diff_cmd_baton *callback_baton,
+                        svn_client_ctx_t *ctx,
+                        apr_pool_t *scratch_pool)
+{
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
+
+  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
+  SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool));
+  if (kind1 != kind2)
+    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                             _("'%s' is not the same node kind as '%s'"),
+                             local_abspath1, local_abspath2);
+
+  if (kind1 == svn_node_file)
+    SVN_ERR(do_arbitrary_files_diff(local_abspath1, local_abspath2,
+                                    svn_dirent_basename(local_abspath2,
+                                                        scratch_pool),
+                                    FALSE, FALSE, NULL,
+                                    callbacks, callback_baton,
+                                    ctx, scratch_pool));
+  else if (kind1 == svn_node_dir)
+    SVN_ERR(do_arbitrary_dirs_diff(local_abspath1, local_abspath2,
+                                   NULL, NULL,
+                                   callbacks, callback_baton,
+                                   ctx, scratch_pool));
+  else
+    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                             _("'%s' is not a file or directory"),
+                             kind1 == svn_node_none ?
+                              local_abspath1 : local_abspath2);
+  return SVN_NO_ERROR;
+}
+
 
 /* Perform a diff between two working-copy paths.
 
@@ -1804,16 +2284,18 @@ diff_wc_wc(const char *path1,
 
   SVN_ERR(svn_dirent_get_absolute(&abspath1, path1, pool));
 
-  /* 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")));
+    {
+      const char *abspath2;
+
+      SVN_ERR(svn_dirent_get_absolute(&abspath2, path2, pool));
+      return svn_error_trace(do_arbitrary_nodes_diff(abspath1, abspath2,
+                                                     callbacks,
+                                                     callback_baton,
+                                                     ctx, pool));
+    }
 
   /* Resolve named revisions to real numbers. */
   err = svn_client__get_revision_number(&callback_baton->revnum1, NULL,
@@ -2209,8 +2691,8 @@ diff_summarize_wc_wc(svn_client_diff_sum
     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")));
+        _("Summarized diffs are only supported between a path's text-base "
+          "and its working files 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. */

Modified: subversion/branches/master-passphrase/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_client/export.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_client/export.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_client/export.c Thu Apr 12 19:37:45 2012
@@ -1236,7 +1236,8 @@ svn_client_export5(svn_revnum_t *result_
 
           SVN_ERR(svn_editor__insert_shims(&export_editor, &edit_baton,
                                            export_editor, edit_baton,
-                                           shim_callbacks, pool, pool));
+                                           NULL, NULL, shim_callbacks,
+                                           pool, pool));
 
           /* Manufacture a basic 'report' to the update reporter. */
           SVN_ERR(svn_ra_do_update2(ra_session,

Modified: subversion/branches/master-passphrase/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_client/merge.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_client/merge.c Thu Apr 12 19:37:45 2012
@@ -893,8 +893,8 @@ filter_self_referential_mergeinfo(apr_ar
   if (is_added)
     return SVN_NO_ERROR;
 
-  SVN_ERR(svn_client_url_from_path2(&target_base.url, target_abspath,
-                                    ctx, pool, pool));
+  SVN_ERR(svn_wc__node_get_url(&target_base.url, ctx->wc_ctx, target_abspath,
+                               pool, pool));
   SVN_ERR(svn_wc__node_get_base_rev(&target_base.rev, ctx->wc_ctx,
                                     target_abspath, pool));
   SVN_ERR(svn_wc__node_get_repos_info(&target_base.repos_root_url,
@@ -6234,7 +6234,7 @@ combine_range_with_segments(apr_array_he
     {
       svn_location_segment_t *segment =
         APR_ARRAY_IDX(segments, i, svn_location_segment_t *);
-      svn_client__pathrev_t loc1, loc2;
+      svn_client__pathrev_t *loc1, *loc2;
       merge_source_t *merge_source;
       const char *path1 = NULL;
       svn_revnum_t rev1;
@@ -6282,25 +6282,17 @@ combine_range_with_segments(apr_array_he
         continue;
 
       /* Build our merge source structure. */
-      loc1.repos_root_url = source_loc->repos_root_url;
-      loc1.repos_uuid = source_loc->repos_uuid;
-      loc1.rev = rev1;
-      loc1.url = svn_path_url_add_component2(source_loc->repos_root_url,
-                                             path1, pool);
-      loc2.repos_root_url = source_loc->repos_root_url;
-      loc2.repos_uuid = source_loc->repos_uuid;
-      loc2.rev = MIN(segment->range_end, maxrev);
-      loc2.url = svn_path_url_add_component2(source_loc->repos_root_url,
-                                             segment->path, pool);
-      merge_source = merge_source_create(&loc1, &loc2, pool);
-
+      loc1 = svn_client__pathrev_create_with_relpath(
+               source_loc->repos_root_url, source_loc->repos_uuid,
+               rev1, path1, pool);
+      loc2 = svn_client__pathrev_create_with_relpath(
+               source_loc->repos_root_url, source_loc->repos_uuid,
+               MIN(segment->range_end, maxrev), segment->path, pool);
       /* If this is subtractive, reverse the whole calculation. */
       if (subtractive)
-        {
-          const svn_client__pathrev_t *tmploc = merge_source->loc1;
-          merge_source->loc1 = merge_source->loc2;
-          merge_source->loc2 = tmploc;
-        }
+        merge_source = merge_source_create(loc2, loc1, pool);
+      else
+        merge_source = merge_source_create(loc1, loc2, pool);
 
       APR_ARRAY_PUSH(merge_source_ts, merge_source_t *) = merge_source;
     }
@@ -9728,7 +9720,7 @@ log_find_operative_revs(void *baton,
       if (!in_catalog)
         {
           svn_mergeinfo_t unmerged_for_key;
-          const char *missing_path;
+          const char *suffix, *missing_path;
 
           /* If there is no mergeinfo on the source tree we'll say
              the "subtree" missing this revision is the root of the
@@ -9736,12 +9728,10 @@ log_find_operative_revs(void *baton,
           if (!subtree_missing_this_rev)
             subtree_missing_this_rev = log_baton->source_repos_rel_path;
 
-          if (subtree_missing_this_rev
-              && strcmp(subtree_missing_this_rev, source_rel_path))
+          suffix = svn_relpath_skip_ancestor(subtree_missing_this_rev,
+                                             source_rel_path);
+          if (suffix)
             {
-              const char *suffix =
-                svn_relpath_skip_ancestor(subtree_missing_this_rev,
-                                          source_rel_path);
               missing_path = apr_pstrmemdup(pool, path,
                                             strlen(path) - strlen(suffix) - 1);
             }

Modified: subversion/branches/master-passphrase/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_client/prop_commands.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_client/prop_commands.c Thu Apr 12 19:37:45 2012
@@ -344,7 +344,7 @@ svn_client_propset_local(const char *pro
                              iterpool);
 
       if ((err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-          || kind == svn_node_unknown || kind == svn_node_none)
+          || (!err && (kind == svn_node_unknown || kind == svn_node_none)))
         {
           if (ctx->notify_func2)
             {

Modified: subversion/branches/master-passphrase/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_client/repos_diff.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_client/repos_diff.c Thu Apr 12 19:37:45 2012
@@ -1464,7 +1464,7 @@ svn_client__get_diff_editor(const svn_de
   shim_callbacks->fetch_baton = eb;
 
   SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
-                                   shim_callbacks,
+                                   NULL, NULL, shim_callbacks,
                                    result_pool, result_pool));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/master-passphrase/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_delta/compat.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_delta/compat.c Thu Apr 12 19:37:45 2012
@@ -138,6 +138,10 @@ struct ev2_edit_baton
   apr_array_header_t *path_order;
   int paths_processed;
 
+  /* For calculating relpaths from Ev1 copyfrom urls. */
+  const char *repos_root;
+  const char *base_relpath;
+
   apr_pool_t *edit_pool;
   struct extra_baton *exb;
   svn_boolean_t closed;
@@ -161,7 +165,7 @@ struct ev2_dir_baton
   const char *path;
   svn_revnum_t base_revision;
 
-  const char *copyfrom_path;
+  const char *copyfrom_relpath;
   svn_revnum_t copyfrom_rev;
 };
 
@@ -593,6 +597,30 @@ run_ev2_actions(struct ev2_edit_baton *e
   return SVN_NO_ERROR;
 }
 
+
+static const char *
+map_to_repos_relpath(struct ev2_edit_baton *eb,
+                     const char *path_or_url,
+                     apr_pool_t *result_pool)
+{
+#ifdef SVN_DEBUG
+  SVN_DBG(("repos_path='%s'\n", path_or_url));
+#endif
+
+  if (svn_path_is_url(path_or_url))
+    {
+      return svn_uri_skip_ancestor(eb->repos_root, path_or_url, result_pool);
+    }
+  else
+    {
+      return svn_relpath_join(eb->base_relpath,
+                              path_or_url[0] == '/'
+                                    ? path_or_url + 1 : path_or_url,
+                              result_pool);
+    }
+}
+
+
 static svn_error_t *
 ev2_set_target_revision(void *edit_baton,
                         svn_revnum_t target_revision,
@@ -617,7 +645,7 @@ ev2_open_root(void *edit_baton,
   struct ev2_edit_baton *eb = edit_baton;
 
   db->eb = eb;
-  db->path = "";
+  db->path = apr_pstrdup(eb->edit_pool, eb->base_relpath);
   db->base_revision = base_revision;
 
   *root_baton = db;
@@ -636,14 +664,15 @@ ev2_delete_entry(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   svn_revnum_t *revnum = apr_palloc(pb->eb->edit_pool, sizeof(*revnum));
-  struct change_node *change = locate_change(pb->eb, path);
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
+  struct change_node *change = locate_change(pb->eb, relpath);
 
   if (SVN_IS_VALID_REVNUM(revision))
     *revnum = revision;
   else
     *revnum = pb->base_revision;
 
-  SVN_ERR(add_action(pb->eb, path, ACTION_DELETE, revnum));
+  SVN_ERR(add_action(pb->eb, relpath, ACTION_DELETE, revnum));
 
   /* ### note: cannot switch to CHANGES just yet. the action loop needs
      ### to see a delete action, and set NEED_DELETE. that is used for
@@ -670,15 +699,18 @@ ev2_add_directory(const char *path,
                   apr_pool_t *result_pool,
                   void **child_baton)
 {
+  /* ### fix this?  */
+  apr_pool_t *scratch_pool = result_pool;
   struct ev2_dir_baton *pb = parent_baton;
   struct ev2_dir_baton *cb = apr_pcalloc(result_pool, sizeof(*cb));
-  struct change_node *change = locate_change(pb->eb, path);
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
+  struct change_node *change = locate_change(pb->eb, relpath);
 
   /* ### assert that RESTRUCTURE is NONE or DELETE?  */
   change->action = RESTRUCTURE_ADD;
 
   cb->eb = pb->eb;
-  cb->path = apr_pstrdup(result_pool, path);
+  cb->path = apr_pstrdup(result_pool, relpath);
   cb->base_revision = pb->base_revision;
   *child_baton = cb;
 
@@ -688,13 +720,13 @@ ev2_add_directory(const char *path,
       svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
 
       *kind = svn_kind_dir;
-      SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+      SVN_ERR(add_action(pb->eb, relpath, ACTION_ADD, kind));
 
-      if (pb->copyfrom_path)
+      if (pb->copyfrom_relpath)
         {
-          const char *name = svn_relpath_basename(path, result_pool);
-          cb->copyfrom_path = apr_pstrcat(result_pool, pb->copyfrom_path,
-                                          "/", name, NULL);
+          const char *name = svn_relpath_basename(relpath, scratch_pool);
+          cb->copyfrom_relpath = svn_relpath_join(pb->copyfrom_relpath, name,
+                                                  result_pool);
           cb->copyfrom_rev = pb->copyfrom_rev;
         }
     }
@@ -703,15 +735,16 @@ ev2_add_directory(const char *path,
       /* A copy */
       struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
 
-      args->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
-      args->copyfrom_rev = copyfrom_revision;
-      SVN_ERR(add_action(pb->eb, path, ACTION_COPY, args));
+      change->copyfrom_path = map_to_repos_relpath(pb->eb, copyfrom_path,
+                                                   pb->eb->edit_pool);
+      change->copyfrom_rev = copyfrom_revision;
 
-      cb->copyfrom_path = args->copyfrom_path;
-      cb->copyfrom_rev = args->copyfrom_rev;
+      args->copyfrom_path = change->copyfrom_path;
+      args->copyfrom_rev = change->copyfrom_rev;
+      SVN_ERR(add_action(pb->eb, relpath, ACTION_COPY, args));
 
-      change->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
-      change->copyfrom_rev = copyfrom_revision;
+      cb->copyfrom_relpath = change->copyfrom_path;
+      cb->copyfrom_rev = change->copyfrom_rev;
     }
 
   return SVN_NO_ERROR;
@@ -724,20 +757,23 @@ ev2_open_directory(const char *path,
                    apr_pool_t *result_pool,
                    void **child_baton)
 {
+  /* ### fix this?  */
+  apr_pool_t *scratch_pool = result_pool;
   struct ev2_dir_baton *pb = parent_baton;
   struct ev2_dir_baton *db = apr_pcalloc(result_pool, sizeof(*db));
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
 
   db->eb = pb->eb;
-  db->path = apr_pstrdup(result_pool, path);
+  db->path = apr_pstrdup(result_pool, relpath);
   db->base_revision = base_revision;
 
-  if (pb->copyfrom_path)
+  if (pb->copyfrom_relpath)
     {
       /* We are inside a copy. */
-      const char *name = svn_relpath_basename(path, result_pool);
+      const char *name = svn_relpath_basename(relpath, scratch_pool);
 
-      db->copyfrom_path = apr_pstrcat(result_pool, pb->copyfrom_path,
-                                      "/", name, NULL);
+      db->copyfrom_relpath = svn_relpath_join(pb->copyfrom_relpath, name,
+                                              result_pool);
       db->copyfrom_rev = pb->copyfrom_rev;
     }
 
@@ -773,9 +809,10 @@ ev2_absent_directory(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
 
   *kind = svn_kind_dir;
-  SVN_ERR(add_action(pb->eb, path, ACTION_ADD_ABSENT, kind));
+  SVN_ERR(add_action(pb->eb, relpath, ACTION_ADD_ABSENT, kind));
 
   return SVN_NO_ERROR;
 }
@@ -788,15 +825,18 @@ ev2_add_file(const char *path,
              apr_pool_t *result_pool,
              void **file_baton)
 {
+  /* ### fix this?  */
+  apr_pool_t *scratch_pool = result_pool;
   struct ev2_file_baton *fb = apr_pcalloc(result_pool, sizeof(*fb));
   struct ev2_dir_baton *pb = parent_baton;
-  struct change_node *change = locate_change(pb->eb, path);
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
+  struct change_node *change = locate_change(pb->eb, relpath);
 
   /* ### assert that RESTRUCTURE is NONE or DELETE?  */
   change->action = RESTRUCTURE_ADD;
 
   fb->eb = pb->eb;
-  fb->path = apr_pstrdup(result_pool, path);
+  fb->path = apr_pstrdup(result_pool, relpath);
   fb->base_revision = pb->base_revision;
   *file_baton = fb;
 
@@ -809,24 +849,26 @@ ev2_add_file(const char *path,
       fb->delta_base = NULL;
 
       *kind = svn_kind_file;
-      SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+      SVN_ERR(add_action(pb->eb, relpath, ACTION_ADD, kind));
     }
   else
     {
       /* A copy */
       struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
 
+      change->copyfrom_path = map_to_repos_relpath(fb->eb, copyfrom_path,
+                                                   fb->eb->edit_pool);
+      change->copyfrom_rev = copyfrom_revision;
+
       SVN_ERR(fb->eb->fetch_base_func(&fb->delta_base,
                                       fb->eb->fetch_base_baton,
-                                      copyfrom_path, copyfrom_revision,
-                                      result_pool, result_pool));
-
-      args->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
-      args->copyfrom_rev = copyfrom_revision;
-      SVN_ERR(add_action(pb->eb, path, ACTION_COPY, args));
-
-      change->copyfrom_path = apr_pstrdup(fb->eb->edit_pool, copyfrom_path);
-      change->copyfrom_rev = copyfrom_revision;
+                                      change->copyfrom_path,
+                                      change->copyfrom_rev,
+                                      result_pool, scratch_pool));
+
+      args->copyfrom_path = change->copyfrom_path;
+      args->copyfrom_rev = change->copyfrom_rev;
+      SVN_ERR(add_action(pb->eb, relpath, ACTION_COPY, args));
     }
 
   return SVN_NO_ERROR;
@@ -839,32 +881,36 @@ ev2_open_file(const char *path,
               apr_pool_t *result_pool,
               void **file_baton)
 {
+  /* ### fix this?  */
+  apr_pool_t *scratch_pool = result_pool;
   struct ev2_file_baton *fb = apr_pcalloc(result_pool, sizeof(*fb));
   struct ev2_dir_baton *pb = parent_baton;
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
 
   fb->eb = pb->eb;
-  fb->path = apr_pstrdup(result_pool, path);
+  fb->path = apr_pstrdup(result_pool, relpath);
   fb->base_revision = base_revision;
 
-  if (pb->copyfrom_path)
+  if (pb->copyfrom_relpath)
     {
       /* We're in a copied directory, so the delta base is going to be
          based up on the copy source. */
-      const char *name = svn_relpath_basename(path, result_pool);
-      const char *copyfrom_path = apr_pstrcat(result_pool, pb->copyfrom_path,
-                                              "/", name, NULL);
+      const char *name = svn_relpath_basename(relpath, scratch_pool);
+      const char *copyfrom_relpath = svn_relpath_join(pb->copyfrom_relpath,
+                                                      name,
+                                                      scratch_pool);
 
       SVN_ERR(fb->eb->fetch_base_func(&fb->delta_base,
                                       fb->eb->fetch_base_baton,
-                                      copyfrom_path, pb->copyfrom_rev,
-                                      result_pool, result_pool));
+                                      copyfrom_relpath, pb->copyfrom_rev,
+                                      result_pool, scratch_pool));
     }
   else
     {
       SVN_ERR(fb->eb->fetch_base_func(&fb->delta_base,
                                       fb->eb->fetch_base_baton,
-                                      path, base_revision,
-                                      result_pool, result_pool));
+                                      relpath, base_revision,
+                                      result_pool, scratch_pool));
     }
 
   *file_baton = fb;
@@ -977,9 +1023,10 @@ ev2_absent_file(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
+  const char *relpath = map_to_repos_relpath(pb->eb, path, scratch_pool);
 
   *kind = svn_kind_file;
-  SVN_ERR(add_action(pb->eb, path, ACTION_ADD_ABSENT, kind));
+  SVN_ERR(add_action(pb->eb, relpath, ACTION_ADD_ABSENT, kind));
 
   return SVN_NO_ERROR;
 }
@@ -1035,6 +1082,8 @@ delta_from_editor(const svn_delta_editor
                   unlock_func_t unlock_func,
                   void *unlock_baton,
                   svn_boolean_t *found_abs_paths,
+                  const char *repos_root,
+                  const char *base_relpath,
                   svn_delta_fetch_props_func_t fetch_props_func,
                   void *fetch_props_baton,
                   svn_delta_fetch_base_func_t fetch_base_func,
@@ -1071,6 +1120,8 @@ delta_from_editor(const svn_delta_editor
   eb->found_abs_paths = found_abs_paths;
   *eb->found_abs_paths = FALSE;
   eb->exb = exb;
+  eb->repos_root = apr_pstrdup(pool, repos_root);
+  eb->base_relpath = apr_pstrdup(pool, base_relpath);
 
   eb->fetch_props_func = fetch_props_func;
   eb->fetch_props_baton = fetch_props_baton;
@@ -1129,6 +1180,8 @@ struct editor_baton
 
   struct operation root;
   svn_boolean_t *make_abs_paths;
+  const char *repos_root;
+  const char *base_relpath;
 
   apr_hash_t *paths;
   apr_pool_t *edit_pool;
@@ -1198,7 +1251,7 @@ build(struct editor_baton *eb,
       svn_revnum_t head,
       apr_pool_t *scratch_pool)
 {
-  apr_array_header_t *path_bits = svn_path_decompose(relpath, scratch_pool);
+  apr_array_header_t *path_bits;
   const char *path_so_far = "";
   struct operation *operation = &eb->root;
   int i;
@@ -1207,10 +1260,13 @@ build(struct editor_baton *eb,
   SVN_ERR_ASSERT((props && action == ACTION_PROPSET)
                 || (!props && action != ACTION_PROPSET) );
 
+  relpath = svn_relpath_skip_ancestor(eb->base_relpath, relpath);
+
   /* Look for any previous operations we've recognized for PATH.  If
      any of PATH's ancestors have not yet been traversed, we'll be
      creating OP_OPEN operations for them as we walk down PATH's path
      components. */
+  path_bits = svn_path_decompose(relpath, scratch_pool);
   for (i = 0; i < path_bits->nelts; ++i)
     {
       const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
@@ -1235,7 +1291,10 @@ build(struct editor_baton *eb,
                                      scratch_pool, scratch_pool));
       else
         SVN_ERR(eb->fetch_props_func(&current_props, eb->fetch_props_baton,
-                                     relpath, rev, scratch_pool,
+                                     svn_relpath_join(eb->base_relpath,
+                                                      relpath,
+                                                      scratch_pool),
+                                     rev, scratch_pool,
                                      scratch_pool));
 
       SVN_ERR(svn_prop_diffs(&propdiffs, props, current_props, scratch_pool));
@@ -1288,8 +1347,15 @@ build(struct editor_baton *eb,
                                     url, rev, scratch_pool));
       else
         operation->kind = kind;
-      operation->copyfrom_url = url;
+
       operation->copyfrom_revision = rev;
+
+      if (eb->repos_root)
+        operation->copyfrom_url = svn_path_url_add_component2(eb->repos_root,
+                                                              url,
+                                                              eb->edit_pool);
+      else
+        operation->copyfrom_url = apr_pstrcat(eb->edit_pool, "/", url, NULL);
     }
   /* Handle mkdir operations (which can be adds or replacements). */
   else if (action == ACTION_MKDIR)
@@ -1936,6 +2002,8 @@ editor_from_delta(svn_editor_t **editor_
                   const svn_delta_editor_t *deditor,
                   void *dedit_baton,
                   svn_boolean_t *send_abs_paths,
+                  const char *repos_root,
+                  const char *base_relpath,
                   svn_cancel_func_t cancel_func,
                   void *cancel_baton,
                   svn_delta_fetch_kind_func_t fetch_kind_func,
@@ -1969,6 +2037,8 @@ editor_from_delta(svn_editor_t **editor_
   eb->dedit_baton = dedit_baton;
   eb->edit_pool = result_pool;
   eb->paths = apr_hash_make(result_pool);
+  eb->repos_root = apr_pstrdup(result_pool, repos_root);
+  eb->base_relpath = apr_pstrdup(result_pool, base_relpath);
 
   eb->fetch_kind_func = fetch_kind_func;
   eb->fetch_kind_baton = fetch_kind_baton;
@@ -2020,6 +2090,8 @@ svn_editor__insert_shims(const svn_delta
                          void **dedit_baton_out,
                          const svn_delta_editor_t *deditor_in,
                          void *dedit_baton_in,
+                         const char *repos_root,
+                         const char *base_relpath,
                          svn_delta_shim_callbacks_t *shim_callbacks,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
@@ -2053,9 +2125,15 @@ svn_editor__insert_shims(const svn_delta
   SVN_ERR_ASSERT(shim_callbacks->fetch_props_func != NULL);
   SVN_ERR_ASSERT(shim_callbacks->fetch_base_func != NULL);
 
+  if (!base_relpath)
+    base_relpath = "";
+  else if (base_relpath[0] == '/')
+    base_relpath += 1;
+
   SVN_ERR(editor_from_delta(&editor, &exb, &unlock_func, &unlock_baton,
                             deditor_in, dedit_baton_in,
-                            found_abs_paths, NULL, NULL,
+                            found_abs_paths, repos_root, base_relpath,
+                            NULL, NULL,
                             shim_callbacks->fetch_kind_func,
                             shim_callbacks->fetch_baton,
                             shim_callbacks->fetch_props_func,
@@ -2064,6 +2142,7 @@ svn_editor__insert_shims(const svn_delta
   SVN_ERR(delta_from_editor(deditor_out, dedit_baton_out, editor,
                             unlock_func, unlock_baton,
                             found_abs_paths,
+                            repos_root, base_relpath,
                             shim_callbacks->fetch_props_func,
                             shim_callbacks->fetch_baton,
                             shim_callbacks->fetch_base_func,

Modified: subversion/branches/master-passphrase/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_delta/editor.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_delta/editor.c Thu Apr 12 19:37:45 2012
@@ -403,8 +403,10 @@ svn_editor_add_directory(svn_editor_t *e
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SVN_ERR_ASSERT(children != NULL);
   SVN_ERR_ASSERT(props != NULL);
+  /* ### validate children are just basenames?  */
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
   CHECK_UNKNOWN_CHILD(editor, relpath);
@@ -453,6 +455,7 @@ svn_editor_add_file(svn_editor_t *editor
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SVN_ERR_ASSERT(checksum != NULL
                     && checksum->kind == SVN_EDITOR_CHECKSUM_KIND);
   SVN_ERR_ASSERT(contents != NULL);
@@ -489,6 +492,7 @@ svn_editor_add_symlink(svn_editor_t *edi
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SVN_ERR_ASSERT(props != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
@@ -520,6 +524,7 @@ svn_editor_add_absent(svn_editor_t *edit
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
   CHECK_UNKNOWN_CHILD(editor, relpath);
@@ -550,6 +555,7 @@ svn_editor_alter_directory(svn_editor_t 
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SVN_ERR_ASSERT(props != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ALTER(editor, relpath);
@@ -582,6 +588,7 @@ svn_editor_alter_file(svn_editor_t *edit
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SVN_ERR_ASSERT((checksum != NULL && contents != NULL)
                  || (checksum == NULL && contents == NULL));
   SVN_ERR_ASSERT(props != NULL || checksum != NULL);
@@ -618,6 +625,7 @@ svn_editor_alter_symlink(svn_editor_t *e
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SVN_ERR_ASSERT(props != NULL || target != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ALTER(editor, relpath);
@@ -648,6 +656,7 @@ svn_editor_delete(svn_editor_t *editor,
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_NOT_BE_COMPLETED(editor, relpath);
 
@@ -677,6 +686,8 @@ svn_editor_copy(svn_editor_t *editor,
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(src_relpath));
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(dst_relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, dst_relpath);
 
@@ -708,6 +719,8 @@ svn_editor_move(svn_editor_t *editor,
 {
   svn_error_t *err = SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(src_relpath));
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(dst_relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_NOT_BE_COMPLETED(editor, src_relpath);
   SHOULD_ALLOW_ADD(editor, dst_relpath);
@@ -746,6 +759,8 @@ svn_editor_rotate(svn_editor_t *editor,
     for (i = 0; i < relpaths->nelts; i++)
       {
         const char *relpath = APR_ARRAY_IDX(relpaths, i, const char *);
+
+        SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
         SHOULD_NOT_BE_COMPLETED(editor, relpath);
       }
   }

Modified: subversion/branches/master-passphrase/subversion/libsvn_delta/xdelta.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_delta/xdelta.c?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_delta/xdelta.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_delta/xdelta.c Thu Apr 12 19:37:45 2012
@@ -29,8 +29,6 @@
 
 #include "svn_delta.h"
 #include "delta.h"
-
-#include "private/svn_adler32.h"
 
 /* This is pseudo-adler32. It is adler32 without the prime modulus.
    The idea is borrowed from monotone, and is a translation of the C++
@@ -67,7 +65,7 @@ adler32_replace(apr_uint32_t adler32, co
   return adler32 + adler32 * 0x10000;
 }
 
-/* Calculate an peudo-adler32 checksum for MATCH_BLOCKSIZE bytes starting
+/* Calculate an pseudo-adler32 checksum for MATCH_BLOCKSIZE bytes starting
    at DATA.  Return the checksum value.  */
 
 static APR_INLINE apr_uint32_t
@@ -182,7 +180,7 @@ init_blocks_table(const char *data,
   apr_size_t nblocks;
   apr_size_t nslots = 1;
 
-  /* Be pesimistic about the block count. */
+  /* Be pessimistic about the block count. */
   nblocks = datalen / MATCH_BLOCKSIZE + 1;
   /* Find nearest larger power of two. */
   while (nslots <= nblocks)
@@ -235,9 +233,10 @@ match_length(const char *a, const char *
   return pos;
 }
 
-/* Return the smallest byte index at which positions left of A and B differ
- * (A[-result] != B[-result]).  If no difference can be found in the first
- * MAX_LEN characters, MAX_LEN will be returned.
+/* Return the number of bytes before A and B that don't differ.  If no
+ * difference can be found in the first MAX_LEN characters,  MAX_LEN will
+ * be returned.  Please note that A-MAX_LEN and B-MAX_LEN must both be
+ * valid addresses.
  */
 static apr_size_t
 reverse_match_length(const char *a, const char *b, apr_size_t max_len)
@@ -266,7 +265,7 @@ reverse_match_length(const char *a, cons
     if (a[0-pos] != b[0-pos])
       return pos - 1;
 
-  /* No mismatch found -> at least MAX_LEN machting chars.
+  /* No mismatch found -> at least MAX_LEN matching chars.
    */
   return max_len;
 }
@@ -275,7 +274,7 @@ reverse_match_length(const char *a, cons
 /* Try to find a match for the target data B in BLOCKS, and then
    extend the match as long as data in A and B at the match position
    continues to match.  We set the position in A we ended up in (in
-   case we extended it backwards) in APOSP and update the correspnding
+   case we extended it backwards) in APOSP and update the corresponding
    position within B given in BPOSP. PENDING_INSERT_START sets the
    lower limit to BPOSP.
    Return number of matching bytes starting at ASOP.  Return 0 if

Modified: subversion/branches/master-passphrase/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_fs_fs/fs.h?rev=1325461&r1=1325460&r2=1325461&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_fs_fs/fs.h Thu Apr 12 19:37:45 2012
@@ -82,6 +82,11 @@ extern "C" {
 #define CONFIG_OPTION_FAIL_STOP          "fail-stop"
 #define CONFIG_SECTION_REP_SHARING       "rep-sharing"
 #define CONFIG_OPTION_ENABLE_REP_SHARING "enable-rep-sharing"
+#define CONFIG_SECTION_DELTIFICATION     "deltification"
+#define CONFIG_OPTION_ENABLE_DIR_DELTIFICATION   "enable-dir-deltification"
+#define CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION "enable-props-deltification"
+#define CONFIG_OPTION_MAX_DELTIFICATION_WALK     "max-deltification-walk"
+#define CONFIG_OPTION_MAX_LINEAR_DELTIFICATION   "max-linear-deltification"
 
 /* The format number of this filesystem.
    This is independent of the repository format number, and
@@ -118,6 +123,10 @@ extern "C" {
 /* The minimum format number that stores node kinds in changed-paths lists. */
 #define SVN_FS_FS__MIN_KIND_IN_CHANGED_FORMAT 4
 
+/* 1.8 deltification options should work with any FSFS repo but to avoid
+ * issues with very old servers, restrict those options to the 1.6+ format*/
+#define SVN_FS_FS__MIN_DELTIFICATION_FORMAT 4
+
 /* The 1.7-dev format, never released, that packed revprops into SQLite
    revprops.db . */
 #define SVN_FS_FS__PACKED_REVPROP_SQLITE_DEV_FORMAT 5
@@ -275,6 +284,19 @@ typedef struct fs_fs_data_t
   /* Whether rep-sharing is supported by the filesystem
    * and allowed by the configuration. */
   svn_boolean_t rep_sharing_allowed;
+
+  /* Whether directory nodes shall be deltified just like file nodes. */
+  svn_boolean_t deltify_directories;
+
+  /* Whether nodes properties shall be deltified. */
+  svn_boolean_t deltify_properties;
+
+  /* Restart deltification histories after each multiple of this value */
+  apr_int64_t max_deltification_walk;
+
+  /* Maximum number of length of the linear part at the top of the
+   * deltification history after which skip deltas will be used. */
+  apr_int64_t max_linear_deltification;
 } fs_fs_data_t;
 
 



Mime
View raw message