You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/12/18 18:36:29 UTC

svn commit: r1220465 [2/13] - in /subversion/branches/file-handle-cache: ./ build/ build/ac-macros/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bindings...

Modified: subversion/branches/file-handle-cache/subversion/include/svn_dirent_uri.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/include/svn_dirent_uri.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/include/svn_dirent_uri.h (original)
+++ subversion/branches/file-handle-cache/subversion/include/svn_dirent_uri.h Sun Dec 18 17:36:24 2011
@@ -122,6 +122,10 @@
  * source -- such as from the network -- is converted to a dirent it
  * should be tested with svn_dirent_is_under_root() before you can
  * assume the path to be a safe local path.
+ *
+ * MEMORY ALLOCATION: A function documented as allocating the result
+ * in a pool may instead return a static string such as "." or "". If
+ * the result is equal to an input, it will duplicate the input.
  */
 
 #ifndef SVN_DIRENT_URI_H
@@ -141,34 +145,39 @@ extern "C" {
 /** Convert @a dirent from the local style to the canonical internal style.
  * "Local style" means native path separators and "." for the empty path.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.6.
  */
 const char *
 svn_dirent_internal_style(const char *dirent,
-                          apr_pool_t *pool);
+                          apr_pool_t *result_pool);
 
 /** Convert @a dirent from the internal style to the local style.
  * "Local style" means native path separators and "." for the empty path.
  * If the input is not canonical, the output may not be canonical.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.6.
  */
 const char *
 svn_dirent_local_style(const char *dirent,
-                       apr_pool_t *pool);
+                       apr_pool_t *result_pool);
 
 /** Convert @a relpath from the local style to the canonical internal style.
  * "Local style" means native path separators and "." for the empty path.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 const char *
 svn_relpath__internal_style(const char *relpath,
-                            apr_pool_t *pool);
+                            apr_pool_t *result_pool);
 
 
-/** Join a base dirent (@a base) with a component (@a component), allocated in
- * @a pool.
+/** Join a base dirent (@a base) with a component (@a component).
  *
  * If either @a base or @a component is the empty string, then the other
  * argument will be copied and returned.  If both are the empty string then
@@ -181,15 +190,17 @@ svn_relpath__internal_style(const char *
  * dirents. Only for "internal" canonicalized dirents, since it uses '/'
  * for the separator.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.6.
  */
 char *
 svn_dirent_join(const char *base,
                 const char *component,
-                apr_pool_t *pool);
+                apr_pool_t *result_pool);
 
-/** Join multiple components onto a @a base dirent, allocated in @a pool. The
- * components are terminated by a @c NULL.
+/** Join multiple components onto a @a base dirent. The components are
+ * terminated by a @c NULL.
  *
  * If any component is the empty string, it will be ignored.
  *
@@ -198,26 +209,30 @@ svn_dirent_join(const char *base,
  *
  * See svn_dirent_join() for further notes about joining dirents.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.6.
  */
 char *
-svn_dirent_join_many(apr_pool_t *pool,
+svn_dirent_join_many(apr_pool_t *result_pool,
                      const char *base,
                      ...);
 
-/** Join a base relpath (@a base) with a component (@a component), allocating
- * the result in @a pool. @a component need not be a single component.
+/** Join a base relpath (@a base) with a component (@a component).
+ * @a component need not be a single component.
  *
  * If either @a base or @a component is the empty path, then the other
  * argument will be copied and returned.  If both are the empty path the
  * empty path is returned.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 char *
 svn_relpath_join(const char *base,
                  const char *component,
-                 apr_pool_t *pool);
+                 apr_pool_t *result_pool);
 
 /** Gets the name of the specified canonicalized @a dirent as it is known
  * within its parent directory. If the @a dirent is root, return "". The
@@ -225,8 +240,8 @@ svn_relpath_join(const char *base,
  *
  * Example: svn_dirent_basename("/foo/bar") -> "bar"
  *
- * The returned basename will be allocated in @a pool. If @a pool is NULL
- * a pointer to the basename in @a dirent is returned.
+ * If @a result_pool is NULL, return a pointer to the basename in @a dirent,
+ * otherwise allocate the result in @a result_pool.
  *
  * @note If an empty string is passed, then an empty string will be returned.
  *
@@ -234,7 +249,7 @@ svn_relpath_join(const char *base,
  */
 const char *
 svn_dirent_basename(const char *dirent,
-                    apr_pool_t *pool);
+                    apr_pool_t *result_pool);
 
 /** Get the dirname of the specified canonicalized @a dirent, defined as
  * the dirent with its basename removed.
@@ -242,16 +257,15 @@ svn_dirent_basename(const char *dirent,
  * If @a dirent is root  ("/", "X:/", "//server/share/") or "", it is returned
  * unchanged.
  *
- * The returned dirname will be allocated in @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.6.
  */
 char *
 svn_dirent_dirname(const char *dirent,
-                   apr_pool_t *pool);
+                   apr_pool_t *result_pool);
 
-/** Divide the canonicalized @a dirent into @a *dirpath and @a
- * *base_name, allocated in @a pool.
+/** Divide the canonicalized @a dirent into @a *dirpath and @a *base_name.
  *
  * If @a dirpath or @a base_name is NULL, then don't set that one.
  *
@@ -272,16 +286,17 @@ svn_dirent_dirname(const char *dirent,
  *             - <pre>"X:foo"         ==>  "X:" and "foo"</pre>
  *  Posix:     - <pre>"X:foo"         ==>  ""   and "X:foo"</pre>
  *
+ * Allocate the results in @a result_pool.
+ *
  * @since New in 1.7.
  */
 void
 svn_dirent_split(const char **dirpath,
                  const char **base_name,
                  const char *dirent,
-                 apr_pool_t *pool);
+                 apr_pool_t *result_pool);
 
-/** Divide the canonicalized @a relpath into @a *dirpath and @a
- * *base_name, allocated in @a pool.
+/** Divide the canonicalized @a relpath into @a *dirpath and @a *base_name.
  *
  * If @a dirpath or @a base_name is NULL, then don't set that one.
  *
@@ -296,13 +311,15 @@ svn_dirent_split(const char **dirpath,
  *             - <pre>"bar"          ==>  ""  and "bar"</pre>
  *             - <pre>""              ==>  ""   and ""</pre>
  *
+ * Allocate the results in @a result_pool.
+ *
  * @since New in 1.7.
  */
 void
 svn_relpath_split(const char **dirpath,
                   const char **base_name,
                   const char *relpath,
-                  apr_pool_t *pool);
+                  apr_pool_t *result_pool);
 
 /** Get the basename of the specified canonicalized @a relpath.  The
  * basename is defined as the last component of the relpath.  If the @a
@@ -311,8 +328,8 @@ svn_relpath_split(const char **dirpath,
  *
  * Example: svn_relpath_basename("/trunk/foo/bar") -> "bar"
  *
- * The returned basename will be allocated in @a pool. If @a
- * pool is NULL a pointer to the basename in @a relpath is returned.
+ * If @a result_pool is NULL, return a pointer to the basename in @a relpath,
+ * otherwise allocate the result in @a result_pool.
  *
  * @note If an empty string is passed, then an empty string will be returned.
  *
@@ -320,24 +337,24 @@ svn_relpath_split(const char **dirpath,
  */
 const char *
 svn_relpath_basename(const char *relpath,
-                     apr_pool_t *pool);
+                     apr_pool_t *result_pool);
 
 /** Get the dirname of the specified canonicalized @a relpath, defined as
  * the relpath with its basename removed.
  *
  * If @a relpath is empty, "" is returned.
  *
- * The returned relpath will be allocated in @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.7.
  */
 char *
 svn_relpath_dirname(const char *relpath,
-                    apr_pool_t *pool);
+                    apr_pool_t *result_pool);
 
 
 /** Divide the canonicalized @a uri into a uri @a *dirpath and a
- * (URI-decoded) relpath @a *base_name, allocated in @a pool.
+ * (URI-decoded) relpath @a *base_name.
  *
  * If @a dirpath or @a base_name is NULL, then don't set that one.
  *
@@ -350,28 +367,30 @@ svn_relpath_dirname(const char *relpath,
  * Examples:
  *   - <pre>"http://server/foo/bar"  ==>  "http://server/foo" and "bar"</pre>
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 void
 svn_uri_split(const char **dirpath,
               const char **base_name,
               const char *uri,
-              apr_pool_t *pool);
+              apr_pool_t *result_pool);
 
 /** Get the (URI-decoded) basename of the specified canonicalized @a
  * uri.  The basename is defined as the last component of the uri.  If
- * the @a uri is root then that is returned.  Otherwise, the returned
- * value will have no slashes in it.
+ * the @a uri is root, return "".  The returned value will have no
+ * slashes in it.
  *
  * Example: svn_uri_basename("http://server/foo/bar") -> "bar"
  *
- * The returned basename will be allocated in @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.7.
  */
 const char *
 svn_uri_basename(const char *uri,
-                 apr_pool_t *pool);
+                 apr_pool_t *result_pool);
 
 /** Get the dirname of the specified canonicalized @a uri, defined as
  * the uri with its basename removed.
@@ -379,13 +398,13 @@ svn_uri_basename(const char *uri,
  * If @a uri is root (e.g. "http://server"), it is returned
  * unchanged.
  *
- * The returned dirname will be allocated in @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.7.
  */
 char *
 svn_uri_dirname(const char *uri,
-                apr_pool_t *pool);
+                apr_pool_t *result_pool);
 
 /** Return TRUE if @a dirent is considered absolute on the platform at
  * hand. E.g. '/foo' on Posix platforms or 'X:/foo', '//server/share/foo'
@@ -431,13 +450,13 @@ svn_uri_is_root(const char *uri,
  *
  * and possibly other semantically inoperative transformations.
  *
- * The returned dirent may be allocated statically or from @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.6.
  */
 const char *
 svn_dirent_canonicalize(const char *dirent,
-                        apr_pool_t *pool);
+                        apr_pool_t *result_pool);
 
 
 /** Return a new relpath like @a relpath, but transformed such that some types
@@ -450,13 +469,13 @@ svn_dirent_canonicalize(const char *dire
  *
  * and possibly other semantically inoperative transformations.
  *
- * The returned relpath may be allocated statically or from @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.7.
  */
 const char *
 svn_relpath_canonicalize(const char *relpath,
-                         apr_pool_t *pool);
+                         apr_pool_t *result_pool);
 
 
 /** Return a new uri like @a uri, but transformed such that some types
@@ -474,16 +493,17 @@ svn_relpath_canonicalize(const char *rel
  *
  * and possibly other semantically inoperative transformations.
  *
- * The returned uri may be allocated statically or from @a pool.
+ * Allocate the result in @a result_pool.
  *
  * @since New in 1.7.
  */
 const char *
 svn_uri_canonicalize(const char *uri,
-                     apr_pool_t *pool);
+                     apr_pool_t *result_pool);
 
-/** Return @c TRUE iff @a dirent is canonical.  Use @a pool for temporary
- * allocations.
+/** Return @c TRUE iff @a dirent is canonical.
+ *
+ * Use @a scratch_pool for temporary allocations.
  *
  * @note The test for canonicalization is currently defined as
  * "looks exactly the same as @c svn_dirent_canonicalize() would make
@@ -494,7 +514,7 @@ svn_uri_canonicalize(const char *uri,
  */
 svn_boolean_t
 svn_dirent_is_canonical(const char *dirent,
-                        apr_pool_t *pool);
+                        apr_pool_t *scratch_pool);
 
 /** Return @c TRUE iff @a relpath is canonical.
  *
@@ -504,37 +524,42 @@ svn_dirent_is_canonical(const char *dire
 svn_boolean_t
 svn_relpath_is_canonical(const char *relpath);
 
-/** Return @c TRUE iff @a uri is canonical.  Use @a pool for temporary
- * allocations.
+/** Return @c TRUE iff @a uri is canonical.
+ *
+ * Use @a scratch_pool for temporary allocations.
  *
  * @see svn_uri_canonicalize()
  * @since New in 1.7.
  */
 svn_boolean_t
 svn_uri_is_canonical(const char *uri,
-                     apr_pool_t *pool);
+                     apr_pool_t *scratch_pool);
 
 /** Return the longest common dirent shared by two canonicalized dirents,
  * @a dirent1 and @a dirent2.  If there's no common ancestor, return the
  * empty path.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.6.
  */
 char *
 svn_dirent_get_longest_ancestor(const char *dirent1,
                                 const char *dirent2,
-                                apr_pool_t *pool);
+                                apr_pool_t *result_pool);
 
 /** Return the longest common path shared by two relative paths,
  * @a relpath1 and @a relpath2.  If there's no common ancestor, return the
  * empty path.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 char *
 svn_relpath_get_longest_ancestor(const char *relpath1,
                                  const char *relpath2,
-                                 apr_pool_t *pool);
+                                 apr_pool_t *result_pool);
 
 /** Return the longest common path shared by two canonicalized uris,
  * @a uri1 and @a uri2.  If there's no common ancestor, return the
@@ -544,37 +569,35 @@ svn_relpath_get_longest_ancestor(const c
  * resources), and (b) share a common ancestor in their path
  * component, i.e. 'protocol://' is not a sufficient ancestor.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 char *
 svn_uri_get_longest_ancestor(const char *uri1,
                              const char *uri2,
-                             apr_pool_t *pool);
+                             apr_pool_t *result_pool);
 
 /** Convert @a relative canonicalized dirent to an absolute dirent and
- * return the results in @a *pabsolute, allocated in @a pool.
+ * return the results in @a *pabsolute.
  * Raise SVN_ERR_BAD_FILENAME if the absolute dirent cannot be determined.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.6.
  */
 svn_error_t *
 svn_dirent_get_absolute(const char **pabsolute,
                         const char *relative,
-                        apr_pool_t *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.
- */
-const char *
-svn_uri__is_child(const char *parent_uri,
-                  const char *child_uri,
-                  apr_pool_t *pool);
+                        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.
  *
+ * If @a result_pool is NULL, return a pointer into @a child_dirent, otherwise
+ * allocate the result in @a result_pool.
+ *
  * ### TODO: Deprecate, as the semantics are trivially
  * obtainable from *_skip_ancestor().
  *
@@ -583,7 +606,7 @@ svn_uri__is_child(const char *parent_uri
 const char *
 svn_dirent_is_child(const char *parent_dirent,
                     const char *child_dirent,
-                    apr_pool_t *pool);
+                    apr_pool_t *result_pool);
 
 /** Return TRUE if @a parent_dirent is an ancestor of @a child_dirent or
  * the dirents are equal, and FALSE otherwise.
@@ -633,6 +656,7 @@ svn_relpath_skip_ancestor(const char *pa
 /** Return the URI-decoded relative path of @a child_uri that is below
  * @a parent_uri, or just "" if @a parent_uri is equal to @a child_uri. If
  * @a child_uri is not below or equal to @a parent_uri, return NULL.
+ *
  * Allocate the result in @a result_pool.
  *
  * @since New in 1.7.
@@ -670,8 +694,8 @@ svn_uri_skip_ancestor(const char *parent
  * If there are no items in @a targets, set @a *pcommon and (if
  * applicable) @a *pcondensed_targets to @c NULL.
  *
- * Allocates @a *pcommon and @a *targets in @a result_pool. All
- * intermediate allocations will be performed in @a scratch_pool.
+ * Allocate the results in @a result_pool. Use @a scratch_pool for
+ * temporary allocations.
  *
  * @since New in 1.7.
  */
@@ -711,8 +735,8 @@ svn_dirent_condense_targets(const char *
  * If there are no items in @a targets, set @a *pcommon and (if
  * applicable) @a *pcondensed_targets to @c NULL.
  *
- * Allocate @a *pcommon and @a *targets in @a result_pool. Temporary
- * allocations will be performed in @a scratch_pool.
+ * Allocate the results in @a result_pool. Use @a scratch_pool for
+ * temporary allocations.
  *
  * @since New in 1.7.
  */
@@ -729,12 +753,14 @@ svn_uri_condense_targets(const char **pc
  * it resolves to a path above @a base_path, or if @a path is an absolute
  * path, then set @a *under_root to @c FALSE. Otherwise, set @a *under_root
  * to @c TRUE and, if @a result_path is not @c NULL, set @a *result_path to
- * the resulting path, allocated in @a result_pool.
+ * the resulting path.
  *
  * @a path need not be canonical. @a base_path must be canonical and
  * @a *result_path will be canonical.
  *
- * Note: Use of this function is strongly encouraged. Do not roll your own.
+ * Allocate the result in @a result_pool.
+ *
+ * @note Use of this function is strongly encouraged. Do not roll your own.
  * (http://cve.mitre.org/cgi-bin/cvename.cgi?name=2007-3846)
  *
  * @since New in 1.7.
@@ -749,22 +775,26 @@ svn_dirent_is_under_root(svn_boolean_t *
 /** Set @a *dirent to the path corresponding to the file:// URL @a url, using
  * the platform-specific file:// rules.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 svn_error_t *
 svn_uri_get_dirent_from_file_url(const char **dirent,
                                  const char *url,
-                                 apr_pool_t *pool);
+                                 apr_pool_t *result_pool);
 
 /** Set @a *url to a file:// URL, corresponding to @a dirent using the
  * platform specific dirent and file:// rules.
  *
+ * Allocate the result in @a result_pool.
+ *
  * @since New in 1.7.
  */
 svn_error_t *
 svn_uri_get_file_url_from_dirent(const char **url,
                                  const char *dirent,
-                                 apr_pool_t *pool);
+                                 apr_pool_t *result_pool);
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/file-handle-cache/subversion/include/svn_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/include/svn_editor.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/include/svn_editor.h (original)
+++ subversion/branches/file-handle-cache/subversion/include/svn_editor.h Sun Dec 18 17:36:24 2011
@@ -123,6 +123,11 @@ extern "C" {
 
 /** An abstract object that edits a target tree.
  *
+ * @note The term "follow" means at any later time in the editor drive.
+ * Terms such as "must", "must not", "required", "shall", "shall not",
+ * "should", "should not", "recommended", "may", and "optional" in this
+ * document are to be interpreted as described in RFC 2119.
+ *
  * \n
  * <h3>Life-Cycle</h3>
  *
@@ -236,8 +241,9 @@ extern "C" {
  *   destination of a copy (where these new, copied nodes are subject to
  *   the Once Rule).
  *
- * - The ancestor of an added or modified node may not be deleted. The
- *   ancestor may not be moved (instead: perform the move, *then* the edits).
+ * - The ancestor of an added, copied-here, moved-here or modified node may
+ *   not be deleted. The ancestor may not be moved (instead: perform the
+ *   move, *then* the edits).
  *
  * - svn_editor_delete() must not be used to replace a path -- i.e.
  *   svn_editor_delete() must not be followed by an svn_editor_add_*() on
@@ -336,11 +342,7 @@ extern "C" {
  * context.
  *
  *
- * @todo ### TODO anything missing? -- allow text and prop change to follow
- * a move or copy. -- set_text() vs. apply_text_delta()? -- If a
- * set_props/set_text/set_target/copy/move/delete in a merge source is
- * applied to a different branch, which side will REVISION arguments reflect
- * and is there still a problem?
+ * @todo ### TODO anything missing?
  *
  * @since New in 1.8.
  */
@@ -699,17 +701,8 @@ svn_editor_setcb_many(svn_editor_t *edit
  * Create a new directory at @a relpath. The immediate parent of @a relpath
  * is expected to exist.
  *
- * Set the properties of the new directory to @a props, which is an
- * apr_hash_t holding key-value pairs. Each key is a const char* of a
- * property name, each value is a const svn_string_t*. If no properties are
- * being set on the new directory, @a props must be NULL.
- *
- * If this add is expected to replace a previously existing file or
- * directory at @a relpath, the revision number of the node to be replaced
- * must be given in @a replaces_rev. Otherwise, @a replaces_rev must be
- * SVN_INVALID_REVNUM.  Note: it is not allowed to call a "delete" followed
- * by an "add" on the same path. Instead, an "add" with @a replaces_rev set
- * accordingly MUST be used.
+ * For descriptions of @a props and @a replaces_rev, see
+ * svn_editor_add_file().
  *
  * A complete listing of the immediate children of @a relpath that will be
  * added subsequently is given in @a children. @a children is an array of
@@ -737,7 +730,7 @@ svn_editor_add_directory(svn_editor_t *e
  * property name, each value is a const svn_string_t*. If no properties are
  * being set on the new file, @a props must be NULL.
  *
- * If this add is expected to replace a previously existing file or
+ * If this add is expected to replace a previously existing file, symlink or
  * directory at @a relpath, the revision number of the node to be replaced
  * must be given in @a replaces_rev. Otherwise, @a replaces_rev must be
  * SVN_INVALID_REVNUM.  Note: it is not allowed to call a "delete" followed
@@ -778,6 +771,7 @@ svn_editor_add_symlink(svn_editor_t *edi
  * Create an "absent" node of kind @a kind at @a relpath. The immediate
  * parent of @a relpath is expected to exist.
  * ### TODO @todo explain "absent".
+ * ### JAF: What are the allowed values of 'kind'?
  *
  * For a description of @a replaces_rev, see svn_editor_add_file().
  *
@@ -800,6 +794,8 @@ svn_editor_add_absent(svn_editor_t *edit
  * ### what about "entry props"? will these still be handled via
  * ### the general prop function?
  *
+ * For a description of @a props, see svn_editor_add_file().
+ *
  * @a complete must be FALSE if and only if
  * - @a relpath is a file and an svn_editor_set_text() call will follow on
  *   the same path, or

Modified: subversion/branches/file-handle-cache/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/include/svn_fs.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/include/svn_fs.h (original)
+++ subversion/branches/file-handle-cache/subversion/include/svn_fs.h Sun Dec 18 17:36:24 2011
@@ -309,8 +309,31 @@ svn_fs_delete_fs(const char *path,
  * means deleting copied, unused logfiles for a Berkeley DB source
  * filesystem.
  *
+ * If @a incremental is TRUE, make an effort to not re-copy information
+ * already present in the destination. If incremental hotcopy is not
+ * implemented, raise SVN_ERR_UNSUPPORTED_FEATURE.
+ *
+ * Use @a scratch_pool for temporary allocations.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_fs_hotcopy2(const char *src_path,
+                const char *dest_path,
+                svn_boolean_t clean,
+                svn_boolean_t incremental,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
+                apr_pool_t *scratch_pool);
+
+/**
+ * Like svn_fs_hotcopy2(), but without the @a incremental parameter
+ * and without cancellation support.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  * @since New in 1.1.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_fs_hotcopy(const char *src_path,
                const char *dest_path,

Modified: subversion/branches/file-handle-cache/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/include/svn_ra.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/include/svn_ra.h (original)
+++ subversion/branches/file-handle-cache/subversion/include/svn_ra.h Sun Dec 18 17:36:24 2011
@@ -1406,8 +1406,9 @@ svn_ra_do_diff(svn_ra_session_t *session
  *
  * If @a discover_changed_paths, then each call to @a receiver passes a
  * <tt>const apr_hash_t *</tt> for the receiver's @a changed_paths argument;
- * the hash's keys are all the paths committed in that revision.
- * Otherwise, each call to receiver passes NULL for @a changed_paths.
+ * the hash's keys are all the paths committed in that revision, the hash's
+ * values are <tt>const svn_log_changed_path2_t *</tt> for each committed
+ * path. Otherwise, each call to receiver passes NULL for @a changed_paths.
  *
  * If @a strict_node_history is set, copy history will not be traversed
  * (if any exists) when harvesting the revision logs for each path.

Modified: subversion/branches/file-handle-cache/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/include/svn_repos.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/include/svn_repos.h (original)
+++ subversion/branches/file-handle-cache/subversion/include/svn_repos.h Sun Dec 18 17:36:24 2011
@@ -516,7 +516,29 @@ svn_repos_fs(svn_repos_t *repos);
  * source filesystem as part of the copy operation; currently, this
  * means deleting copied, unused logfiles for a Berkeley DB source
  * repository.
+ *
+ * If @a incremental is TRUE, make an effort to not re-copy information
+ * already present in the destination. If incremental hotcopy is not
+ * implemented by the filesystem backend, raise SVN_ERR_UNSUPPORTED_FEATURE.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_repos_hotcopy2(const char *src_path,
+                   const char *dst_path,
+                   svn_boolean_t clean_logs,
+                   svn_boolean_t incremental,
+                   svn_cancel_func_t cancel_func,
+                   void *cancel_baton,
+                   apr_pool_t *pool);
+
+/** 
+ * Like svn_repos_hotcopy2(), but without the @a incremental parameter
+ * and without cancellation support.
+ *
+ * @deprecated Provided for backward compatibility with the 1.6 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_repos_hotcopy(const char *src_path,
                   const char *dst_path,
@@ -2991,6 +3013,9 @@ svn_repos_authz_read(svn_authz_t **authz
  * to TRUE if at least one path is accessible with the @a
  * required_access.
  *
+ * For compatibility with 1.6, and earlier, @a repos_name can be NULL
+ * in which case it is equivalent to a @a repos_name of "".
+ *
  * @since New in 1.3.
  */
 svn_error_t *

Modified: subversion/branches/file-handle-cache/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/include/svn_wc.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/include/svn_wc.h (original)
+++ subversion/branches/file-handle-cache/subversion/include/svn_wc.h Sun Dec 18 17:36:24 2011
@@ -1354,7 +1354,9 @@ typedef struct svn_wc_notify_t {
    * In all other cases, it is @c NULL.  @since New in 1.5 */
   const char *changelist_name;
 
-  /** When @c action is #svn_wc_notify_merge_begin, and both the
+  /** When @c action is #svn_wc_notify_merge_begin or
+   * #svn_wc_notify_foreign_merge_begin or
+   * #svn_wc_notify_merge_record_info_begin, and both the
    * left and right sides of the merge are from the same URL.  In all
    * other cases, it is @c NULL.  @since New in 1.5 */
   svn_merge_range_t *merge_range;

Modified: subversion/branches/file-handle-cache/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/add.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/add.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/add.c Sun Dec 18 17:36:24 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;
 }
 
@@ -819,6 +809,11 @@ mkdir_urls(const apr_array_header_t *url
       const char *bname;
       svn_uri_split(&common, &bname, common, pool);
       APR_ARRAY_PUSH(targets, const char *) = bname;
+
+      if (*bname == '\0')
+        return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                 _("There is no valid uri above '%s'"),
+                                 common);
     }
   else
     {
@@ -841,6 +836,12 @@ mkdir_urls(const apr_array_header_t *url
           const char *bname;
 
           svn_uri_split(&common, &bname, common, pool);
+
+          if (*bname == '\0')
+             return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                      _("There is no valid uri above '%s'"),
+                                      common);
+
           for (i = 0; i < targets->nelts; i++)
             {
               const char *path = APR_ARRAY_IDX(targets, i, const char *);

Modified: subversion/branches/file-handle-cache/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/cleanup.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/cleanup.c Sun Dec 18 17:36:24 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/file-handle-cache/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/client.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/client.h (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/client.h Sun Dec 18 17:36:24 2011
@@ -105,6 +105,7 @@ svn_error_t *svn_client__get_copy_source
    specify the point(s) of interest (typically the revisions referred
    to as the "operative range" for a given operation) along that history.
 
+   START_REVISION and/or END_REVISION may be NULL if not wanted.
    END may be NULL or of kind svn_opt_revision_unspecified (in either case
    END_URL and END_REVISION are not touched by the function);
    START and REVISION may not.
@@ -131,9 +132,9 @@ svn_error_t *svn_client__get_copy_source
    Use POOL for all allocations.  */
 svn_error_t *
 svn_client__repos_locations(const char **start_url,
-                            svn_opt_revision_t **start_revision,
+                            svn_revnum_t *start_revision,
                             const char **end_url,
-                            svn_opt_revision_t **end_revision,
+                            svn_revnum_t *end_revision,
                             svn_ra_session_t *ra_session,
                             const char *path,
                             const svn_opt_revision_t *revision,
@@ -142,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
@@ -168,19 +185,30 @@ svn_client__repos_location_segments(apr_
                                     apr_pool_t *pool);
 
 
-/* Set *ANCESTOR_PATH and *ANCESTOR_REVISION to the youngest common
-   ancestor path (a path relative to the root of the repository) and
-   revision, respectively, of the two locations identified as
-   PATH_OR_URL1@REV1 and PATH_OR_URL2@REV1.  Use the authentication
-   baton cached in CTX to authenticate against the repository.
-   This function assumes that PATH_OR_URL1@REV1 and PATH_OR_URL2@REV1
-   both refer to the same repository.  Use POOL for all allocations. */
+/* Find the common ancestor of two locations in a repository.
+   Ancestry is determined by the 'copy-from' relationship and the normal
+   successor relationship.
+
+   Set *ANCESTOR_RELPATH, *ANCESTOR_URL, and *ANCESTOR_REVISION to the
+   path (relative to the root of the repository, with no leading '/'),
+   URL, and revision, respectively, of the youngest common ancestor of
+   the two locations URL1@REV1 and URL2@REV2.  Set *ANCESTOR_RELPATH and
+   *ANCESTOR_URL to NULL and *ANCESTOR_REVISION to SVN_INVALID_REVNUM if
+   they have no common ancestor.  This function assumes that URL1@REV1
+   and URL2@REV2 both refer to the same repository.
+
+   Use the authentication baton cached in CTX to authenticate against
+   the repository.  Use POOL for all allocations.
+
+   See also svn_client__youngest_common_ancestor().
+*/
 svn_error_t *
-svn_client__get_youngest_common_ancestor(const char **ancestor_path,
+svn_client__get_youngest_common_ancestor(const char **ancestor_relpath,
+                                         const char **ancestor_url,
                                          svn_revnum_t *ancestor_revision,
-                                         const char *path_or_url1,
+                                         const char *url1,
                                          svn_revnum_t rev1,
-                                         const char *path_or_url2,
+                                         const char *url2,
                                          svn_revnum_t rev2,
                                          svn_client_ctx_t *ctx,
                                          apr_pool_t *pool);
@@ -197,8 +225,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
@@ -249,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
@@ -386,6 +413,19 @@ svn_error_t * svn_client__wc_delete(cons
                                     svn_client_ctx_t *ctx,
                                     apr_pool_t *pool);
 
+
+/* Like svn_client__wc_delete(), but deletes mulitple TARGETS efficiently. */
+svn_error_t *
+svn_client__wc_delete_many(const apr_array_header_t *targets,
+                           svn_boolean_t force,
+                           svn_boolean_t dry_run,
+                           svn_boolean_t keep_local,
+                           svn_wc_notify_func2_t notify_func,
+                           void *notify_baton,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *pool);
+
+
 /* Make PATH and add it to the working copy, optionally making all the
    intermediate parent directories if MAKE_PARENTS is TRUE. */
 svn_error_t *

Modified: subversion/branches/file-handle-cache/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/commit.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/commit.c Sun Dec 18 17:36:24 2011
@@ -145,19 +145,22 @@ send_file_contents(const char *path,
       if (svn_subst_translation_required(eol_style, eol, keywords,
                                          FALSE, TRUE))
         {
-          svn_boolean_t repair = FALSE;
+          if (eol_style == svn_subst_eol_style_unknown)
+            return svn_error_createf(SVN_ERR_IO_UNKNOWN_EOL, NULL,
+                                    _("%s property on '%s' contains "
+                                      "unrecognized EOL-style '%s'"),
+                                    SVN_PROP_EOL_STYLE, path,
+                                    eol_style_val->data);
 
+          /* We're importing, so translate files with 'native' eol-style to
+           * repository-normal form, not to this platform's native EOL. */
           if (eol_style == svn_subst_eol_style_native)
             eol = SVN_SUBST_NATIVE_EOL_STR;
-          else if (eol_style == svn_subst_eol_style_fixed)
-            repair = TRUE;
-          else if (eol_style != svn_subst_eol_style_none)
-            return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);
 
           /* Wrap the working copy stream with a filter to detranslate it. */
           contents = svn_subst_stream_translated(contents,
                                                  eol,
-                                                 repair,
+                                                 TRUE /* repair */,
                                                  keywords,
                                                  FALSE /* expand */,
                                                  pool);
@@ -822,7 +825,7 @@ svn_client_import4(const char *path,
                     ignore_unknown_node_types, ctx, subpool)))
     {
       svn_error_clear(editor->abort_edit(edit_baton, subpool));
-      return err;
+      return svn_error_trace(err);
     }
 
   svn_pool_destroy(subpool);
@@ -901,12 +904,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 +1170,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 +1336,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 +1712,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/file-handle-cache/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/commit_util.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/commit_util.c Sun Dec 18 17:36:24 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/file-handle-cache/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/copy.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/copy.c Sun Dec 18 17:36:24 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);
@@ -795,7 +781,6 @@ repos_to_repos_copy(const apr_array_head
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
       apr_hash_t *mergeinfo;
-      svn_opt_revision_t *src_rev;
 
       /* Are the source and destination URLs at or under REPOS_ROOT? */
       if (! (svn_uri__is_ancestor(repos_root, pair->src_abspath_or_url)
@@ -805,18 +790,11 @@ repos_to_repos_copy(const apr_array_head
            _("Source and destination URLs appear not to point to the "
              "same repository."));
 
-      /* Resolve revision keywords and such into real revision number,
-         passing NULL for the path (to ensure error if trying to get a
-         revision based on the working copy). */
-      SVN_ERR(svn_client__get_revision_number(&pair->src_revnum, &youngest,
-                                              ctx->wc_ctx, NULL,
-                                              ra_session,
-                                              &pair->src_op_revision, pool));
-
-      /* Run the history function to get the source's URL in the
+      /* Run the history function to get the source's URL and revnum in the
          operational revision. */
       SVN_ERR(svn_ra_reparent(ra_session, pair->src_abspath_or_url, pool));
-      SVN_ERR(svn_client__repos_locations(&pair->src_abspath_or_url, &src_rev,
+      SVN_ERR(svn_client__repos_locations(&pair->src_abspath_or_url,
+                                          &pair->src_revnum,
                                           NULL, NULL,
                                           ra_session,
                                           pair->src_abspath_or_url,
@@ -897,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
@@ -921,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
@@ -950,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;
             }
         }
     }
@@ -967,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);
@@ -1021,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)
@@ -1277,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)
@@ -1783,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,
@@ -1817,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. */
@@ -1826,11 +1778,10 @@ repos_to_wc_copy(const apr_array_header_
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
       const char *src;
-      svn_opt_revision_t *new_rev;
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_client__repos_locations(&src, &new_rev, NULL, NULL,
+      SVN_ERR(svn_client__repos_locations(&src, &pair->src_revnum, NULL, NULL,
                                           NULL,
                                           pair->src_abspath_or_url,
                                           &pair->src_peg_revision,
@@ -1857,18 +1808,6 @@ repos_to_wc_copy(const apr_array_header_
                                                NULL, NULL, FALSE, TRUE,
                                                ctx, pool));
 
-  /* Pass null for the path, to ensure error if trying to get a
-     revision based on the working copy.  */
-  for (i = 0; i < copy_pairs->nelts; i++)
-    {
-      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
-                                                    svn_client__copy_pair_t *);
-
-      SVN_ERR(svn_client__get_revision_number(&pair->src_revnum, NULL,
-                                              ctx->wc_ctx, NULL, ra_session,
-                                              &pair->src_op_revision, pool));
-    }
-
   /* Get the correct src path for the peg revision used, and verify that we
      aren't overwriting an existing path. */
   for (i = 0; i < copy_pairs->nelts; i++)
@@ -1930,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/file-handle-cache/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/delete.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/delete.c Sun Dec 18 17:36:24 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,
@@ -272,6 +272,12 @@ delete_urls_multi_repos(const apr_array_
           APR_ARRAY_PUSH(relpaths_list, const char *) = repos_relpath;
         }
 
+      /* Check we identified a non-root relpath.  Return an RA error
+         code for 1.6 compatibility. */
+      if (!repos_relpath || !*repos_relpath)
+        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                                 "URL '%s' not within a repository", uri);
+
       /* Now, test to see if the thing actually exists. */
       SVN_ERR(svn_ra_check_path(ra_session, repos_relpath, SVN_INVALID_REVNUM,
                                 &kind, pool));
@@ -329,29 +335,43 @@ svn_client__wc_delete(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* Callback baton for delete_with_write_lock_baton. */
-struct delete_with_write_lock_baton
-{
-  const char *path;
-  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)
+svn_error_t *
+svn_client__wc_delete_many(const apr_array_header_t *targets,
+                           svn_boolean_t force,
+                           svn_boolean_t dry_run,
+                           svn_boolean_t keep_local,
+                           svn_wc_notify_func2_t notify_func,
+                           void *notify_baton,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *pool)
 {
-  struct delete_with_write_lock_baton *args = baton;
+  int i;
+  apr_array_header_t *abs_targets;
+
+  abs_targets = apr_array_make(pool, targets->nelts, sizeof(const char *));
+  for (i = 0; i < targets->nelts; i++)
+    {
+      const char *path = APR_ARRAY_IDX(targets, i, const char *);
+      const char *local_abspath;
+
+      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+      APR_ARRAY_PUSH(abs_targets, const char *) = local_abspath;
+
+      if (!force && !keep_local)
+        /* Verify that there are no "awkward" files */
+        SVN_ERR(svn_client__can_delete(local_abspath, ctx, pool));
+    }
+
+  if (!dry_run)
+    /* Mark the entry for commit deletion and perform wc deletion */
+    return svn_error_trace(svn_wc__delete_many(ctx->wc_ctx, abs_targets,
+                                               keep_local, TRUE,
+                                               ctx->cancel_func,
+                                               ctx->cancel_baton,
+                                               notify_func, notify_baton,
+                                               pool));
 
-  /* Let the working copy library handle the PATH. */
-  return svn_client__wc_delete(args->path, args->force,
-                               FALSE, args->keep_local,
-                               args->ctx->notify_func2,
-                               args->ctx->notify_baton2,
-                               args->ctx, scratch_pool);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -379,32 +399,75 @@ svn_client_delete4(const apr_array_heade
     }
   else
     {
-      apr_pool_t *subpool = svn_pool_create(pool);
+      const char *local_abspath;
+      apr_hash_t *wcroots;
+      apr_hash_index_t *hi;
       int i;
-
+      int j;
+      apr_pool_t *iterpool;
+      svn_boolean_t is_new_target;
+
+      /* Build a map of wcroots and targets within them. */
+      wcroots = apr_hash_make(pool);
+      iterpool = svn_pool_create(pool);
       for (i = 0; i < paths->nelts; i++)
         {
-          struct delete_with_write_lock_baton dwwlb;
-          const char *path = APR_ARRAY_IDX(paths, i, const char *);
-          const char *local_abspath;
+          const char *wcroot_abspath;
+          apr_array_header_t *targets;
 
-          svn_pool_clear(subpool);
+          svn_pool_clear(iterpool);
 
           /* See if the user wants us to stop. */
           if (ctx->cancel_func)
             SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
-          SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
-          dwwlb.path = path;
-          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,
-                                               local_abspath, TRUE,
-                                               pool, subpool));
+          SVN_ERR(svn_dirent_get_absolute(&local_abspath,
+                                          APR_ARRAY_IDX(paths, i,
+                                                        const char *),
+                                          pool));
+          SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, ctx->wc_ctx,
+                                      local_abspath, pool, iterpool));
+          targets = apr_hash_get(wcroots, wcroot_abspath,
+                                 APR_HASH_KEY_STRING);
+          if (targets == NULL)
+            {
+              targets = apr_array_make(pool, 1, sizeof(const char *));
+              apr_hash_set(wcroots, wcroot_abspath, APR_HASH_KEY_STRING,
+                           targets);
+             }
+
+          /* Make sure targets are unique. */
+          is_new_target = TRUE;
+          for (j = 0; j < targets->nelts; j++)
+            {
+              if (strcmp(APR_ARRAY_IDX(targets, j, const char *),
+                         local_abspath) == 0)
+                {
+                  is_new_target = FALSE;
+                  break;
+                }
+            }
+
+          if (is_new_target)
+            APR_ARRAY_PUSH(targets, const char *) = local_abspath;
+        }
+
+      /* 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);
+
+          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(subpool);
+      svn_pool_destroy(iterpool);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/file-handle-cache/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_client/deprecated.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_client/deprecated.c Sun Dec 18 17:36:24 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,