subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1100712 - /subversion/trunk/subversion/libsvn_client/externals.c
Date Sun, 08 May 2011 10:29:16 GMT
Author: rhuijben
Date: Sun May  8 10:29:15 2011
New Revision: 1100712

URL: http://svn.apache.org/viewvc?rev=1100712&view=rev
Log:
In preparation for handling file external updates atomicly without the normal
update editor, stop using the standard switch support for switching and
checking out file externals.

* subversion/libsvn_client/externals.c
  (relegate_dir_external_with_write_lock_baton): Remove unneeded baton.
  (relegate_dir_external): Add arguments from baton.

  (switch_dir_external): Assume that the passed path is absolute. Update call
    to relegate_dir_external.
  (switch_file_external): Switch directly instead of delegating to
    svn_client__switch_internal. Stop checking the parent of the file external
    as tree conflict problems would be reported on the file itself.

Modified:
    subversion/trunk/subversion/libsvn_client/externals.c

Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1100712&r1=1100711&r2=1100712&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Sun May  8 10:29:15 2011
@@ -80,17 +80,7 @@ struct handle_external_item_change_baton
   apr_pool_t *iterpool;
 };
 
-
-struct relegate_dir_external_with_write_lock_baton {
-  const char *local_abspath;
-  svn_wc_context_t *wc_ctx;
-  svn_cancel_func_t cancel_func;
-  void *cancel_baton;
-};
-
-/* Note: All arguments are in the baton above.
- *
- * Remove the directory at LOCAL_ABSPATH from revision control, and do the
+/* Remove the directory at LOCAL_ABSPATH from revision control, and do the
  * same to any revision controlled directories underneath LOCAL_ABSPATH
  * (including directories not referred to by parent svn administrative areas);
  * then if LOCAL_ABSPATH is empty afterwards, remove it, else rename it to a
@@ -101,16 +91,17 @@ struct relegate_dir_external_with_write_
  * Use SCRATCH_POOL for all temporary allocation.
  */
 static svn_error_t *
-relegate_dir_external(void *baton,
-                      apr_pool_t *result_pool,
+relegate_dir_external(svn_wc_context_t *wc_ctx,
+                      const char *local_abspath,
+                      svn_cancel_func_t cancel_func,
+                      void *cancel_baton,
                       apr_pool_t *scratch_pool)
 {
-  struct relegate_dir_external_with_write_lock_baton *b = baton;
   svn_error_t *err = SVN_NO_ERROR;
 
-  err = svn_wc_remove_from_revision_control2(b->wc_ctx, b->local_abspath,
+  err = svn_wc_remove_from_revision_control2(wc_ctx, local_abspath,
                                              TRUE, FALSE,
-                                             b->cancel_func, b->cancel_baton,
+                                             cancel_func, cancel_baton,
                                              scratch_pool);
   if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
     {
@@ -121,7 +112,7 @@ relegate_dir_external(void *baton,
       svn_error_clear(err);
       err = SVN_NO_ERROR;
 
-      svn_dirent_split(&parent_dir, &dirname, b->local_abspath, scratch_pool);
+      svn_dirent_split(&parent_dir, &dirname, local_abspath, scratch_pool);
 
       /* Reserve the new dir name. */
       SVN_ERR(svn_io_open_uniquely_named(NULL, &new_path,
@@ -151,7 +142,7 @@ relegate_dir_external(void *baton,
       svn_error_clear(svn_io_remove_file2(new_path, TRUE, scratch_pool));
 
       /* Rename. */
-      SVN_ERR(svn_io_file_rename(b->local_abspath, new_path, scratch_pool));
+      SVN_ERR(svn_io_file_rename(local_abspath, new_path, scratch_pool));
     }
 
   return svn_error_return(err);
@@ -160,7 +151,7 @@ relegate_dir_external(void *baton,
 /* Try to update a directory external at PATH to URL at REVISION.
    Use POOL for temporary allocations, and use the client context CTX. */
 static svn_error_t *
-switch_dir_external(const char *path,
+switch_dir_external(const char *local_abspath,
                     const char *url,
                     const svn_opt_revision_t *revision,
                     const svn_opt_revision_t *peg_revision,
@@ -171,13 +162,12 @@ switch_dir_external(const char *path,
   svn_node_kind_t kind;
   svn_error_t *err;
   apr_pool_t *subpool = svn_pool_create(pool);
-  const char *local_abspath;
 
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   /* If path is a directory, try to update/switch to the correct URL
      and revision. */
-  SVN_ERR(svn_io_check_path(path, &kind, pool));
+  SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
   if (kind == svn_node_dir)
     {
       const char *node_url;
@@ -232,7 +222,8 @@ switch_dir_external(const char *path,
                   SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root,
                                                  subpool));
 
-                  err = svn_client_relocate2(path, repos_root_url, repos_root,
+                  err = svn_client_relocate2(local_abspath, repos_root_url,
+                                             repos_root,
                                              FALSE, ctx, subpool);
                   /* If the relocation failed because the new URL points
                      to another repository, then we need to relegate and
@@ -249,7 +240,7 @@ switch_dir_external(const char *path,
                     return svn_error_return(err);
                 }
 
-              SVN_ERR(svn_client__switch_internal(NULL, path, url,
+              SVN_ERR(svn_client__switch_internal(NULL, local_abspath, url,
                                                   peg_revision, revision,
                                                   svn_depth_infinity,
                                                   TRUE, FALSE, FALSE,
@@ -273,24 +264,19 @@ switch_dir_external(const char *path,
 
   if (kind == svn_node_dir)
     {
-      struct relegate_dir_external_with_write_lock_baton baton;
-
-      baton.local_abspath = local_abspath;
-      baton.wc_ctx = ctx->wc_ctx;
-      baton.cancel_func = ctx->cancel_func;
-      baton.cancel_baton = ctx->cancel_baton;
-
       /* Buh-bye, old and busted ... */
       SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, local_abspath,
                                          FALSE, pool, pool));
 
-      SVN_ERR(relegate_dir_external(&baton, pool, pool));
+      SVN_ERR(relegate_dir_external(ctx->wc_ctx, local_abspath,
+                                    ctx->cancel_func, ctx->cancel_baton,
+                                    pool));
     }
   else
     {
       /* The target dir might have multiple components.  Guarantee
          the path leading down to the last component. */
-      const char *parent = svn_dirent_dirname(path, pool);
+      const char *parent = svn_dirent_dirname(local_abspath, pool);
       SVN_ERR(svn_io_make_dir_recursively(parent, pool));
     }
 
@@ -301,11 +287,11 @@ switch_dir_external(const char *path,
                                        ctx, pool);
 }
 
-/* Try to update a file external at PATH to URL at REVISION using a
-   access baton that has a write lock.  Use POOL for temporary
+/* Try to update a file external at LOCAL_ABSPATH to URL at REVISION using a
+   access baton that has a write lock.  Use SCRATCH_POOL for temporary
    allocations, and use the client context CTX. */
 static svn_error_t *
-switch_file_external(const char *path,
+switch_file_external(const char *local_abspath,
                      const char *url,
                      const svn_opt_revision_t *peg_revision,
                      const svn_opt_revision_t *revision,
@@ -315,37 +301,53 @@ switch_file_external(const char *path,
                      const char *repos_root_url,
                      svn_boolean_t *timestamp_sleep,
                      svn_client_ctx_t *ctx,
-                     apr_pool_t *pool)
+                     apr_pool_t *scratch_pool)
 {
-  apr_pool_t *subpool = svn_pool_create(pool);
-  const char *anchor;
-  const char *anchor_abspath;
-  const char *local_abspath;
+  apr_pool_t *subpool = svn_pool_create(scratch_pool);
+  const char *dir_abspath;
   const char *target;
   svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
                                                  SVN_CONFIG_CATEGORY_CONFIG,
                                                  APR_HASH_KEY_STRING) : NULL;
   svn_boolean_t use_commit_times;
+  const char *diff3_cmd;
+  const char *preserved_exts_str;
+  const apr_array_header_t *preserved_exts;
   svn_boolean_t locked_here;
   svn_error_t *err = NULL;
   svn_node_kind_t kind;
 
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
   /* See if the user wants last-commit timestamps instead of current ones. */
   SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
                               SVN_CONFIG_SECTION_MISCELLANY,
                               SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
 
-  /* There must be a working copy to place the file external into. */
-  SVN_ERR(svn_wc_get_actual_target2(&anchor, &target, ctx->wc_ctx, path,
-                                    subpool, subpool));
-  SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, subpool));
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
+  
+
+  /* Get the external diff3, if any. */
+  svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
+                 SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
+
+  if (diff3_cmd != NULL)
+    SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, subpool));
+
+  /* See which files the user wants to preserve the extension of when
+     conflict files are made. */
+  svn_config_get(cfg, &preserved_exts_str, SVN_CONFIG_SECTION_MISCELLANY,
+                 SVN_CONFIG_OPTION_PRESERVED_CF_EXTS, "");
+  preserved_exts = *preserved_exts_str
+    ? svn_cstring_split(preserved_exts_str, "\n\r\t\v ", FALSE, subpool)
+    : NULL;
+
+  svn_dirent_split(&dir_abspath, &target, local_abspath, subpool);
 
   /* Try to get a access baton for the anchor using the input access
      baton.  If this fails and returns SVN_ERR_WC_NOT_LOCKED, then try
      to get a new access baton to support inserting a file external
      into a directory external. */
-  SVN_ERR(svn_wc_locked2(&locked_here, NULL, ctx->wc_ctx, anchor_abspath,
+  SVN_ERR(svn_wc_locked2(&locked_here, NULL, ctx->wc_ctx, dir_abspath,
                          subpool));
   if (!locked_here)
     {
@@ -354,7 +356,7 @@ switch_file_external(const char *path,
       /* Check that the repository root URL for the newly opened
          wc is the same as the file external. */
       SVN_ERR(svn_client__get_repos_root(&dest_wc_repos_root_url,
-                                         anchor_abspath,
+                                         dir_abspath,
                                          ctx, subpool, subpool));
 
       if (0 != strcmp(repos_root_url, dest_wc_repos_root_url))
@@ -364,7 +366,7 @@ switch_file_external(const char *path,
              "copy from a different repository rooted at '%s'"),
            url, dest_wc_repos_root_url);
 
-      SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, anchor_abspath,
+      SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, dir_abspath,
                                          FALSE, subpool, subpool));
     }
 
@@ -392,41 +394,20 @@ switch_file_external(const char *path,
       if (! file_external)
         {
           if (!locked_here)
-            SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+            SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, dir_abspath,
                                                subpool));
 
           return svn_error_createf(
               SVN_ERR_CLIENT_FILE_EXTERNAL_OVERWRITE_VERSIONED, 0,
              _("The file external from '%s' cannot overwrite the existing "
                "versioned item at '%s'"),
-             url, svn_dirent_local_style(path, pool));
+             url, svn_dirent_local_style(local_abspath, subpool));
         }
     }
   else
     {
-      svn_boolean_t text_conflicted;
-      svn_boolean_t prop_conflicted;
-      svn_boolean_t tree_conflicted;
       svn_node_kind_t disk_kind;
 
-      /* Check for a conflict on the containing directory.  Because a
-         switch is done on the added file later, it will leave a
-         conflict on the directory.  To prevent resolving a conflict
-         due to another change on the directory, do not allow a file
-         external to be added when one exists. */
-      err = svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
-                                 &tree_conflicted, ctx->wc_ctx,
-                                 anchor_abspath, subpool);
-      if (err)
-        goto cleanup;
-
-      if (text_conflicted || prop_conflicted || tree_conflicted)
-        return svn_error_createf
-          (SVN_ERR_WC_FOUND_CONFLICT, 0,
-           _("The file external from '%s' cannot be written to '%s' while "
-             "'%s' remains in conflict"),
-          url, path, anchor);
-
       err = svn_io_check_path(local_abspath, &disk_kind, subpool);
 
       if (err)
@@ -448,30 +429,64 @@ switch_file_external(const char *path,
         goto cleanup;
     }
 
-  err = svn_client__switch_internal(NULL, path, url, peg_revision, revision,
-                                    svn_depth_empty,
-                                    FALSE, /* depth_is_sticky */
-                                    TRUE, /* ignore_externals */
-                                    FALSE, /* allow_unver_obstructions */
-                                    FALSE, /* apply_local_external_mods */
-                                    TRUE, /* ignore_ancestry */
-                                    FALSE, /* innerswitch */
-                                    timestamp_sleep,
-                                    ctx,
-                                    pool);
-  if (err)
-    goto cleanup;
-
-  if (!locked_here)
-    SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, subpool));
-
-  svn_pool_destroy(subpool);
-  return SVN_NO_ERROR;
+  {
+    const svn_ra_reporter3_t *reporter;
+    void *report_baton;
+    const svn_delta_editor_t *switch_editor;
+    void *switch_baton;
+    const char *anchor_url;
+    const char *switch_rev_url;
+    svn_revnum_t revnum;
+
+    SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, dir_abspath,
+                                 subpool, subpool));
+    if (! anchor_url)
+      return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
+                               _("Directory '%s' has no URL"),
+                               svn_dirent_local_style(dir_abspath, subpool));
+
+    /* Open an RA session to 'source' URL */
+    SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
+                                             &switch_rev_url,
+                                             url, dir_abspath,
+                                             peg_revision, revision,
+                                             ctx, subpool));
+
+    SVN_ERR(svn_ra_reparent(ra_session, url, subpool));
+
+    SVN_ERR(svn_wc_get_switch_editor4(&switch_editor, &switch_baton,
+                                      &revnum, ctx->wc_ctx,
+                                      dir_abspath, target,
+                                      switch_rev_url, use_commit_times,
+                                      svn_depth_infinity, FALSE, FALSE, TRUE,
+                                      diff3_cmd, preserved_exts,
+                                      ctx->conflict_func2,
+                                      ctx->conflict_baton2,
+                                      NULL, NULL,
+                                      ctx->cancel_func, ctx->cancel_baton,
+                                      ctx->notify_func2, ctx->notify_baton2,
+                                      subpool, subpool));
+
+    /* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
+     invalid revnum, that means RA will use the latest revision. */
+  SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton, revnum,
+                            target, svn_depth_unknown, url,
+                            switch_editor, switch_baton, subpool));
+
+  SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath,
+                                  reporter, report_baton, 
+                                  TRUE, svn_depth_infinity, FALSE, TRUE,
+                                  use_commit_times,
+                                  NULL, NULL,
+                                  ctx->cancel_func, ctx->cancel_baton,
+                                  ctx->notify_func2, ctx->notify_baton2,
+                                  subpool));
+  }
 
- cleanup:
+cleanup:
   if (!locked_here)
-    svn_error_clear(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
-                                               subpool));
+    err = svn_error_compose_create(err,
+             svn_wc__release_write_lock(ctx->wc_ctx, dir_abspath, subpool));
 
   svn_pool_destroy(subpool);
   return svn_error_return(err);



Mime
View raw message