You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2010/11/02 18:28:34 UTC

svn commit: r1030136 - in /subversion/trunk/subversion: include/svn_path.h include/svn_wc.h libsvn_client/copy.c libsvn_wc/adm_ops.c

Author: julianfoad
Date: Tue Nov  2 17:28:21 2010
New Revision: 1030136

URL: http://svn.apache.org/viewvc?rev=1030136&view=rev
Log:
Split out from svn_wc_add4() the functionality for integrating a nested
checkout as a scheduled copy.

* subversion/include/svn_wc.h
  (svn_wc__integrate_nested_wc_as_copy): New function.

* subversion/libsvn_wc/adm_ops.c
  (integrate_nested_wc_as_copy): New function, extracted from ...
  (svn_wc_add4): ... here.
  (svn_wc__integrate_nested_wc_as_copy): New function.

* subversion/libsvn_client/copy.c
  (repos_to_wc_copy_single): Use the new function instead of svn_wc_add4().

Modified:
    subversion/trunk/subversion/include/svn_path.h
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_client/copy.c
    subversion/trunk/subversion/libsvn_wc/adm_ops.c

Modified: subversion/trunk/subversion/include/svn_path.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_path.h?rev=1030136&r1=1030135&r2=1030136&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_path.h (original)
+++ subversion/trunk/subversion/include/svn_path.h Tue Nov  2 17:28:21 2010
@@ -243,6 +243,7 @@ svn_path_split(const char *path,
  * directory -- that is, if prepending it as a component to an existing
  * path would result in no meaningful change.
  */
+/* J: For RELPATHs only. Doc should just not say "or ... that is ...". */
 int
 svn_path_is_empty(const char *path);
 
@@ -286,6 +287,7 @@ svn_path_is_canonical(const char *path, 
 /** Return an integer greater than, equal to, or less than 0, according
  * as @a path1 is greater than, equal to, or less than @a path2.
  */
+/* J: Should be per path kind. */
 int
 svn_path_compare_paths(const char *path1, const char *path2);
 
@@ -416,6 +418,7 @@ svn_path_condense_targets(const char **p
  *     between saying "i'm in foo, update bar" and "i'm in foo/bar,
  *     update '.'"
  */
+/* J: Ought to be specific to OSPATHs or URLPATHs. */
 svn_error_t *
 svn_path_remove_redundancies(apr_array_header_t **pcondensed_targets,
                              const apr_array_header_t *targets,
@@ -427,6 +430,7 @@ svn_path_remove_redundancies(apr_array_h
  * absolute, the first component will be a lone dir separator (the
  * root directory).
  */
+/* J: Separate per path kind, or only for RELPATH. */
 apr_array_header_t *
 svn_path_decompose(const char *path, apr_pool_t *pool);
 
@@ -439,6 +443,7 @@ svn_path_decompose(const char *path, apr
  *
  * @since New in 1.5.
  */
+/* J: Per path kind, or only for RELPATH. */
 const char *
 svn_path_compose(const apr_array_header_t *components, apr_pool_t *pool);
 
@@ -458,6 +463,7 @@ svn_path_is_single_path_component(const 
  *
  * @since New in 1.1.
  */
+/* J: Per path kind. */
 svn_boolean_t
 svn_path_is_backpath_present(const char *path);
 
@@ -524,6 +530,7 @@ svn_path_is_ancestor(const char *path1, 
  *
  * @since New in 1.2.
  */
+/* J: Should it check a single component? Start with "/"? */
 svn_error_t *
 svn_path_check_valid(const char *path, apr_pool_t *pool);
 
@@ -535,6 +542,7 @@ svn_path_check_valid(const char *path, a
  */
 
 /** Return TRUE iff @a path looks like a valid absolute URL. */
+/* J: OK as is. */
 svn_boolean_t
 svn_path_is_url(const char *path);
 
@@ -545,10 +553,12 @@ svn_path_is_uri_safe(const char *path);
 /** Return a URI-encoded copy of @a path, allocated in @a pool.  (@a
     path can be an arbitrary UTF-8 string and does not have to be a
     canonical path.) */
+/* J: Input must be valid URL/URI syntax, as it is parsed. */
 const char *
 svn_path_uri_encode(const char *path, apr_pool_t *pool);
 
 /** Return a URI-decoded copy of @a path, allocated in @a pool. */
+/* J: OK as is. */
 const char *
 svn_path_uri_decode(const char *path, apr_pool_t *pool);
 
@@ -579,6 +589,7 @@ svn_path_uri_decode(const char *path, ap
  *
  * @since New in 1.6.
  */
+/* J: Replace "component" by "RELPATH". Another API can join 2 URLs. */
 const char *
 svn_path_url_add_component2(const char *url,
                             const char *component,
@@ -627,12 +638,14 @@ svn_path_uri_autoescape(const char *uri,
  */
 
 /** Convert @a path_utf8 from UTF-8 to the internal encoding used by APR. */
+/* J: OSPATH only. */
 svn_error_t *
 svn_path_cstring_from_utf8(const char **path_apr,
                            const char *path_utf8,
                            apr_pool_t *pool);
 
 /** Convert @a path_apr from the internal encoding used by APR to UTF-8. */
+/* J: OSPATH only. */
 svn_error_t *
 svn_path_cstring_to_utf8(const char **path_utf8,
                          const char *path_apr,

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1030136&r1=1030135&r2=1030136&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Tue Nov  2 17:28:21 2010
@@ -4222,7 +4222,7 @@ svn_wc_delete(const char *path,
  * If @a local_abspath does not exist as file, directory or symlink, return
  * #SVN_ERR_WC_PATH_NOT_FOUND.
  *
- * This is equivalent to svn_wc_add4() case 2a.
+ * This is a replacement for svn_wc_add4() case 2a.
  *
  * ### TODO: Allow the caller to provide the node's properties?
  *
@@ -4236,6 +4236,28 @@ svn_wc_add_from_disk(svn_wc_context_t *w
                      apr_pool_t *scratch_pool);
 
 /**
+ * Convert the nested pristine working copy rooted at @a local_abspath into
+ * a copied subtree in the outer working copy.
+ *
+ * @a local_abspath must be the root of a nested working copy that has no
+ * local modifications.  The parent directory of @a local_abspath must be a
+ * versioned directory in the outer WC, and must belong to the same
+ * repository as the nested WC.  The nested WC will be integrated into the
+ * parent's WC, and will no longer be a separate WC.
+ *
+ * Call @a notify_func (if it is not @c NULL) with the @a notify_baton and
+ * the path.
+ *
+ * This is a replacement for svn_wc_add4() case 1.
+ */
+svn_error_t *
+svn_wc__integrate_nested_wc_as_copy(svn_wc_context_t *wc_ctx,
+                                    const char *local_abspath,
+                                    svn_wc_notify_func2_t notify_func,
+                                    void *notify_baton,
+                                    apr_pool_t *scratch_pool);
+
+/**
  * Put @a local_abspath under version control by registering it as addition
  * or copy in the database containing its parent. The new node is scheduled
  * for addition to the repository below its parent node.
@@ -4272,6 +4294,9 @@ svn_wc_add_from_disk(svn_wc_context_t *w
  * When the @a local_abspath has been added, then @a notify_func will be
  * called (if it is not @c NULL) with the @a notify_baton and the path.
  *
+ * @note For case 1, prefer svn_wc__integrate_nested_wc_as_copy().
+ * @note For case 2a, prefer svn_wc_add_from_disk().
+ *
  * @since New in 1.7.
  */
 svn_error_t *

Modified: subversion/trunk/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy.c?rev=1030136&r1=1030135&r2=1030136&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy.c Tue Nov  2 17:28:21 2010
@@ -1449,10 +1449,10 @@ repos_to_wc_copy_single(svn_client__copy
           /* Schedule dst_path for addition in parent, with copy history.
              (This function also recursively puts a 'copied' flag on every
              entry). */
-          SVN_ERR(svn_wc_add4(ctx->wc_ctx, dst_abspath, svn_depth_infinity,
-                              pair->src_abspath_or_url, pair->src_revnum,
-                              ctx->cancel_func, ctx->cancel_baton,
-                              ctx->notify_func2, ctx->notify_baton2, pool));
+          SVN_ERR(svn_wc__integrate_nested_wc_as_copy(ctx->wc_ctx, dst_abspath,
+                                                      ctx->notify_func2,
+                                                      ctx->notify_baton2,
+                                                      pool));
 
           /* ### Recording of implied mergeinfo should really occur
              ### *before* the notification callback is invoked by

Modified: subversion/trunk/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_ops.c?rev=1030136&r1=1030135&r2=1030136&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_ops.c Tue Nov  2 17:28:21 2010
@@ -953,6 +953,68 @@ check_can_add_node(svn_node_kind_t *kind
   return SVN_NO_ERROR;
 }
 
+/* Convert the nested pristine working copy rooted at LOCAL_ABSPATH into
+ * a copied subtree in the outer working copy.
+ *
+ * LOCAL_ABSPATH must be the root of a nested working copy that has no
+ * local modifications.  The parent directory of LOCAL_ABSPATH must be a
+ * versioned directory in the outer WC, and must belong to the same
+ * repository as the nested WC.  The nested WC will be integrated into the
+ * parent's WC, and will no longer be a separate WC. */
+static svn_error_t *
+integrate_nested_wc_as_copy(svn_wc_context_t *wc_ctx,
+                            const char *local_abspath,
+                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_t *db = wc_ctx->db;
+  const char *moved_abspath;
+
+  /* Drop any references to the wc that is to be rewritten */
+  SVN_ERR(svn_wc__db_drop_root(db, local_abspath, scratch_pool));
+
+  /* Move the admin dir from the wc to a temporary location: MOVED_ABSPATH */
+  {
+    const char *tmpdir_abspath, *moved_adm_abspath, *adm_abspath;
+
+    SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, db,
+                                           svn_dirent_dirname(local_abspath,
+                                                              scratch_pool),
+                                           scratch_pool, scratch_pool));
+    SVN_ERR(svn_io_open_unique_file3(NULL, &moved_abspath, tmpdir_abspath,
+                                     svn_io_file_del_on_close,
+                                     scratch_pool, scratch_pool));
+    SVN_ERR(svn_io_dir_make(moved_abspath, APR_OS_DEFAULT, scratch_pool));
+
+    adm_abspath = svn_wc__adm_child(local_abspath, "", scratch_pool);
+    moved_adm_abspath = svn_wc__adm_child(moved_abspath, "", scratch_pool);
+    SVN_ERR(svn_io_file_move(adm_abspath, moved_adm_abspath, scratch_pool));
+  }
+
+  /* Copy entries from temporary location into the main db */
+  SVN_ERR(svn_wc_copy3(wc_ctx, moved_abspath, local_abspath,
+                       TRUE /* metadata_only */,
+                       NULL, NULL, NULL, NULL, scratch_pool));
+
+  /* Cleanup the temporary admin dir */
+  SVN_ERR(svn_wc__db_drop_root(db, moved_abspath, scratch_pool));
+  SVN_ERR(svn_io_remove_dir2(moved_abspath, FALSE, NULL, NULL,
+                             scratch_pool));
+
+  /* The subdir is now part of our parent working copy. Our caller assumes
+     that we return the new node locked, so obtain a lock if we didn't
+     receive the lock via our depth infinity lock */
+  {
+    svn_boolean_t owns_lock;
+    SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, local_abspath,
+                                        FALSE, scratch_pool));
+    if (!owns_lock)
+      SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
+                                       scratch_pool));
+  }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc_add4(svn_wc_context_t *wc_ctx,
             const char *local_abspath,
@@ -1083,50 +1145,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
     }
   else  /* Case 1: Integrating a separate WC into this one, in place */
     {
-      const char *moved_abspath;
-
-      /* Drop any references to the wc that is to be rewritten */
-      SVN_ERR(svn_wc__db_drop_root(db, local_abspath, scratch_pool));
-
-      /* Move the admin dir from the wc to a temporary location: MOVED_ABSPATH */
-      {
-        const char *tmpdir_abspath, *moved_adm_abspath, *adm_abspath;
-
-        SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, db,
-                                               svn_dirent_dirname(local_abspath,
-                                                                  scratch_pool),
-                                               scratch_pool, scratch_pool));
-        SVN_ERR(svn_io_open_unique_file3(NULL, &moved_abspath, tmpdir_abspath,
-                                         svn_io_file_del_on_close,
-                                         scratch_pool, scratch_pool));
-        SVN_ERR(svn_io_dir_make(moved_abspath, APR_OS_DEFAULT, scratch_pool));
-
-        adm_abspath = svn_wc__adm_child(local_abspath, "", scratch_pool);
-        moved_adm_abspath = svn_wc__adm_child(moved_abspath, "", scratch_pool);
-        SVN_ERR(svn_io_file_move(adm_abspath, moved_adm_abspath, scratch_pool));
-      }
-
-      /* Copy entries from temporary location into the main db */
-      SVN_ERR(svn_wc_copy3(wc_ctx, moved_abspath, local_abspath,
-                           TRUE /* metadata_only */,
-                           NULL, NULL, NULL, NULL, scratch_pool));
-
-      /* Cleanup the temporary admin dir */
-      SVN_ERR(svn_wc__db_drop_root(db, moved_abspath, scratch_pool));
-      SVN_ERR(svn_io_remove_dir2(moved_abspath, FALSE, NULL, NULL,
-                                 scratch_pool));
-
-      /* The subdir is now part of our parent working copy. Our caller assumes
-         that we return the new node locked, so obtain a lock if we didn't
-         receive the lock via our depth infinity lock */
-      {
-        svn_boolean_t owns_lock;
-        SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, local_abspath,
-                                            FALSE, scratch_pool));
-        if (!owns_lock)
-          SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
-                                           scratch_pool));
-      }
+      SVN_ERR(integrate_nested_wc_as_copy(wc_ctx, local_abspath,
+                                          scratch_pool));
     }
 
   /* Report the addition to the caller. */
@@ -1143,6 +1163,45 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
 }
 
 svn_error_t *
+svn_wc__integrate_nested_wc_as_copy(svn_wc_context_t *wc_ctx,
+                                    const char *local_abspath,
+                                    svn_wc_notify_func2_t notify_func,
+                                    void *notify_baton,
+                                    apr_pool_t *scratch_pool)
+{
+  svn_wc__db_t *db = wc_ctx->db;
+  svn_boolean_t is_wc_root;
+
+  /* Precondition: LOCAL_ABSPATH is the root of a separate WC. */
+  SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
+                                db, local_abspath, scratch_pool));
+  if (! is_wc_root)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                             _("'%s' is not a WC root"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+
+  /* Precondition: parent(LOCAL_ABSPATH) is a versioned directory in an
+   * acceptable state. */
+  SVN_ERR(check_can_add_to_parent(NULL, NULL, wc_ctx, local_abspath,
+                                  scratch_pool, scratch_pool));
+
+  SVN_ERR(integrate_nested_wc_as_copy(wc_ctx, local_abspath, scratch_pool));
+
+  /* Report the addition to the caller. */
+  if (notify_func != NULL)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(local_abspath, svn_wc_notify_add, scratch_pool);
+
+      notify->kind = svn_node_dir;
+      (*notify_func)(notify_baton, notify, scratch_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_wc_add_from_disk(svn_wc_context_t *wc_ctx,
                      const char *local_abspath,
                      svn_wc_notify_func2_t notify_func,