You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2011/11/14 15:32:07 UTC

svn commit: r1201727 [1/4] - in /subversion/branches/showing-merge-info: ./ contrib/client-side/emacs/ notes/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ subversion/libsvn_diff/ subversion/libsvn_r...

Author: julianfoad
Date: Mon Nov 14 14:32:05 2011
New Revision: 1201727

URL: http://svn.apache.org/viewvc?rev=1201727&view=rev
Log:
On the 'showing-merge-info' branch: Catch up to trunk@1201723.

Modified:
    subversion/branches/showing-merge-info/   (props changed)
    subversion/branches/showing-merge-info/CHANGES
    subversion/branches/showing-merge-info/Makefile.in
    subversion/branches/showing-merge-info/configure.ac
    subversion/branches/showing-merge-info/contrib/client-side/emacs/dsvn.el
    subversion/branches/showing-merge-info/notes/knobs
    subversion/branches/showing-merge-info/subversion/include/private/svn_dep_compat.h
    subversion/branches/showing-merge-info/subversion/include/private/svn_opt_private.h
    subversion/branches/showing-merge-info/subversion/include/private/svn_ra_private.h
    subversion/branches/showing-merge-info/subversion/include/private/svn_wc_private.h
    subversion/branches/showing-merge-info/subversion/include/svn_client.h
    subversion/branches/showing-merge-info/subversion/include/svn_dirent_uri.h
    subversion/branches/showing-merge-info/subversion/libsvn_client/add.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/cleanup.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/client.h
    subversion/branches/showing-merge-info/subversion/libsvn_client/commit.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/commit_util.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/copy.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/delete.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/deprecated.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/externals.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/info.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/list.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/log.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/merge.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/mergeinfo.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/patch.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/prop_commands.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/ra.c
    subversion/branches/showing-merge-info/subversion/libsvn_client/util.c
    subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c
    subversion/branches/showing-merge-info/subversion/libsvn_diff/diff_file.c
    subversion/branches/showing-merge-info/subversion/libsvn_ra/ra_loader.c
    subversion/branches/showing-merge-info/subversion/libsvn_ra_local/ra_plugin.c
    subversion/branches/showing-merge-info/subversion/libsvn_ra_neon/commit.c
    subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c
    subversion/branches/showing-merge-info/subversion/libsvn_subr/opt.c
    subversion/branches/showing-merge-info/subversion/libsvn_subr/sqlite.c
    subversion/branches/showing-merge-info/subversion/libsvn_subr/target.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_files.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/entries.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/externals.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/node.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/upgrade.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql
    subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c
    subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h
    subversion/branches/showing-merge-info/subversion/svn/cl.h
    subversion/branches/showing-merge-info/subversion/svn/commit-cmd.c
    subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c
    subversion/branches/showing-merge-info/subversion/svn/delete-cmd.c
    subversion/branches/showing-merge-info/subversion/svn/import-cmd.c
    subversion/branches/showing-merge-info/subversion/svn/main.c
    subversion/branches/showing-merge-info/subversion/svn/mkdir-cmd.c
    subversion/branches/showing-merge-info/subversion/svn/move-cmd.c
    subversion/branches/showing-merge-info/subversion/svn/relocate-cmd.c
    subversion/branches/showing-merge-info/subversion/svnsync/main.c
    subversion/branches/showing-merge-info/subversion/tests/cmdline/basic_tests.py
    subversion/branches/showing-merge-info/subversion/tests/cmdline/commit_tests.py
    subversion/branches/showing-merge-info/subversion/tests/cmdline/externals_tests.py
    subversion/branches/showing-merge-info/subversion/tests/cmdline/merge_tests.py
    subversion/branches/showing-merge-info/subversion/tests/cmdline/mergeinfo_tests.py
    subversion/branches/showing-merge-info/subversion/tests/cmdline/patch_tests.py
    subversion/branches/showing-merge-info/subversion/tests/cmdline/svntest/actions.py
    subversion/branches/showing-merge-info/subversion/tests/libsvn_subr/dirent_uri-test.c

Propchange: subversion/branches/showing-merge-info/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 14 14:32:05 2011
@@ -57,4 +57,4 @@
 /subversion/branches/tree-conflicts:868291-873154
 /subversion/branches/tree-conflicts-notify:873926-874008
 /subversion/branches/uris-as-urls:1060426-1064427
-/subversion/trunk:1177607-1198699
+/subversion/trunk:1177607-1201723

Modified: subversion/branches/showing-merge-info/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/CHANGES?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/CHANGES (original)
+++ subversion/branches/showing-merge-info/CHANGES Mon Nov 14 14:32:05 2011
@@ -11,6 +11,7 @@ http://svn.apache.org/repos/asf/subversi
 
   - Minor new features and improvements:
     * new 'svnadmin load --revision' load filtering support (issue #3734)
+    * new 'commit --include-externals' option (related to issues #1167, #3563)
 
   - Client-side bugfixes:
     *
@@ -295,10 +296,10 @@ http://svn.apache.org/repos/asf/subversi
     * fix 'log -g' excessive duplicate output (issue #3650)
     * fix svnsync copyfrom handling bug with BDB (r1036429)
     * server-side validation of svn:mergeinfo syntax during commit (issue #3895)
-    * fix remotely triggerable mod_dav_svn DoS
+    * fix remotely triggerable mod_dav_svn DoS (r1130303)
             See CVE-2011-1783, and descriptive advisory at
             http://subversion.apache.org/security/CVE-2011-1783-advisory.txt
-    * fix potential leak of authz-protected file contents
+    * fix potential leak of authz-protected file contents (r1130303)
             See CVE-2011-1921, and descriptive advisory at
             http://subversion.apache.org/security/CVE-2011-1921-advisory.txt
 

Modified: subversion/branches/showing-merge-info/Makefile.in
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/Makefile.in?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/Makefile.in (original)
+++ subversion/branches/showing-merge-info/Makefile.in Mon Nov 14 14:32:05 2011
@@ -99,6 +99,10 @@ javahl_libdir = @libdir@
 javahl_test_rootdir=$(abs_builddir)/subversion/bindings/javahl/test-work
 javahl_test_srcdir=$(abs_srcdir)/subversion/bindings/javahl
 
+gnome_auth_dir = $(abs_builddir)/subversion/libsvn_auth_gnome_keyring/.libs
+kwallet_auth_dir = $(abs_builddir)/subversion/libsvn_auth_kwallet/.libs
+auth_plugin_dirs = $(gnome_auth_dir):$(kwallet_auth_dir)
+
 MSGFMT = @MSGFMT@
 MSGFMTFLAGS = @MSGFMTFLAGS@
 MSGMERGE = @MSGMERGE@
@@ -484,6 +488,7 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
 	    flags="--list --milestone-filter=$(MILESTONE_FILTER)             \
 		   --mode-filter=$(MODE_FILTER) --log-to-stdout $$flags";    \
 	  fi;                                                                \
+	  LD_LIBRARY_PATH='$(auth_plugin_dirs):$(LD_LIBRARY_PATH)'           \
 	  $(PYTHON) $(top_srcdir)/build/run_tests.py                         \
 	            --config-file $(top_srcdir)/subversion/tests/tests.conf  \
 	            $$flags                                                  \

Modified: subversion/branches/showing-merge-info/configure.ac
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/configure.ac?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/configure.ac (original)
+++ subversion/branches/showing-merge-info/configure.ac Mon Nov 14 14:32:05 2011
@@ -172,6 +172,18 @@ SQLITE_URL="http://www.sqlite.org/sqlite
 SVN_LIB_SQLITE(${SQLITE_MINIMUM_VER}, ${SQLITE_RECOMMENDED_VER},
                ${SQLITE_URL})
 
+AC_ARG_ENABLE(sqlite-compatibility-version,
+  AS_HELP_STRING([--enable-sqlite-compatibility-version=X.Y.Z],
+                 [Allow binary to run against SQLite as old as ARG]),
+  [sqlite_compat_ver=$enableval],[sqlite_compat_ver=no])
+
+if test -n "$sqlite_compat_ver" && test "$sqlite_compat_ver" != no; then
+  SVN_SQLITE_VERNUM_PARSE([$sqlite_compat_ver],
+                          [sqlite_compat_ver_num])
+  CFLAGS="-DSVN_SQLITE_MIN_VERSION='\"$sqlite_compat_ver\"' $CFLAGS"
+  CFLAGS="-DSVN_SQLITE_MIN_VERSION_NUMBER=$sqlite_compat_ver_num $CFLAGS"
+fi
+
 dnl Set up a number of directories ---------------------
 
 dnl Create SVN_BINDIR for proper substitution

Modified: subversion/branches/showing-merge-info/contrib/client-side/emacs/dsvn.el
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/contrib/client-side/emacs/dsvn.el?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/contrib/client-side/emacs/dsvn.el (original)
+++ subversion/branches/showing-merge-info/contrib/client-side/emacs/dsvn.el Mon Nov 14 14:32:05 2011
@@ -130,12 +130,19 @@
   :type 'boolean
   :group 'dsvn)
 
+;; start-file-process and process-file are needed for tramp but only appeared
+;; in Emacs 23 and 22 respectively.
+(setq svn-start-file-process
+  (if (fboundp 'start-file-process) 'start-file-process 'start-process))
+(setq svn-process-file
+  (if (fboundp 'process-file) 'process-file 'call-process))
+
 (defun svn-call-process (program buffer &rest args)
   "Run svn and wait for it to finish.
 Argument PROGRAM is the svn binary to run.
 Argument BUFFER is the buffer in which to insert output.
 Optional argument ARGS are the arguments to svn."
-  (let ((proc (apply 'start-process "svn" buffer program args)))
+  (let ((proc (apply svn-start-file-process "svn" buffer program args)))
     (set-process-coding-system proc 'utf-8)
     (set-process-filter proc 'svn-output-filter)
     (while (eq (process-status proc) 'run)
@@ -161,7 +168,7 @@ Return non-NIL if there was any output."
       (setq buffer-read-only t)
       (let ((cmd `(,svn-program ,subcommand ,@args))
             proc)
-        (setq proc (apply 'start-process "svn" buf cmd))
+        (setq proc (apply svn-start-file-process "svn" buf cmd))
         (set-process-coding-system proc 'utf-8)
         (set-process-filter proc 'svn-output-filter)
         (while (eq (process-status proc) 'run)
@@ -184,7 +191,7 @@ Returns the buffer that holds the output
     (with-current-buffer buf
       (erase-buffer)
       (setq default-directory dir))
-    (apply 'call-process svn-program nil buf nil (symbol-name command) args)
+    (apply svn-process-file svn-program nil buf nil (symbol-name command) args)
     buf))
 
 (defun svn-run-for-stdout (command args)
@@ -192,7 +199,7 @@ Returns the buffer that holds the output
 Argument COMMAND is the svn subcommand to run.
 Optional argument ARGS is a list of arguments."
   (let ((output-buffer (generate-new-buffer "*svn-stdout*")))
-    (apply 'call-process svn-program nil (list output-buffer nil) nil
+    (apply svn-process-file svn-program nil (list output-buffer nil) nil
 	   (symbol-name command) args)
     (let ((stdout (with-current-buffer output-buffer (buffer-string))))
       (kill-buffer output-buffer)
@@ -255,7 +262,7 @@ buffer to describe what is going on."
             args (cons "-v" args)))
     (unless (memq command svn-noninteractive-blacklist)
       (setq args (cons "--non-interactive" args)))
-    (setq proc (apply 'start-process "svn" (current-buffer)
+    (setq proc (apply svn-start-file-process "svn" (current-buffer)
                       svn-program command-s args))
     (if (fboundp filter-func)
         (set-process-filter proc filter-func)

Modified: subversion/branches/showing-merge-info/notes/knobs
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/notes/knobs?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/notes/knobs (original)
+++ subversion/branches/showing-merge-info/notes/knobs Mon Nov 14 14:32:05 2011
@@ -44,6 +44,8 @@ SVN_MERGE__ALLOW_ALL_FORWARD_MERGES_FROM
 SVN_USE_WIN32_CRASHHANDLER
 SVN_DAV_SEND_VTXN_NAME
 SVN_DISABLE_PREFIX_SUFFIX_SCANNING
+SVN_SQLITE_MIN_VERSION_NUMBER
+SVN_SQLITE_MIN_VERSION
 
 2.3 Debugging Support
 
@@ -205,6 +207,24 @@ SVN_I_LIKE_LATENCY_SO_IGNORE_HTTPV2
   Default:   not defined
   Suggested: not defined
 
+4.8 SVN_SQLITE_MIN_VERSION_NUMBER
+
+  Scope:     libsvn_subr
+  Purpose:   The minimum SQLite version to have run-time support for.
+  Range:     SQLite version numbers, as packed integers
+  Default:   SQLITE_VERSION_NUMBER (i.e., the compile-time-sqlite version)
+  Suggested: not defined (to use default)
+
+4.9 SVN_SQLITE_MIN_VERSION
+
+  Scope:     libsvn_subr
+  Purpose:   See SVN_SQLITE_MIN_VERSION_NUMBER.  The two must be overridden
+             (or not overridden) together; defining one but leaving the other
+             at its default will cause undefined behaviour.
+  Range:     SQLite versions, as string literals
+  Default:   SQLITE_VERSION
+  Suggested: not defined (to use default)
+
 
 5 Defines controling debug support
 ==================================

Modified: subversion/branches/showing-merge-info/subversion/include/private/svn_dep_compat.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/private/svn_dep_compat.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/private/svn_dep_compat.h (original)
+++ subversion/branches/showing-merge-info/subversion/include/private/svn_dep_compat.h Mon Nov 14 14:32:05 2011
@@ -107,6 +107,32 @@ typedef apr_uint32_t apr_uintptr_t;
 #endif /* SERF_VERSION_AT_LEAST */
 
 /**
+ * By default, if libsvn is built against one version of SQLite
+ * and then run using an older version, svn will error out:
+ *
+ *     svn: Couldn't perform atomic initialization
+ *     svn: SQLite compiled for 3.7.4, but running with 3.7.3
+ *
+ * That can be annoying when building on a modern system in order
+ * to deploy on a less modern one.  So these constants allow one
+ * to specify how old the system being deployed on might be.
+ * For example,
+ *
+ *     EXTRA_CFLAGS += -DSVN_SQLITE_MIN_VERSION_NUMBER=3007003
+ *     EXTRA_CFLAGS += '-DSVN_SQLITE_MIN_VERSION="3.7.3"'
+ *
+ * turns on code that works around infelicities in older versions
+ * as far back as 3.7.3 and relaxes the check at initialization time
+ * to permit them.
+ *
+ * @since New in 1.8.
+ */
+#ifndef SVN_SQLITE_MIN_VERSION_NUMBER
+#define SVN_SQLITE_MIN_VERSION_NUMBER SQLITE_VERSION_NUMBER
+#define SVN_SQLITE_MIN_VERSION SQLITE_VERSION
+#endif /* SVN_SQLITE_MIN_VERSION_NUMBER */
+
+/**
  * Check at compile time if the SQLite version is at least a certain
  * level.
  * @param major The major version component of the version checked
@@ -120,7 +146,7 @@ typedef apr_uint32_t apr_uintptr_t;
  */
 #ifndef SQLITE_VERSION_AT_LEAST
 #define SQLITE_VERSION_AT_LEAST(major,minor,patch)                     \
-((major*1000000 + minor*1000 + patch) <= SQLITE_VERSION_NUMBER)
+((major*1000000 + minor*1000 + patch) <= SVN_SQLITE_MIN_VERSION_NUMBER)
 #endif /* SQLITE_VERSION_AT_LEAST */
 
 #ifdef __cplusplus

Modified: subversion/branches/showing-merge-info/subversion/include/private/svn_opt_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/private/svn_opt_private.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/private/svn_opt_private.h (original)
+++ subversion/branches/showing-merge-info/subversion/include/private/svn_opt_private.h Mon Nov 14 14:32:05 2011
@@ -129,6 +129,26 @@ const char *
 svn_opt__revision_to_string(const svn_opt_revision_t *revision,
                             apr_pool_t *result_pool);
 
+/**
+ * Create a revision range structure from two revisions.  Return a new range
+ * allocated in @a result_pool with the start and end initialized to
+ * (deep copies of) @a *start_revision and @a *end_revision.
+ */
+svn_opt_revision_range_t *
+svn_opt__revision_range_create(const svn_opt_revision_t *start_revision,
+                               const svn_opt_revision_t *end_revision,
+                               apr_pool_t *result_pool);
+
+/**
+ * Create a revision range structure from two revnums.  Return a new range
+ * allocated in @a result_pool with the start and end kinds initialized to
+ * #svn_opt_revision_number and values @a start_revnum and @a end_revnum.
+ */
+svn_opt_revision_range_t *
+svn_opt__revision_range_from_revnums(svn_revnum_t start_revnum,
+                                     svn_revnum_t end_revnum,
+                                     apr_pool_t *result_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/showing-merge-info/subversion/include/private/svn_ra_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/private/svn_ra_private.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/private/svn_ra_private.h (original)
+++ subversion/branches/showing-merge-info/subversion/include/private/svn_ra_private.h Mon Nov 14 14:32:05 2011
@@ -116,6 +116,16 @@ svn_ra__release_operational_lock(svn_ra_
                                  const svn_string_t *mylocktoken,
                                  apr_pool_t *scratch_pool);
 
+
+/** Like svn_ra_get_path_relative_to_root(), except returning a fspath
+ * (starting with '/') instead of a relpath.
+ */
+svn_error_t *
+svn_ra__get_fspath_relative_to_root(svn_ra_session_t *ra_session,
+                                    const char **fspath,
+                                    const char *url,
+                                    apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/showing-merge-info/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/private/svn_wc_private.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/showing-merge-info/subversion/include/private/svn_wc_private.h Mon Nov 14 14:32:05 2011
@@ -131,6 +131,55 @@ svn_wc__read_external_info(svn_node_kind
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool);
 
+/** See svn_wc__committable_externals_below(). */
+typedef struct svn_wc__committable_external_info_t {
+
+  /* The local absolute path where the external should be checked out. */
+  const char *local_abspath;
+
+  /* The relpath part of the source URL the external should be checked out
+   * from. */
+  const char *repos_relpath;
+
+  /* The root URL part of the source URL the external should be checked out
+   * from. */
+  const char *repos_root_url;
+
+  /* Set to either svn_kind_file or svn_kind_dir. */
+  svn_kind_t kind;
+
+} svn_wc__committable_external_info_t;
+
+/* Add svn_wc__committable_external_info_t* items to *EXTERNALS, describing
+ * 'committable' externals checked out below LOCAL_ABSPATH. Recursively find
+ * all nested externals (externals defined inside externals).
+ *
+ * In this context, a 'committable' external belongs to the same repository as
+ * LOCAL_ABSPATH, is not revision-pegged and is currently checked out in the
+ * WC. (Local modifications are not tested for.)
+ *
+ * *EXTERNALS must be initialized either to NULL or to a pointer created with
+ * apr_array_make(..., sizeof(svn_wc__committable_external_info_t *)). If
+ * *EXTERNALS is initialized to NULL, an array will be allocated from
+ * RESULT_POOL as necessary. If no committable externals are found,
+ * *EXTERNALS is left unchanged.
+ *
+ * DEPTH limits the recursion below LOCAL_ABSPATH.
+ *
+ * This function will not find externals defined in some parent WC above
+ * LOCAL_ABSPATH's WC-root.
+ *
+ * ###TODO: Add a WRI_ABSPATH (wc root indicator) separate from LOCAL_ABSPATH,
+ * to allow searching any wc-root for externals under LOCAL_ABSPATH, not only
+ * LOCAL_ABSPATH's most immediate wc-root. */
+svn_error_t *
+svn_wc__committable_externals_below(apr_array_header_t **externals,
+                                    svn_wc_context_t *wc_ctx,
+                                    const char *local_abspath,
+                                    svn_depth_t depth,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool);
+
 /* Gets a mapping from const char * local abspaths of externals to the const
    char * local abspath of where they are defined for all externals defined
    at or below LOCAL_ABSPATH.
@@ -358,8 +407,9 @@ svn_wc__node_get_children(const apr_arra
  * of the node at @a local_abspath into @a *repos_root_url
  * and @a *repos_uuid. Use @a wc_ctx to access the working copy
  * for @a local_abspath, @a scratch_pool for all temporary allocations,
- * @a result_pool for result allocations. Note: the result may be NULL if the
- * given node has no repository root associated with it (e.g. locally added).
+ * @a result_pool for result allocations. Note: the results will be NULL if
+ * the node does not exist or is not under version control. If the node is
+ * locally added, return the repository root it will have if committed.
  *
  * Either output argument may be NULL, indicating no interest.
  */
@@ -749,6 +799,35 @@ svn_wc__call_with_write_lock(svn_wc__wit
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool);
 
+/** Evaluate the expression @a expr while holding a write lock on
+ * @a local_abspath.
+ *
+ * @a expr must yield an (svn_error_t *) error code.  If the error code
+ * is not #SVN_NO_ERROR, cause the function using this macro to return
+ * the error to its caller.
+ *
+ * If @a lock_anchor is TRUE, determine if @a local_abspath has an anchor
+ * that should be locked instead.
+ *
+ * Use @a wc_ctx for working copy access.
+ *
+ * The lock is guaranteed to be released after evaluating @a expr.
+ */
+#define SVN_WC__CALL_WITH_WRITE_LOCK(expr, wc_ctx, local_abspath,             \
+                                     lock_anchor, scratch_pool)               \
+  do {                                                                        \
+    svn_error_t *svn_wc__err1, *svn_wc__err2;                                 \
+    const char *svn_wc__lock_root_abspath;                                    \
+    SVN_ERR(svn_wc__acquire_write_lock(&svn_wc__lock_root_abspath, wc_ctx,    \
+                                       local_abspath, lock_anchor,            \
+                                       scratch_pool, scratch_pool));          \
+    svn_wc__err1 = svn_error_trace(expr);                                     \
+    svn_wc__err2 = svn_wc__release_write_lock(                                \
+                     wc_ctx, svn_wc__lock_root_abspath, scratch_pool);        \
+    SVN_ERR(svn_error_compose_create(svn_wc__err1, svn_wc__err2));            \
+  } while (0)
+
+
 /**
  * Calculates the schedule and copied status of a node as that would
  * have been stored in an svn_wc_entry_t instance.

Modified: subversion/branches/showing-merge-info/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/svn_client.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/svn_client.h (original)
+++ subversion/branches/showing-merge-info/subversion/include/svn_client.h Mon Nov 14 14:32:05 2011
@@ -2073,6 +2073,22 @@ svn_client_import(svn_client_commit_info
  * #TRUE, changes to descendants are only committed if they are itself
  * included via @a depth and targets.
  *
+ * If @a include_file_externals and/or @a include_dir_externals are #TRUE,
+ * also commit all file and/or dir externals (respectively) that are reached
+ * by recursion, with these exceptions: Never recurse to externals
+ * - that have a fixed revision or
+ * - that come from a different repository root URL (dir externals).
+ * These flags affect only recursion; externals that directly appear in @a
+ * targets are always included in the commit.
+ *
+ * ### TODO: currently, file externals hidden inside an unversioned dir are
+ *     skipped deliberately, because we can't commit those yet.
+ *     See STMT_SELECT_COMMITTABLE_EXTERNALS_BELOW.
+ *
+ * ### TODO: With @c depth_immediates, this function acts as if
+ *     @a include_dir_externals was passed #FALSE, but caller expects
+ *     immediate child dir externals to be included @c depth_empty.
+ *
  * When @a commit_as_operations is #TRUE it is possible to delete a node and
  * all its descendants by selecting just the root of the deletion. If it is
  * set to #FALSE this will raise an error.
@@ -2086,6 +2102,26 @@ svn_client_import(svn_client_commit_info
  *
  * Use @a pool for any temporary allocations.
  *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_client_commit6(const apr_array_header_t *targets,
+                   svn_depth_t depth,
+                   svn_boolean_t keep_locks,
+                   svn_boolean_t keep_changelists,
+                   svn_boolean_t commit_as_operations,
+                   svn_boolean_t include_file_externals,
+                   svn_boolean_t include_dir_externals,
+                   const apr_array_header_t *changelists,
+                   const apr_hash_t *revprop_table,
+                   svn_commit_callback2_t commit_callback,
+                   void *commit_baton,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool);
+
+/**
+ * Similar to svn_client_commit6(), but passes @a include_file_externals as
+ * TRUE and @a include_dir_externals as FALSE.
  * @since New in 1.7.
  */
 svn_error_t *
@@ -3526,10 +3562,10 @@ svn_client_merge(const char *source1,
  * pristine, unswitched working copy -- in other words, it must
  * reflect a single revision tree, the "target".  The mergeinfo on @a
  * source must reflect that all of the target has been merged into it.
- * Then this behaves like a merge with svn_client_merge3() from the
+ * Then this behaves like a merge with svn_client_merge4() from the
  * target's URL to the source.
  *
- * All other options are handled identically to svn_client_merge3().
+ * All other options are handled identically to svn_client_merge4().
  * The depth of the merge is always #svn_depth_infinity.
  *
  * @since New in 1.5.
@@ -3680,6 +3716,8 @@ svn_client_get_mergeinfo_catalog(svn_mer
                                  apr_pool_t *scratch_pool);
 
 /**
+ * Get the mergeinfo for a single target node (ignoring any subtrees).
+ *
  * Set @a *mergeinfo to a hash mapping <tt>const char *</tt> merge
  * source URLs to <tt>apr_array_header_t *</tt> rangelists (arrays of
  * <tt>svn_merge_range_t *</tt> ranges) describing the ranges which
@@ -3724,6 +3762,9 @@ typedef svn_error_t *
                            apr_pool_t *pool);
 
 /**
+ * Describe the revisions that either have or have not been merged from
+ * one source branch (or subtree) into another.
+ *
  * If @a finding_merged is TRUE, then drive log entry callbacks
  * @a receiver / @a receiver_baton with the revisions merged from
  * @a source_peg into @a target_peg.  If @a finding_merged is FALSE

Modified: subversion/branches/showing-merge-info/subversion/include/svn_dirent_uri.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/include/svn_dirent_uri.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/include/svn_dirent_uri.h (original)
+++ subversion/branches/showing-merge-info/subversion/include/svn_dirent_uri.h Mon Nov 14 14:32:05 2011
@@ -591,17 +591,6 @@ svn_dirent_get_absolute(const char **pab
                         const char *relative,
                         apr_pool_t *result_pool);
 
-/** Similar to svn_uri_skip_ancestor(), except that if @a child_uri is
- * the same as @a parent_uri, it is not considered a child, so the result
- * is @c NULL; an empty string is never returned.
- *
- * Allocate the result in @a result_pool.
- */
-const char *
-svn_uri__is_child(const char *parent_uri,
-                  const char *child_uri,
-                  apr_pool_t *result_pool);
-
 /** Similar to svn_dirent_skip_ancestor(), except that if @a child_dirent is
  * the same as @a parent_dirent, it is not considered a child, so the result
  * is @c NULL; an empty string is never returned.

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/add.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/add.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/add.c Mon Nov 14 14:32:05 2011
@@ -494,31 +494,27 @@ add_dir_recursive(const char *dir_abspat
 }
 
 
-struct add_with_write_lock_baton {
-  const char *local_abspath;
-  svn_depth_t depth;
-  svn_boolean_t force;
-  svn_boolean_t no_ignore;
-  svn_client_ctx_t *ctx;
-
-  /* Absolute path to the first existing parent directory of local_abspath.
-   * If not NULL, all missing parents of local_abspath must be created
-   * before local_abspath can be added. */
-  const char *existing_parent_abspath;
-};
-
-/* The main logic of the public svn_client_add4. */
+/* The main logic of the public svn_client_add4.
+ *
+ * EXISTING_PARENT_ABSPATH is the absolute path to the first existing
+ * parent directory of local_abspath. If not NULL, all missing parents
+ * of LOCAL_ABSPATH must be created before LOCAL_ABSPATH can be added. */
 static svn_error_t *
-add(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+add(const char *local_abspath,
+    svn_depth_t depth,
+    svn_boolean_t force,
+    svn_boolean_t no_ignore,
+    const char *existing_parent_abspath,
+    svn_client_ctx_t *ctx,
+    apr_pool_t *scratch_pool)
 {
   svn_node_kind_t kind;
   svn_error_t *err;
-  struct add_with_write_lock_baton *b = baton;
   svn_magic__cookie_t *magic_cookie;
 
   svn_magic__init(&magic_cookie, scratch_pool);
 
-  if (b->existing_parent_abspath)
+  if (existing_parent_abspath)
     {
       const char *parent_abspath;
       const char *child_relpath;
@@ -526,9 +522,9 @@ add(void *baton, apr_pool_t *result_pool
       int i;
       apr_pool_t *iterpool;
 
-      parent_abspath = b->existing_parent_abspath;
-      child_relpath = svn_dirent_is_child(b->existing_parent_abspath,
-                                          b->local_abspath, NULL);
+      parent_abspath = existing_parent_abspath;
+      child_relpath = svn_dirent_is_child(existing_parent_abspath,
+                                          local_abspath, NULL);
       components = svn_path_decompose(child_relpath, scratch_pool);
       iterpool = svn_pool_create(scratch_pool);
       for (i = 0; i < components->nelts - 1; i++)
@@ -538,8 +534,8 @@ add(void *baton, apr_pool_t *result_pool
 
           svn_pool_clear(iterpool);
 
-          if (b->ctx->cancel_func)
-            SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
+          if (ctx->cancel_func)
+            SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
           component = APR_ARRAY_IDX(components, i, const char *);
           parent_abspath = svn_dirent_join(parent_abspath, component,
@@ -548,29 +544,27 @@ add(void *baton, apr_pool_t *result_pool
           if (disk_kind != svn_node_none && disk_kind != svn_node_dir)
             return svn_error_createf(SVN_ERR_CLIENT_NO_VERSIONED_PARENT, NULL,
                                      _("'%s' prevents creating parent of '%s'"),
-                                     parent_abspath, b->local_abspath);
+                                     parent_abspath, local_abspath);
 
           SVN_ERR(svn_io_make_dir_recursively(parent_abspath, scratch_pool));
-          SVN_ERR(svn_wc_add_from_disk(b->ctx->wc_ctx, parent_abspath,
-                                       b->ctx->notify_func2,
-                                       b->ctx->notify_baton2,
+          SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, parent_abspath,
+                                       ctx->notify_func2, ctx->notify_baton2,
                                        scratch_pool));
         }
       svn_pool_destroy(iterpool);
     }
 
-  SVN_ERR(svn_io_check_path(b->local_abspath, &kind, scratch_pool));
+  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
   if (kind == svn_node_dir)
     {
       /* We use add_dir_recursive for all directory targets
          and pass depth along no matter what it is, so that the
          target's depth will be set correctly. */
-      err = add_dir_recursive(b->local_abspath, b->depth,
-                              b->force, b->no_ignore, magic_cookie, b->ctx,
-                              scratch_pool);
+      err = add_dir_recursive(local_abspath, depth, force, no_ignore,
+                              magic_cookie, ctx, scratch_pool);
     }
   else if (kind == svn_node_file)
-    err = add_file(b->local_abspath, magic_cookie, b->ctx, scratch_pool);
+    err = add_file(local_abspath, magic_cookie, ctx, scratch_pool);
   else if (kind == svn_node_none)
     {
       svn_boolean_t tree_conflicted;
@@ -578,7 +572,7 @@ add(void *baton, apr_pool_t *result_pool
       /* Provide a meaningful error message if the node does not exist
        * on disk but is a tree conflict victim. */
       err = svn_wc_conflicted_p3(NULL, NULL, &tree_conflicted,
-                                 b->ctx->wc_ctx, b->local_abspath,
+                                 ctx->wc_ctx, local_abspath,
                                  scratch_pool);
       if (err)
         svn_error_clear(err);
@@ -587,22 +581,22 @@ add(void *baton, apr_pool_t *result_pool
                                  _("'%s' is an existing item in conflict; "
                                    "please mark the conflict as resolved "
                                    "before adding a new item here"),
-                                 svn_dirent_local_style(b->local_abspath,
+                                 svn_dirent_local_style(local_abspath,
                                                         scratch_pool));
 
       return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
                                _("'%s' not found"),
-                               svn_dirent_local_style(b->local_abspath,
+                               svn_dirent_local_style(local_abspath,
                                                       scratch_pool));
     }
   else
     return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                              _("Unsupported node kind for path '%s'"),
-                             svn_dirent_local_style(b->local_abspath,
+                             svn_dirent_local_style(local_abspath,
                                                     scratch_pool));
 
   /* Ignore SVN_ERR_ENTRY_EXISTS when FORCE is set.  */
-  if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && b->force)
+  if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
     {
       svn_error_clear(err);
       err = SVN_NO_ERROR;
@@ -675,7 +669,7 @@ svn_client_add4(const char *path,
 {
   const char *parent_abspath;
   const char *local_abspath;
-  struct add_with_write_lock_baton baton;
+  const char *existing_parent_abspath;
 
   if (svn_path_is_url(path))
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -695,30 +689,26 @@ svn_client_add4(const char *path,
   else
     parent_abspath = svn_dirent_dirname(local_abspath, pool);
 
-  baton.existing_parent_abspath = NULL;
+  existing_parent_abspath = NULL;
   if (add_parents)
     {
       apr_pool_t *subpool;
-      const char *existing_parent_abspath;
+      const char *existing_parent_abspath2;
 
       subpool = svn_pool_create(pool);
-      SVN_ERR(find_existing_parent(&existing_parent_abspath, ctx,
+      SVN_ERR(find_existing_parent(&existing_parent_abspath2, ctx,
                                    parent_abspath, pool, subpool));
-      if (strcmp(existing_parent_abspath, parent_abspath) != 0)
-        baton.existing_parent_abspath = existing_parent_abspath;
+      if (strcmp(existing_parent_abspath2, parent_abspath) != 0)
+        existing_parent_abspath = existing_parent_abspath2;
       svn_pool_destroy(subpool);
     }
 
-  baton.local_abspath = local_abspath;
-  baton.depth = depth;
-  baton.force = force;
-  baton.no_ignore = no_ignore;
-  baton.ctx = ctx;
-  SVN_ERR(svn_wc__call_with_write_lock(add, &baton, ctx->wc_ctx,
-                                       baton.existing_parent_abspath
-                                         ? baton.existing_parent_abspath
-                                         : parent_abspath,
-                                       FALSE, pool, pool));
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+    add(local_abspath, depth, force, no_ignore, existing_parent_abspath,
+        ctx, pool),
+    ctx->wc_ctx,
+    existing_parent_abspath ? existing_parent_abspath : parent_abspath,
+    FALSE /* lock_anchor */, pool);
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/cleanup.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/cleanup.c Mon Nov 14 14:32:05 2011
@@ -88,7 +88,7 @@ fetch_repos_info(const char **repos_root
   svn_ra_session_t *ra_session;
 
   /* The same info is likely to retrieved multiple times (e.g. externals) */
-  if (ri->last_repos && svn_uri__is_child(ri->last_repos, url, scratch_pool))
+  if (ri->last_repos && svn_uri__is_ancestor(ri->last_repos, url))
     {
       *repos_root = apr_pstrdup(result_pool, ri->last_repos);
       *repos_uuid = apr_pstrdup(result_pool, ri->last_uuid);

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/client.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/client.h (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/client.h Mon Nov 14 14:32:05 2011
@@ -143,6 +143,22 @@ svn_client__repos_locations(const char *
                             svn_client_ctx_t *ctx,
                             apr_pool_t *pool);
 
+/* Trace a line of history of a particular versioned resource back to a
+ * specific revision.
+ *
+ * Set *OP_URL to the URL that the object PEG_URL@PEG_REVNUM had in
+ * revision OP_REVNUM.
+ * RA_SESSION is required. */
+svn_error_t *
+svn_client__repos_location(const char **start_url,
+                           svn_ra_session_t *ra_session,
+                           const char *peg_url,
+                           svn_revnum_t peg_revnum,
+                           svn_revnum_t op_revnum,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
+
 
 /* Set *SEGMENTS to an array of svn_location_segment_t * objects, each
    representing a reposition location segment for the history of PATH
@@ -198,8 +214,9 @@ svn_client__get_youngest_common_ancestor
    and should only be used if PATH_OR_URL is a url
      ### else NULL? what's it for?
 
-   If PEG_REVISION's kind is svn_opt_revision_unspecified, it is
-   interpreted as "head" for a URL or "working" for a working-copy path.
+   If PEG_REVISION->kind is 'unspecified', the peg revision is 'head'
+   for a URL or 'working' for a WC path.  If REVISION->kind is
+   'unspecified', the operative revision is the peg revision.
 
    Store the resulting ra_session in *RA_SESSION_P.  Store the actual
    revision number of the object in *REV_P, and the final resulting
@@ -261,14 +278,12 @@ svn_client__ensure_ra_session_url(const 
                                   apr_pool_t *pool);
 
 /* Return the path of ABSPATH_OR_URL relative to the repository root
-   (REPOS_ROOT) in REL_PATH (URI-decoded), both allocated in RESULT_POOL.
+   in REL_PATH (URI-decoded), allocated in RESULT_POOL.
    If INCLUDE_LEADING_SLASH is set, the returned result will have a leading
    slash; otherwise, it will not.
 
-   The remaining parameters are used to procure the repository root.
-   Either REPOS_ROOT or RA_SESSION -- but not both -- may be NULL.
-   REPOS_ROOT should be passed when available as an optimization (in
-   that order of preference).
+   REPOS_ROOT and RA_SESSION may be NULL if ABSPATH_OR_URL is a WC path,
+   otherwise at least one of them must be non-null.
 
    CAUTION:  While having a leading slash on a so-called relative path
    might work out well for functionality that interacts with

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/commit.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/commit.c Mon Nov 14 14:32:05 2011
@@ -901,12 +901,11 @@ collect_lock_tokens(apr_hash_t **result,
     {
       const char *url = svn__apr_hash_index_key(hi);
       const char *token = svn__apr_hash_index_val(hi);
+      const char *relpath = svn_uri_skip_ancestor(base_url, url, pool);
 
-      if (svn_uri__is_ancestor(base_url, url))
+      if (relpath)
         {
-          url = svn_uri_skip_ancestor(base_url, url, pool);
-
-          apr_hash_set(*result, url, APR_HASH_KEY_STRING, token);
+          apr_hash_set(*result, relpath, APR_HASH_KEY_STRING, token);
         }
     }
 
@@ -1168,12 +1167,113 @@ check_url_kind(void *baton,
                                   kind, scratch_pool));
 }
 
+/* Recurse into every target in REL_TARGETS, finding committable externals
+ * nested within. Append these to REL_TARGETS itself. The paths in REL_TARGETS
+ * are assumed to be / will be created relative to BASE_ABSPATH. The remaining
+ * arguments correspond to those of svn_client_commit6(). */
+static svn_error_t*
+append_externals_as_explicit_targets(apr_array_header_t *rel_targets,
+                                     const char *base_abspath,
+                                     svn_boolean_t include_file_externals,
+                                     svn_boolean_t include_dir_externals,
+                                     svn_depth_t depth,
+                                     svn_client_ctx_t *ctx,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  int rel_targets_nelts_fixed;
+  int i;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  /* Easy part of applying DEPTH to externals. */
+  if (depth == svn_depth_empty)
+     {
+       /* Don't recurse. */
+       return SVN_NO_ERROR;
+     }
+   else if (depth != svn_depth_infinity)
+     {
+       include_dir_externals = FALSE;
+       /* We slip in dir externals as explicit targets. When we do that,
+       * depth_immediates should become depth_empty for dir externals targets.
+       * But adding the dir external to the list of targets makes it get
+       * handled with depth_immediates itself, and thus will also include the
+       * immediate children of the dir external. So do dir externals only with
+       * depth_infinity or not at all.
+       * ### TODO: Maybe rework this (and svn_client_commit6()) into separate
+       * ### target lists, "duplicating" REL_TARGETS: one for the user's
+       * ### targets and one for the overlayed externals targets, and pass an
+       * ### appropriate depth for the externals targets in a separate call to
+       * ### svn_client__harvest_committables(). The only gain is correct
+       * ### handling of this very specific case: during 'svn commit
+       * ### --depth=immediates --include-externals', commit dir externals
+       * ### (only immediate children of a target) with depth_empty instead of
+       * ### not at all. No other effect. So not doing that for now. */
+     }
+
+  if (! (include_file_externals || include_dir_externals))
+    return SVN_NO_ERROR;
+
+  /* Iterate *and* grow REL_TARGETS at the same time. */
+  rel_targets_nelts_fixed = rel_targets->nelts;
+
+  for (i = 0; i < rel_targets_nelts_fixed; i++)
+    {
+      int j;
+      const char *target;
+      apr_array_header_t *externals = NULL;
+
+      svn_pool_clear(iterpool);
+
+      target = svn_dirent_join(base_abspath,
+                               APR_ARRAY_IDX(rel_targets, i, const char *),
+                               iterpool);
+
+      /* ### TODO: Possible optimization: No need to do this for file targets.
+       * ### But what's cheaper, stat'ing the file system or querying the db?
+       * ### --> future. */
+
+      SVN_ERR(svn_wc__committable_externals_below(&externals, ctx->wc_ctx,
+                                                  target, depth,
+                                                  iterpool, iterpool));
+
+      if (externals != NULL)
+        {
+          const char *rel_target;
+
+          for (j = 0; j < externals->nelts; j++)
+            {
+              svn_wc__committable_external_info_t *xinfo =
+                         APR_ARRAY_IDX(externals, j,
+                                       svn_wc__committable_external_info_t *);
+
+              if ((xinfo->kind == svn_kind_file && ! include_file_externals)
+                  || (xinfo->kind == svn_kind_dir && ! include_dir_externals))
+                continue;
+
+              rel_target = svn_dirent_skip_ancestor(base_abspath,
+                                                    xinfo->local_abspath);
+              
+              SVN_ERR_ASSERT(rel_target != NULL && *rel_target != '\0');
+
+              APR_ARRAY_PUSH(rel_targets, const char *) =
+                                         apr_pstrdup(result_pool, rel_target);
+            }
+        }
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
-svn_client_commit5(const apr_array_header_t *targets,
+svn_client_commit6(const apr_array_header_t *targets,
                    svn_depth_t depth,
                    svn_boolean_t keep_locks,
                    svn_boolean_t keep_changelists,
                    svn_boolean_t commit_as_operations,
+                   svn_boolean_t include_file_externals,
+                   svn_boolean_t include_dir_externals,
                    const apr_array_header_t *changelists,
                    const apr_hash_t *revprop_table,
                    svn_commit_callback2_t commit_callback,
@@ -1233,6 +1333,12 @@ svn_client_commit5(const apr_array_heade
   if (rel_targets->nelts == 0)
     APR_ARRAY_PUSH(rel_targets, const char *) = "";
 
+  SVN_ERR(append_externals_as_explicit_targets(rel_targets, base_abspath,
+                                               include_file_externals,
+                                               include_dir_externals,
+                                               depth, ctx,
+                                               pool, pool));
+
   SVN_ERR(determine_lock_targets(&lock_targets, ctx->wc_ctx, base_abspath,
                                  rel_targets, pool, iterpool));
 
@@ -1603,3 +1709,25 @@ svn_client_commit5(const apr_array_heade
   return svn_error_trace(reconcile_errors(cmt_err, unlock_err, bump_err,
                                           pool));
 }
+
+svn_error_t *
+svn_client_commit5(const apr_array_header_t *targets,
+                   svn_depth_t depth,
+                   svn_boolean_t keep_locks,
+                   svn_boolean_t keep_changelists,
+                   svn_boolean_t commit_as_operations,
+                   const apr_array_header_t *changelists,
+                   const apr_hash_t *revprop_table,
+                   svn_commit_callback2_t commit_callback,
+                   void *commit_baton,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool)
+{
+  return svn_client_commit6(targets, depth, keep_locks, keep_changelists,
+                            commit_as_operations,
+                            TRUE,  /* include_file_externals */
+                            FALSE, /* include_dir_externals */
+                            changelists, revprop_table, commit_callback,
+                            commit_baton, ctx, pool);
+}
+

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/commit_util.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/commit_util.c Mon Nov 14 14:32:05 2011
@@ -410,6 +410,12 @@ bail_on_tree_conflicted_ancestor(svn_wc_
    when harvesting committables; that is, don't add a path to
    COMMITTABLES unless it's a member of one of those changelists.
 
+   IS_EXPLICIT_TARGET should always be passed as TRUE, except when
+   harvest_committables() calls itself in recursion. This provides a way to
+   tell whether LOCAL_ABSPATH was an original target or whether it was reached
+   by recursing deeper into a dir target. (This is used to skip all file
+   externals that aren't explicit commit targets.)
+
    If CANCEL_FUNC is non-null, call it with CANCEL_BATON to see
    if the user has cancelled the operation.
 
@@ -428,6 +434,7 @@ harvest_committables(svn_wc_context_t *w
                      apr_hash_t *changelists,
                      svn_boolean_t skip_files,
                      svn_boolean_t skip_dirs,
+                     svn_boolean_t is_explicit_target,
                      svn_client__check_url_kind_t check_url_func,
                      void *check_url_baton,
                      svn_cancel_func_t cancel_func,
@@ -543,10 +550,24 @@ harvest_committables(svn_wc_context_t *w
          svn_dirent_local_style(local_abspath, scratch_pool));
     }
 
-  /* ### in need of comment */
-  if (copy_mode
-      && is_update_root
-      && db_kind == svn_node_file)
+  /* Handle file externals.
+   * (IS_UPDATE_ROOT is more generally defined, but at the moment this
+   * condition matches only file externals.)
+   *
+   * Don't copy files that svn:externals brought into the WC. So in copy_mode,
+   * even explicit targets are skipped.
+   *
+   * Exclude file externals from recursion. Hande file externals only when
+   * passed as explicit target. Note that svn_client_commit6() passes all
+   * committable externals in as explicit targets iff they count.
+   *
+   * Also note that dir externals will never be reached recursively by this
+   * function, since svn_wc__node_get_children_of_working_node() (used below
+   * to recurse) does not return switched subdirs. */
+  if (is_update_root
+      && db_kind == svn_node_file
+      && (copy_mode
+          || ! is_explicit_target))
     {
       return SVN_NO_ERROR;
     }
@@ -841,6 +862,7 @@ harvest_committables(svn_wc_context_t *w
                                        changelists,
                                        (depth < svn_depth_files),
                                        (depth < svn_depth_immediates),
+                                       FALSE, /* IS_EXPLICIT_TARGET */
                                        check_url_func, check_url_baton,
                                        cancel_func, cancel_baton,
                                        notify_func, notify_baton,
@@ -1125,6 +1147,7 @@ svn_client__harvest_committables(svn_cli
                                    FALSE /* COPY_MODE_ROOT */,
                                    depth, just_locked, changelist_hash,
                                    FALSE, FALSE,
+                                   TRUE /* IS_EXPLICIT_TARGET */,
                                    check_url_func, check_url_baton,
                                    ctx->cancel_func, ctx->cancel_baton,
                                    ctx->notify_func2, ctx->notify_baton2,
@@ -1218,6 +1241,7 @@ harvest_copy_committables(void *baton, v
                                FALSE,  /* JUST_LOCKED */
                                NULL,
                                FALSE, FALSE, /* skip files, dirs */
+                               TRUE, /* IS_EXPLICIT_TARGET (don't care) */
                                btn->check_url_func,
                                btn->check_url_baton,
                                btn->ctx->cancel_func,

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/copy.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/copy.c Mon Nov 14 14:32:05 2011
@@ -240,47 +240,41 @@ get_copy_pair_ancestors(const apr_array_
 }
 
 
-struct do_wc_to_wc_copies_with_write_lock_baton {
-  const apr_array_header_t *copy_pairs;
-  svn_client_ctx_t *ctx;
-  const char *dst_parent;
-};
-
 /* The guts of do_wc_to_wc_copies */
 static svn_error_t *
-do_wc_to_wc_copies_with_write_lock(void *baton,
-                                   apr_pool_t *result_pool,
+do_wc_to_wc_copies_with_write_lock(const apr_array_header_t *copy_pairs,
+                                   const char *dst_parent,
+                                   svn_client_ctx_t *ctx,
                                    apr_pool_t *scratch_pool)
 {
-  struct do_wc_to_wc_copies_with_write_lock_baton *b = baton;
   int i;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_error_t *err = SVN_NO_ERROR;
 
-  for (i = 0; i < b->copy_pairs->nelts; i++)
+  for (i = 0; i < copy_pairs->nelts; i++)
     {
       const char *dst_abspath;
-      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(b->copy_pairs, i,
+      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
       svn_pool_clear(iterpool);
 
       /* Check for cancellation */
-      if (b->ctx->cancel_func)
-        SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
+      if (ctx->cancel_func)
+        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
       /* Perform the copy */
       dst_abspath = svn_dirent_join(pair->dst_parent_abspath, pair->base_name,
                                     iterpool);
-      err = svn_wc_copy3(b->ctx->wc_ctx, pair->src_abspath_or_url, dst_abspath,
+      err = svn_wc_copy3(ctx->wc_ctx, pair->src_abspath_or_url, dst_abspath,
                          FALSE /* metadata_only */,
-                         b->ctx->cancel_func, b->ctx->cancel_baton,
-                         b->ctx->notify_func2, b->ctx->notify_baton2, iterpool);
+                         ctx->cancel_func, ctx->cancel_baton,
+                         ctx->notify_func2, ctx->notify_baton2, iterpool);
       if (err)
         break;
     }
   svn_pool_destroy(iterpool);
 
-  svn_io_sleep_for_timestamps(b->dst_parent, scratch_pool);
+  svn_io_sleep_for_timestamps(dst_parent, scratch_pool);
   SVN_ERR(err);
   return SVN_NO_ERROR;
 }
@@ -293,7 +287,6 @@ do_wc_to_wc_copies(const apr_array_heade
                    apr_pool_t *pool)
 {
   const char *dst_parent, *dst_parent_abspath;
-  struct do_wc_to_wc_copies_with_write_lock_baton baton;
 
   SVN_ERR(get_copy_pair_ancestors(copy_pairs, NULL, &dst_parent, NULL, pool));
   if (copy_pairs->nelts == 1)
@@ -301,40 +294,31 @@ do_wc_to_wc_copies(const apr_array_heade
 
   SVN_ERR(svn_dirent_get_absolute(&dst_parent_abspath, dst_parent, pool));
 
-  baton.copy_pairs = copy_pairs;
-  baton.ctx = ctx;
-  baton.dst_parent = dst_parent;
-  SVN_ERR(svn_wc__call_with_write_lock(do_wc_to_wc_copies_with_write_lock,
-                                       &baton, ctx->wc_ctx, dst_parent_abspath,
-                                       FALSE, pool, pool));
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+    do_wc_to_wc_copies_with_write_lock(copy_pairs, dst_parent, ctx, pool),
+    ctx->wc_ctx, dst_parent_abspath, FALSE, pool);
 
   return SVN_NO_ERROR;
 }
 
-struct do_wc_to_wc_moves_with_locks_baton {
-  svn_client_ctx_t *ctx;
-  svn_client__copy_pair_t *pair;
-  const char *dst_parent_abspath;
-  svn_boolean_t lock_src;
-  svn_boolean_t lock_dst;
-};
-
 /* The locked bit of do_wc_to_wc_moves. */
 static svn_error_t *
-do_wc_to_wc_moves_with_locks2(void *baton,
-                              apr_pool_t *result_pool,
+do_wc_to_wc_moves_with_locks2(svn_client__copy_pair_t *pair,
+                              const char *dst_parent_abspath,
+                              svn_boolean_t lock_src,
+                              svn_boolean_t lock_dst,
+                              svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
-  struct do_wc_to_wc_moves_with_locks_baton *b = baton;
   const char *dst_abspath;
 
-  dst_abspath = svn_dirent_join(b->dst_parent_abspath, b->pair->base_name,
+  dst_abspath = svn_dirent_join(dst_parent_abspath, pair->base_name,
                                 scratch_pool);
 
-  SVN_ERR(svn_wc_move(b->ctx->wc_ctx, b->pair->src_abspath_or_url,
+  SVN_ERR(svn_wc_move(ctx->wc_ctx, pair->src_abspath_or_url,
                      dst_abspath, FALSE /* metadata_only */,
-                     b->ctx->cancel_func, b->ctx->cancel_baton,
-                     b->ctx->notify_func2, b->ctx->notify_baton2,
+                     ctx->cancel_func, ctx->cancel_baton,
+                     ctx->notify_func2, ctx->notify_baton2,
                      scratch_pool));
 
   return SVN_NO_ERROR;
@@ -342,18 +326,21 @@ do_wc_to_wc_moves_with_locks2(void *bato
 
 /* Wrapper to add an optional second lock */
 static svn_error_t *
-do_wc_to_wc_moves_with_locks1(void *baton,
-                              apr_pool_t *result_pool,
+do_wc_to_wc_moves_with_locks1(svn_client__copy_pair_t *pair,
+                              const char *dst_parent_abspath,
+                              svn_boolean_t lock_src,
+                              svn_boolean_t lock_dst,
+                              svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
-  struct do_wc_to_wc_moves_with_locks_baton *b = baton;
-
-  if (b->lock_dst)
-    SVN_ERR(svn_wc__call_with_write_lock(do_wc_to_wc_moves_with_locks2, b,
-                                         b->ctx->wc_ctx, b->dst_parent_abspath,
-                                         FALSE, result_pool, scratch_pool));
+  if (lock_dst)
+    SVN_WC__CALL_WITH_WRITE_LOCK(
+      do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src,
+                                    lock_dst, ctx, scratch_pool),
+      ctx->wc_ctx, dst_parent_abspath, FALSE, scratch_pool);
   else
-    SVN_ERR(do_wc_to_wc_moves_with_locks2(b, result_pool, scratch_pool));
+    SVN_ERR(do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src,
+                                          lock_dst, ctx, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -373,7 +360,7 @@ do_wc_to_wc_moves(const apr_array_header
   for (i = 0; i < copy_pairs->nelts; i++)
     {
       const char *src_parent_abspath;
-      struct do_wc_to_wc_moves_with_locks_baton baton;
+      svn_boolean_t lock_src, lock_dst;
 
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
@@ -397,32 +384,31 @@ do_wc_to_wc_moves(const apr_array_header
           || svn_dirent_is_child(src_parent_abspath, pair->dst_parent_abspath,
                                  iterpool))
         {
-          baton.lock_src = TRUE;
-          baton.lock_dst = FALSE;
+          lock_src = TRUE;
+          lock_dst = FALSE;
         }
       else if (svn_dirent_is_child(pair->dst_parent_abspath, src_parent_abspath,
                                    iterpool))
         {
-          baton.lock_src = FALSE;
-          baton.lock_dst = TRUE;
+          lock_src = FALSE;
+          lock_dst = TRUE;
         }
       else
         {
-          baton.lock_src = TRUE;
-          baton.lock_dst = TRUE;
+          lock_src = TRUE;
+          lock_dst = TRUE;
         }
 
       /* Perform the copy and then the delete. */
-      baton.ctx = ctx;
-      baton.pair = pair;
-      baton.dst_parent_abspath = pair->dst_parent_abspath;
-      if (baton.lock_src)
-        SVN_ERR(svn_wc__call_with_write_lock(do_wc_to_wc_moves_with_locks1,
-                                             &baton,
-                                             ctx->wc_ctx, src_parent_abspath,
-                                             FALSE, iterpool, iterpool));
+      if (lock_src)
+        SVN_WC__CALL_WITH_WRITE_LOCK(
+          do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
+                                        lock_src, lock_dst, ctx, iterpool),
+          ctx->wc_ctx, src_parent_abspath,
+          FALSE, iterpool);
       else
-        SVN_ERR(do_wc_to_wc_moves_with_locks1(&baton, iterpool, iterpool));
+        SVN_ERR(do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
+                                              lock_src, lock_dst, ctx, iterpool));
 
     }
   svn_pool_destroy(iterpool);
@@ -889,8 +875,6 @@ repos_to_repos_copy(const apr_array_head
      directories of the destination that don't yet exist.  */
   if (make_parents)
     {
-      const char *dir;
-
       new_dirs = apr_array_make(pool, 0, sizeof(const char *));
 
       /* If this is a move, TOP_URL is at least the common ancestor of
@@ -913,17 +897,17 @@ repos_to_repos_copy(const apr_array_head
 
                 svn copy --parents URL/src URL/dst
 
-             where src exists and dst does not.  The svn_uri_dirname()
-             call above will produce a string equivalent to TOP_URL,
-             which means svn_uri_is_child() will return NULL.  In this
-             case, do not try to add dst to the NEW_DIRS list since it
+             where src exists and dst does not.  If the dirname of the
+             destination path is equal to TOP_URL,
+             do not try to add dst to the NEW_DIRS list since it
              will be added to the commit items array later in this
              function. */
-          dir = svn_uri__is_child(
-                  top_url,
-                  svn_uri_dirname(first_pair->dst_abspath_or_url, pool),
-                  pool);
-          if (dir)
+          const char *dir = svn_uri_skip_ancestor(
+                              top_url,
+                              svn_uri_dirname(first_pair->dst_abspath_or_url,
+                                              pool),
+                              pool);
+          if (dir && *dir)
             SVN_ERR(find_absent_parents1(ra_session, dir, new_dirs, pool));
         }
       /* If, however, this is *not* a move, TOP_URL only points to the
@@ -942,8 +926,9 @@ repos_to_repos_copy(const apr_array_head
           for (i = 0; i < new_urls->nelts; i++)
             {
               const char *new_url = APR_ARRAY_IDX(new_urls, i, const char *);
-              dir = svn_uri__is_child(top_url, new_url, pool);
-              APR_ARRAY_PUSH(new_dirs, const char *) = dir ? dir : "";
+              const char *dir = svn_uri_skip_ancestor(top_url, new_url, pool);
+
+              APR_ARRAY_PUSH(new_dirs, const char *) = dir;
             }
         }
     }
@@ -959,10 +944,12 @@ repos_to_repos_copy(const apr_array_head
                                                     svn_client__copy_pair_t *);
       path_driver_info_t *info = APR_ARRAY_IDX(path_infos, i,
                                                path_driver_info_t *);
+      const char *relpath = svn_uri_skip_ancestor(pair->dst_abspath_or_url,
+                                                  pair->src_abspath_or_url,
+                                                  pool);
 
       if ((strcmp(pair->dst_abspath_or_url, repos_root) != 0)
-          && (svn_uri__is_child(pair->dst_abspath_or_url,
-                                pair->src_abspath_or_url, pool) != NULL))
+          && (relpath != NULL && *relpath != '\0'))
         {
           info->resurrection = TRUE;
           top_url = svn_uri_dirname(top_url, pool);
@@ -1013,9 +1000,7 @@ repos_to_repos_copy(const apr_array_head
 
       /* Figure out the basename that will result from this operation,
          and ensure that we aren't trying to overwrite existing paths.  */
-      dst_rel = svn_uri__is_child(top_url, pair->dst_abspath_or_url, pool);
-      if (! dst_rel)
-        dst_rel = "";
+      dst_rel = svn_uri_skip_ancestor(top_url, pair->dst_abspath_or_url, pool);
       SVN_ERR(svn_ra_check_path(ra_session, dst_rel, youngest,
                                 &dst_kind, pool));
       if (dst_kind != svn_node_none)
@@ -1269,9 +1254,8 @@ wc_to_repos_copy(const apr_array_header_
         APR_ARRAY_IDX(copy_pairs, i, svn_client__copy_pair_t *);
 
       svn_pool_clear(iterpool);
-      dst_rel = svn_uri__is_child(top_dst_url,
-                                  pair->dst_abspath_or_url,
-                                  iterpool);
+      dst_rel = svn_uri_skip_ancestor(top_dst_url, pair->dst_abspath_or_url,
+                                      iterpool);
       SVN_ERR(svn_ra_check_path(ra_session, dst_rel, SVN_INVALID_REVNUM,
                                 &dst_kind, iterpool));
       if (dst_kind != svn_node_none)
@@ -1775,29 +1759,6 @@ repos_to_wc_copy_locked(const apr_array_
   return SVN_NO_ERROR;
 }
 
-struct repos_to_wc_copy_baton {
-  const apr_array_header_t *copy_pairs;
-  const char *top_dst_path;
-  svn_boolean_t ignore_externals;
-  svn_ra_session_t *ra_session;
-  svn_client_ctx_t *ctx;
-};
-
-/* Implements svn_wc__with_write_lock_func_t. */
-static svn_error_t *
-repos_to_wc_copy_cb(void *baton,
-                    apr_pool_t *result_pool,
-                    apr_pool_t *scratch_pool)
-{
-  struct repos_to_wc_copy_baton *b = baton;
-
-  SVN_ERR(repos_to_wc_copy_locked(b->copy_pairs, b->top_dst_path,
-                                  b->ignore_externals, b->ra_session,
-                                  b->ctx, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
 static svn_error_t *
 repos_to_wc_copy(const apr_array_header_t *copy_pairs,
                  svn_boolean_t make_parents,
@@ -1809,7 +1770,6 @@ repos_to_wc_copy(const apr_array_header_
   const char *top_src_url, *top_dst_path;
   apr_pool_t *iterpool = svn_pool_create(pool);
   const char *lock_abspath;
-  struct repos_to_wc_copy_baton baton;
   int i;
 
   /* Get the real path for the source, based upon its peg revision. */
@@ -1909,15 +1869,10 @@ repos_to_wc_copy(const apr_array_header_
     }
   svn_pool_destroy(iterpool);
 
-  baton.copy_pairs = copy_pairs;
-  baton.top_dst_path = top_dst_path;
-  baton.ignore_externals = ignore_externals;
-  baton.ra_session = ra_session;
-  baton.ctx = ctx;
-
-  SVN_ERR(svn_wc__call_with_write_lock(repos_to_wc_copy_cb, &baton,
-                                       ctx->wc_ctx, lock_abspath,
-                                       FALSE, pool, pool));
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+    repos_to_wc_copy_locked(copy_pairs, top_dst_path, ignore_externals,
+                            ra_session, ctx, pool),
+    ctx->wc_ctx, lock_abspath, FALSE, pool);
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/delete.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/delete.c Mon Nov 14 14:32:05 2011
@@ -237,7 +237,7 @@ delete_urls_multi_repos(const apr_array_
       for (hi = apr_hash_first(pool, sessions); hi; hi = apr_hash_next(hi))
         {
           repos_root = svn__apr_hash_index_key(hi);
-          repos_relpath = svn_uri__is_child(repos_root, uri, pool);
+          repos_relpath = svn_uri_skip_ancestor(repos_root, uri, pool);
 
           if (repos_relpath)
             {
@@ -264,7 +264,7 @@ delete_urls_multi_repos(const apr_array_
           SVN_ERR(svn_ra_reparent(ra_session, repos_root, pool));
 
           apr_hash_set(sessions, repos_root, APR_HASH_KEY_STRING, ra_session);
-          repos_relpath = svn_uri__is_child(repos_root, uri, pool);
+          repos_relpath = svn_uri_skip_ancestor(repos_root, uri, pool);
 
           relpaths_list = apr_array_make(pool, 1, sizeof(const char *));
           apr_hash_set(relpaths, repos_root, APR_HASH_KEY_STRING,
@@ -368,30 +368,6 @@ svn_client__wc_delete_many(const apr_arr
   return SVN_NO_ERROR;
 }
 
-/* Callback baton for delete_with_write_lock_baton. */
-struct delete_with_write_lock_baton
-{
-  const apr_array_header_t *targets;
-  svn_boolean_t force;
-  svn_boolean_t keep_local;
-  svn_client_ctx_t *ctx;
-};
-
-/* Implements svn_wc__with_write_lock_func_t. */
-static svn_error_t *
-delete_with_write_lock_func(void *baton,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool)
-{
-  struct delete_with_write_lock_baton *args = baton;
-
-  return svn_client__wc_delete_many(args->targets, args->force,
-                                    FALSE, args->keep_local,
-                                    args->ctx->notify_func2,
-                                    args->ctx->notify_baton2,
-                                    args->ctx, scratch_pool);
-}
-
 svn_error_t *
 svn_client_delete4(const apr_array_header_t *paths,
                    svn_boolean_t force,
@@ -417,8 +393,6 @@ svn_client_delete4(const apr_array_heade
     }
   else
     {
-      struct delete_with_write_lock_baton dwwlb;
-      const char *wcroot_abspath;
       const char *local_abspath;
       apr_hash_t *wcroots;
       apr_hash_index_t *hi;
@@ -432,6 +406,7 @@ svn_client_delete4(const apr_array_heade
       iterpool = svn_pool_create(pool);
       for (i = 0; i < paths->nelts; i++)
         {
+          const char *wcroot_abspath;
           apr_array_header_t *targets;
 
           svn_pool_clear(iterpool);
@@ -474,17 +449,17 @@ svn_client_delete4(const apr_array_heade
       /* Delete the targets from each working copy in turn. */
       for (hi = apr_hash_first(pool, wcroots); hi; hi = apr_hash_next(hi))
         {
+          const char *wcroot_abspath = svn__apr_hash_index_key(hi);
+          const apr_array_header_t *targets = svn__apr_hash_index_val(hi);
+
           svn_pool_clear(iterpool);
 
-          wcroot_abspath = svn__apr_hash_index_key(hi);
-          dwwlb.targets = svn__apr_hash_index_val(hi);
-          dwwlb.force = force;
-          dwwlb.keep_local = keep_local;
-          dwwlb.ctx = ctx;
-          SVN_ERR(svn_wc__call_with_write_lock(delete_with_write_lock_func,
-                                               &dwwlb, ctx->wc_ctx,
-                                               wcroot_abspath, TRUE,
-                                               iterpool, iterpool));
+          SVN_WC__CALL_WITH_WRITE_LOCK(
+            svn_client__wc_delete_many(targets, force, FALSE, keep_local,
+                                       ctx->notify_func2, ctx->notify_baton2,
+                                       ctx, iterpool),
+            ctx->wc_ctx, wcroot_abspath, TRUE /* lock_anchor */,
+            iterpool);
         }
       svn_pool_destroy(iterpool);
     }

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/deprecated.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/deprecated.c Mon Nov 14 14:32:05 2011
@@ -44,6 +44,7 @@
 #include "client.h"
 #include "mergeinfo.h"
 
+#include "private/svn_opt_private.h"
 #include "private/svn_wc_private.h"
 #include "svn_private_config.h"
 
@@ -1362,16 +1363,11 @@ svn_client_log4(const apr_array_header_t
                 apr_pool_t *pool)
 {
   apr_array_header_t *revision_ranges;
-  svn_opt_revision_range_t *range;
-
-  range = apr_palloc(pool, sizeof(svn_opt_revision_range_t));
-  range->start = *start;
-  range->end = *end;
 
   revision_ranges = apr_array_make(pool, 1,
                                    sizeof(svn_opt_revision_range_t *));
-
-  APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) = range;
+  APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
+    = svn_opt__revision_range_create(start, end, pool);
 
   return svn_client_log5(targets, peg_revision, revision_ranges, limit,
                          discover_changed_paths, strict_node_history,
@@ -1577,13 +1573,11 @@ svn_client_merge_peg2(const char *source
                       svn_client_ctx_t *ctx,
                       apr_pool_t *pool)
 {
-  svn_opt_revision_range_t range;
   apr_array_header_t *ranges_to_merge =
     apr_array_make(pool, 1, sizeof(svn_opt_revision_range_t *));
 
-  range.start = *revision1;
-  range.end = *revision2;
-  APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *) = &range;
+  APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *)
+    = svn_opt__revision_range_create(revision1, revision2, pool);
   return svn_client_merge_peg3(source, ranges_to_merge,
                                peg_revision,
                                target_wcpath,

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/externals.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/externals.c Mon Nov 14 14:32:05 2011
@@ -606,6 +606,7 @@ handle_external_item_change(const struct
   svn_ra_session_t *ra_session;
   svn_client__ra_session_from_path_results ra_cache = { 0 };
   const char *new_url;
+  svn_node_kind_t kind;
 
   ra_cache.kind = svn_node_unknown;
 
@@ -624,43 +625,38 @@ handle_external_item_change(const struct
                                                 parent_dir_url,
                                                 scratch_pool, scratch_pool));
 
-  /* If the external is being checked out, exported or updated,
-     determine if the external is a file or directory. */
-  if (new_item)
-    {
-      svn_node_kind_t kind;
-
-      /* Get the RA connection. */
-      SVN_ERR(svn_client__ra_session_from_path(&ra_session,
-                                               &ra_cache.ra_revnum,
-                                               &ra_cache.ra_session_url,
-                                               new_url, NULL,
-                                               &(new_item->peg_revision),
-                                               &(new_item->revision), eb->ctx,
-                                               scratch_pool));
-
-      SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid,
-                               scratch_pool));
-      SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url,
-                                     scratch_pool));
-      SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind,
-                                scratch_pool));
+  /* Determine if the external is a file or directory. */
+  /* Get the RA connection. */
+  SVN_ERR(svn_client__ra_session_from_path(&ra_session,
+                                           &ra_cache.ra_revnum,
+                                           &ra_cache.ra_session_url,
+                                           new_url, NULL,
+                                           &(new_item->peg_revision),
+                                           &(new_item->revision), eb->ctx,
+                                           scratch_pool));
+
+  SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid,
+                           scratch_pool));
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url,
+                                 scratch_pool));
+  SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind,
+                            scratch_pool));
+
+  if (svn_node_none == kind)
+    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                             _("URL '%s' at revision %ld doesn't exist"),
+                             ra_cache.ra_session_url,
+                             ra_cache.ra_revnum);
+
+  if (svn_node_dir != kind && svn_node_file != kind)
+    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                             _("URL '%s' at revision %ld is not a file "
+                               "or a directory"),
+                             ra_cache.ra_session_url,
+                             ra_cache.ra_revnum);
 
-      if (svn_node_none == kind)
-        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                 _("URL '%s' at revision %ld doesn't exist"),
-                                 ra_cache.ra_session_url,
-                                 ra_cache.ra_revnum);
-
-      if (svn_node_dir != kind && svn_node_file != kind)
-        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                 _("URL '%s' at revision %ld is not a file "
-                                   "or a directory"),
-                                 ra_cache.ra_session_url,
-                                 ra_cache.ra_revnum);
+  ra_cache.kind = kind;
 
-      ra_cache.kind = kind;
-    }
 
   /* Not protecting against recursive externals.  Detecting them in
      the global case is hard, and it should be pretty obvious to a
@@ -679,87 +675,44 @@ handle_external_item_change(const struct
 
   if (! old_defining_abspath)
     {
-      /* This branch is only used during a checkout or an export. */
-
-      switch (ra_cache.kind)
-        {
-        case svn_node_dir:
-          /* The target dir might have multiple components.  Guarantee
-             the path leading down to the last component. */
-          SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath,
-                                                                 scratch_pool),
-                                              scratch_pool));
-
-          SVN_ERR(switch_dir_external(
-                   local_abspath, new_url,
-                   &(new_item->peg_revision), &(new_item->revision),
-                   parent_dir_abspath, eb->timestamp_sleep, eb->ctx,
-                   scratch_pool));
-          break;
-        case svn_node_file:
-          if (strcmp(eb->repos_root_url, ra_cache.repos_root_url))
-            return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                      _("Unsupported external: "
-                        "url of file external '%s' is not in repository '%s'"),
-                      new_url, eb->repos_root_url);
-          SVN_ERR(switch_file_external(local_abspath,
-                                       new_url,
-                                       &new_item->peg_revision,
-                                       &new_item->revision,
-                                       parent_dir_abspath,
-                                       ra_session,
-                                       ra_cache.ra_session_url,
-                                       ra_cache.ra_revnum,
-                                       ra_cache.repos_root_url,
-                                       eb->timestamp_sleep, eb->ctx,
-                                       scratch_pool));
-          break;
-        default:
-          SVN_ERR_MALFUNCTION();
-          break;
-        }
+      /* The target dir might have multiple components.  Guarantee the path
+         leading down to the last component. */
+      SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath,
+                                                             scratch_pool),
+                                          scratch_pool));
     }
-  else
-    {
-      /* This branch handles a definition change or simple update. */
 
-      /* Either the URL changed, or the exact same item is present in
-         both hashes, and caller wants to update such unchanged items.
-         In the latter case, the call below will try to make sure that
-         the external really is a WC pointing to the correct
-         URL/revision. */
-      switch (ra_cache.kind)
-        {
-        case svn_node_dir:
-          SVN_ERR(switch_dir_external(local_abspath, new_url,
-                                      &(new_item->peg_revision),
-                                      &(new_item->revision),
-                                      parent_dir_abspath,
-                                      eb->timestamp_sleep, eb->ctx,
-                                      scratch_pool));
-          break;
-        case svn_node_file:
-          if (strcmp(eb->repos_root_url, ra_cache.repos_root_url))
-            return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                      _("Unsupported external: "
-                        "url of file external '%s' is not in repository '%s'"),
-                      new_url, eb->repos_root_url);
-          SVN_ERR(switch_file_external(local_abspath,
-                                       new_url,
-                                       &new_item->peg_revision,
-                                       &new_item->revision,
-                                       parent_dir_abspath,
-                                       ra_session,
-                                       ra_cache.ra_session_url,
-                                       ra_cache.ra_revnum,
-                                       ra_cache.repos_root_url,
-                                       eb->timestamp_sleep, eb->ctx,
-                                       scratch_pool));
-          break;
-        default:
-          SVN_ERR_MALFUNCTION();
-          break;
-        }
+  switch (ra_cache.kind)
+    {
+      case svn_node_dir:
+        SVN_ERR(switch_dir_external(local_abspath, new_url,
+                                    &(new_item->peg_revision),
+                                    &(new_item->revision),
+                                    parent_dir_abspath,
+                                    eb->timestamp_sleep, eb->ctx,
+                                    scratch_pool));
+        break;
+      case svn_node_file:
+        if (strcmp(eb->repos_root_url, ra_cache.repos_root_url))
+          return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                    _("Unsupported external: "
+                      "url of file external '%s' is not in repository '%s'"),
+                    new_url, eb->repos_root_url);
+        SVN_ERR(switch_file_external(local_abspath,
+                                     new_url,
+                                     &new_item->peg_revision,
+                                     &new_item->revision,
+                                     parent_dir_abspath,
+                                     ra_session,
+                                     ra_cache.ra_session_url,
+                                     ra_cache.ra_revnum,
+                                     ra_cache.repos_root_url,
+                                     eb->timestamp_sleep, eb->ctx,
+                                     scratch_pool));
+        break;
+      default:
+        SVN_ERR_MALFUNCTION();
+        break;
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/info.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/info.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/info.c Mon Nov 14 14:32:05 2011
@@ -145,8 +145,8 @@ push_dir_info(svn_ra_session_t *ra_sessi
 
       path = svn_relpath_join(dir, name, subpool);
       URL = svn_path_url_add_component2(session_URL, name, subpool);
-      fs_path = svn_fspath__canonicalize(svn_uri__is_child(repos_root, URL,
-                                                           subpool), subpool);
+      fs_path = svn_fspath__canonicalize(
+                  svn_uri_skip_ancestor(repos_root, URL, subpool), subpool);
 
       lock = apr_hash_get(locks, fs_path, APR_HASH_KEY_STRING);
 

Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/list.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/list.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/list.c Mon Nov 14 14:32:05 2011
@@ -32,6 +32,7 @@
 #include "client.h"
 
 #include "private/svn_fspath.h"
+#include "private/svn_ra_private.h"
 #include "svn_private_config.h"
 
 /* Get the directory entries of DIR at REV (relative to the root of
@@ -239,7 +240,6 @@ svn_client_list2(const char *path_or_url
   svn_revnum_t rev;
   svn_dirent_t *dirent;
   const char *url;
-  const char *repos_root;
   const char *fs_path;
   svn_error_t *err;
   apr_hash_t *locks;
@@ -254,11 +254,8 @@ svn_client_list2(const char *path_or_url
                                            peg_revision,
                                            revision, ctx, pool));
 
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool));
-
-  SVN_ERR(svn_client__path_relative_to_root(&fs_path, ctx->wc_ctx, url,
-                                            repos_root, TRUE, ra_session,
-                                            pool, pool));
+  SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &fs_path, url,
+                                              pool));
 
   SVN_ERR(ra_stat_compatible(ra_session, rev, &dirent, dirent_fields,
                              ctx, pool));