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

svn commit: r1220893 [3/19] - in /subversion/branches/fs-py: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/ subversion/bindings/javahl/native/ su...

Modified: subversion/branches/fs-py/subversion/libsvn_client/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/blame.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/blame.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/blame.c Mon Dec 19 18:49:34 2011
@@ -592,7 +592,6 @@ svn_client_blame5(const char *target,
 {
   struct file_rev_baton frb;
   svn_ra_session_t *ra_session;
-  const char *url;
   svn_revnum_t start_revnum, end_revnum;
   struct blame *walk, *walk_merged = NULL;
   apr_pool_t *iterpool;
@@ -611,9 +610,8 @@ svn_client_blame5(const char *target,
     SVN_ERR(svn_dirent_get_absolute(&target_abspath_or_url, target, pool));
 
   /* Get an RA plugin for this filesystem object. */
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &end_revnum,
-                                           &url, target, NULL,
-                                           peg_revision, end,
+  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &end_revnum, NULL,
+                                           target, NULL, peg_revision, end,
                                            ctx, pool));
 
   SVN_ERR(svn_client__get_revision_number(&start_revnum, NULL, ctx->wc_ctx,

Modified: subversion/branches/fs-py/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/cleanup.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/cleanup.c Mon Dec 19 18:49:34 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/fs-py/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/client.h?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/client.h (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/client.h Mon Dec 19 18:49:34 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,12 +225,13 @@ 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
-   URL in *URL_P.
+   URL in *URL_P. REV_P and/or URL_P may be NULL if not wanted.
 
    Use authentication baton cached in CTX to authenticate against the
    repository.
@@ -248,30 +277,13 @@ svn_client__ensure_ra_session_url(const 
                                   const char *session_url,
                                   apr_pool_t *pool);
 
-/* Set *REPOS_ROOT and *REPOS_UUID, to the URL and UUID that represent
-   the root of the repository in with ABSPATH_OR_URL is versioned.
-   Use the authentication baton and working copy context cached in CTX as
-   necessary.  REPOS_ROOT and/or REPOS_UUID may be NULL if not wanted.
-
-   Allocate *REPOS_ROOT and *REPOS_UUID in RESULT_POOL.
-   Use SCRATCH_POOL for temporary allocations. */
-svn_error_t *
-svn_client__get_repos_root(const char **repos_root,
-                           const char **repos_uuid,
-                           const char *abspath_or_url,
-                           svn_client_ctx_t *ctx,
-                           apr_pool_t *result_pool,
-                           apr_pool_t *scratch_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
@@ -401,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/fs-py/subversion/libsvn_client/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/cmdline.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/cmdline.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/cmdline.c Mon Dec 19 18:49:34 2011
@@ -114,8 +114,8 @@ check_root_url_of_target(const char **ro
   if (!svn_path_is_url(truepath))
     SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, pool));
 
-  err = svn_client__get_repos_root(&tmp_root_url, NULL, truepath,
-                                   ctx, pool, pool);
+  err = svn_client_get_repos_root(&tmp_root_url, NULL, truepath,
+                                  ctx, pool, pool);
 
   if (err)
     {
@@ -347,7 +347,11 @@ svn_client_args_to_target_array2(apr_arr
        */
       if (root_url == NULL)
         {
-          err = svn_client_root_url_from_path(&root_url, "", ctx, pool);
+          const char *current_abspath;
+
+          SVN_ERR(svn_dirent_get_absolute(&current_abspath, "", pool));
+          err = svn_client_get_repos_root(&root_url, NULL /* uuid */,
+                                          current_abspath, ctx, pool, pool);
           if (err || root_url == NULL)
             return svn_error_create(SVN_ERR_WC_NOT_WORKING_COPY, err,
                                     _("Resolving '^/': no repository root "

Modified: subversion/branches/fs-py/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/commit.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/commit.c Mon Dec 19 18:49:34 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/fs-py/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/commit_util.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/commit_util.c Mon Dec 19 18:49:34 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/fs-py/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/copy.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/copy.c Mon Dec 19 18:49:34 2011
@@ -121,7 +121,7 @@ calculate_target_mergeinfo(svn_ra_sessio
       const char *old_session_url = NULL;
       SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
                                                 ra_session, src_url, pool));
-      SVN_ERR(svn_client__get_repos_mergeinfo(ra_session, &src_mergeinfo,
+      SVN_ERR(svn_client__get_repos_mergeinfo(&src_mergeinfo, ra_session,
                                               "", src_revnum,
                                               svn_mergeinfo_inherited,
                                               TRUE, pool));
@@ -150,7 +150,7 @@ extend_wc_mergeinfo(const char *target_a
 
   /* Combine the provided mergeinfo with any mergeinfo from the WC. */
   if (wc_mergeinfo && mergeinfo)
-    SVN_ERR(svn_mergeinfo_merge(wc_mergeinfo, mergeinfo, pool));
+    SVN_ERR(svn_mergeinfo_merge2(wc_mergeinfo, mergeinfo, pool, pool));
   else if (! wc_mergeinfo)
     wc_mergeinfo = mergeinfo;
 
@@ -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)
@@ -1400,7 +1376,8 @@ wc_to_repos_copy(const apr_array_header_
                                           pair->src_abspath_or_url,
                                           iterpool, iterpool));
       if (wc_mergeinfo && mergeinfo)
-        SVN_ERR(svn_mergeinfo_merge(mergeinfo, wc_mergeinfo, iterpool));
+        SVN_ERR(svn_mergeinfo_merge2(mergeinfo, wc_mergeinfo, iterpool,
+                                     iterpool));
       else if (! mergeinfo)
         mergeinfo = wc_mergeinfo;
       if (mergeinfo)
@@ -1745,8 +1722,9 @@ repos_to_wc_copy_locked(const apr_array_
       parent = top_dst_path;
 
     SVN_ERR(svn_dirent_get_absolute(&parent_abspath, parent, scratch_pool));
-    dst_err = svn_client_uuid_from_path2(&dst_uuid, parent_abspath, ctx,
-                                         scratch_pool, scratch_pool);
+    dst_err = svn_client_get_repos_root(NULL /* root_url */, &dst_uuid,
+                                        parent_abspath, ctx,
+                                        scratch_pool, scratch_pool);
     if (dst_err && dst_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
       return dst_err;
 
@@ -1781,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,
@@ -1815,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. */
@@ -1824,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,
@@ -1855,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++)
@@ -1928,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/fs-py/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/delete.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/delete.c Mon Dec 19 18:49:34 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/fs-py/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/deprecated.c?rev=1220893&r1=1220892&r2=1220893&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/deprecated.c Mon Dec 19 18:49:34 2011
@@ -39,10 +39,12 @@
 #include "svn_props.h"
 #include "svn_utf.h"
 #include "svn_string.h"
+#include "svn_pools.h"
 
 #include "client.h"
 #include "mergeinfo.h"
 
+#include "private/svn_opt_private.h"
 #include "private/svn_wc_private.h"
 #include "svn_private_config.h"
 
@@ -1361,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,
@@ -1576,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,
@@ -2464,6 +2459,41 @@ svn_client_revert(const apr_array_header
 
 /*** From ra.c ***/
 svn_error_t *
+svn_client_uuid_from_url(const char **uuid,
+                         const char *url,
+                         svn_client_ctx_t *ctx,
+                         apr_pool_t *pool)
+{
+  svn_ra_session_t *ra_session;
+  apr_pool_t *subpool = svn_pool_create(pool);
+
+  /* use subpool to create a temporary RA session */
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url,
+                                               NULL, /* no base dir */
+                                               NULL, FALSE, TRUE,
+                                               ctx, subpool));
+
+  SVN_ERR(svn_ra_get_uuid2(ra_session, uuid, pool));
+
+  /* destroy the RA session */
+  svn_pool_destroy(subpool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_uuid_from_path2(const char **uuid,
+                           const char *local_abspath,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+    svn_wc__node_get_repos_info(NULL, uuid, ctx->wc_ctx, local_abspath,
+                                result_pool, scratch_pool));
+}
+
+svn_error_t *
 svn_client_uuid_from_path(const char **uuid,
                           const char *path,
                           svn_wc_adm_access_t *adm_access,
@@ -2479,6 +2509,20 @@ svn_client_uuid_from_path(const char **u
 
 /*** From url.c ***/
 svn_error_t *
+svn_client_root_url_from_path(const char **url,
+                              const char *path_or_url,
+                              svn_client_ctx_t *ctx,
+                              apr_pool_t *pool)
+{
+  if (!svn_path_is_url(path_or_url))
+    SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
+
+  return svn_error_trace(
+           svn_client_get_repos_root(url, NULL, path_or_url,
+                                     ctx, pool, pool));
+}
+
+svn_error_t *
 svn_client_url_from_path(const char **url,
                          const char *path_or_url,
                          apr_pool_t *pool)