subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1659395 [2/2] - in /subversion/trunk: ./ contrib/client-side/svncopy/ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ sub...
Date Thu, 12 Feb 2015 20:38:02 GMT
Modified: subversion/trunk/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/externals.c?rev=1659395&r1=1659394&r2=1659395&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/externals.c (original)
+++ subversion/trunk/subversion/libsvn_wc/externals.c Thu Feb 12 20:38:01 2015
@@ -68,6 +68,7 @@
  * the revision if the revision is found.  Set REV_IDX to the index in
  * LINE_PARTS where the revision specification starts.  Remove from
  * LINE_PARTS the element(s) that specify the revision.
+ * Set REV_STR to the element that specifies the revision.
  * PARENT_DIRECTORY_DISPLAY and LINE are given to return a nice error
  * string.
  *
@@ -76,6 +77,7 @@
  */
 static svn_error_t *
 find_and_remove_externals_revision(int *rev_idx,
+                                   const char **rev_str,
                                    const char **line_parts,
                                    int num_line_parts,
                                    svn_wc_external_item2_t *item,
@@ -137,6 +139,8 @@ find_and_remove_externals_revision(int *
             line_parts[j] = line_parts[j+shift_count];
           line_parts[num_line_parts-shift_count] = NULL;
 
+          *rev_str = apr_psprintf(pool, "-r%s", digits_ptr);
+
           /* Found the revision, so leave the function immediately, do
            * not continue looking for additional revisions. */
           return SVN_NO_ERROR;
@@ -158,7 +162,8 @@ find_and_remove_externals_revision(int *
 }
 
 svn_error_t *
-svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
+svn_wc__parse_externals_description(apr_array_header_t **externals_p,
+                                    apr_array_header_t **parser_infos_p,
                                     const char *defining_directory,
                                     const char *desc,
                                     svn_boolean_t canonicalize_url,
@@ -166,6 +171,7 @@ svn_wc_parse_externals_description3(apr_
 {
   int i;
   apr_array_header_t *externals = NULL;
+  apr_array_header_t *parser_infos = NULL;
   apr_array_header_t *lines = svn_cstring_split(desc, "\n\r", TRUE, pool);
   const char *defining_directory_display = svn_path_is_url(defining_directory) ?
     defining_directory : svn_dirent_local_style(defining_directory, pool);
@@ -175,6 +181,10 @@ svn_wc_parse_externals_description3(apr_
   if (externals_p)
     externals = apr_array_make(pool, 1, sizeof(svn_wc_external_item2_t *));
 
+  if (parser_infos_p)
+    parser_infos =
+      apr_array_make(pool, 1, sizeof(svn_wc__externals_parser_info_t *));
+
   for (i = 0; i < lines->nelts; i++)
     {
       const char *line = APR_ARRAY_IDX(lines, i, const char *);
@@ -186,10 +196,12 @@ svn_wc_parse_externals_description3(apr_
       const char *token1;
       svn_boolean_t token0_is_url;
       svn_boolean_t token1_is_url;
+      svn_wc__externals_parser_info_t *info = NULL;
 
       /* Index into line_parts where the revision specification
          started. */
       int rev_idx = -1;
+      const char *rev_str = NULL;
 
       if ((! line) || (line[0] == '#'))
         continue;
@@ -209,6 +221,9 @@ svn_wc_parse_externals_description3(apr_
       item->revision.kind = svn_opt_revision_unspecified;
       item->peg_revision.kind = svn_opt_revision_unspecified;
 
+      if (parser_infos)
+        info = apr_pcalloc(pool, sizeof(*info));
+
       /*
        * There are six different formats of externals:
        *
@@ -240,6 +255,7 @@ svn_wc_parse_externals_description3(apr_
          set item->revision to the parsed revision. */
       /* ### ugh. stupid cast. */
       SVN_ERR(find_and_remove_externals_revision(&rev_idx,
+                                                 &rev_str,
                                                  (const char **)line_parts,
                                                  num_line_parts, item,
                                                  defining_directory_display,
@@ -290,12 +306,34 @@ svn_wc_parse_externals_description3(apr_
           SVN_ERR(svn_opt_parse_path(&item->peg_revision, &item->url,
                                      token0, pool));
           item->target_dir = token1;
+
+          if (info)
+            {
+              info->format = svn_wc__external_description_format_2;
+
+              if (rev_str)
+                info->rev_str = apr_pstrdup(pool, rev_str);
+
+              if (item->peg_revision.kind != svn_opt_revision_unspecified)
+                info->peg_rev_str = strrchr(token0, '@');
+            }
         }
       else
         {
           item->target_dir = token0;
           item->url = token1;
           item->peg_revision = item->revision;
+
+          if (info)
+            {
+              info->format = svn_wc__external_description_format_1;
+
+              if (rev_str)
+                {
+                  info->rev_str = apr_pstrdup(pool, rev_str);
+                  info->peg_rev_str = info->rev_str;
+                }
+            }
         }
 
       SVN_ERR(svn_opt_resolve_revisions(&item->peg_revision,
@@ -333,15 +371,34 @@ svn_wc_parse_externals_description3(apr_
 
       if (externals)
         APR_ARRAY_PUSH(externals, svn_wc_external_item2_t *) = item;
+      if (parser_infos)
+        APR_ARRAY_PUSH(parser_infos, svn_wc__externals_parser_info_t *) = info;
     }
 
   if (externals_p)
     *externals_p = externals;
+  if (parser_infos_p)
+    *parser_infos_p = parser_infos;
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
+svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
+                                    const char *defining_directory,
+                                    const char *desc,
+                                    svn_boolean_t canonicalize_url,
+                                    apr_pool_t *pool)
+{
+  return svn_error_trace(svn_wc__parse_externals_description(externals_p,
+                                                             NULL,
+                                                             defining_directory,
+                                                             desc,
+                                                             canonicalize_url,
+                                                             pool));
+}
+
+svn_error_t *
 svn_wc__externals_find_target_dups(apr_array_header_t **duplicate_targets,
                                    apr_array_header_t *externals,
                                    apr_pool_t *pool,

Modified: subversion/trunk/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1659395&r1=1659394&r2=1659395&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Thu Feb 12 20:38:01 2015
@@ -248,6 +248,7 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t remove_ignored;    /* remove ignored items */
   svn_boolean_t no_newline;        /* do not output the trailing newline */
   svn_boolean_t show_passwords;    /* show cached passwords */
+  svn_boolean_t pin_externals;     /* pin externals to last-changed revisions */
 } svn_cl__opt_state_t;
 
 

Modified: subversion/trunk/subversion/svn/copy-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/copy-cmd.c?rev=1659395&r1=1659394&r2=1659395&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/copy-cmd.c (original)
+++ subversion/trunk/subversion/svn/copy-cmd.c Thu Feb 12 20:38:01 2015
@@ -167,8 +167,10 @@ svn_cl__copy(apr_getopt_t *os,
     SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3), opt_state,
                                        NULL, ctx->config, pool));
 
-  err = svn_client_copy6(sources, dst_path, TRUE,
+  err = svn_client_copy7(sources, dst_path, TRUE,
                          opt_state->parents, opt_state->ignore_externals,
+                         opt_state->pin_externals,
+                         NULL, /* pin all externals */
                          opt_state->revprop_table,
                          (opt_state->quiet ? NULL : svn_cl__print_commit_info),
                          NULL,

Modified: subversion/trunk/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/svn.c?rev=1659395&r1=1659394&r2=1659395&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/svn.c (original)
+++ subversion/trunk/subversion/svn/svn.c Thu Feb 12 20:38:01 2015
@@ -144,7 +144,8 @@ typedef enum svn_cl__longopt_t {
   opt_remove_unversioned,
   opt_remove_ignored,
   opt_no_newline,
-  opt_show_passwords
+  opt_show_passwords,
+  opt_pin_externals,
 } svn_cl__longopt_t;
 
 
@@ -418,6 +419,10 @@ const apr_getopt_option_t svn_cl__option
   {"remove-ignored", opt_remove_ignored, 0, N_("remove ignored items")},
   {"no-newline", opt_no_newline, 0, N_("do not output the trailing newline")},
   {"show-passwords", opt_show_passwords, 0, N_("show cached passwords")},
+  {"pin-externals", opt_pin_externals, 0,
+                       N_("pin externals with no explicit revision to their\n"
+                          "                             "
+                          "current revision (recommended when tagging)")},
 
   /* Long-opt Aliases
    *
@@ -608,7 +613,8 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "  contact the repository.  As such, they may not, by default, be able\n"
      "  to propagate merge tracking information from the source of the copy\n"
      "  to the destination.\n"),
-    {'r', 'q', opt_ignore_externals, opt_parents, SVN_CL__LOG_MSG_OPTIONS} },
+    {'r', 'q', opt_ignore_externals, opt_parents, SVN_CL__LOG_MSG_OPTIONS,
+     opt_pin_externals} },
 
   { "delete", svn_cl__delete, {"del", "remove", "rm"}, N_
     ("Remove files and directories from version control.\n"
@@ -2390,6 +2396,9 @@ sub_main(int *exit_code, int argc, const
       case opt_show_passwords:
         opt_state.show_passwords = TRUE;
         break;
+      case opt_pin_externals:
+        opt_state.pin_externals = TRUE;
+        break;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */

Modified: subversion/trunk/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/externals_tests.py?rev=1659395&r1=1659394&r2=1659395&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/externals_tests.py Thu Feb 12 20:38:01 2015
@@ -3541,6 +3541,339 @@ def replace_tree_with_foreign_external(s
                                         None, None, None, None, None, 1,
                                         '-r', '2', wc_dir)
 
+
+def verify_pinned_externals(sbox, external_url_for, base_path_or_url,
+                            external_youngest_rev, other_external_youngest_rev):
+  "helper for pin-externals tests"
+
+  expected_output = [
+    '%s@%d gamma\n' % (external_url_for["A/B/gamma"],
+                       external_youngest_rev),
+    '\n',
+  ]
+  if svntest.sandbox.is_url(base_path_or_url):
+    target = base_path_or_url + '/A_copy/B'
+  else:
+    target = sbox.ospath('A_copy/B')
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'propget', 'svn:externals',
+                                     target)
+  expected_output = [
+    'exdir_G -r%d %s\n' % (other_external_youngest_rev,
+                           external_url_for["A/C/exdir_G"]),
+    '%s exdir_H\n' % external_url_for["A/C/exdir_H"],
+    '\n',
+  ]
+  if svntest.sandbox.is_url(base_path_or_url):
+    target = base_path_or_url + '/A_copy/C'
+  else:
+    target = sbox.ospath('A_copy/C')
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'propget', 'svn:externals',
+                                     target)
+  expected_output = [
+    '%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),
+    'exdir_A/H -r1 %s\n' % external_url_for["A/D/exdir_A/H"],
+    '%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):
+    target = base_path_or_url + '/A_copy/D'
+  else:
+    target = sbox.ospath('A_copy/D')
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'propget', 'svn:externals',
+                                     target)
+
+
+def copy_pin_externals_repos_repos(sbox):
+  "svn copy --pin-externals repos->repos"
+
+  external_url_for = externals_test_setup(sbox)
+
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_dir = repo_dir + ".other"
+
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+
+  # Perform a repos->repos copy, pinning externals
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     repo_url + '/A',
+                                     repo_url + '/A_copy',
+                                     '-m', 'copy',
+                                     '--pin-externals')
+  verify_pinned_externals(sbox, external_url_for, repo_url,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_repos_wc(sbox):
+  "svn copy --pin-externals repos->wc"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_dir = repo_dir + ".other"
+
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  # Perform a repos->wc copy, pinning externals
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     repo_url + '/A',
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+  verify_pinned_externals(sbox, external_url_for, wc_dir,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_wc_repos(sbox):
+  "svn copy --pin-externals wc->repos"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_dir = repo_dir + ".other"
+
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  # Perform a wc->repos copy, pinning externals
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     repo_url + '/A_copy',
+                                     '-m', 'copy',
+                                     '--pin-externals')
+  verify_pinned_externals(sbox, external_url_for, repo_url,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_wc_wc(sbox):
+  "svn copy --pin-externals wc->wc"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_dir = repo_dir + ".other"
+
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  # Perform a wc->wc copy, pinning externals
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+  verify_pinned_externals(sbox, external_url_for, wc_dir,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_moved_external(sbox):
+  "pin externals which were moved since last changed"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_dir = repo_dir + ".other"
+
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  # Test behaviour for external URLs which were moved since
+  # their last-changed revision.
+  sbox.simple_move('A/D/gamma', 'A/D/gamma-moved')
+  sbox.simple_commit()
+  change_external(sbox.ospath('A/B'), '^/A/D/gamma-moved gamma', commit=True)
+  sbox.simple_update()
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+  external_url_for["A/B/gamma"] = '^/A/D/gamma-moved'
+  verify_pinned_externals(sbox, external_url_for, wc_dir,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_removed_in_head(sbox):
+  "already pinned external which was removed in HEAD"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_url = repo_url + ".other"
+  other_repo_dir = repo_dir + ".other"
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  # Test an already pinned external which was removed in HEAD.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'rm',
+                                     other_repo_url + '/A/D/H',
+                                     '-m', 'remove A/D/H')
+  sbox.simple_update()
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+  verify_pinned_externals(sbox, external_url_for, wc_dir,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_from_old_rev(sbox):
+  "copy from an old revision with pinning"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+  repo_dir       = sbox.repo_dir
+  other_repo_url = repo_url + ".other"
+  other_repo_dir = repo_dir + ".other"
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+  # Create a couple of revisions affecting 'A'.
+  for i in range(5):
+    svntest.main.file_append(sbox.ospath('A/mu'), 'a new line')
+    sbox.simple_commit()
+  sbox.simple_update()
+
+  # Test a copy from an old revision with pinning.
+  external_youngest_rev = svntest.main.youngest(repo_dir)
+  other_external_youngest_rev = svntest.main.youngest(other_repo_dir)
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'copy',
+                                     os.path.join(wc_dir, 'A@6'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+  external_url_for["A/B/gamma"] = '^/A/D/gamma'
+  verify_pinned_externals(sbox, external_url_for, wc_dir,
+                          external_youngest_rev, other_external_youngest_rev)
+
+
+def copy_pin_externals_wc_local_mods(sbox):
+  "cannot pin WC externals with local mods"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  svntest.main.file_append(sbox.ospath('A/C/exdir_G/pi'), 'this file changed')
+  expected_stderr = verify.RegexOutput(".*Cannot pin.*local modifications.*",
+                                       match_all=False)
+  svntest.actions.run_and_verify_svn(None, expected_stderr,
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+
+
+def copy_pin_externals_wc_switched_subtrees(sbox):
+  "cannot pin WC externals with switched subtrees"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'switch', '--ignore-ancestry', '^/A/B',
+                                     sbox.ospath('A/D/exdir_A/C'))
+  expected_stderr = verify.RegexOutput(".*Cannot pin.*switched subtree.*",
+                                       match_all=False)
+  svntest.actions.run_and_verify_svn(None, expected_stderr,
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+
+
+def copy_pin_externals_wc_mixed_revisions(sbox):
+  "cannot pin WC externals with mixed revisions"
+
+  external_url_for = externals_test_setup(sbox)
+
+  wc_dir         = sbox.wc_dir
+  repo_url       = sbox.repo_url
+
+  # Create a working copy.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'checkout',
+                                     repo_url, wc_dir)
+
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'update', '-r1',
+                                     sbox.ospath('A/D/exdir_A/mu'))
+  expected_stderr = verify.RegexOutput(".*Cannot pin.*mixed-revision.*",
+                                       match_all=False)
+  svntest.actions.run_and_verify_svn(None, expected_stderr,
+                                     'copy',
+                                     os.path.join(wc_dir, 'A'),
+                                     os.path.join(wc_dir, 'A_copy'),
+                                     '--pin-externals')
+
+
 def nested_notification(sbox):
   "notification for nested externals"
 
@@ -3638,6 +3971,16 @@ test_list = [ None,
               switch_relative_externals,
               copy_file_external_to_repo,
               replace_tree_with_foreign_external,
+              copy_pin_externals_repos_repos,
+              copy_pin_externals_repos_wc,
+              copy_pin_externals_wc_repos,
+              copy_pin_externals_wc_wc,
+              copy_pin_externals_moved_external,
+              copy_pin_externals_removed_in_head,
+              copy_pin_externals_from_old_rev,
+              copy_pin_externals_wc_local_mods,
+              copy_pin_externals_wc_switched_subtrees,
+              copy_pin_externals_wc_mixed_revisions,
               nested_notification,
              ]
 

Modified: subversion/trunk/subversion/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=1659395&r1=1659394&r2=1659395&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Thu Feb 12 20:38:01 2015
@@ -35,6 +35,8 @@
 #include "svn_repos.h"
 #include "svn_subst.h"
 #include "private/svn_wc_private.h"
+#include "svn_props.h"
+#include "svn_hash.h"
 
 #include "../svn_test.h"
 #include "../svn_test_fs.h"
@@ -1055,6 +1057,236 @@ test_remote_only_status(const svn_test_o
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_copy_pin_externals(const svn_test_opts_t *opts,
+                        apr_pool_t *pool)
+{
+  svn_opt_revision_t rev;
+  svn_opt_revision_t peg_rev;
+  const char *repos_url;
+  const char *A_url;
+  const char *A_copy_url;
+  const char *wc_path;
+  svn_client_ctx_t *ctx;
+  const svn_string_t *propval;
+  apr_hash_t *externals_to_pin;
+  apr_array_header_t *external_items;
+  apr_array_header_t *copy_sources;
+  svn_wc_external_item2_t items[6];
+  svn_client_copy_source_t copy_source;
+  apr_hash_t *props;
+  apr_array_header_t *pinned_externals_descs;
+  apr_array_header_t *pinned_externals;
+  int i;
+  int num_tested_externals;
+  svn_stringbuf_t *externals_test_prop;
+  struct pin_externals_test_data {
+    const char *src_external_desc;
+    const char *expected_dst_external_desc;
+  } pin_externals_test_data[] = {
+    { "^/A/D/gamma B/gamma",    "^/A/D/gamma@2 B/gamma" },
+    { "-r1 ^/A/D/G C/exdir_G",  "-r1 ^/A/D/G C/exdir_G" },
+    { "^/A/D/H@1 C/exdir_H",    "^/A/D/H@1 C/exdir_H"  },
+    { "^/A/D/H C/exdir_H2",     "^/A/D/H@2 C/exdir_H2" },
+    { "-r1 ^/A/B D/z/y/z/blah", "-r1 ^/A/B@2 D/z/y/z/blah" } ,
+    { "-r1 ^/A/D@2 exdir_D", "-r1 ^/A/D@2 exdir_D" },
+    /* Dated revision should retain their date string exactly. */
+    { "-r{1970-01-01T00:00} ^/A/C 70s", "-r{1970-01-01T00:00} ^/A/C@2 70s"}, 
+    { "-r{2004-02-23} ^/svn 1.0", "-r{2004-02-23} ^/svn 1.0"}, 
+    { NULL },
+  };
+
+  /* Create a filesytem and repository containing the Greek tree. */
+  SVN_ERR(create_greek_repos(&repos_url, "pin-externals", opts, pool));
+
+  wc_path = svn_test_data_path("pin-externals-working-copy", pool);
+
+  /* Remove old test data from the previous run */
+  SVN_ERR(svn_io_remove_dir2(wc_path, TRUE, NULL, NULL, pool));
+
+  SVN_ERR(svn_io_make_dir_recursively(wc_path, pool));
+  svn_test_add_dir_cleanup(wc_path);
+
+  rev.kind = svn_opt_revision_head;
+  peg_rev.kind = svn_opt_revision_unspecified;
+  SVN_ERR(svn_client_create_context(&ctx, pool));
+
+  /* Configure some externals on ^/A */
+  i = 0;
+  externals_test_prop = svn_stringbuf_create_empty(pool);
+  while (pin_externals_test_data[i].src_external_desc)
+    {
+      svn_stringbuf_appendcstr(externals_test_prop,
+                               pin_externals_test_data[i].src_external_desc);
+      svn_stringbuf_appendbyte(externals_test_prop, '\n');
+      i++;
+    }
+  propval = svn_string_create_from_buf(externals_test_prop, pool);
+  A_url = apr_pstrcat(pool, repos_url, "/A", SVN_VA_NULL);
+  SVN_ERR(svn_client_propset_remote(SVN_PROP_EXTERNALS, propval,
+                                    A_url, TRUE, 1, NULL,
+                                    NULL, NULL, ctx, pool));
+
+  /* Set up parameters for pinning some externals. */
+  externals_to_pin = apr_hash_make(pool);
+
+  items[0].url = "^/A/D/gamma";
+  items[0].target_dir = "B/gamma";
+  items[1].url = "^/A/B";
+  items[1].target_dir = "D/z/y/z/blah";
+  items[2].url = "^/A/D/H";
+  items[2].target_dir = "C/exdir_H2";
+  items[3].url= "^/A/D";
+  items[3].target_dir= "exdir_D";
+  items[4].url = "^/A/C";
+  items[4].target_dir = "70s";
+  /* Also add an entry which doesn't match any actual definition. */
+  items[5].url = "^/this/does/not/exist";
+  items[5].target_dir = "in/test/data";
+
+  external_items = apr_array_make(pool, 2, sizeof(svn_wc_external_item2_t *));
+  for (i = 0; i < sizeof(items) / sizeof(items[0]); i++)
+    APR_ARRAY_PUSH(external_items, svn_wc_external_item2_t *) = &items[i];
+  svn_hash_sets(externals_to_pin, A_url, external_items);
+
+  /* Copy ^/A to ^/A_copy, pinning two non-pinned externals. */
+  copy_source.path = A_url;
+  copy_source.revision = &rev;
+  copy_source.peg_revision = &peg_rev;
+  copy_sources = apr_array_make(pool, 1, sizeof(svn_client_copy_source_t *));
+  APR_ARRAY_PUSH(copy_sources, svn_client_copy_source_t *) = &copy_source;
+  A_copy_url = apr_pstrcat(pool, repos_url, "/A_copy", SVN_VA_NULL);
+  SVN_ERR(svn_client_copy7(copy_sources, A_copy_url, FALSE, FALSE,
+                           FALSE, TRUE, externals_to_pin,
+                           NULL, NULL, NULL, ctx, pool));
+
+  /* Verify that externals were pinned as expected. */
+  SVN_ERR(svn_client_propget5(&props, NULL, SVN_PROP_EXTERNALS,
+                              A_copy_url, &peg_rev, &rev, NULL,
+                              svn_depth_empty, NULL, ctx, pool, pool));
+  propval = svn_hash_gets(props, A_copy_url);
+  SVN_TEST_ASSERT(propval);
+
+  /* Test the unparsed representation of copied externals descriptions. */
+  pinned_externals_descs = svn_cstring_split(propval->data, "\n", FALSE, pool);
+  for (i = 0; i < pinned_externals_descs->nelts; i++)
+    {
+      const char *externals_desc;
+      const char *expected_desc;
+      
+      externals_desc = APR_ARRAY_IDX(pinned_externals_descs, i, const char *);
+      expected_desc = pin_externals_test_data[i].expected_dst_external_desc;
+      SVN_TEST_STRING_ASSERT(externals_desc, expected_desc);
+    }
+  /* Ensure all test cases were tested. */
+  SVN_TEST_ASSERT(i == (sizeof(pin_externals_test_data) /
+                        sizeof(pin_externals_test_data[0]) - 1));
+  
+  SVN_ERR(svn_wc_parse_externals_description3(&pinned_externals, A_copy_url,
+                                              propval->data, TRUE, pool));
+
+  /* For completeness, test the parsed representation, too */
+  num_tested_externals = 0;
+  for (i = 0; i < pinned_externals->nelts; i++)
+    {
+      svn_wc_external_item2_t *item;
+
+      item = APR_ARRAY_IDX(pinned_externals, i, svn_wc_external_item2_t *);
+      if (strcmp(item->url, "^/A/D/gamma") == 0)
+        {
+          SVN_TEST_STRING_ASSERT(item->target_dir, "B/gamma");
+          /* Pinned to r2. */
+          SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->revision.value.number == 2);
+          SVN_TEST_ASSERT(item->peg_revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->peg_revision.value.number == 2);
+          num_tested_externals++;
+        }
+      else if (strcmp(item->url, "^/A/D/G") == 0)
+        {
+          SVN_TEST_STRING_ASSERT(item->target_dir, "C/exdir_G");
+          /* Not pinned. */
+          SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->revision.value.number == 1);
+          SVN_TEST_ASSERT(item->peg_revision.kind == svn_opt_revision_head);
+          num_tested_externals++;
+        }
+      else if (strcmp(item->url, "^/A/D/H") == 0)
+        {
+          if (strcmp(item->target_dir, "C/exdir_H") == 0)
+            {
+              /* Was already pinned to r1. */
+              SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_number);
+              SVN_TEST_ASSERT(item->revision.value.number == 1);
+              SVN_TEST_ASSERT(item->peg_revision.kind ==
+                              svn_opt_revision_number);
+              SVN_TEST_ASSERT(item->peg_revision.value.number == 1);
+              num_tested_externals++;
+            }
+          else if (strcmp(item->target_dir, "C/exdir_H2") == 0)
+            {
+              /* Pinned to r2. */
+              SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_number);
+              SVN_TEST_ASSERT(item->revision.value.number == 2);
+              SVN_TEST_ASSERT(item->peg_revision.kind ==
+                              svn_opt_revision_number);
+              SVN_TEST_ASSERT(item->peg_revision.value.number == 2);
+              num_tested_externals++;
+            }
+          else
+            SVN_TEST_ASSERT(FALSE); /* unknown external */
+        }
+      else if (strcmp(item->url, "^/A/B") == 0)
+        {
+          SVN_TEST_STRING_ASSERT(item->target_dir, "D/z/y/z/blah");
+          /* Pinned to r2. */
+          SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->revision.value.number == 1);
+          SVN_TEST_ASSERT(item->peg_revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->peg_revision.value.number == 2);
+          num_tested_externals++;
+        }
+      else if (strcmp(item->url, "^/A/D") == 0)
+        {
+          SVN_TEST_STRING_ASSERT(item->target_dir, "exdir_D");
+          /* Pinned to r2. */
+          SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->revision.value.number == 1);
+          SVN_TEST_ASSERT(item->peg_revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->peg_revision.value.number == 2);
+          num_tested_externals++;
+        }
+      else if (strcmp(item->url, "^/A/C") == 0)
+        {
+          SVN_TEST_STRING_ASSERT(item->target_dir, "70s");
+          /* Pinned to r2. */
+          SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_date);
+          /* Don't bother testing the exact date value here. */
+          SVN_TEST_ASSERT(item->peg_revision.kind == svn_opt_revision_number);
+          SVN_TEST_ASSERT(item->peg_revision.value.number == 2);
+          num_tested_externals++;
+        }
+      else if (strcmp(item->url, "^/svn") == 0)
+        {
+          SVN_TEST_STRING_ASSERT(item->target_dir, "1.0");
+          /* Was and not in externals_to_pin, operative revision was a date. */
+          SVN_TEST_ASSERT(item->revision.kind == svn_opt_revision_date);
+          /* Don't bother testing the exact date value here. */
+          SVN_TEST_ASSERT(item->peg_revision.kind == svn_opt_revision_head);
+          num_tested_externals++;
+        }
+      else
+        SVN_TEST_ASSERT(FALSE); /* unknown URL */
+    }
+
+  /* Ensure all test cases were tested. */
+  SVN_TEST_ASSERT(num_tested_externals == (sizeof(pin_externals_test_data) /
+                                           sizeof(pin_externals_test_data[0])
+                                          - 1));
+
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== */
 
 
@@ -1079,6 +1311,8 @@ static struct svn_test_descriptor_t test
                        "test svn_client_suggest_merge_sources"),
     SVN_TEST_OPTS_PASS(test_remote_only_status,
                        "test svn_client_status6 with ignore_local_mods"),
+    SVN_TEST_OPTS_PASS(test_copy_pin_externals,
+                       "test svn_client_copy7 with externals_to_pin"),
     SVN_TEST_NULL
   };
 

Propchange: subversion/trunk/subversion/tests/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Feb 12 20:38:01 2015
@@ -56,6 +56,7 @@
 /subversion/branches/nfc-nfd-aware-client/subversion/tests/libsvn_fs_x:870276,870376
 /subversion/branches/node_pool/subversion/tests/libsvn_fs_x:1304828-1305388
 /subversion/branches/performance/subversion/tests/libsvn_fs_x:979193,980118,981087,981090,981189,981194,981287,981684,981827,982043,982355,983398,983406,983430,983474,983488,983490,983760,983764,983766,983770,984927,984973,984984,985014,985037,985046,985472,985477,985482,985487-985488,985493,985497,985500,985514,985601,985603,985606,985669,985673,985695,985697,986453,986465,986485,986491-986492,986517,986521,986605,986608,986817,986832,987865,987868-987869,987872,987886-987888,987893,988319,988898,990330,990533,990535-990537,990541,990568,990572,990574-990575,990600,990759,992899,992904,992911,993127,993141,994956,995478,995507,995603,998012,998858,999098,1001413,1001417,1004291,1022668,1022670,1022676,1022715,1022719,1025660,1025672,1027193,1027203,1027206,1027214,1027227,1028077,1028092,1028094,1028104,1028107,1028111,1028354,1029038,1029042-1029043,1029054-1029055,1029062-1029063,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029229-1029230,1029232,1029335-10293
 36,1029339-1029340,1029342,1029344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,1033294,1035869,1035882,1039511,1043705,1053735,1056015,1066452,1067683,1067697-1078365
+/subversion/branches/pin-externals/subversion/tests/libsvn_fs_x:1643757-1659392
 /subversion/branches/py-tests-as-modules/subversion/tests/libsvn_fs_x:956579-1033052
 /subversion/branches/ra_serf-digest-authn/subversion/tests/libsvn_fs_x:875693-876404
 /subversion/branches/reintegrate-improvements/subversion/tests/libsvn_fs_x:873853-874164



Mime
View raw message