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

svn commit: r1655872 - in /subversion/branches/pin-externals/subversion: libsvn_client/copy.c tests/cmdline/externals_tests.py

Author: stsp
Date: Thu Jan 29 21:52:36 2015
New Revision: 1655872

URL: http://svn.apache.org/r1655872
Log:
On the pin-externals branch, make WC->WC copies offline operations notI
contact the reposiory even if --pin-externals is active.

Suggested by: brane
              rhuijben

* subversion/libsvn_client/copy.c
  (pin_externals_prop): Rewrite this function such that externals are
   never implicitly pinned with -rN (where N is the last-changed revision).
   A peg revision suffices. If the copy source is a WC determine the peg
   revision of externals from the checked out external (file or dir) and
   error out if the external isn't checked out. Stop resolving -r{DATE}
   style operative and peg revisions to a revision number and pin such
   externals to a dated revision instead.

* subversion/tests/cmdline/externals_tests.py
  (copy_pin_externals): Adjust expected output. Fix a problem in this test
   where some externals were unversioned after a parent directory was moved.
 

Modified:
    subversion/branches/pin-externals/subversion/libsvn_client/copy.c
    subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py

Modified: subversion/branches/pin-externals/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_client/copy.c?rev=1655872&r1=1655871&r2=1655872&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_client/copy.c Thu Jan 29 21:52:36 2015
@@ -179,7 +179,7 @@ get_copy_pair_ancestors(const apr_array_
 
 /* Pin all externals listed in EXTERNALS_PROP_VAL to their last-changed
  * revision. Return a new property value in *PINNED_EXTERNALS allocated
- * in RESULT_POOL. LOCAL_ABSPATH_OR_URL is the path defining the
+ * in RESULT_POOL. LOCAL_ABSPATH_OR_URL is the path or URL defining the
  * svn:externals property. Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
@@ -193,7 +193,6 @@ pin_externals_prop(svn_string_t **pinned
 {
   svn_stringbuf_t *buf;
   apr_array_header_t *external_items;
-  const char *session_url;
   int i;
   apr_pool_t *iterpool;
 
@@ -208,95 +207,110 @@ pin_externals_prop(svn_string_t **pinned
   for (i = 0; i < external_items->nelts; i++)
     {
       svn_wc_external_item2_t *item;
+      svn_opt_revision_t external_pegrev;
       const char *pinned_desc;
-      const char *resolved_url;
-      const char *defining_url;
-      svn_ra_session_t *external_ra_session;
-      svn_revnum_t external_youngest_rev;
-      svn_dirent_t *dirent;
+      const char *rev_str;
+      const char *peg_rev_str;
       
       svn_pool_clear(iterpool);
 
-      if (!svn_path_is_url(local_abspath_or_url))
-        SVN_ERR(svn_wc__node_get_url(&defining_url, ctx->wc_ctx,
-                                     local_abspath_or_url,
-                                     iterpool, iterpool));
-      else
-        defining_url = local_abspath_or_url;
-
       item = APR_ARRAY_IDX(external_items, i, svn_wc_external_item2_t *);
-      SVN_ERR(svn_wc__resolve_relative_external_url(&resolved_url, item,
-                                                    repos_root_url,
-                                                    defining_url,
-                                                    iterpool,
-                                                    iterpool));
-      SVN_ERR(svn_client__open_ra_session_internal(&external_ra_session,
-                                                   NULL, resolved_url,
-                                                   NULL, NULL, FALSE, FALSE,
-                                                   ctx, iterpool,
-                                                   iterpool));
-      SVN_ERR(svn_ra_get_session_url(external_ra_session, &session_url, scratch_pool));
-      if (item->peg_revision.kind == svn_opt_revision_unspecified ||
-          item->peg_revision.kind == svn_opt_revision_head)
+
+      if (item->peg_revision.kind == svn_opt_revision_date)
+        {
+          external_pegrev.kind = svn_opt_revision_date;
+          external_pegrev.value.date = item->peg_revision.value.date;
+        }
+      else if (item->peg_revision.kind == svn_opt_revision_number)
         {
-          SVN_ERR(svn_ra_get_latest_revnum(external_ra_session,
-                                           &external_youngest_rev,
-                                           iterpool));
+          external_pegrev.kind = svn_opt_revision_number;
+          external_pegrev.value.number = item->peg_revision.value.number;
         }
       else
         {
-          if (item->peg_revision.kind == svn_opt_revision_date)
+          SVN_ERR_ASSERT(
+            item->peg_revision.kind == svn_opt_revision_head ||
+            item->peg_revision.kind == svn_opt_revision_unspecified);
+
+          if (svn_path_is_url(local_abspath_or_url))
             {
-              item->peg_revision.kind = svn_opt_revision_number;
-              SVN_ERR(svn_ra_get_dated_revision(external_ra_session,
-                                                &item->peg_revision.value.number,
-                                                item->peg_revision.value.date,
-                                                iterpool));
+              const char *resolved_url;
+              svn_ra_session_t *external_ra_session;
+              svn_revnum_t latest_revnum;
+
+              SVN_ERR(svn_wc__resolve_relative_external_url(
+                        &resolved_url, item, repos_root_url,
+                        local_abspath_or_url, iterpool, iterpool));
+              SVN_ERR(svn_client__open_ra_session_internal(&external_ra_session,
+                                                           NULL, resolved_url,
+                                                           NULL, NULL, FALSE,
+                                                           FALSE, ctx,
+                                                           iterpool,
+                                                           iterpool));
+              SVN_ERR(svn_ra_get_latest_revnum(external_ra_session,
+                                               &latest_revnum,
+                                               iterpool));
+
+              external_pegrev.kind = svn_opt_revision_number;
+              external_pegrev.value.number = latest_revnum;
             }
+          else
+            {
+              const char *external_abspath;
+              svn_node_kind_t external_kind;
 
-          SVN_ERR_ASSERT(item->peg_revision.kind == svn_opt_revision_number);
-          external_youngest_rev = item->peg_revision.value.number;
+              external_abspath = svn_dirent_join(local_abspath_or_url,
+                                                 item->target_dir,
+                                                 iterpool);
+              SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL,
+                                                 NULL, NULL, ctx->wc_ctx,
+                                                 local_abspath_or_url,
+                                                 external_abspath, TRUE,
+                                                 iterpool,
+                                                 iterpool));
+              if (external_kind == svn_node_none)
+                return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+                                         NULL,
+                                         _("Cannot pin external '%s' defined "
+                                           "in %s at '%s' because it is not "
+                                           "checked out in the working copy "
+                                           "at '%s'"),
+                                           item->url, SVN_PROP_EXTERNALS,
+                                           svn_dirent_local_style(
+                                             local_abspath_or_url, iterpool),
+                                           svn_dirent_local_style(
+                                             external_abspath, iterpool));
+
+              external_pegrev.kind = svn_opt_revision_number;
+              SVN_ERR(svn_wc__node_get_repos_info(&external_pegrev.value.number,
+                                                  NULL, NULL, NULL,
+                                                  ctx->wc_ctx, external_abspath,
+                                                  iterpool, iterpool));
+            }
         }
-        
-      SVN_ERR(svn_ra_stat(external_ra_session, "",
-                          external_youngest_rev,
-                          &dirent,
-                          iterpool));
-      if (dirent == NULL)
-        return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
-                                 _("Cannot pin external URL '%s' since it "
-                                   "does not exist at revision %lu"),
-                                 resolved_url, external_youngest_rev);
 
       if (item->revision.kind == svn_opt_revision_date)
-        {
-          item->revision.kind = svn_opt_revision_number;
-          SVN_ERR(svn_ra_get_dated_revision(external_ra_session,
-                                            &item->revision.value.number,
-                                            item->revision.value.date,
-                                            iterpool));
-        }
+        rev_str = apr_psprintf(iterpool, "-r{%s} ",
+                              svn_time_to_cstring(item->revision.value.date,
+                                                  iterpool));
+      else if (item->revision.kind == svn_opt_revision_number)
+        rev_str = apr_psprintf(iterpool, "-r%ld ", item->revision.value.number);
+      else
+        rev_str = "";
 
-      if (item->revision.kind != svn_opt_revision_number)
-        {
-          item->revision.kind = svn_opt_revision_number;
-          item->revision.value.number = dirent->created_rev;
-        }
+      SVN_ERR_ASSERT(external_pegrev.kind == svn_opt_revision_date ||
+                     external_pegrev.kind == svn_opt_revision_number);
+      if (external_pegrev.kind == svn_opt_revision_date)
+        peg_rev_str = apr_psprintf(iterpool, "@{%s}",
+                                   svn_time_to_cstring(
+                                     external_pegrev.value.date,
+                                     iterpool));
+      else
+        peg_rev_str = apr_psprintf(iterpool, "@%ld",
+                                   external_pegrev.value.number);
 
-      if (item->peg_revision.kind != svn_opt_revision_number)
-        {
-          item->peg_revision.kind = svn_opt_revision_number;
-          item->peg_revision.value.number = dirent->created_rev;
-        }
- 
-      SVN_ERR_ASSERT(item->revision.kind == svn_opt_revision_number);
-      SVN_ERR_ASSERT(item->peg_revision.kind == svn_opt_revision_number);
-
-      pinned_desc = apr_psprintf(iterpool, "-r%lu %s@%lu %s\n",
-                                 item->revision.value.number,
-                                 item->url,
-                                 external_youngest_rev,
-                                 item->target_dir);
+      pinned_desc = apr_psprintf(iterpool, "%s%s%s %s\n", rev_str, item->url,
+                                 peg_rev_str, item->target_dir);
       svn_stringbuf_appendcstr(buf, pinned_desc);
     }
   svn_pool_destroy(iterpool);

Modified: subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py?rev=1655872&r1=1655871&r2=1655872&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py Thu Jan 29 21:52:36 2015
@@ -3571,13 +3571,11 @@ def copy_pin_externals(sbox):
 
   # Verify that externals have been pinned.
   last_changed_rev_gamma = 1
-  last_changed_rev_A = 5
   A_copy_D_path = 'A_copy/D'
   def verify_pinned_externals(base_path_or_url):
     expected_output = [
-      '-r%d %s@%d gamma\n' % (last_changed_rev_gamma, 
-                              external_url_for["A/B/gamma"],
-                              external_youngest_rev),
+      '%s@%d gamma\n' % (external_url_for["A/B/gamma"],
+                         external_youngest_rev),
       '\n',
     ]
     if svntest.sandbox.is_url(base_path_or_url):
@@ -3588,8 +3586,8 @@ def copy_pin_externals(sbox):
                                        'propget', 'svn:externals',
                                        target)
     expected_output = [
-      '-r3 %s@%d exdir_G\n' % (external_url_for["A/C/exdir_G"],
-                               other_external_youngest_rev),
+      '%s@%d exdir_G\n' % (external_url_for["A/C/exdir_G"],
+                           other_external_youngest_rev),
       # Note: A/D/H was last changed in r5, but exdir_H's external
       # definition's URL is already pinned to r1.
       '-r1 %s exdir_H\n' % external_url_for["A/C/exdir_H"],
@@ -3603,14 +3601,13 @@ def copy_pin_externals(sbox):
                                        'propget', 'svn:externals',
                                        target)
     expected_output = [
-      '-r%d %s@%d exdir_A\n' % (last_changed_rev_A,
-                               external_url_for["A/D/exdir_A"],
-                               other_external_youngest_rev),
-      '-r3 %s@%d exdir_A/G\n' % (external_url_for["A/D/exdir_A/G/"],
-                                 other_external_youngest_rev),
+      '%s@%d exdir_A\n' % (external_url_for["A/D/exdir_A"],
+                           other_external_youngest_rev),
+      '%s@%d exdir_A/G\n' % (external_url_for["A/D/exdir_A/G/"],
+                             other_external_youngest_rev),
       '-r1 %s@1 exdir_A/H\n' % external_url_for["A/D/exdir_A/H"],
-      '-r4 %s@%d x/y/z/blah\n' % (external_url_for["A/D/x/y/z/blah"],
-                                  other_external_youngest_rev),
+      '%s@%d x/y/z/blah\n' % (external_url_for["A/D/x/y/z/blah"],
+                              other_external_youngest_rev),
       '\n',
     ]
     if svntest.sandbox.is_url(base_path_or_url):
@@ -3663,6 +3660,7 @@ def copy_pin_externals(sbox):
 
   # Perform a wc->wc copy, pinning externals
   external_youngest_rev = svntest.main.youngest(repo_dir)
+  sbox.simple_update()
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'copy',
                                      os.path.join(wc_dir, 'A'),
@@ -3701,7 +3699,10 @@ def copy_pin_externals(sbox):
   sbox.simple_move('A/D', 'A/D-moved')
   change_external(sbox.ospath('A/B'), '^/A/D-moved/gamma-moved gamma', commit=False)
   sbox.simple_commit()
-  sbox.simple_update()
+  # remove externals which are now considered unversioned obstructions...
+  svntest.main.safe_rmtree(sbox.ospath('A/D-moved/exdir_A'))
+  svntest.main.safe_rmtree(sbox.ospath('A/D-moved/x'))
+  sbox.simple_update() # pull above externals back in
   external_youngest_rev = svntest.main.youngest(repo_dir)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'copy',
@@ -3732,7 +3733,6 @@ def copy_pin_externals(sbox):
                                      os.path.join(wc_dir, 'A'),
                                      os.path.join(wc_dir, 'A_copy'),
                                      '--pin-externals')
-  last_changed_rev_A = 6
   verify_pinned_externals(wc_dir)
 
   # Clean up.