You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2011/08/23 16:03:14 UTC

svn commit: r1160699 [1/3] - in /subversion/branches/issue-3975: ./ build/ notes/ subversion/bindings/swig/ruby/test/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_ra_serf/ subversion/libsvn_ra_svn/ subvers...

Author: pburba
Date: Tue Aug 23 14:03:12 2011
New Revision: 1160699

URL: http://svn.apache.org/viewvc?rev=1160699&view=rev
Log:
On the issue-3975 branch: Sync with ^/subversion/trunk.

Added:
    subversion/branches/issue-3975/notes/diff-data-flows.txt
      - copied unchanged from r1160684, subversion/trunk/notes/diff-data-flows.txt
Modified:
    subversion/branches/issue-3975/   (props changed)
    subversion/branches/issue-3975/CHANGES
    subversion/branches/issue-3975/build/transform_sql.py
    subversion/branches/issue-3975/notes/moves
    subversion/branches/issue-3975/subversion/bindings/swig/ruby/test/test_client.rb
    subversion/branches/issue-3975/subversion/include/private/svn_sqlite.h
    subversion/branches/issue-3975/subversion/include/svn_client.h
    subversion/branches/issue-3975/subversion/include/svn_wc.h
    subversion/branches/issue-3975/subversion/libsvn_client/client.h
    subversion/branches/issue-3975/subversion/libsvn_client/diff.c
    subversion/branches/issue-3975/subversion/libsvn_client/merge.c
    subversion/branches/issue-3975/subversion/libsvn_client/repos_diff.c
    subversion/branches/issue-3975/subversion/libsvn_client/repos_diff_summarize.c
    subversion/branches/issue-3975/subversion/libsvn_client/status.c
    subversion/branches/issue-3975/subversion/libsvn_ra_serf/blame.c
    subversion/branches/issue-3975/subversion/libsvn_ra_serf/commit.c
    subversion/branches/issue-3975/subversion/libsvn_ra_svn/cyrus_auth.c
    subversion/branches/issue-3975/subversion/libsvn_subr/cmdline.c
    subversion/branches/issue-3975/subversion/libsvn_subr/magic.c
    subversion/branches/issue-3975/subversion/libsvn_subr/svn_cache_config.c
    subversion/branches/issue-3975/subversion/libsvn_subr/utf.c
    subversion/branches/issue-3975/subversion/libsvn_subr/validate.c
    subversion/branches/issue-3975/subversion/libsvn_wc/adm_ops.c
    subversion/branches/issue-3975/subversion/libsvn_wc/diff_local.c
    subversion/branches/issue-3975/subversion/libsvn_wc/questions.c
    subversion/branches/issue-3975/subversion/libsvn_wc/status.c
    subversion/branches/issue-3975/subversion/libsvn_wc/tree_conflicts.c
    subversion/branches/issue-3975/subversion/libsvn_wc/update_editor.c
    subversion/branches/issue-3975/subversion/libsvn_wc/upgrade.c
    subversion/branches/issue-3975/subversion/libsvn_wc/wc-metadata.sql
    subversion/branches/issue-3975/subversion/libsvn_wc/wc-queries.sql
    subversion/branches/issue-3975/subversion/libsvn_wc/wc.h
    subversion/branches/issue-3975/subversion/libsvn_wc/wc_db.c
    subversion/branches/issue-3975/subversion/libsvn_wc/wc_db.h
    subversion/branches/issue-3975/subversion/mod_dav_svn/liveprops.c
    subversion/branches/issue-3975/subversion/mod_dav_svn/mod_dav_svn.c
    subversion/branches/issue-3975/subversion/svn/main.c
    subversion/branches/issue-3975/subversion/svn/tree-conflicts.c
    subversion/branches/issue-3975/subversion/svndumpfilter/main.c
    subversion/branches/issue-3975/subversion/tests/cmdline/changelist_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/copy_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/diff_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/input_validation_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/patch_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/revert_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/svndumpfilter_tests.py
    subversion/branches/issue-3975/subversion/tests/cmdline/upgrade_tests.py
    subversion/branches/issue-3975/subversion/tests/libsvn_diff/parse-diff-test.c
    subversion/branches/issue-3975/tools/dist/collect_sigs.py
    subversion/branches/issue-3975/tools/dist/dist.sh
    subversion/branches/issue-3975/tools/dist/release.py

Propchange: subversion/branches/issue-3975/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Aug 23 14:03:12 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/issue-3975/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Aug 23 14:03:12 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:1152931-1158857
+/subversion/trunk:1152931-1160684

Modified: subversion/branches/issue-3975/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/CHANGES?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/CHANGES (original)
+++ subversion/branches/issue-3975/CHANGES Tue Aug 23 14:03:12 2011
@@ -29,7 +29,6 @@ the 1.6 release:  http://subversion.apac
 
   - Minor new features and improvements:
     * Better handling of HTTP redirects (issue #2779)
-    * make Serf the default DAV access method, if available (r875974)
     * Improved and much more consistent path handling (issue #2028, and others)
     * 'svnadmin load' rewrites changed revnums in mergeinfo (issue #3020)
     * Error message and help text improvements
@@ -129,7 +128,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)
@@ -143,7 +142,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)

Modified: subversion/branches/issue-3975/build/transform_sql.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/build/transform_sql.py?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/build/transform_sql.py (original)
+++ subversion/branches/issue-3975/build/transform_sql.py Tue Aug 23 14:03:12 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/issue-3975/notes/moves
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/notes/moves?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/notes/moves (original)
+++ subversion/branches/issue-3975/notes/moves Tue Aug 23 14:03:12 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/issue-3975/subversion/bindings/swig/ruby/test/test_client.rb
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/bindings/swig/ruby/test/test_client.rb?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/bindings/swig/ruby/test/test_client.rb (original)
+++ subversion/branches/issue-3975/subversion/bindings/swig/ruby/test/test_client.rb Tue Aug 23 14:03:12 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/issue-3975/subversion/include/private/svn_sqlite.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/include/private/svn_sqlite.h?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/include/private/svn_sqlite.h (original)
+++ subversion/branches/issue-3975/subversion/include/private/svn_sqlite.h Tue Aug 23 14:03:12 2011
@@ -373,13 +373,12 @@ svn_sqlite__with_immediate_transaction(s
 
 /* Helper function to handle several SQLite operations inside a shared lock.
    This callback is similar to svn_sqlite__with_transaction(), but can be
-   nested (even with a transaction) and changes in the callback are always
-   committed when this function returns.
+   nested (even with a transaction).
 
-   For SQLite 3.6.8 and later using this function as a wrapper around a group
-   of operations can give a *huge* performance boost as the shared-read lock
-   will be shared over multiple statements, instead of being reobtained
-   everytime, which requires disk and/or network io.
+   Using this function as a wrapper around a group of operations can give a
+   *huge* performance boost as the shared-read lock will be shared over
+   multiple statements, instead of being reobtained every time, which may
+   require disk and/or network io, depending on SQLite's locking strategy.
 
    SCRATCH_POOL will be passed to the callback (NULL is valid).
 

Modified: subversion/branches/issue-3975/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/include/svn_client.h?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/include/svn_client.h (original)
+++ subversion/branches/issue-3975/subversion/include/svn_client.h Tue Aug 23 14:03:12 2011
@@ -2776,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/issue-3975/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/include/svn_wc.h?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/include/svn_wc.h (original)
+++ subversion/branches/issue-3975/subversion/include/svn_wc.h Tue Aug 23 14:03:12 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;
 

Modified: subversion/branches/issue-3975/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_client/client.h?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_client/client.h (original)
+++ subversion/branches/issue-3975/subversion/libsvn_client/client.h Tue Aug 23 14:03:12 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);
 
 /* ---------------------------------------------------------------- */
 

Modified: subversion/branches/issue-3975/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_client/diff.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_client/diff.c Tue Aug 23 14:03:12 2011
@@ -820,10 +820,9 @@ diff_props_changed(svn_wc_notify_state_t
                    svn_boolean_t dir_was_added,
                    const apr_array_header_t *propchanges,
                    apr_hash_t *original_props,
-                   void *diff_baton,
+                   struct diff_cmd_baton *diff_cmd_baton,
                    apr_pool_t *scratch_pool)
 {
-  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
   apr_array_header_t *props;
   svn_boolean_t show_diff_header;
 
@@ -891,7 +890,7 @@ diff_dir_props_changed(svn_wc_notify_sta
                                             dir_was_added,
                                             propchanges,
                                             original_props,
-                                            diff_baton,
+                                            diff_cmd_baton,
                                             scratch_pool));
 }
 
@@ -911,9 +910,8 @@ diff_content_changed(const char *path,
                      svn_diff_operation_kind_t operation,
                      const char *copyfrom_path,
                      svn_revnum_t copyfrom_rev,
-                     void *diff_baton)
+                     struct diff_cmd_baton *diff_cmd_baton)
 {
-  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
   int exitcode;
   apr_pool_t *subpool = svn_pool_create(diff_cmd_baton->pool);
   svn_stream_t *os;
@@ -1105,6 +1103,7 @@ diff_file_changed(svn_wc_notify_state_t 
                   apr_pool_t *scratch_pool)
 {
   struct diff_cmd_baton *diff_cmd_baton = diff_baton;
+
   if (diff_cmd_baton->anchor)
     path = svn_dirent_join(diff_cmd_baton->anchor, path, scratch_pool);
   if (tmpfile1)
@@ -1112,11 +1111,11 @@ diff_file_changed(svn_wc_notify_state_t 
                                  tmpfile1, tmpfile2, rev1, rev2,
                                  mimetype1, mimetype2,
                                  svn_diff_op_modified, NULL,
-                                 SVN_INVALID_REVNUM, diff_baton));
+                                 SVN_INVALID_REVNUM, diff_cmd_baton));
   if (prop_changes->nelts > 0)
     SVN_ERR(diff_props_changed(prop_state, tree_conflicted,
                                path, FALSE, prop_changes,
-                               original_props, diff_baton, scratch_pool));
+                               original_props, diff_cmd_baton, scratch_pool));
   if (content_state)
     *content_state = svn_wc_notify_state_unknown;
   if (prop_state)
@@ -1166,17 +1165,17 @@ diff_file_added(svn_wc_notify_state_t *c
                                  tmpfile1, tmpfile2, rev1, rev2,
                                  mimetype1, mimetype2,
                                  svn_diff_op_copied, copyfrom_path,
-                                 copyfrom_revision, diff_baton));
+                                 copyfrom_revision, diff_cmd_baton));
   else if (tmpfile1)
     SVN_ERR(diff_content_changed(path,
                                  tmpfile1, tmpfile2, rev1, rev2,
                                  mimetype1, mimetype2,
                                  svn_diff_op_added, NULL, SVN_INVALID_REVNUM,
-                                 diff_baton));
+                                 diff_cmd_baton));
   if (prop_changes->nelts > 0)
     SVN_ERR(diff_props_changed(prop_state, tree_conflicted,
                                path, FALSE, prop_changes,
-                               original_props, diff_baton, scratch_pool));
+                               original_props, diff_cmd_baton, scratch_pool));
   if (content_state)
     *content_state = svn_wc_notify_state_unknown;
   if (prop_state)
@@ -1224,7 +1223,7 @@ diff_file_deleted(svn_wc_notify_state_t 
                                      diff_cmd_baton->revnum2,
                                      mimetype1, mimetype2,
                                      svn_diff_op_deleted, NULL,
-                                     SVN_INVALID_REVNUM, diff_baton));
+                                     SVN_INVALID_REVNUM, diff_cmd_baton));
     }
 
   /* We don't list all the deleted properties. */
@@ -1753,7 +1752,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 +1762,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 +1970,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 +2007,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 +2097,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 +2107,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 +2118,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 +2152,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 +2167,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 +2406,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 +2424,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/issue-3975/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_client/merge.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_client/merge.c Tue Aug 23 14:03:12 2011
@@ -5038,7 +5038,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/issue-3975/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_client/repos_diff.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_client/repos_diff.c Tue Aug 23 14:03:12 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);
@@ -475,9 +486,6 @@ open_root(void *edit_baton,
   struct edit_baton *eb = edit_baton;
   struct dir_baton *b = make_dir_baton("", NULL, eb, FALSE, pool);
 
-  /* Override the wcpath in our baton. */
-  b->wcpath = apr_pstrdup(pool, eb->target);
-
   SVN_ERR(get_dirprops_from_ra(b, base_revision));
 
   *root_baton = b;
@@ -485,7 +493,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 +562,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 +984,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;
 
@@ -1325,6 +1340,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,
@@ -1355,6 +1371,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/issue-3975/subversion/libsvn_client/repos_diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_client/repos_diff_summarize.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_client/repos_diff_summarize.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_client/repos_diff_summarize.c Tue Aug 23 14:03:12 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);
-}

Modified: subversion/branches/issue-3975/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_client/status.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_client/status.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_client/status.c Tue Aug 23 14:03:12 2011
@@ -85,12 +85,22 @@ tweak_status(void *baton,
   /* If the status item has an entry, but doesn't belong to one of the
      changelists our caller is interested in, we filter out this status
      transmission.  */
-  if (sb->changelist_hash
-      && (! status->changelist
-          || ! apr_hash_get(sb->changelist_hash, status->changelist,
-                            APR_HASH_KEY_STRING)))
+  if (sb->changelist_hash)
     {
-      return SVN_NO_ERROR;
+      if (status->changelist)
+        {
+          /* Skip unless the caller requested this changelist. */
+          if (! apr_hash_get(sb->changelist_hash, status->changelist,
+                             APR_HASH_KEY_STRING))
+            return SVN_NO_ERROR;
+        }
+      else
+        {
+          /* Skip unless the caller requested changelist-lacking items. */
+          if (! apr_hash_get(sb->changelist_hash, "",
+                             APR_HASH_KEY_STRING))
+            return SVN_NO_ERROR;
+        }
     }
 
   /* If we know that the target was deleted in HEAD of the repository,

Modified: subversion/branches/issue-3975/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_ra_serf/blame.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_ra_serf/blame.c Tue Aug 23 14:03:12 2011
@@ -159,8 +159,7 @@ create_propval(blame_info_t *info)
                                     info->prop_attr_len + 1);
     }
 
-  /* Include the null term. */
-  s = svn_string_ncreate(info->prop_attr, info->prop_attr_len + 1, info->pool);
+  s = svn_string_ncreate(info->prop_attr, info->prop_attr_len, info->pool);
   if (info->prop_base64)
     {
       s = svn_base64_decode_string(s, info->pool);

Modified: subversion/branches/issue-3975/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_ra_serf/commit.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_ra_serf/commit.c Tue Aug 23 14:03:12 2011
@@ -94,7 +94,7 @@ typedef struct commit_context_t {
 typedef struct proppatch_context_t {
   apr_pool_t *pool;
 
-  const char *name;
+  const char *relpath;
   const char *path;
 
   commit_context_t *commit;
@@ -146,7 +146,10 @@ typedef struct dir_context_t {
   /* Our parent */
   struct dir_context_t *parent_dir;
 
-  /* The directory name; if NULL, we're the 'root' */
+  /* The directory name; if "", we're the 'root' */
+  const char *relpath;
+
+  /* The basename of the directory. "" for the 'root' */
   const char *name;
 
   /* The base revision of the dir. */
@@ -178,6 +181,7 @@ typedef struct file_context_t {
 
   dir_context_t *parent_dir;
 
+  const char *relpath;
   const char *name;
 
   /* The checked out context for this file. */
@@ -311,44 +315,6 @@ handle_checkout(serf_request_t *request,
   return err;
 }
 
-/* Return the relative path from DIR's topmost parent to DIR, in
-   Subversion's internal path style, allocated in POOL.  Use POOL for
-   temporary work as well.  */
-static const char *
-relative_dir_path(dir_context_t *dir, apr_pool_t *pool)
-{
-  const char *rel_path = "";
-  apr_array_header_t *components;
-  dir_context_t *dir_ptr = dir;
-  int i;
-
-  components = apr_array_make(pool, 1, sizeof(const char *));
-
-  for (dir_ptr = dir; dir_ptr; dir_ptr = dir_ptr->parent_dir)
-    APR_ARRAY_PUSH(components, const char *) = dir_ptr->name;
-
-  for (i = 0; i < components->nelts; i++)
-    {
-      rel_path = svn_relpath_join(rel_path,
-                                  APR_ARRAY_IDX(components, i, const char *),
-                                  pool);
-    }
-
-  return rel_path;
-}
-
-
-/* Return the relative path from FILE's topmost parent to FILE, in
-   Subversion's internal path style, allocated in POOL.  Use POOL for
-   temporary work as well.  */
-static const char *
-relative_file_path(file_context_t *f, apr_pool_t *pool)
-{
-  const char *dir_path = relative_dir_path(f->parent_dir, pool);
-  return svn_relpath_join(dir_path, f->name, pool);
-}
-
-
 static svn_error_t *
 checkout_dir(dir_context_t *dir)
 {
@@ -375,8 +341,7 @@ checkout_dir(dir_context_t *dir)
           dir->checkout->activity_url = dir->commit->activity_url;
           dir->checkout->resource_url =
             svn_path_url_add_component2(dir->parent_dir->checkout->resource_url,
-                                        svn_relpath_basename(dir->name, NULL),
-                                        dir->pool);
+                                        dir->name, dir->pool);
 
           return SVN_NO_ERROR;
         }
@@ -428,8 +393,7 @@ checkout_dir(dir_context_t *dir)
       if (err->apr_err == SVN_ERR_FS_CONFLICT)
         SVN_ERR_W(err, apr_psprintf(dir->pool,
                   _("Directory '%s' is out of date; try updating"),
-                  svn_dirent_local_style(relative_dir_path(dir, dir->pool),
-                                         dir->pool)));
+                  svn_dirent_local_style(dir->relpath, dir->pool)));
       return err;
     }
 
@@ -563,8 +527,8 @@ checkout_file(file_context_t *file)
           file->checkout->activity_url = file->commit->activity_url;
           file->checkout->resource_url =
             svn_path_url_add_component2(parent_dir->checkout->resource_url,
-                                        svn_relpath__is_child(parent_dir->name,
-                                                              file->name,
+                                        svn_relpath__is_child(parent_dir->relpath,
+                                                              file->relpath,
                                                               file->pool),
                                         file->pool);
           return SVN_NO_ERROR;
@@ -585,7 +549,7 @@ checkout_file(file_context_t *file)
 
   SVN_ERR(get_version_url(&(file->checkout->checkout_url),
                           file->commit->session, file->commit->conn,
-                          file->name, file->base_revision,
+                          file->relpath, file->base_revision,
                           NULL, file->pool));
 
   handler->body_delegate = create_checkout_body;
@@ -611,8 +575,7 @@ checkout_file(file_context_t *file)
       if (err->apr_err == SVN_ERR_FS_CONFLICT)
         SVN_ERR_W(err, apr_psprintf(file->pool,
                   _("File '%s' is out of date; try updating"),
-                  svn_dirent_local_style(relative_file_path(file, file->pool),
-                                         file->pool)));
+                  svn_dirent_local_style(file->relpath, file->pool)));
       return err;
     }
 
@@ -839,11 +802,11 @@ setup_proppatch_headers(serf_bucket_t *h
                                            proppatch->base_revision));
     }
 
-  if (proppatch->name && proppatch->commit->lock_tokens)
+  if (proppatch->relpath && proppatch->commit->lock_tokens)
     {
       const char *token;
 
-      token = apr_hash_get(proppatch->commit->lock_tokens, proppatch->name,
+      token = apr_hash_get(proppatch->commit->lock_tokens, proppatch->relpath,
                            APR_HASH_KEY_STRING);
 
       if (token)
@@ -1061,7 +1024,7 @@ setup_put_headers(serf_bucket_t *headers
     {
       const char *token;
 
-      token = apr_hash_get(ctx->commit->lock_tokens, ctx->name,
+      token = apr_hash_get(ctx->commit->lock_tokens, ctx->relpath,
                            APR_HASH_KEY_STRING);
 
       if (token)
@@ -1118,9 +1081,8 @@ setup_copy_dir_headers(serf_bucket_t *he
   else
     {
       uri.path = (char *)svn_path_url_add_component2(
-        dir->parent_dir->checkout->resource_url,
-        svn_relpath_basename(dir->name, pool),
-        pool);
+                                    dir->parent_dir->checkout->resource_url,
+                                    dir->name, pool);
     }
   absolute_uri = apr_uri_unparse(pool, &uri, 0);
 
@@ -1398,6 +1360,7 @@ open_root(void *edit_baton,
       dir->pool = dir_pool;
       dir->commit = ctx;
       dir->base_revision = base_revision;
+      dir->relpath = "";
       dir->name = "";
       dir->changed_props = apr_hash_make(dir->pool);
       dir->removed_props = apr_hash_make(dir->pool);
@@ -1479,12 +1442,13 @@ open_root(void *edit_baton,
       dir->pool = dir_pool;
       dir->commit = ctx;
       dir->base_revision = base_revision;
+      dir->relpath = "";
       dir->name = "";
       dir->changed_props = apr_hash_make(dir->pool);
       dir->removed_props = apr_hash_make(dir->pool);
 
       SVN_ERR(get_version_url(&dir->url, dir->commit->session,
-                              dir->commit->conn, dir->name,
+                              dir->commit->conn, dir->relpath,
                               dir->base_revision, ctx->checked_in_url,
                               dir->pool));
       ctx->checked_in_url = dir->url;
@@ -1563,7 +1527,7 @@ delete_entry(const char *path,
       SVN_ERR(checkout_dir(dir));
       delete_target = svn_path_url_add_component2(dir->checkout->resource_url,
                                                   svn_relpath_basename(path,
-                                                                       pool),
+                                                                       NULL),
                                                   pool);
     }
 
@@ -1658,7 +1622,8 @@ add_directory(const char *path,
   dir->base_revision = SVN_INVALID_REVNUM;
   dir->copy_revision = copyfrom_revision;
   dir->copy_path = copyfrom_path;
-  dir->name = apr_pstrdup(dir->pool, path);
+  dir->relpath = apr_pstrdup(dir->pool, path);
+  dir->name = svn_relpath_basename(dir->relpath, NULL);
   dir->changed_props = apr_hash_make(dir->pool);
   dir->removed_props = apr_hash_make(dir->pool);
 
@@ -1674,11 +1639,10 @@ add_directory(const char *path,
       SVN_ERR(checkout_dir(parent));
 
       dir->url = svn_path_url_add_component2(parent->commit->checked_in_url,
-                                             path, dir->pool);
+                                             dir->name, dir->pool);
       mkcol_target = svn_path_url_add_component2(
                                parent->checkout->resource_url,
-                               svn_relpath_basename(path, dir->pool),
-                               dir->pool);
+                               dir->name, dir->pool);
     }
 
   handler = apr_pcalloc(dir->pool, sizeof(*handler));
@@ -1772,7 +1736,8 @@ open_directory(const char *path,
 
   dir->added = FALSE;
   dir->base_revision = base_revision;
-  dir->name = apr_pstrdup(dir->pool, path);
+  dir->relpath = apr_pstrdup(dir->pool, path);
+  dir->name = svn_relpath_basename(dir->relpath, NULL);
   dir->changed_props = apr_hash_make(dir->pool);
   dir->removed_props = apr_hash_make(dir->pool);
 
@@ -1785,7 +1750,7 @@ open_directory(const char *path,
     {
       SVN_ERR(get_version_url(&dir->url,
                               dir->commit->session, dir->commit->conn,
-                              dir->name, dir->base_revision,
+                              dir->relpath, dir->base_revision,
                               dir->commit->checked_in_url, dir->pool));
     }
   *child_baton = dir;
@@ -1863,7 +1828,7 @@ close_directory(void *dir_baton,
       proppatch_ctx->pool = pool;
       proppatch_ctx->progress.pool = pool;
       proppatch_ctx->commit = dir->commit;
-      proppatch_ctx->name = dir->name;
+      proppatch_ctx->relpath = dir->relpath;
       proppatch_ctx->changed_props = dir->changed_props;
       proppatch_ctx->removed_props = dir->removed_props;
       proppatch_ctx->base_revision = dir->base_revision;
@@ -1902,7 +1867,8 @@ add_file(const char *path,
 
   new_file->parent_dir = dir;
   new_file->commit = dir->commit;
-  new_file->name = apr_pstrdup(new_file->pool, path);
+  new_file->relpath = apr_pstrdup(new_file->pool, path);
+  new_file->name = svn_relpath_basename(new_file->relpath, NULL);
   new_file->added = TRUE;
   new_file->base_revision = SVN_INVALID_REVNUM;
   new_file->copy_path = copy_path;
@@ -1925,8 +1891,7 @@ add_file(const char *path,
 
       new_file->url =
         svn_path_url_add_component2(dir->checkout->resource_url,
-                                    svn_relpath_basename(path, new_file->pool),
-                                    new_file->pool);
+                                    new_file->name, new_file->pool);
     }
 
   while (deleted_parent && deleted_parent[0] != '\0')
@@ -1992,7 +1957,8 @@ open_file(const char *path,
 
   new_file->parent_dir = parent;
   new_file->commit = parent->commit;
-  new_file->name = apr_pstrdup(new_file->pool, path); /* TODO: basename? */
+  new_file->relpath = apr_pstrdup(new_file->pool, path);
+  new_file->name = svn_relpath_basename(new_file->relpath, NULL);
   new_file->added = FALSE;
   new_file->base_revision = base_revision;
   new_file->changed_props = apr_hash_make(new_file->pool);
@@ -2213,7 +2179,7 @@ close_file(void *file_baton,
       proppatch = apr_pcalloc(ctx->pool, sizeof(*proppatch));
       proppatch->pool = ctx->pool;
       proppatch->progress.pool = pool;
-      proppatch->name = ctx->name;
+      proppatch->relpath = ctx->relpath;
       proppatch->path = ctx->url;
       proppatch->commit = ctx->commit;
       proppatch->changed_props = ctx->changed_props;

Modified: subversion/branches/issue-3975/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_ra_svn/cyrus_auth.c Tue Aug 23 14:03:12 2011
@@ -28,7 +28,6 @@
 #include <apr_want.h>
 #include <apr_general.h>
 #include <apr_strings.h>
-#include <apr_atomic.h>
 #include <apr_thread_mutex.h>
 #include <apr_version.h>
 

Modified: subversion/branches/issue-3975/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_subr/cmdline.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_subr/cmdline.c Tue Aug 23 14:03:12 2011
@@ -37,7 +37,6 @@
 
 #include <apr_errno.h>          /* for apr_strerror */
 #include <apr_general.h>        /* for apr_initialize/apr_terminate */
-#include <apr_atomic.h>         /* for apr_atomic_init */
 #include <apr_strings.h>        /* for apr_snprintf */
 #include <apr_pools.h>
 

Modified: subversion/branches/issue-3975/subversion/libsvn_subr/magic.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_subr/magic.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_subr/magic.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_subr/magic.c Tue Aug 23 14:03:12 2011
@@ -45,8 +45,9 @@
 struct svn_magic__cookie_t {
 #ifdef SVN_HAVE_LIBMAGIC
   magic_t magic;
-#endif
+#else
   char dummy;
+#endif
 };
 
 #ifdef SVN_HAVE_LIBMAGIC

Modified: subversion/branches/issue-3975/subversion/libsvn_subr/svn_cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_subr/svn_cache_config.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_subr/svn_cache_config.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_subr/svn_cache_config.c Tue Aug 23 14:03:12 2011
@@ -147,6 +147,9 @@ svn_cache__get_global_membuffer_cache(vo
       /* Handle race condition: if we are the first to create a
        * cache object, make it our global singleton. Otherwise,
        * discard the new cache and keep the existing one.
+       *
+       * Cast is necessary because of APR bug:
+       * https://issues.apache.org/bugzilla/show_bug.cgi?id=50731
        */
       old_cache = apr_atomic_casptr((volatile void **)&cache, new_cache, NULL);
       if (old_cache != NULL)

Modified: subversion/branches/issue-3975/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_subr/utf.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_subr/utf.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_subr/utf.c Tue Aug 23 14:03:12 2011
@@ -90,8 +90,8 @@ static apr_hash_t *xlate_handle_hash = N
  * using atomic xchange ops, i.e. without further thread synchronization.
  * If the respective item is NULL, fallback to hash lookup.
  */
-static volatile void *xlat_ntou_static_handle = NULL;
-static volatile void *xlat_uton_static_handle = NULL;
+static void * volatile xlat_ntou_static_handle = NULL;
+static void * volatile xlat_uton_static_handle = NULL;
 
 /* Clean up the xlate handle cache. */
 static apr_status_t
@@ -182,11 +182,13 @@ get_xlate_key(const char *topage,
  * the caller.
  */
 static APR_INLINE void*
-atomic_swap(volatile void **mem, void *new_value)
+atomic_swap(void * volatile * mem, void *new_value)
 {
 #if APR_HAS_THREADS
 #if APR_VERSION_AT_LEAST(1,3,0)
-   return apr_atomic_xchgptr(mem, new_value);
+  /* Cast is necessary because of APR bug:
+     https://issues.apache.org/bugzilla/show_bug.cgi?id=50731 */
+   return apr_atomic_xchgptr((volatile void **)mem, new_value);
 #else
    /* old APRs don't support atomic swaps. Simply return the
     * input to the caller for further proccessing. */

Modified: subversion/branches/issue-3975/subversion/libsvn_subr/validate.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3975/subversion/libsvn_subr/validate.c?rev=1160699&r1=1160698&r2=1160699&view=diff
==============================================================================
--- subversion/branches/issue-3975/subversion/libsvn_subr/validate.c (original)
+++ subversion/branches/issue-3975/subversion/libsvn_subr/validate.c Tue Aug 23 14:03:12 2011
@@ -45,6 +45,7 @@ svn_mime_type_validate(const char *mime_
      specification, e.g., "text/html; charset=UTF-8", make sure we're
      only looking at the media type here. */
   const apr_size_t len = strcspn(mime_type, "; ");
+  const apr_size_t len2 = strlen(mime_type);
   const char *const slash_pos = strchr(mime_type, '/');
   apr_size_t i;
   const char *tspecials = "()<>@,;:\\\"/[]?=";
@@ -69,7 +70,19 @@ svn_mime_type_validate(const char *mime_
             || (strchr(tspecials, mime_type[i]) != NULL)))
         return svn_error_createf
           (SVN_ERR_BAD_MIME_TYPE, NULL,
-           _("MIME type '%s' contains invalid character '%c'"),
+           _("MIME type '%s' contains invalid character '%c' "
+             "in media type"),
+           mime_type, mime_type[i]);
+    }
+
+  /* Check the whole string for unsafe characters. (issue #2872) */
+  for (i = 0; i < len2; i++)
+    {
+      if (svn_ctype_iscntrl(mime_type[i]) && mime_type[i] != '\t')
+        return svn_error_createf(
+           SVN_ERR_BAD_MIME_TYPE, NULL,
+           _("MIME type '%s' contains invalid character '0x%02x' "
+             "in postfix"),
            mime_type, mime_type[i]);
     }