You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/08/22 17:21:15 UTC

svn commit: r1160299 [1/3] - in /subversion/branches/fs-py: ./ build/ notes/ subversion/bindings/ctypes-python/test/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/tigr...

Author: hwright
Date: Mon Aug 22 15:21:13 2011
New Revision: 1160299

URL: http://svn.apache.org/viewvc?rev=1160299&view=rev
Log:
On the fs-py branch:
Bring up-to-date with trunk.

Added:
    subversion/branches/fs-py/notes/hold
      - copied unchanged from r1160298, subversion/trunk/notes/hold
Modified:
    subversion/branches/fs-py/   (props changed)
    subversion/branches/fs-py/CHANGES
    subversion/branches/fs-py/build/transform_sql.py
    subversion/branches/fs-py/notes/moves
    subversion/branches/fs-py/subversion/bindings/ctypes-python/test/setup_path.py
    subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.cpp
    subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.h
    subversion/branches/fs-py/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
    subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
    subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
    subversion/branches/fs-py/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
    subversion/branches/fs-py/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
    subversion/branches/fs-py/subversion/bindings/swig/python/svn/repos.py
    subversion/branches/fs-py/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py
    subversion/branches/fs-py/subversion/bindings/swig/ruby/test/test_client.rb
    subversion/branches/fs-py/subversion/include/svn_client.h
    subversion/branches/fs-py/subversion/include/svn_ra.h
    subversion/branches/fs-py/subversion/include/svn_wc.h
    subversion/branches/fs-py/subversion/libsvn_client/cat.c
    subversion/branches/fs-py/subversion/libsvn_client/client.h
    subversion/branches/fs-py/subversion/libsvn_client/diff.c
    subversion/branches/fs-py/subversion/libsvn_client/merge.c
    subversion/branches/fs-py/subversion/libsvn_client/repos_diff.c
    subversion/branches/fs-py/subversion/libsvn_client/repos_diff_summarize.c
    subversion/branches/fs-py/subversion/libsvn_client/status.c
    subversion/branches/fs-py/subversion/libsvn_ra_serf/blame.c
    subversion/branches/fs-py/subversion/libsvn_ra_serf/commit.c
    subversion/branches/fs-py/subversion/libsvn_ra_serf/locks.c
    subversion/branches/fs-py/subversion/libsvn_subr/validate.c
    subversion/branches/fs-py/subversion/libsvn_wc/adm_ops.c
    subversion/branches/fs-py/subversion/libsvn_wc/diff_local.c
    subversion/branches/fs-py/subversion/libsvn_wc/status.c
    subversion/branches/fs-py/subversion/libsvn_wc/tree_conflicts.c
    subversion/branches/fs-py/subversion/libsvn_wc/update_editor.c
    subversion/branches/fs-py/subversion/libsvn_wc/wc-metadata.sql
    subversion/branches/fs-py/subversion/libsvn_wc/wc-queries.sql
    subversion/branches/fs-py/subversion/libsvn_wc/wc_db.c
    subversion/branches/fs-py/subversion/libsvn_wc/wc_db.h
    subversion/branches/fs-py/subversion/libsvn_wc/wc_db_wcroot.c
    subversion/branches/fs-py/subversion/libsvn_wc/workqueue.c
    subversion/branches/fs-py/subversion/mod_dav_svn/liveprops.c
    subversion/branches/fs-py/subversion/mod_dav_svn/mod_dav_svn.c
    subversion/branches/fs-py/subversion/svn/main.c
    subversion/branches/fs-py/subversion/svn/status.c
    subversion/branches/fs-py/subversion/svn/tree-conflicts.c
    subversion/branches/fs-py/subversion/svndumpfilter/main.c
    subversion/branches/fs-py/subversion/svnversion/main.c
    subversion/branches/fs-py/subversion/tests/cmdline/changelist_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/copy_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/depth_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/diff_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/input_validation_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/merge_reintegrate_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/merge_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/patch_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/revert_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/special_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/svndumpfilter_tests.py
    subversion/branches/fs-py/subversion/tests/cmdline/svntest/main.py
    subversion/branches/fs-py/subversion/tests/cmdline/svnversion_tests.py
    subversion/branches/fs-py/subversion/tests/libsvn_diff/parse-diff-test.c
    subversion/branches/fs-py/tools/dist/collect_sigs.py
    subversion/branches/fs-py/tools/dist/dist.sh
    subversion/branches/fs-py/tools/dist/release.py

Propchange: subversion/branches/fs-py/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Aug 22 15:21:13 2011
@@ -18,7 +18,7 @@ autogen-standalone.mk
 autom4te.cache
 gen-make.opts
 tests.log*
-fails.log
+fails.log*
 db4-win32
 db
 *.o

Propchange: subversion/branches/fs-py/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Aug 22 15:21:13 2011
@@ -54,4 +54,4 @@
 /subversion/branches/tree-conflicts:868291-873154
 /subversion/branches/tree-conflicts-notify:873926-874008
 /subversion/branches/uris-as-urls:1060426-1064427
-/subversion/trunk:1154223-1157792
+/subversion/trunk:1154223-1160298

Modified: subversion/branches/fs-py/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/CHANGES?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/CHANGES (original)
+++ subversion/branches/fs-py/CHANGES Mon Aug 22 15:21:13 2011
@@ -2,6 +2,9 @@ Version 1.8.0
 (?? ??? 2011, from /branches/1.8.x)
 http://svn.apache.org/repos/asf/subversion/tags/1.8.0
 
+ User-visible changes:
+    * don't leave unversioned files when reverting copies (issue #3101)
+
  Developer-visible changes:
   - API changes:
     * fix inconsistent handling of log revs without changed paths (issue #3694)
@@ -126,7 +129,7 @@ the 1.6 release:  http://subversion.apac
     * fixed: executable flag of binary file lost during merge (issue #3686)
     * fixed: merging a symlink-turned-regular-file breaks the wc (issue #2530)
     * fixed: can't remove file externals (issue #3351)
-    * fixed: 'svn unlock' attempts to unlock  wrong token on DAV (issue #3794)
+    * fixed: 'svn unlock' attempts to unlock wrong token on DAV (issue #3794)
     * fixed: forced DAV 'svn unlock' results in 403, not warning (issue #3801)
     * fixed: rm -> ci -> cp = missing directory (issue #2763)
     * fixed: 'svn info' returns parent info on missing dirs (issue #3178)
@@ -140,7 +143,7 @@ the 1.6 release:  http://subversion.apac
     * allow SVNListParentPath to be used with authz (issue #2753)
     * allow nav to repo list from repo top with SVNListParentPath (issue #3159)
     * allow repositories in the root of a drive on windows (issue #3535)
-    * don't destroy mergeinnfo with 'svnadmin load --parent-dir' (issue #3547)
+    * don't destroy mergeinfo with 'svnadmin load --parent-dir' (issue #3547)
     * fixed: 'svnadmin hotcopy' does not duplicate symlinks (issue #2591)
     * fixed: post-revprop-change errors cancel commit (issue #2990)
     * fixed: mod_dav_svn runs pre-revprop-change hook twice (issue #3085)
@@ -182,6 +185,7 @@ the 1.6 release:  http://subversion.apac
     * notifications sent when mergeinfo changes (r877588)
     * add information on text and property mods in log APIs (r877688)
     * fixed: svn_ra_local__get_file() leaks file descriptors (issue #3290)
+    * swig-py: always set ChangedPath.path (issue #2630)
 
   - Bindings:
     * New JavaHL package: org.apache.subversion

Modified: subversion/branches/fs-py/build/transform_sql.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/build/transform_sql.py?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/build/transform_sql.py (original)
+++ subversion/branches/fs-py/build/transform_sql.py Mon Aug 22 15:21:13 2011
@@ -103,6 +103,11 @@ class Processor(object):
     for line in input.split('\n'):
       line = line.replace('"', '\\"')
 
+      # '/'+1 == '0'
+      line = re.sub(r'IS_STRICT_DESCENDANT_OF[(]([A-Za-z_.]+), ([?][0-9]+)[)]',
+                    r"((\1) > (\2) || '/' AND (\1) < (\2) || '0') ",
+                    line)
+
       if line.strip():
         handled = False
 

Modified: subversion/branches/fs-py/notes/moves
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/notes/moves?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/notes/moves (original)
+++ subversion/branches/fs-py/notes/moves Mon Aug 22 15:21:13 2011
@@ -1,20 +1,20 @@
 
- =========================================================================
- This file sketches ideas about how we could improve move support in wc-ng
- =========================================================================
+ =======================
+ Moves in Subversion 1.8
+ =======================
 
 This file purposefully talks about 'moves' rather than 'renames'.
 This isn't about true renames as requested in issue #898.
-Rather, these ideas keep the add+delete concept while trying to make
-moves behave more in a way that one would expect if true renames were
-implemented, as requested in issue #3631.
-
-These ideas only cover local (client-side) moves in the working copy.
-They attempt to reuse as much existing code as possible, so new
-functionality will be implemented as part of existing copy/delete
-code paths unless doing so is not feasible.
+Rather, we keep the add+delete concept while trying to make moves behave
+more in a way that one would expect if true renames were implemented,
+as requested in issue #3631. See also the umbrella issue #3630.
+
+So far the changes only cover local (client-side) moves in the working copy.
+We reuse as much existing code as possible, so new functionality is
+implemented as part of existing copy/delete code paths unless doing
+so is not feasible.
 
-One significant change from how copies work is that moves will be tracked
+One significant change from how copies work is that moves are tracked
 both ways, i.e. one can locate the add-half of a move if given the
 delete-half, and locate the delete-half if given the add-half.
 
@@ -30,17 +30,17 @@ The goals are:
     when talking to the server.
 
 
-
 Notes regarding specific layers of Subversion follow below.
 
 
 == wc.db ==
 
-There already exist columns in the NODES table we use to differentiate
+The following columns in the NODES table are used to differentiate
 moves from copies:
 
   /* Boolean value, specifying if this node was moved here (rather than just
-     copied). The source of the move is specified in copyfrom_*.  */
+     copied). The source of the move is implied by a different node with
+     a moved_to column pointing at this node. */
   moved_here  INTEGER,
 
   /* If the underlying node was moved away (rather than just deleted), this
@@ -48,30 +48,39 @@ moves from copies:
      This is set only on the root of a move, and is NULL for all children.
 
      Note that moved_to never refers to *this* node. It always refers
-     to the "underlying" node, whether that is BASE or a child node
-     implied from a parent's move/copy.  */
+     to the "underlying" node in the BASE tree. A non-NULL moved_to column
+     is only valid in rows where op_depth == 0. */
   moved_to  TEXT,
 
-These will be used as described in their docstrings.
+Some new queries were added which use these columns:
 
+  STMT_SELECT_MOVED_FROM_RELPATH
+  STMT_UPDATE_MOVED_TO_RELPATH
+  STMT_CLEAR_MOVED_TO_RELPATH
+  STMT_CLEAR_MOVED_TO_RELPATH_RECURSIVE
+  STMT_SELECT_MOVED_HERE_CHILDREN
+
+More queries might be needed (TBD).
 
-== libsvn_wc ==
 
-Various wc_db and svn_wc interfaces will be extended for moves.
-New interfaces will be modeled after (and share code with) their
-existing copy or delete equivalents as much as possible.
-See r1146119 for an example of how existing code will be reused.
+== libsvn_wc ==
 
-Some existing interfaces will be extended, e.g. the _scan_addition()
-and _scan_deletion() interfaces will be extended to differentiate
+In the internal wc_db API, the _scan_addition() and _scan_deletion()
+interfaces were extended to make use of new DB queries to differentiate
 moved nodes from copied, added, and deleted nodes.
 
-### gstein: note that scan_addition() already returns status_moved_here,
-###   and scan_deletion() returns a MOVED_TO_ABSPATH. these functions
-###   should already do what you're asking (with bitrot and "untested"
-###   caveats since I first implemented them).
+Two functions were built on top of the wc_db API and added to the
+private libsvn_wc API:
+  svn_wc__node_was_moved_away() provides, for a given local_abspath:
+    - the moved_to abspath within the working copy
+    - the abspath of the op-root of the copy operation that created
+      the node at the moved_to abspath
+  svn_wc__node_was_moved_here() provides, for a given local_abspath:
+    - the moved_from abspath within the working copy
+    - the abspath of the op-root of the delete operation that deleted
+      the node at the moved_from abspath
 
-There might be some public API changes (TBD).
+More API changes might be needed (TBD).
 
 We might require a working copy upgrade when going from 1.7 to 1.8,
 and only allow new move functionality to be used with 1.8 working copies.
@@ -79,40 +88,48 @@ and only allow new move functionality to
 
 == libsvn_client ==
 
-This layer already uses existing svn_wc move APIs. For those callers
-APIs changes will hopefully be fairly transparent, apart from changes
-that enhance behaviour of move operations.
-
-Some code that is expected to change behaviour:
-
- - commit: Commit will refuse to commit anything if only one half of
-    a move appears in the commit target list, or if only one half of
-    a move is picked up by recursion.
-
- - revert: Revert will by default revert both nodes involved in a move,
-    independent of which half of the move is mentioned in the revert
-    target list. If only one half of a move is picked up by recursion,
-    revert will refuse to revert anything.
-    If the delete-half has been replaced by another node after
-    it has been deleted, revert will require both the add and delete
-    half to appear in the revert target list or be picked up by recursion
-    (i.e. the node replacing the delete-half has to be reverted explicitly
-     or via recursion).
-
- - status: Status will provide information about both halfs of a move,
-    in a way that allows the user to tell that both halfs belong to
-    the same move operation.
-
- - update/merge: Update and Merge will use move information to auto-resolve
-    the "local move vs. incoming edit" tree conflict scenario.
+This layer already uses 1.7 and earlier svn_wc move APIs. For callers
+of such APIs, changes will hopefully be fairly transparent apart from
+changes that enhance behaviour of move operations.
+
+Interfaces which have changed behaviour:
+
+ svn_client_commit: Commit will refuse to commit anything if only one
+   half of a move appears in the commit target list, or if only one half of
+   a move is picked up by recursion.
+
+ svn_client_revert: The behaviour of this API is not changed, but it
+   is worth noting how it behaves for moves:
+   - If both halves of a move are among the revert targets (either by
+     virtue of being listed explicitly, or by being picked up during
+     recursion), the entire move is reverted.
+   - If only one half of a move is among the revert targets, the other
+     half will be transformed into a normal copy or delete.
+     See http://svn.haxx.se/dev/archive-2011-08/0239.shtml for rationale.
+
+ - svn_client_status: Status provides the moved-to abspath for a moved-away
+     nodes, and the moved-from abspath for a moved-here node.
+     Note that, mostly due to performance reasons, only information about
+     roots of moves is provided. Children of moved nodes aren't marked as such.
+
+ - svn_client_info: Like status, except that it also provides move
+     information about children of moved nodes.
+
+ - svn_client_patch: Patch uses move information to apply changes to files
+     which have been moved locally.
+
+Interfaces which have not changed behaviour yet but will change in 1.8.0:
+
+ - svn_client_update/svn_client_merge: Update and Merge will use move
+    information to auto-resolve the "local move vs. incoming edit"
+    tree conflict scenario.
 
  - diff: Diff will use move information to generate 'rename from' headers
-    when the --git option is used.
+    when the --git option is used. (A related problem is making diff use
+    correct copyfrom in repos-repos diffs, which is not trivial.)
 
- - patch: Patch will use move information to apply changes to files
-    which have been moved locally.
+Several public APIs may still be bumped as their behaviour changes.
 
-Several public APIs may be bumped as their behaviour changes.
 For backwards compatibility, APIs released prior to 1.8 will continue
 to treat moves just like 1.7 and earlier releases did. (However, see
 also the note on working copy upgrades above, which might affect to
@@ -121,15 +138,15 @@ what degree the APIs need to stay compat
 
 == svn ==
 
-The svn client will present moves similar to but distinct from copy
-operations. E.g. it might show moves like this:
+The svn client presents moves similar to but distinct from copy operations. 
+
+svn status shows move roots:
 
 $ svn status
 A  +    foo
-   > moved from 'bar'
+        > moved from 'bar'
 D       bar
-   > moved to 'foo'
+        > moved to 'foo'
 $
 
-(If the above is done, we should also show copyfrom for normal copies
-this way, but as "copied from '%s'")
+svn info shows additional Moved-To: and Moved-From: lines for any moved node.

Modified: subversion/branches/fs-py/subversion/bindings/ctypes-python/test/setup_path.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/ctypes-python/test/setup_path.py?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/ctypes-python/test/setup_path.py (original)
+++ subversion/branches/fs-py/subversion/bindings/ctypes-python/test/setup_path.py Mon Aug 22 15:21:13 2011
@@ -25,8 +25,8 @@
 import sys
 import os
 
-src_swig_python_tests_dir = os.path.dirname(os.path.dirname(__file__))
-sys.path[0:0] = [ src_swig_python_tests_dir ]
+src_ctypes_python_tests_dir = os.path.dirname(os.path.dirname(__file__))
+sys.path[0:0] = [ src_ctypes_python_tests_dir ]
 
 import csvn.core
 csvn.core.svn_cmdline_init("", csvn.core.stderr)

Modified: subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.cpp?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.cpp Mon Aug 22 15:21:13 2011
@@ -898,7 +898,9 @@ void SVNClient::propertySetLocal(Targets
                                          ctx, subPool.getPool()), );
 }
 
-void SVNClient::propertySetRemote(const char *path, const char *name,
+void SVNClient::propertySetRemote(const char *path, long base_rev,
+                                  const char *name,
+                                  CommitMessage *message,
                                   JNIByteArray &value, bool force,
                                   RevpropTable &revprops,
                                   CommitCallback *callback)
@@ -916,12 +918,12 @@ void SVNClient::propertySetRemote(const 
     Path intPath(path, subPool);
     SVN_JNI_ERR(intPath.error_occured(), );
 
-    svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
+    svn_client_ctx_t *ctx = context.getContext(message, subPool);
     if (ctx == NULL)
         return;
 
     SVN_JNI_ERR(svn_client_propset_remote(name, val, intPath.c_str(),
-                                          force, SVN_INVALID_REVNUM,
+                                          force, base_rev,
                                           revprops.hash(subPool),
                                           CommitCallback::callback, callback,
                                           ctx, subPool.getPool()), );

Modified: subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.h?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.h (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/native/SVNClient.h Mon Aug 22 15:21:13 2011
@@ -81,7 +81,8 @@ class SVNClient :public SVNBase
   void propertySetLocal(Targets &targets, const char *name, JNIByteArray &value,
                         svn_depth_t depth, StringArray &changelists,
                         bool force);
-  void propertySetRemote(const char *path, const char *name,
+  void propertySetRemote(const char *path, long base_rev, const char *name,
+                         CommitMessage *message,
                          JNIByteArray &value, bool force,
                          RevpropTable &revprops, CommitCallback *callback);
   void properties(const char *path, Revision &revision,

Modified: subversion/branches/fs-py/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Mon Aug 22 15:21:13 2011
@@ -922,8 +922,9 @@ Java_org_apache_subversion_javahl_SVNCli
 
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_propertySetRemote
-(JNIEnv *env, jobject jthis, jstring jpath, jstring jname,
- jbyteArray jvalue, jboolean jforce, jobject jrevpropTable, jobject jcallback)
+(JNIEnv *env, jobject jthis, jstring jpath, jlong jbaseRev, jstring jname,
+ jbyteArray jvalue, jobject jmessage, jboolean jforce, jobject jrevpropTable,
+ jobject jcallback)
 {
   JNIEntry(SVNClient, propertySet);
   SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -940,6 +941,10 @@ Java_org_apache_subversion_javahl_SVNCli
   if (JNIUtil::isExceptionThrown())
     return;
 
+  CommitMessage message(jmessage);
+  if (JNIUtil::isExceptionThrown())
+    return;
+
   JNIByteArray value(jvalue);
   if (JNIUtil::isExceptionThrown())
     return;
@@ -949,8 +954,9 @@ Java_org_apache_subversion_javahl_SVNCli
     return;
 
   CommitCallback callback(jcallback);
-  cl->propertySetRemote(path, name, value, jforce ? true:false, revprops,
-                        jcallback ? &callback : NULL);
+  cl->propertySetRemote(path, jbaseRev, name, &message, value,
+                        jforce ? true:false,
+                        revprops, jcallback ? &callback : NULL);
 }
 
 JNIEXPORT void JNICALL

Modified: subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Mon Aug 22 15:21:13 2011
@@ -649,7 +649,8 @@ public interface ISVNClient
                           boolean force)
             throws ClientException;
 
-    void propertySetRemote(String path, String name, byte[] value,
+    void propertySetRemote(String path, long baseRev, String name,
+                           byte[] value, CommitMessageCallback handler,
                            boolean force, Map<String, String> revpropTable,
                            CommitCallback callback)
             throws ClientException;

Modified: subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java Mon Aug 22 15:21:13 2011
@@ -307,7 +307,9 @@ public class SVNClient implements ISVNCl
                                         boolean force)
             throws ClientException;
 
-    public native void propertySetRemote(String path, String name, byte[] value,
+    public native void propertySetRemote(String path, long baseRev,
+                                         String name, byte[] value,
+                                         CommitMessageCallback handler,
                                          boolean force,
                                          Map<String, String> revpropTable,
                                          CommitCallback callback)

Modified: subversion/branches/fs-py/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java Mon Aug 22 15:21:13 2011
@@ -1878,8 +1878,12 @@ public class SVNClient implements SVNCli
         {
             if (Path.isURL(path))
             {
-                aSVNClient.propertySetRemote(path, name,
+                Info2[] infos = info2(path, Revision.HEAD, Revision.HEAD,
+                                      false);
+
+                aSVNClient.propertySetRemote(path, infos[0].getRev(), name,
                                        value == null ? null : value.getBytes(),
+                                       cachedHandler,
                                        force, revpropTable, null);
             }
             else

Modified: subversion/branches/fs-py/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original)
+++ subversion/branches/fs-py/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Mon Aug 22 15:21:13 2011
@@ -3110,6 +3110,53 @@ public class BasicTests extends SVNTests
     }
 
     /**
+     * Test the basic SVNClient.propertySetRemote functionality.
+     * @throws Throwable
+     */
+    public void testPropEdit() throws Throwable
+    {
+        final String PROP = "abc";
+        final byte[] VALUE = new String("def").getBytes();
+        final byte[] NEWVALUE = new String("newvalue").getBytes();
+        // create the test working copy
+        OneTest thisTest = new OneTest();
+
+        Set<String> pathSet = new HashSet<String>();
+        // set a property on A/D/G/rho file
+        pathSet.clear();
+        pathSet.add(thisTest.getWCPath()+"/A/D/G/rho");
+        client.propertySetLocal(pathSet, PROP, VALUE,
+                                Depth.infinity, null, false);
+        thisTest.getWc().setItemPropStatus("A/D/G/rho", Status.Kind.modified);
+
+        // test the status of the working copy
+        thisTest.checkStatus();
+
+        // commit the changes
+        checkCommitRevision(thisTest, "wrong revision number from commit", 2,
+                            thisTest.getWCPathSet(), "log msg", Depth.infinity,
+                            false, false, null, null);
+
+        thisTest.getWc().setItemPropStatus("A/D/G/rho", Status.Kind.normal);
+
+        // check the status of the working copy
+        thisTest.checkStatus();
+        
+        // now edit the propval directly in the repository
+        long baseRev = 2L;
+        client.propertySetRemote(thisTest.getUrl()+"/A/D/G/rho", baseRev, PROP, NEWVALUE,
+                                 new ConstMsg("edit prop"), false, null, null);
+        
+        // update the WC and verify that the property was changed
+        client.update(thisTest.getWCPathSet(), Revision.HEAD, Depth.infinity, false, false,
+                      false, false);
+        byte[] propVal = client.propertyGet(thisTest.getWCPath()+"/A/D/G/rho", PROP, null, null);
+
+        assertEquals(new String(propVal), new String(NEWVALUE));
+
+    }
+
+    /**
      * Test tolerance of unversioned obstructions when adding paths with
      * {@link org.apache.subversion.javahl.SVNClient#checkout()},
      * {@link org.apache.subversion.javahl.SVNClient#update()}, and

Modified: subversion/branches/fs-py/subversion/bindings/swig/python/svn/repos.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/swig/python/svn/repos.py?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/swig/python/svn/repos.py (original)
+++ subversion/branches/fs-py/subversion/bindings/swig/python/svn/repos.py Mon Aug 22 15:21:13 2011
@@ -72,12 +72,28 @@ class ChangedPath:
 
 
 class ChangeCollector(_svndelta.Editor):
-  """Available Since: 1.2.0
+  """An editor that, when driven, walks a revision or a transaction and
+  incrementally invokes a callback with ChangedPath instances corresponding to
+  paths changed in that revision.
+
+  Available Since: 1.2.0
   """
 
   # BATON FORMAT: [path, base_path, base_rev]
 
   def __init__(self, fs_ptr, root, pool=None, notify_cb=None):
+    """Construct a walker over the svn_fs_root_t ROOT, which must
+    be in the svn_fs_t FS_PTR.  Invoke NOTIFY_CB with a single argument
+    of type ChangedPath for each change under ROOT.
+
+    At this time, two ChangedPath objects will be passed for a path that had
+    been replaced in the revision/transaction.  This may change in the future.
+  
+    ### Can't we deduce FS_PTR from ROOT?
+
+    ### POOL is unused
+    """
+
     self.fs_ptr = fs_ptr
     self.changes = { } # path -> ChangedPathEntry()
     self.roots = { } # revision -> svn_svnfs_root_t
@@ -136,9 +152,9 @@ class ChangeCollector(_svndelta.Editor):
     self.changes[path] = ChangedPath(item_type,
                                      False,
                                      False,
-                                     base_path,
+                                     base_path,       # base_path
                                      parent_baton[2], # base_rev
-                                     None,            # (new) path
+                                     path,            # path
                                      False,           # added
                                      CHANGE_ACTION_DELETE,
                                      )

Modified: subversion/branches/fs-py/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py (original)
+++ subversion/branches/fs-py/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py Mon Aug 22 15:21:13 2011
@@ -407,7 +407,7 @@ class SubversionChangeset(Changeset):
                 else:
                     base_path = None
             action = ''
-            if not change.path:
+            if change.action == repos.CHANGE_ACTION_DELETE:
                 action = Changeset.DELETE
                 deletions[change.base_path] = idx
             elif change.added:

Modified: subversion/branches/fs-py/subversion/bindings/swig/ruby/test/test_client.rb
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/bindings/swig/ruby/test/test_client.rb?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/bindings/swig/ruby/test/test_client.rb (original)
+++ subversion/branches/fs-py/subversion/bindings/swig/ruby/test/test_client.rb Mon Aug 22 15:21:13 2011
@@ -1287,7 +1287,6 @@ class SvnClientTest < Test::Unit::TestCa
         ctx.mv(path1, path2)
       end
       ctx.revert([path1, path2])
-      FileUtils.rm(path2)
 
       File.open(path1, "w") {|f| f.print(src2)}
       assert_nothing_raised do

Modified: subversion/branches/fs-py/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/include/svn_client.h?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/include/svn_client.h (original)
+++ subversion/branches/fs-py/subversion/include/svn_client.h Mon Aug 22 15:21:13 2011
@@ -2207,18 +2207,38 @@ typedef struct svn_client_status_t
   const void *backwards_compatibility_baton;
 
   /** Set to the local absolute path that this node was moved from, if this
-   * file or directory has been moved here locally. */
+   * file or directory has been moved here locally and is the root of that
+   * move. Otherwise set to NULL.
+   *
+   * This will be NULL for moved-here nodes that are just part of a subtree
+   * that was moved along (and are not themselves a root of a different move
+   * operation).
+   * 
+   * @since New in 1.8. */
   const char *moved_from_abspath;
 
   /** Set to the local absolute path that this node was moved to, if this file
-   * or directory has been moved away locally. */
+   * or directory has been moved away locally and corresponds to the root
+   * of the destination side of the move. Otherwise set to NULL.
+   *
+   * Note: Saying just "root" here could be misleading. For example:
+   *   svn mv A AA;
+   *   svn mv AA/B BB;
+   * creates a situation where A/B is moved-to BB, but one could argue that
+   * the move source's root actually was AA/B. Note that, as far as the
+   * working copy is concerned, above case is exactly identical to:
+   *   svn mv A/B BB;
+   *   svn mv A AA;
+   * In both situations, @a moved_to_abspath would be set for nodes A (moved
+   * to AA) and A/B (moved to BB), only.
+   *
+   * This will be NULL for moved-away nodes that were just part of a subtree
+   * that was moved along (and are not themselves a root of a different move
+   * operation).
+   *
+   * @since New in 1.8. */
   const char *moved_to_abspath;
 
-  /* If this file or directory has been moved away locally, set this to the
-   * local absolute path that was the root of the move-away, i.e. to the
-   * op-root of the delete-half of the move operation. */
-  const char *moved_to_op_root_abspath;
-
   /* NOTE! Please update svn_client_status_dup() when adding new fields here. */
 } svn_client_status_t;
 
@@ -2756,6 +2776,10 @@ svn_client_blame(const char *path_or_url
  * If @a show_copies_as_adds is TRUE, then copied files will not be diffed
  * against their copyfrom source, and will appear in the diff output
  * in their entirety, as if they were newly added.
+ * ### BUGS: For a repos-repos diff, this is ignored. Instead, a file is
+ *     diffed against its copyfrom source iff the file is the diff target
+ *     and not if some parent directory is the diff target. For a repos-WC
+ *     diff, this is ignored if the file is the diff target.
  *
  * If @a use_git_diff_format is TRUE, then the git's extended diff format
  * will be used.

Modified: subversion/branches/fs-py/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/include/svn_ra.h?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/include/svn_ra.h (original)
+++ subversion/branches/fs-py/subversion/include/svn_ra.h Mon Aug 22 15:21:13 2011
@@ -1695,7 +1695,8 @@ svn_ra_get_file_revs(svn_ra_session_t *s
 /**
  * Lock each path in @a path_revs, which is a hash whose keys are the
  * paths to be locked, and whose values are the corresponding base
- * revisions for each path.
+ * revisions for each path.  The keys are (const char *) and the
+ * revisions are (svn_revnum_t *).
  *
  * Note that locking is never anonymous, so any server implementing
  * this function will have to "pull" a username from the client, if

Modified: subversion/branches/fs-py/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/include/svn_wc.h?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/include/svn_wc.h (original)
+++ subversion/branches/fs-py/subversion/include/svn_wc.h Mon Aug 22 15:21:13 2011
@@ -1551,7 +1551,11 @@ typedef enum svn_wc_conflict_reason_t
   /** Object is already added or schedule-add. @since New in 1.6. */
   svn_wc_conflict_reason_added,
   /** Object is already replaced. @since New in 1.7. */
-  svn_wc_conflict_reason_replaced
+  svn_wc_conflict_reason_replaced,
+  /** Object is moved away. @since New in 1.8. */
+  svn_wc_conflict_reason_moved_away,
+  /** Object is moved here. @since New in 1.8. */
+  svn_wc_conflict_reason_moved_here
 
 } svn_wc_conflict_reason_t;
 
@@ -3618,18 +3622,38 @@ typedef struct svn_wc_status3_t
   /** @} */
 
   /** Set to the local absolute path that this node was moved from, if this
-   * file or directory has been moved here locally. */
+   * file or directory has been moved here locally and is the root of that
+   * move. Otherwise set to NULL.
+   *
+   * This will be NULL for moved-here nodes that are just part of a subtree
+   * that was moved along (and are not themselves a root of a different move
+   * operation).
+   * 
+   * @since New in 1.8. */
   const char *moved_from_abspath;
 
   /** Set to the local absolute path that this node was moved to, if this file
-   * or directory has been moved away locally. */
+   * or directory has been moved away locally and corresponds to the root
+   * of the destination side of the move. Otherwise set to NULL.
+   *
+   * Note: Saying just "root" here could be misleading. For example:
+   *   svn mv A AA;
+   *   svn mv AA/B BB;
+   * creates a situation where A/B is moved-to BB, but one could argue that
+   * the move source's root actually was AA/B. Note that, as far as the
+   * working copy is concerned, above case is exactly identical to:
+   *   svn mv A/B BB;
+   *   svn mv A AA;
+   * In both situations, @a moved_to_abspath would be set for nodes A (moved
+   * to AA) and A/B (moved to BB), only.
+   *
+   * This will be NULL for moved-away nodes that were just part of a subtree
+   * that was moved along (and are not themselves a root of a different move
+   * operation).
+   *
+   * @since New in 1.8. */
   const char *moved_to_abspath;
 
-  /* If this file or directory has been moved away locally, set this to the
-   * local absolute path that was the root of the move-away, i.e. to the
-   * op-root of the delete-half of the move operation. */
-  const char *moved_to_op_root_abspath;
-
   /* NOTE! Please update svn_wc_dup_status3() when adding new fields here. */
 } svn_wc_status3_t;
 

Modified: subversion/branches/fs-py/subversion/libsvn_client/cat.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/cat.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/cat.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/cat.c Mon Aug 22 15:21:13 2011
@@ -50,6 +50,7 @@ svn_client__get_normalized_stream(svn_st
                                   const char *local_abspath,
                                   const svn_opt_revision_t *revision,
                                   svn_boolean_t expand_keywords,
+                                  svn_boolean_t normalize_eols,
                                   svn_cancel_func_t cancel_func,
                                   void *cancel_baton,
                                   apr_pool_t *result_pool,
@@ -163,8 +164,10 @@ svn_client__get_normalized_stream(svn_st
 
   /* Wrap the output stream if translation is needed. */
   if (eol != NULL || kw != NULL)
-    input = svn_subst_stream_translated(input, eol, FALSE, kw, expand_keywords,
-                                        result_pool);
+    input = svn_subst_stream_translated(
+      input,
+      (eol_style && normalize_eols) ? SVN_SUBST_NATIVE_EOL_STR : eol,
+      FALSE, kw, expand_keywords, result_pool);
 
   *normal_stream = input;
 
@@ -211,7 +214,7 @@ svn_client_cat2(svn_stream_t *out,
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url, pool));
       SVN_ERR(svn_client__get_normalized_stream(&normal_stream, ctx->wc_ctx,
-                                            local_abspath, revision, TRUE,
+                                            local_abspath, revision, TRUE, FALSE,
                                             ctx->cancel_func, ctx->cancel_baton,
                                             pool, pool));
 

Modified: subversion/branches/fs-py/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/client.h?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/client.h (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/client.h Mon Aug 22 15:21:13 2011
@@ -595,11 +595,22 @@ svn_client__switch_internal(svn_revnum_t
 
    DEPTH is the depth to recurse.
 
-   RA_SESSION defines the additional RA session for requesting file
-   contents.
+   RA_SESSION is an RA session through which this editor may fetch
+   properties, file contents and directory listings of the 'old' side of the
+   diff. It is a separate RA session from the one through which this editor
+   is being driven.
 
    REVISION is the start revision in the comparison.
 
+   For each deleted directory, if WALK_DELETED_DIRS is true then just call
+   the 'dir_deleted' callback once, otherwise call the 'file_deleted' or
+   'dir_deleted' callback for each individual node in that subtree.
+
+   If TEXT_DELTAS is FALSE, then do not expect text deltas from the edit
+   drive, nor send text deltas to the diff callbacks.
+   ### TODO: The implementation currently does send text deltas to the diff
+       callbacks in many cases even if they are not wanted.
+
    If NOTIFY_FUNC is non-null, invoke it with NOTIFY_BATON for each
    file and directory operated on during the edit.
 
@@ -613,6 +624,7 @@ svn_client__get_diff_editor(const svn_de
                             svn_ra_session_t *ra_session,
                             svn_revnum_t revision,
                             svn_boolean_t walk_deleted_dirs,
+                            svn_boolean_t text_deltas,
                             const svn_wc_diff_callbacks4_t *diff_callbacks,
                             void *diff_cmd_baton,
                             svn_cancel_func_t cancel_func,
@@ -626,29 +638,23 @@ svn_client__get_diff_editor(const svn_de
 
 /*** Editor for diff summary ***/
 
-/* Create an editor for a repository diff summary, i.e. comparing one
-   repository version against the other and only providing information
-   about the changed items without the text deltas.
+/* Set *CALLBACKS and *CALLBACK_BATON to a set of diff callbacks that will
+   report a diff summary, i.e. only providing information about the changed
+   items without the text deltas.
 
-   TARGET is the target of the diff, relative to the root of the edit.
+   TARGET is the target path, relative to the anchor, of the diff.
 
    SUMMARIZE_FUNC is called with SUMMARIZE_BATON as parameter by the
-   created svn_delta_editor_t for each changed item.
-
-   See svn_client__get_diff_editor() for a description of the other
-   parameters.  */
+   created callbacks for each changed item.
+*/
 svn_error_t *
-svn_client__get_diff_summarize_editor(const char *target,
-                                      svn_client_diff_summarize_func_t
-                                      summarize_func,
-                                      void *summarize_baton,
-                                      svn_ra_session_t *ra_session,
-                                      svn_revnum_t revision,
-                                      svn_cancel_func_t cancel_func,
-                                      void *cancel_baton,
-                                      const svn_delta_editor_t **editor,
-                                      void **edit_baton,
-                                      apr_pool_t *pool);
+svn_client__get_diff_summarize_callbacks(
+                        svn_wc_diff_callbacks4_t **callbacks,
+                        void **callback_baton,
+                        const char *target,
+                        svn_client_diff_summarize_func_t summarize_func,
+                        void *summarize_baton,
+                        apr_pool_t *pool);
 
 /* ---------------------------------------------------------------- */
 
@@ -1051,13 +1057,21 @@ svn_client__ensure_revprop_table(apr_has
 
 /* Return a potentially translated version of local file LOCAL_ABSPATH
    in NORMAL_STREAM.  REVISION must be one of the following: BASE, COMMITTED,
-   WORKING.  Uses SCRATCH_POOL for temporary allocations. */
+   WORKING.
+
+   EXPAND_KEYWORDS operates as per the EXPAND argument to
+   svn_subst_stream_translated, which see.  If NORMALIZE_EOLS is TRUE and
+   LOCAL_ABSPATH requires translation, then normalize the line endings in
+   *NORMAL_STREAM.
+
+   Uses SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_client__get_normalized_stream(svn_stream_t **normal_stream,
                                   svn_wc_context_t *wc_ctx,
                                   const char *local_abspath,
                                   const svn_opt_revision_t *revision,
                                   svn_boolean_t expand_keywords,
+                                  svn_boolean_t normalize_eols,
                                   svn_cancel_func_t cancel_func,
                                   void *cancel_baton,
                                   apr_pool_t *result_pool,

Modified: subversion/branches/fs-py/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/diff.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/diff.c Mon Aug 22 15:21:13 2011
@@ -1753,7 +1753,8 @@ diff_repos_repos(const svn_wc_diff_callb
   SVN_ERR(svn_client__get_diff_editor(
                 &diff_editor, &diff_edit_baton,
                 NULL, "", depth,
-                extra_ra_session, rev1, TRUE,
+                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 */,
@@ -1762,7 +1763,7 @@ diff_repos_repos(const svn_wc_diff_callb
   /* 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. */
@@ -1970,6 +1971,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,
@@ -2006,6 +2008,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,
@@ -2038,6 +2098,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,
@@ -2046,6 +2108,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,
@@ -2053,10 +2119,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,
+            NULL /* wc_ctx */, "", 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
@@ -2084,6 +2153,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;
@@ -2098,10 +2168,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")));
 }
 
 
@@ -2331,10 +2407,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 *
@@ -2350,10 +2425,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/fs-py/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/merge.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/merge.c Mon Aug 22 15:21:13 2011
@@ -1854,7 +1854,7 @@ files_same_p(svn_boolean_t *same,
       /* Compare the file content, translating 'mine' to 'normal' form. */
       SVN_ERR(svn_client__get_normalized_stream(&mine_stream, wc_ctx,
                                                 mine_abspath, &working_rev,
-                                                FALSE, NULL, NULL,
+                                                FALSE, TRUE, NULL, NULL,
                                                 scratch_pool, scratch_pool));
 
       SVN_ERR(svn_stream_open_readonly(&older_stream, older_abspath,
@@ -5022,7 +5022,8 @@ drive_merge_report_editor(const char *ta
                                       merge_b->ctx->wc_ctx, target_abspath,
                                       depth,
                                       merge_b->ra_session2, revision1,
-                                      FALSE,
+                                      FALSE /* walk_deleted_dirs */,
+                                      TRUE /* text_deltas */,
                                       &merge_callbacks, merge_b,
                                       merge_b->ctx->cancel_func,
                                       merge_b->ctx->cancel_baton,

Modified: subversion/branches/fs-py/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/repos_diff.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/repos_diff.c Mon Aug 22 15:21:13 2011
@@ -98,6 +98,9 @@ struct edit_baton {
      FALSE otherwise. */
   svn_boolean_t walk_deleted_repos_dirs;
 
+  /* Whether to report text deltas */
+  svn_boolean_t text_deltas;
+
   /* A callback used to see if the client wishes to cancel the running
      operation. */
   svn_cancel_func_t cancel_func;
@@ -315,11 +318,19 @@ get_file_mime_types(const char **mimetyp
 }
 
 
-/* Get revision REVISION of the file described by B from the repository.
- * Set B->path_start_revision to the path of a new temporary file containing
- * the file's text.  Set B->pristine_props to a new hash containing the
- * file's properties.  Install a pool cleanup handler on B->pool to delete
- * the file.
+/* Get revision B->base_revision of the file described by B from the
+ * repository, through B->edit_baton->ra_session.
+ *
+ * Unless PROPS_ONLY is true:
+ *   Set B->path_start_revision to the path of a new temporary file containing
+ *   the file's text.
+ *   Set B->start_md5_checksum to that file's MD-5 checksum.
+ *   Install a pool cleanup handler on B->pool to delete the file.
+ *
+ * Always:
+ *   Set B->pristine_props to a new hash containing the file's properties.
+ *
+ * Allocate all results in B->pool.
  */
 static svn_error_t *
 get_file_from_ra(struct file_baton *b,
@@ -332,7 +343,7 @@ get_file_from_ra(struct file_baton *b,
 
       SVN_ERR(svn_stream_open_unique(&fstream, &(b->path_start_revision), NULL,
                                      svn_io_file_del_on_pool_cleanup,
-                                     scratch_pool, scratch_pool));
+                                     b->pool, scratch_pool));
 
       fstream = svn_stream_checksummed2(fstream, NULL, &b->start_md5_checksum,
                                         svn_checksum_md5, TRUE, scratch_pool);
@@ -485,7 +496,7 @@ open_root(void *edit_baton,
 }
 
 /* Recursively walk tree rooted at DIR (at REVISION) in the repository,
- * reporting all files as deleted.  Part of a workaround for issue 2333.
+ * reporting all children as deleted.  Part of a workaround for issue 2333.
  *
  * DIR is a repository path relative to the URL in RA_SESSION.  REVISION
  * must be a valid revision number, not SVN_INVALID_REVNUM.  EB is the
@@ -554,13 +565,20 @@ diff_deleted_dir(const char *dir,
         }
 
       if (dirent->kind == svn_node_dir)
-        SVN_ERR(diff_deleted_dir(path,
-                                 revision,
-                                 ra_session,
-                                 eb,
-                                 cancel_func,
-                                 cancel_baton,
-                                 iterpool));
+        {
+          const char *wcpath = svn_dirent_join(eb->target, path, iterpool);
+
+          SVN_ERR(eb->diff_callbacks->dir_deleted(
+                                NULL, NULL, wcpath,
+                                eb->diff_cmd_baton, iterpool));
+          SVN_ERR(diff_deleted_dir(path,
+                                   revision,
+                                   ra_session,
+                                   eb,
+                                   cancel_func,
+                                   cancel_baton,
+                                   iterpool));
+        }
     }
 
   svn_pool_destroy(iterpool);
@@ -969,7 +987,7 @@ close_file(void *file_baton,
 
   scratch_pool = b->pool;
 
-  if (expected_md5_digest)
+  if (expected_md5_digest && eb->text_deltas)
     {
       svn_checksum_t *expected_md5_checksum;
 
@@ -1086,7 +1104,13 @@ close_file(void *file_baton,
   return SVN_NO_ERROR;
 }
 
-/* An svn_delta_editor_t function.  */
+/* Report any accumulated prop changes via the 'dir_props_changed' callback,
+ * and then call the 'dir_closed' callback.  Notify about any deleted paths
+ * within this directory that have not already been notified, and then about
+ * this directory itself (unless it was added, in which case the notification
+ * was done at that time).
+ *
+ * An svn_delta_editor_t function.  */
 static svn_error_t *
 close_directory(void *dir_baton,
                 apr_pool_t *pool)
@@ -1110,6 +1134,7 @@ close_directory(void *dir_baton,
   if (!b->added && b->propchanges->nelts > 0)
     remove_non_prop_changes(b->pristine_props, b->propchanges);
 
+  /* Report any prop changes. */
   if (b->propchanges->nelts > 0)
     {
       svn_boolean_t tree_conflicted = FALSE;
@@ -1134,8 +1159,8 @@ close_directory(void *dir_baton,
                                          b->edit_baton->diff_cmd_baton,
                                          scratch_pool));
 
-  /* Don't notify added directories as they triggered notification
-     in add_directory. */
+  /* Notify about any deleted paths within this directory that have not
+   * already been notified. */
   if (!skipped && !b->added && eb->notify_func)
     {
       apr_hash_index_t *hi;
@@ -1157,6 +1182,8 @@ close_directory(void *dir_baton,
         }
     }
 
+  /* Notify about this directory itself (unless it was added, in which
+   * case the notification was done at that time). */
   if (!b->added && eb->notify_func)
     {
       svn_wc_notify_t *notify;
@@ -1188,7 +1215,9 @@ close_directory(void *dir_baton,
 }
 
 
-/* An svn_delta_editor_t function.  */
+/* Record a prop change, which we will report later in close_file().
+ *
+ * An svn_delta_editor_t function.  */
 static svn_error_t *
 change_file_prop(void *file_baton,
                  const char *name,
@@ -1209,7 +1238,9 @@ change_file_prop(void *file_baton,
   return SVN_NO_ERROR;
 }
 
-/* An svn_delta_editor_t function.  */
+/* Make a note of this prop change, to be reported when the dir is closed.
+ *
+ * An svn_delta_editor_t function.  */
 static svn_error_t *
 change_dir_prop(void *dir_baton,
                 const char *name,
@@ -1243,7 +1274,8 @@ close_edit(void *edit_baton,
   return SVN_NO_ERROR;
 }
 
-/* An svn_delta_editor_t function.  */
+/* Notify that the node at PATH is 'missing'.
+ * An svn_delta_editor_t function.  */
 static svn_error_t *
 absent_directory(const char *path,
                  void *parent_baton,
@@ -1272,7 +1304,8 @@ absent_directory(const char *path,
 }
 
 
-/* An svn_delta_editor_t function.  */
+/* Notify that the node at PATH is 'missing'.
+ * An svn_delta_editor_t function.  */
 static svn_error_t *
 absent_file(const char *path,
             void *parent_baton,
@@ -1310,6 +1343,7 @@ svn_client__get_diff_editor(const svn_de
                             svn_ra_session_t *ra_session,
                             svn_revnum_t revision,
                             svn_boolean_t walk_deleted_dirs,
+                            svn_boolean_t text_deltas,
                             const svn_wc_diff_callbacks4_t *diff_callbacks,
                             void *diff_cmd_baton,
                             svn_cancel_func_t cancel_func,
@@ -1340,6 +1374,7 @@ svn_client__get_diff_editor(const svn_de
   eb->notify_func = notify_func;
   eb->notify_baton = notify_baton;
   eb->walk_deleted_repos_dirs = walk_deleted_dirs;
+  eb->text_deltas = text_deltas;
   eb->cancel_func = cancel_func;
   eb->cancel_baton = cancel_baton;
 

Modified: subversion/branches/fs-py/subversion/libsvn_client/repos_diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/repos_diff_summarize.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/repos_diff_summarize.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/repos_diff_summarize.c Mon Aug 22 15:21:13 2011
@@ -1,5 +1,5 @@
 /*
- * repos_diff_summarize.c -- The diff summarize editor for summarizing
+ * repos_diff_summarize.c -- The diff callbacks for summarizing
  * the differences of two repository versions
  *
  * ====================================================================
@@ -30,9 +30,9 @@
 #include "client.h"
 
 
-/* Overall crawler editor baton.  */
-struct edit_baton {
-  /* The target of the diff, relative to the root of the edit */
+/* Diff callbacks baton.  */
+struct summarize_baton_t {
+  /* The target path of the diff, relative to the anchor; "" if target == anchor. */
   const char *target;
 
   /* The summarize callback passed down from the API */
@@ -41,412 +41,295 @@ struct edit_baton {
   /* The summarize callback baton */
   void *summarize_func_baton;
 
-  /* An RA session used to check the kind of deleted paths */
-  svn_ra_session_t *ra_session;
-
-  /* The start revision for the comparison */
-  svn_revnum_t revision;
-
-  /* TRUE if the operation needs to walk deleted dirs on the "old" side.
-     FALSE otherwise. */
-  svn_boolean_t walk_deleted_repos_dirs;
-
-  /* A callback used to see if the client wishes to cancel the running
-     operation. */
-  svn_cancel_func_t cancel_func;
-
-  /* A baton to pass to the cancellation callback. */
-  void *cancel_baton;
-
+  /* Which paths have a prop change. Key is a (const char *) path; the value
+   * is any non-null pointer to indicate that this path has a prop change. */
+  apr_hash_t *prop_changes;
 };
 
 
-/* Item baton. */
-struct item_baton {
-  /* The overall crawler editor baton */
-  struct edit_baton *edit_baton;
-
-  /* The summarize filled by the editor calls, NULL if this item hasn't
-     been modified (yet) */
-  svn_client_diff_summarize_t *summarize;
-
-  /* The path of the file or directory within the repository */
-  const char *path;
-
-  /* The kind of this item */
-  svn_node_kind_t node_kind;
-
-  /* The file/directory pool */
-  apr_pool_t *item_pool;
-};
-
-
-/* Create an item baton, with the fields initialized to EDIT_BATON, PATH,
- * NODE_KIND and POOL, respectively.  Allocate the returned structure in POOL.
- */
-static struct item_baton *
-create_item_baton(struct edit_baton *edit_baton,
-                  const char *path,
-                  svn_node_kind_t node_kind,
-                  apr_pool_t *pool)
-{
-  struct item_baton *b = apr_pcalloc(pool, sizeof(*b));
-
-  b->edit_baton = edit_baton;
-  /* Issue #2765: b->path is supposed to be relative to the target.
-     If the target is a file, just use an empty path.  This way the
-     receiver can just concatenate this path to the original path
-     without doing any extra checks. */
-  if (node_kind == svn_node_file && strcmp(path, edit_baton->target) == 0)
-    b->path =  "";
-  else
-    b->path = apr_pstrdup(pool, path);
-  b->node_kind = node_kind;
-  b->item_pool = pool;
-
-  return b;
-}
-
-/* Make sure that this item baton contains a summarize struct.
- * If it doesn't before this call, allocate a new struct in the item's pool,
- * initializing the diff kind to normal.
- * All other fields are also initialized from IB or to NULL/invalid values. */
-static void
-ensure_summarize(struct item_baton *ib)
-{
-  svn_client_diff_summarize_t *sum;
-  if (ib->summarize)
-    return;
-
-  sum = apr_pcalloc(ib->item_pool, sizeof(*sum));
-
-  sum->node_kind = ib->node_kind;
-  sum->summarize_kind = svn_client_diff_summarize_kind_normal;
-  sum->path = ib->path;
-
-  ib->summarize = sum;
-}
-
-
-/* An svn_delta_editor_t function. The root of the comparison hierarchy */
+/* Call B->summarize_func with B->summarize_func_baton, passing it a
+ * summary object composed from PATH (but made to be relative to the target
+ * of the diff), SUMMARIZE_KIND, PROP_CHANGED (or FALSE if the action is an
+ * add or delete) and NODE_KIND. */
 static svn_error_t *
-open_root(void *edit_baton,
-          svn_revnum_t base_revision,
-          apr_pool_t *pool,
-          void **root_baton)
+send_summary(struct summarize_baton_t *b,
+             const char *path,
+             svn_client_diff_summarize_kind_t summarize_kind,
+             svn_boolean_t prop_changed,
+             svn_node_kind_t node_kind,
+             apr_pool_t *scratch_pool)
 {
-  struct item_baton *ib = create_item_baton(edit_baton, "",
-                                            svn_node_dir, pool);
+  svn_client_diff_summarize_t *sum = apr_pcalloc(scratch_pool, sizeof(*sum));
 
-  *root_baton = ib;
-  return SVN_NO_ERROR;
-}
+  /* PATH is relative to the anchor of the diff, but SUM->path needs to be
+     relative to the target of the diff. */
+  sum->path = svn_relpath_skip_ancestor(b->target, path);
+  sum->summarize_kind = summarize_kind;
+  if (summarize_kind == svn_client_diff_summarize_kind_modified
+      || summarize_kind == svn_client_diff_summarize_kind_normal)
+    sum->prop_changed = prop_changed;
+  sum->node_kind = node_kind;
 
-/* Recursively walk the tree rooted at DIR (at REVISION) in the
- * repository, reporting all files as deleted.  Part of a workaround
- * for issue 2333.
- *
- * DIR is a repository path relative to the URL in RA_SESSION.  REVISION
- * may be NULL, in which case it defaults to HEAD.  EDIT_BATON is the
- * overall crawler editor baton.  If CANCEL_FUNC is not NULL, then it
- * should refer to a cancellation function (along with CANCEL_BATON).
- */
-/* ### TODO: Handle depth. */
-static svn_error_t *
-diff_deleted_dir(const char *dir,
-                 svn_revnum_t revision,
-                 svn_ra_session_t *ra_session,
-                 void *edit_baton,
-                 svn_cancel_func_t cancel_func,
-                 void *cancel_baton,
-                 apr_pool_t *pool)
-{
-  struct edit_baton *eb = edit_baton;
-  apr_hash_t *dirents;
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  apr_hash_index_t *hi;
-
-  if (cancel_func)
-    SVN_ERR(cancel_func(cancel_baton));
-
-  SVN_ERR(svn_ra_get_dir2(ra_session,
-                          &dirents,
-                          NULL, NULL,
-                          dir,
-                          revision,
-                          SVN_DIRENT_KIND,
-                          pool));
-
-  for (hi = apr_hash_first(pool, dirents); hi;
-       hi = apr_hash_next(hi))
-    {
-      const char *path;
-      const char *name = svn__apr_hash_index_key(hi);
-      svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
-      svn_node_kind_t kind;
-      svn_client_diff_summarize_t *sum;
-
-      svn_pool_clear(iterpool);
-
-      path = svn_relpath_join(dir, name, iterpool);
-
-      SVN_ERR(svn_ra_check_path(eb->ra_session,
-                                path,
-                                eb->revision,
-                                &kind,
-                                iterpool));
-
-      sum = apr_pcalloc(iterpool, sizeof(*sum));
-      sum->summarize_kind = svn_client_diff_summarize_kind_deleted;
-      sum->path = path;
-      sum->node_kind = kind;
-
-      SVN_ERR(eb->summarize_func(sum,
-                                 eb->summarize_func_baton,
-                                 iterpool));
-
-      if (dirent->kind == svn_node_dir)
-        SVN_ERR(diff_deleted_dir(path,
-                                 revision,
-                                 ra_session,
-                                 eb,
-                                 cancel_func,
-                                 cancel_baton,
-                                 iterpool));
-    }
-
-  svn_pool_destroy(iterpool);
+  SVN_ERR(b->summarize_func(sum, b->summarize_func_baton, scratch_pool));
   return SVN_NO_ERROR;
 }
 
-/* An svn_delta_editor_t function.  */
-static svn_error_t *
-delete_entry(const char *path,
-             svn_revnum_t base_revision,
-             void *parent_baton,
-             apr_pool_t *pool)
-{
-  struct item_baton *ib = parent_baton;
-  struct edit_baton *eb = ib->edit_baton;
-  svn_client_diff_summarize_t *sum;
-  svn_node_kind_t kind;
-
-  /* We need to know if this is a directory or a file */
-  SVN_ERR(svn_ra_check_path(eb->ra_session,
-                            path,
-                            eb->revision,
-                            &kind,
-                            pool));
-
-  sum = apr_pcalloc(pool, sizeof(*sum));
-  sum->summarize_kind = svn_client_diff_summarize_kind_deleted;
-  sum->path = path;
-  sum->node_kind = kind;
-
-  SVN_ERR(eb->summarize_func(sum, eb->summarize_func_baton, pool));
-
-  if (kind == svn_node_dir)
-        SVN_ERR(diff_deleted_dir(path,
-                                 eb->revision,
-                                 eb->ra_session,
-                                 eb,
-                                 eb->cancel_func,
-                                 eb->cancel_baton,
-                                 pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* An svn_delta_editor_t function.  */
-static svn_error_t *
-add_directory(const char *path,
-              void *parent_baton,
-              const char *copyfrom_path,
-              svn_revnum_t copyfrom_rev,
-              apr_pool_t *pool,
-              void **child_baton)
+/* Are there any changes to relevant (normal) props in PROPCHANGES? */
+static svn_boolean_t
+props_changed(const apr_array_header_t *propchanges,
+              apr_pool_t *scratch_pool)
 {
-  struct item_baton *pb = parent_baton;
-  struct item_baton *cb;
+  apr_array_header_t *props;
 
-  cb = create_item_baton(pb->edit_baton, path, svn_node_dir, pool);
-  ensure_summarize(cb);
-  cb->summarize->summarize_kind = svn_client_diff_summarize_kind_added;
-
-  *child_baton = cb;
-  return SVN_NO_ERROR;
+  svn_error_clear(svn_categorize_props(propchanges, NULL, NULL, &props,
+                                       scratch_pool));
+  return (props->nelts != 0);
 }
 
-/* An svn_delta_editor_t function.  */
+
 static svn_error_t *
-open_directory(const char *path,
-               void *parent_baton,
-               svn_revnum_t base_revision,
-               apr_pool_t *pool,
-               void **child_baton)
+cb_dir_deleted(svn_wc_notify_state_t *state,
+               svn_boolean_t *tree_conflicted,
+               const char *path,
+               void *diff_baton,
+               apr_pool_t *scratch_pool)
 {
-  struct item_baton *pb = parent_baton;
-  struct item_baton *cb;
+  struct summarize_baton_t *b = diff_baton;
 
-  cb = create_item_baton(pb->edit_baton, path, svn_node_dir, pool);
+  SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_deleted,
+                       FALSE, svn_node_dir, scratch_pool));
 
-  *child_baton = cb;
+  if (state)
+    *state = svn_wc_notify_state_inapplicable;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
   return SVN_NO_ERROR;
 }
 
-
-/* An svn_delta_editor_t function.  */
 static svn_error_t *
-close_directory(void *dir_baton,
-                apr_pool_t *pool)
+cb_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 *originalprops,
+                void *diff_baton,
+                apr_pool_t *scratch_pool)
 {
-  struct item_baton *ib = dir_baton;
-  struct edit_baton *eb = ib->edit_baton;
+  struct summarize_baton_t *b = diff_baton;
 
-  if (ib->summarize)
-    SVN_ERR(eb->summarize_func(ib->summarize, eb->summarize_func_baton,
-                               pool));
+  SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_deleted,
+                       FALSE, svn_node_file, scratch_pool));
 
+  if (state)
+    *state = svn_wc_notify_state_inapplicable;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
   return SVN_NO_ERROR;
 }
 
-
-/* An svn_delta_editor_t function.  */
 static svn_error_t *
-add_file(const char *path,
-         void *parent_baton,
-         const char *copyfrom_path,
-         svn_revnum_t copyfrom_rev,
-         apr_pool_t *pool,
-         void **file_baton)
+cb_dir_added(svn_wc_notify_state_t *state,
+             svn_boolean_t *tree_conflicted,
+             svn_boolean_t *skip,
+             svn_boolean_t *skip_children,
+             const char *path,
+             svn_revnum_t rev,
+             const char *copyfrom_path,
+             svn_revnum_t copyfrom_revision,
+             void *diff_baton,
+             apr_pool_t *scratch_pool)
 {
-  struct item_baton *pb = parent_baton;
-  struct item_baton *cb;
-
-  cb = create_item_baton(pb->edit_baton, path, svn_node_file, pool);
-  ensure_summarize(cb);
-  cb->summarize->summarize_kind = svn_client_diff_summarize_kind_added;
-
-  *file_baton = cb;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
+  if (skip)
+    *skip = FALSE;
+  if (skip_children)
+    *skip_children = FALSE;
   return SVN_NO_ERROR;
 }
 
-/* An svn_delta_editor_t function.  */
 static svn_error_t *
-open_file(const char *path,
-          void *parent_baton,
-          svn_revnum_t base_revision,
-          apr_pool_t *pool,
-          void **file_baton)
+cb_dir_opened(svn_boolean_t *tree_conflicted,
+              svn_boolean_t *skip,
+              svn_boolean_t *skip_children,
+              const char *path,
+              svn_revnum_t rev,
+              void *diff_baton,
+              apr_pool_t *scratch_pool)
 {
-  struct item_baton *pb = parent_baton;
-  struct item_baton *cb;
-
-  cb = create_item_baton(pb->edit_baton, path, svn_node_file, pool);
-
-  *file_baton = cb;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
+  if (skip)
+    *skip = FALSE;
+  if (skip_children)
+    *skip_children = FALSE;
   return SVN_NO_ERROR;
 }
 
-/* An svn_delta_editor_t function.  */
 static svn_error_t *
-apply_textdelta(void *file_baton,
-                const char *base_checksum,
-                apr_pool_t *pool,
-                svn_txdelta_window_handler_t *handler,
-                void **handler_baton)
+cb_dir_closed(svn_wc_notify_state_t *contentstate,
+              svn_wc_notify_state_t *propstate,
+              svn_boolean_t *tree_conflicted,
+              const char *path,
+              svn_boolean_t dir_was_added,
+              void *diff_baton,
+              apr_pool_t *scratch_pool)
 {
-  struct item_baton *ib = file_baton;
+  struct summarize_baton_t *b = diff_baton;
+  svn_boolean_t prop_change;
 
-  ensure_summarize(ib);
-  if (ib->summarize->summarize_kind == svn_client_diff_summarize_kind_normal)
-    ib->summarize->summarize_kind = svn_client_diff_summarize_kind_modified;
-
-  *handler = svn_delta_noop_window_handler;
-  *handler_baton = NULL;
+  prop_change = apr_hash_get(b->prop_changes, path, APR_HASH_KEY_STRING) != NULL;
+  if (dir_was_added || prop_change)
+    SVN_ERR(send_summary(b, path,
+                         dir_was_added ? svn_client_diff_summarize_kind_added
+                                       : svn_client_diff_summarize_kind_normal,
+                         prop_change, svn_node_dir, scratch_pool));
 
+  if (contentstate)
+    *contentstate = svn_wc_notify_state_inapplicable;
+  if (propstate)
+    *propstate = svn_wc_notify_state_inapplicable;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
   return SVN_NO_ERROR;
 }
 
-
-/* An svn_delta_editor_t function.  */
 static svn_error_t *
-close_file(void *file_baton,
-           const char *text_checksum,
-           apr_pool_t *pool)
-{
-  struct item_baton *fb = file_baton;
-  struct edit_baton *eb = fb->edit_baton;
-
-  if (fb->summarize)
-    SVN_ERR(eb->summarize_func(fb->summarize, eb->summarize_func_baton,
-                               pool));
-
+cb_file_added(svn_wc_notify_state_t *contentstate,
+              svn_wc_notify_state_t *propstate,
+              svn_boolean_t *tree_conflicted,
+              const char *path,
+              const char *tmpfile1,
+              const char *tmpfile2,
+              svn_revnum_t rev1,
+              svn_revnum_t rev2,
+              const char *mimetype1,
+              const char *mimetype2,
+              const char *copyfrom_path,
+              svn_revnum_t copyfrom_revision,
+              const apr_array_header_t *propchanges,
+              apr_hash_t *originalprops,
+              void *diff_baton,
+              apr_pool_t *scratch_pool)
+{
+  struct summarize_baton_t *b = diff_baton;
+
+  SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_added,
+                       props_changed(propchanges, scratch_pool),
+                       svn_node_file, scratch_pool));
+
+  if (contentstate)
+    *contentstate = svn_wc_notify_state_inapplicable;
+  if (propstate)
+    *propstate = svn_wc_notify_state_inapplicable;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+cb_file_opened(svn_boolean_t *tree_conflicted,
+               svn_boolean_t *skip,
+               const char *path,
+               svn_revnum_t rev,
+               void *diff_baton,
+               apr_pool_t *scratch_pool)
+{
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
+  if (skip)
+    *skip = FALSE;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+cb_file_changed(svn_wc_notify_state_t *contentstate,
+                svn_wc_notify_state_t *propstate,
+                svn_boolean_t *tree_conflicted,
+                const char *path,
+                const char *tmpfile1,
+                const char *tmpfile2,
+                svn_revnum_t rev1,
+                svn_revnum_t rev2,
+                const char *mimetype1,
+                const char *mimetype2,
+                const apr_array_header_t *propchanges,
+                apr_hash_t *originalprops,
+                void *diff_baton,
+                apr_pool_t *scratch_pool)
+{
+  struct summarize_baton_t *b = diff_baton;
+  svn_boolean_t text_change = (tmpfile2 != NULL);
+
+  SVN_ERR(send_summary(b, path,
+                       text_change ? svn_client_diff_summarize_kind_modified
+                                   : svn_client_diff_summarize_kind_normal,
+                       props_changed(propchanges, scratch_pool),
+                       svn_node_file, scratch_pool));
+
+  if (contentstate)
+    *contentstate = svn_wc_notify_state_inapplicable;
+  if (propstate)
+    *propstate = svn_wc_notify_state_inapplicable;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+cb_dir_props_changed(svn_wc_notify_state_t *propstate,
+                     svn_boolean_t *tree_conflicted,
+                     const char *path,
+                     svn_boolean_t dir_was_added,
+                     const apr_array_header_t *propchanges,
+                     apr_hash_t *original_props,
+                     void *diff_baton,
+                     apr_pool_t *scratch_pool)
+{
+  struct summarize_baton_t *b = diff_baton;
+
+  if (props_changed(propchanges, scratch_pool))
+    apr_hash_set(b->prop_changes, path, APR_HASH_KEY_STRING, path);
+
+  if (propstate)
+    *propstate = svn_wc_notify_state_inapplicable;
+  if (tree_conflicted)
+    *tree_conflicted = FALSE;
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_client__get_diff_summarize_callbacks(
+                        svn_wc_diff_callbacks4_t **callbacks,
+                        void **callback_baton,
+                        const char *target,
+                        svn_client_diff_summarize_func_t summarize_func,
+                        void *summarize_baton,
+                        apr_pool_t *pool)
+{
+  svn_wc_diff_callbacks4_t *cb = apr_palloc(pool, sizeof(*cb));
+  struct summarize_baton_t *b = apr_palloc(pool, sizeof(*b));
+
+  b->target = target;
+  b->summarize_func = summarize_func;
+  b->summarize_func_baton = summarize_baton;
+  b->prop_changes = apr_hash_make(pool);
+
+  cb->file_opened = cb_file_opened;
+  cb->file_changed = cb_file_changed;
+  cb->file_added = cb_file_added;
+  cb->file_deleted = cb_file_deleted;
+  cb->dir_deleted = cb_dir_deleted;
+  cb->dir_opened = cb_dir_opened;
+  cb->dir_added = cb_dir_added;
+  cb->dir_props_changed = cb_dir_props_changed;
+  cb->dir_closed = cb_dir_closed;
 
-/* An svn_delta_editor_t function, implementing both change_file_prop and
- * change_dir_prop.  */
-static svn_error_t *
-change_prop(void *entry_baton,
-            const char *name,
-            const svn_string_t *value,
-            apr_pool_t *pool)
-{
-  struct item_baton *ib = entry_baton;
-
-  if (svn_property_kind(NULL, name) == svn_prop_regular_kind)
-    {
-      ensure_summarize(ib);
-
-      if (ib->summarize->summarize_kind != svn_client_diff_summarize_kind_added)
-        ib->summarize->prop_changed = TRUE;
-    }
+  *callbacks = cb;
+  *callback_baton = b;
 
   return SVN_NO_ERROR;
 }
-
-/* Create a repository diff summarize editor and baton.  */
-svn_error_t *
-svn_client__get_diff_summarize_editor(const char *target,
-                                      svn_client_diff_summarize_func_t
-                                      summarize_func,
-                                      void *summarize_baton,
-                                      svn_ra_session_t *ra_session,
-                                      svn_revnum_t revision,
-                                      svn_cancel_func_t cancel_func,
-                                      void *cancel_baton,
-                                      const svn_delta_editor_t **editor,
-                                      void **edit_baton,
-                                      apr_pool_t *pool)
-{
-  svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool);
-  struct edit_baton *eb = apr_palloc(pool, sizeof(*eb));
-
-  eb->target = target;
-  eb->summarize_func = summarize_func;
-  eb->summarize_func_baton = summarize_baton;
-  eb->ra_session = ra_session;
-  eb->revision = revision;
-  eb->walk_deleted_repos_dirs = TRUE;
-  eb->cancel_func = cancel_func;
-  eb->cancel_baton = cancel_baton;
-
-  tree_editor->open_root = open_root;
-  tree_editor->delete_entry = delete_entry;
-  tree_editor->add_directory = add_directory;
-  tree_editor->open_directory = open_directory;
-  tree_editor->change_dir_prop = change_prop;
-  tree_editor->close_directory = close_directory;
-
-  tree_editor->add_file = add_file;
-  tree_editor->open_file = open_file;
-  tree_editor->apply_textdelta = apply_textdelta;
-  tree_editor->change_file_prop = change_prop;
-  tree_editor->close_file = close_file;
-
-  return svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
-                                           tree_editor, eb, editor, edit_baton,
-                                           pool);
-}