You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by jc...@apache.org on 2010/11/21 01:48:26 UTC

svn commit: r1037363 [20/22] - in /subversion/branches/diff-optimizations-bytes: ./ build/ build/generator/ build/generator/templates/ build/win32/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversi...

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/add-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/add-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/add-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/add-cmd.c Sun Nov 21 00:48:20 2010
@@ -71,10 +71,8 @@ svn_cl__add(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
 
   iterpool = svn_pool_create(pool);

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/cat-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/cat-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/cat-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/cat-cmd.c Sun Nov 21 00:48:20 2010
@@ -68,8 +68,8 @@ svn_cl__cat(apr_getopt_t *os,
       SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
 
       /* Get peg revisions. */
-      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
-                                 subpool));
+      SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truepath, target,
+                                     subpool));
 
       SVN_ERR(svn_cl__try(svn_client_cat2(out, truepath, &peg_revision,
                                           &(opt_state->start_revision),

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/changelist-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/changelist-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/changelist-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/changelist-cmd.c Sun Nov 21 00:48:20 2010
@@ -55,9 +55,6 @@ svn_cl__changelist(apr_getopt_t *os,
       apr_array_header_t *args;
       SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
       changelist_name = APR_ARRAY_IDX(args, 0, const char *);
-      if (changelist_name[0] == '\0')
-        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                _("Changelist names must not be empty"));
       SVN_ERR(svn_utf_cstring_to_utf8(&changelist_name,
                                       changelist_name, pool));
     }
@@ -79,10 +76,8 @@ svn_cl__changelist(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
 
   if (opt_state->quiet)

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h Sun Nov 21 00:48:20 2010
@@ -569,6 +569,21 @@ svn_cl__notifier_mark_checkout(void *bat
 svn_error_t *
 svn_cl__notifier_mark_export(void *baton);
 
+/* Baton for use with svn_cl__check_externals_failed_notify_wrapper(). */
+struct svn_cl__check_externals_failed_notify_baton
+{
+  svn_wc_notify_func2_t wrapped_func; /* The "real" notify_func2. */
+  void *wrapped_baton;                /* The "real" notify_func2 baton. */
+  svn_boolean_t had_externals_error;  /* Did something fail in an external? */
+};
+
+/* Notification function wrapper (implements `svn_wc_notify_func2_t').
+   Use with an svn_cl__check_externals_failed_notify_baton BATON. */
+void
+svn_cl__check_externals_failed_notify_wrapper(void *baton,
+                                              const svn_wc_notify_t *n,
+                                              apr_pool_t *pool);
+
 /* Print conflict stats accumulated in NOTIFY_BATON.
  * Return any error encountered during printing.
  * Do all allocations in POOL.*/
@@ -795,6 +810,13 @@ svn_cl__eat_peg_revisions(apr_array_head
                           const apr_array_header_t *targets,
                           apr_pool_t *pool);
 
+/* Like svn_opt_parse_path(), but canonicalizes dirent/URL */
+svn_error_t *
+svn_cl__opt_parse_path(svn_opt_revision_t *rev,
+                       const char **truepath,
+                       const char *path,
+                       apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/cleanup-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/cleanup-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/cleanup-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/cleanup-cmd.c Sun Nov 21 00:48:20 2010
@@ -64,10 +64,8 @@ svn_cl__cleanup(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/conflict-callbacks.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/conflict-callbacks.c Sun Nov 21 00:48:20 2010
@@ -61,7 +61,7 @@ svn_cl__accept_from_word(const char *wor
 {
   /* Shorthand options are consistent with  svn_cl__conflict_handler(). */
   if (strcmp(word, SVN_CL__ACCEPT_POSTPONE) == 0
-      || strcmp(word, "p") == 0)
+      || strcmp(word, "p") == 0 || strcmp(word, ":-P") == 0)
     return svn_cl__accept_postpone;
   if (strcmp(word, SVN_CL__ACCEPT_BASE) == 0)
     /* ### shorthand? */
@@ -70,22 +70,22 @@ svn_cl__accept_from_word(const char *wor
     /* ### shorthand? */
     return svn_cl__accept_working;
   if (strcmp(word, SVN_CL__ACCEPT_MINE_CONFLICT) == 0
-      || strcmp(word, "mc") == 0)
+      || strcmp(word, "mc") == 0 || strcmp(word, "X-)") == 0)
     return svn_cl__accept_mine_conflict;
   if (strcmp(word, SVN_CL__ACCEPT_THEIRS_CONFLICT) == 0
-      || strcmp(word, "tc") == 0)
+      || strcmp(word, "tc") == 0 || strcmp(word, "X-(") == 0)
     return svn_cl__accept_theirs_conflict;
   if (strcmp(word, SVN_CL__ACCEPT_MINE_FULL) == 0
-      || strcmp(word, "mf") == 0)
+      || strcmp(word, "mf") == 0 || strcmp(word, ":-)") == 0)
     return svn_cl__accept_mine_full;
   if (strcmp(word, SVN_CL__ACCEPT_THEIRS_FULL) == 0
-      || strcmp(word, "tf") == 0)
+      || strcmp(word, "tf") == 0 || strcmp(word, ":-(") == 0)
     return svn_cl__accept_theirs_full;
   if (strcmp(word, SVN_CL__ACCEPT_EDIT) == 0
-      || strcmp(word, "e") == 0)
+      || strcmp(word, "e") == 0 || strcmp(word, ":-E") == 0)
     return svn_cl__accept_edit;
   if (strcmp(word, SVN_CL__ACCEPT_LAUNCH) == 0
-      || strcmp(word, "l") == 0)
+      || strcmp(word, "l") == 0 || strcmp(word, ":-l") == 0)
     return svn_cl__accept_launch;
   /* word is an invalid action. */
   return svn_cl__accept_invalid;
@@ -529,13 +529,13 @@ svn_cl__conflict_handler(svn_wc_conflict
                                           "resolve conflict\n"
                 "  (s)  show all         - show this list\n\n")));
             }
-          else if (strcmp(answer, "p") == 0)
+          else if (strcmp(answer, "p") == 0 || strcmp(answer, ":-P") == 0)
             {
               /* Do nothing, let file be marked conflicted. */
               (*result)->choice = svn_wc_conflict_choose_postpone;
               break;
             }
-          else if (strcmp(answer, "mc") == 0)
+          else if (strcmp(answer, "mc") == 0 || strcmp(answer, "X-)") == 0)
             {
               if (desc->is_binary)
                 {
@@ -559,7 +559,7 @@ svn_cl__conflict_handler(svn_wc_conflict
                 (*result)->save_merged = TRUE;
               break;
             }
-          else if (strcmp(answer, "tc") == 0)
+          else if (strcmp(answer, "tc") == 0 || strcmp(answer, "X-(") == 0)
             {
               if (desc->is_binary)
                 {
@@ -582,14 +582,14 @@ svn_cl__conflict_handler(svn_wc_conflict
                 (*result)->save_merged = TRUE;
               break;
             }
-          else if (strcmp(answer, "mf") == 0)
+          else if (strcmp(answer, "mf") == 0 || strcmp(answer, ":-)") == 0)
             {
               (*result)->choice = svn_wc_conflict_choose_mine_full;
               if (performed_edit)
                 (*result)->save_merged = TRUE;
               break;
             }
-          else if (strcmp(answer, "tf") == 0)
+          else if (strcmp(answer, "tf") == 0 || strcmp(answer, ":-(") == 0)
             {
               (*result)->choice = svn_wc_conflict_choose_theirs_full;
               if (performed_edit)
@@ -637,13 +637,13 @@ svn_cl__conflict_handler(svn_wc_conflict
               SVN_ERR(show_diff(desc, subpool));
               knows_something = TRUE;
             }
-          else if (strcmp(answer, "e") == 0)
+          else if (strcmp(answer, "e") == 0 || strcmp(answer, ":-E") == 0)
             {
               SVN_ERR(open_editor(&performed_edit, desc, b, subpool));
               if (performed_edit)
                 knows_something = TRUE;
             }
-          else if (strcmp(answer, "l") == 0)
+          else if (strcmp(answer, "l") == 0 || strcmp(answer, ":-l") == 0)
             {
               if (desc->kind == svn_wc_conflict_kind_property)
                 {
@@ -729,17 +729,17 @@ svn_cl__conflict_handler(svn_wc_conflict
                 "(overwrite pre-existing item)\n"
                 "  (h)  help        - show this help\n\n")));
             }
-          if (strcmp(answer, "p") == 0)
+          if (strcmp(answer, "p") == 0 || strcmp(answer, ":-P") == 0)
             {
               (*result)->choice = svn_wc_conflict_choose_postpone;
               break;
             }
-          if (strcmp(answer, "mf") == 0)
+          if (strcmp(answer, "mf") == 0 || strcmp(answer, ":-)") == 0)
             {
               (*result)->choice = svn_wc_conflict_choose_mine_full;
               break;
             }
-          if (strcmp(answer, "tf") == 0)
+          if (strcmp(answer, "tf") == 0 || strcmp(answer, ":-(") == 0)
             {
               (*result)->choice = svn_wc_conflict_choose_theirs_full;
               break;

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/export-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/export-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/export-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/export-cmd.c Sun Nov 21 00:48:20 2010
@@ -52,6 +52,7 @@ svn_cl__export(apr_getopt_t *os,
   svn_error_t *err;
   svn_opt_revision_t peg_revision;
   const char *truefrom;
+  struct svn_cl__check_externals_failed_notify_baton nwb;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -85,16 +86,21 @@ svn_cl__export(apr_getopt_t *os,
     }
 
   if (svn_path_is_url(to))
-    return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                              NULL,
-                                              _("'%s' is not a local path"),
-                                              to));
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("'%s' is not a local path"), to);
+
   if (! opt_state->quiet)
     SVN_ERR(svn_cl__notifier_mark_export(ctx->notify_baton2));
 
   if (opt_state->depth == svn_depth_unknown)
     opt_state->depth = svn_depth_infinity;
 
+  nwb.wrapped_func = ctx->notify_func2;
+  nwb.wrapped_baton = ctx->notify_baton2;
+  nwb.had_externals_error = FALSE;
+  ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper;
+  ctx->notify_baton2 = &nwb;
+
   /* Do the export. */
   err = svn_client_export5(NULL, truefrom, to, &peg_revision,
                            &(opt_state->start_revision),
@@ -106,5 +112,10 @@ svn_cl__export(apr_getopt_t *os,
               _("Destination directory exists; please remove "
                 "the directory or use --force to overwrite"));
 
+  if (nwb.had_externals_error)
+    return svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL,
+                            _("Failure occured processing one or more "
+                              "externals definitions"));
+
   return svn_error_return(err);
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/import-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/import-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/import-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/import-cmd.c Sun Nov 21 00:48:20 2010
@@ -101,10 +101,9 @@ svn_cl__import(apr_getopt_t *os,
     }
 
   if (svn_path_is_url(path))
-    return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                              NULL,
-                                              _("'%s' is not a local path"),
-                                              path));
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("'%s' is not a local path"), path);
+
   if (! svn_path_is_url(url))
     return svn_error_createf
       (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/list-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/list-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/list-cmd.c Sun Nov 21 00:48:20 2010
@@ -268,8 +268,8 @@ svn_cl__list(apr_getopt_t *os,
       SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
 
       /* Get peg revisions. */
-      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
-                                 subpool));
+      SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truepath, target,
+                                     subpool));
 
       if (opt_state->xml)
         {

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/log-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/log-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/log-cmd.c Sun Nov 21 00:48:20 2010
@@ -647,12 +647,11 @@ svn_cl__log(apr_getopt_t *os,
           target = APR_ARRAY_IDX(targets, i, const char *);
 
           if (svn_path_is_url(target) || target[0] == '/')
-            return svn_error_return(svn_error_createf(
-                                      SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                      _("Only relative paths can be specified"
-                                        " after a URL for 'svn log', "
-                                        "but '%s' is not a relative path"),
-                                      target));
+            return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                     _("Only relative paths can be specified"
+                                       " after a URL for 'svn log', "
+                                       "but '%s' is not a relative path"),
+                                     target);
         }
     }
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/main.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/main.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/main.c Sun Nov 21 00:48:20 2010
@@ -367,6 +367,7 @@ const apr_getopt_option_t svn_cl__option
   {"iw",            opt_ignore_whitespace, 0, NULL},
   {"idiff",         opt_internal_diff, 0, NULL},
   {"keep-locks",    opt_no_unlock, 0, NULL},
+  {"keep-cl",       opt_keep_changelists, 0, NULL},
 
   {0,               0, 0, 0},
 };
@@ -905,10 +906,14 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "    svn:externals  - A newline separated list of module specifiers,\n"
      "      each of which consists of a URL and a relative directory path,\n"
      "      similar to the syntax of the 'svn checkout' command:\n"
-     "        http://example.com/repos/zag foo/bar\n"
-     "      An optional peg revision may be appended to the URL to pin the\n"
+     "        http://example.com/repos/zig foo/bar\n"
+     "      A revision to check out can optionally be specified to pin the\n"
      "      external to a known revision:\n"
-     "        http://example.com/repos/zig@42 foo\n"
+     "        -r25 http://example.com/repos/zig foo/bar\n"
+     "      To unambiguously identify an element at a path which has been\n"
+     "      deleted (possibly even deleted multiple times in its history),\n"
+     "      an optional peg revision can be appended to the URL:\n"
+     "        -r25 http://example.com/repos/zig@42 foo/bar\n"
      "      Relative URLs are indicated by starting the URL with one\n"
      "      of the following strings:\n"
      "        ../  to the parent directory of the extracted external\n"
@@ -1168,10 +1173,17 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "  are applied to the obstructing path.  Obstructing paths are reported\n"
      "  in the first column with code 'E'.\n"
      "\n"
+     "  If the specified update target is missing from the working copy but its\n"
+     "  immediate parent directory is present, checkout the target into its\n"
+     "  parent directory at the specified depth.  If --parents is specified,\n"
+     "  create any missing parent directories of the target by checking them\n"
+     "  out, too, at depth=empty.\n"
+     "\n"
      "  Use the --set-depth option to set a new working copy depth on the\n"
      "  targets of this operation.\n"),
     {'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_force,
-     opt_ignore_externals, opt_changelist, opt_editor_cmd, opt_accept} },
+     opt_ignore_externals, opt_changelist, opt_editor_cmd, opt_accept,
+     opt_parents} },
 
   { "upgrade", svn_cl__upgrade, {0}, N_
     ("Upgrade the metadata storage format for a working copy.\n"
@@ -1375,17 +1387,24 @@ main(int argc, const char *argv[])
               svn_opt_revision_range_t *range;
               const char *change_str =
                 APR_ARRAY_IDX(change_revs, i, const char *);
+              const char *s = change_str;
+              svn_boolean_t is_negative;
 
-              /* Allow any number of 'r's to prefix a revision number.
-                 ### TODO: Any reason we're not just using opt.c's
-                 ### revision-parsing code here?  Then -c could take
-                 ### "{DATE}" and the special words. */
-              while (*change_str == 'r')
-                change_str++;
-              changeno = changeno_end = strtol(change_str, &end, 10);
-              if (end != change_str && *end == '-')
+              /* Check for a leading minus to allow "-c -r42".
+               * The is_negative flag is used to handle "-c -42" and "-c -r42".
+               * The "-c r-42" case is handled by strtol() returning a
+               * negative number. */
+              is_negative = (*s == '-');
+              if (is_negative)
+                s++;
+
+              /* Allow any number of 'r's to prefix a revision number. */
+              while (*s == 'r')
+                s++;
+              changeno = changeno_end = strtol(s, &end, 10);
+              if (end != s && *end == '-')
                 {
-                  if (changeno < 0)
+                  if (changeno < 0 || is_negative)
                     {
                       err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                               _("Negative number in range (%s)"
@@ -1393,10 +1412,10 @@ main(int argc, const char *argv[])
                                               change_str);
                       return svn_cmdline_handle_exit_error(err, pool, "svn: ");
                     }
-                  change_str = end+1;
-                  while (*change_str == 'r')
-                    change_str++;
-                  changeno_end = strtol(change_str, &end, 10);
+                  s = end + 1;
+                  while (*s == 'r')
+                    s++;
+                  changeno_end = strtol(s, &end, 10);
                 }
               if (end == change_str || *end != '\0')
                 {
@@ -1413,6 +1432,9 @@ main(int argc, const char *argv[])
                   return svn_cmdline_handle_exit_error(err, pool, "svn: ");
                 }
 
+              if (is_negative)
+                changeno = -changeno;
+
               /* Figure out the range:
                     -c N  -> -r N-1:N
                     -c -N -> -r N:N-1

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/notify.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/notify.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/notify.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/notify.c Sun Nov 21 00:48:20 2010
@@ -952,3 +952,18 @@ svn_cl__notifier_mark_export(void *baton
   nb->is_export = TRUE;
   return SVN_NO_ERROR;
 }
+
+void
+svn_cl__check_externals_failed_notify_wrapper(void *baton,
+                                              const svn_wc_notify_t *n,
+                                              apr_pool_t *pool)
+{
+  struct svn_cl__check_externals_failed_notify_baton *nwb = baton;
+
+  if (n->action == svn_wc_notify_failed_external)
+    nwb->had_externals_error = TRUE;
+
+  if (nwb->wrapped_func)
+    nwb->wrapped_func(nwb->wrapped_baton, n, pool);
+}
+

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/patch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/patch-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/patch-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/patch-cmd.c Sun Nov 21 00:48:20 2010
@@ -48,29 +48,42 @@ svn_cl__patch(apr_getopt_t *os,
 {
   svn_cl__opt_state_t *opt_state;
   svn_client_ctx_t *ctx;
-  apr_array_header_t *args;
   apr_array_header_t *targets;
   const char *abs_patch_path;
+  const char *patch_path;
   const char *abs_target_path;
+  const char *target_path;
 
   opt_state = ((svn_cl__cmd_baton_t *)baton)->opt_state;
   ctx = ((svn_cl__cmd_baton_t *)baton)->ctx;
 
-  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
-  SVN_ERR(svn_dirent_get_absolute(&abs_patch_path,
-                                  APR_ARRAY_IDX(args, 0, const char *),
-                                  pool));
-
-  SVN_ERR(svn_client_args_to_target_array(&targets, os, opt_state->targets,
-                                          ctx, pool));
-  if (targets->nelts > 1)
+  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+                                                      opt_state->targets,
+                                                      ctx, pool));
+  SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
+
+  if (targets->nelts > 2)
     return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
 
-  svn_opt_push_implicit_dot_target(targets, pool);
-  SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
-  SVN_ERR(svn_dirent_get_absolute(&abs_target_path,
-                                  APR_ARRAY_IDX(targets, 0, const char *),
-                                  pool));
+  patch_path = APR_ARRAY_IDX(targets, 0, const char *);
+
+  if (svn_path_is_url(patch_path))
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("'%s' is not a local path"), patch_path);
+
+  SVN_ERR(svn_dirent_get_absolute(&abs_patch_path, patch_path, pool));
+
+  if (targets->nelts == 1)
+    target_path = ""; /* "" is the canonical form of "." */
+  else
+    {
+      target_path = APR_ARRAY_IDX(targets, 1, const char *);
+
+      if (svn_path_is_url(target_path))
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target_path);
+    }
+  SVN_ERR(svn_dirent_get_absolute(&abs_target_path, target_path, pool));
 
   SVN_ERR(svn_client_patch(abs_patch_path, abs_target_path,
                            opt_state->dry_run, opt_state->strip,

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/relocate-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/relocate-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/relocate-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/relocate-cmd.c Sun Nov 21 00:48:20 2010
@@ -97,6 +97,16 @@ svn_cl__relocate(apr_getopt_t *os,
           apr_pool_t *subpool = svn_pool_create(scratch_pool);
           int i;
 
+          /* Target working copy root dir must be local. */
+          for (i = 2; i < targets->nelts; i++)
+            {
+              path = APR_ARRAY_IDX(targets, i, const char *);
+              if (svn_path_is_url(path))
+                return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                         _("'%s' is not a local path"),
+                                         path);
+            }
+
           for (i = 2; i < targets->nelts; i++)
             {
               svn_pool_clear(subpool);

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/resolve-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/resolve-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/resolve-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/resolve-cmd.c Sun Nov 21 00:48:20 2010
@@ -101,10 +101,8 @@ svn_cl__resolve(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
   
   iterpool = svn_pool_create(scratch_pool);

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/resolved-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/resolved-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/resolved-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/resolved-cmd.c Sun Nov 21 00:48:20 2010
@@ -71,10 +71,8 @@ svn_cl__resolved(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
   
   iterpool = svn_pool_create(scratch_pool);

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/revert-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/revert-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/revert-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/revert-cmd.c Sun Nov 21 00:48:20 2010
@@ -72,10 +72,8 @@ svn_cl__revert(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
 
   err = svn_client_revert2(targets, opt_state->depth,

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/status-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/status-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/status-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/status-cmd.c Sun Nov 21 00:48:20 2010
@@ -255,10 +255,8 @@ svn_cl__status(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
 
   /* We want our -u statuses to be against HEAD. */

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/switch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/switch-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/switch-cmd.c Sun Nov 21 00:48:20 2010
@@ -101,6 +101,7 @@ svn_cl__switch(apr_getopt_t *os,
   svn_opt_revision_t peg_revision;
   svn_depth_t depth;
   svn_boolean_t depth_is_sticky;
+  struct svn_cl__check_externals_failed_notify_baton nwb;
 
   /* This command should discover (or derive) exactly two cmdline
      arguments: a local path to update ("target"), and a new url to
@@ -143,6 +144,12 @@ svn_cl__switch(apr_getopt_t *os,
       (SVN_ERR_BAD_URL, NULL,
        _("'%s' does not appear to be a URL"), switch_url);
 
+  /* Target path cannot be URL */
+  if (svn_path_is_url(target))
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("'%s' is not a local path"),
+                             target);
+
   /* Canonicalize the URL. */
   switch_url = svn_uri_canonicalize(switch_url, scratch_pool);
 
@@ -158,6 +165,12 @@ svn_cl__switch(apr_getopt_t *os,
       depth_is_sticky = FALSE;
     }
 
+  nwb.wrapped_func = ctx->notify_func2;
+  nwb.wrapped_baton = ctx->notify_baton2;
+  nwb.had_externals_error = FALSE;
+  ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper;
+  ctx->notify_baton2 = &nwb;
+
   /* Do the 'switch' update. */
   SVN_ERR(svn_client_switch2(NULL, target, switch_url, &peg_revision,
                              &(opt_state->start_revision), depth,
@@ -165,7 +178,12 @@ svn_cl__switch(apr_getopt_t *os,
                              opt_state->force, ctx, scratch_pool));
 
   if (! opt_state->quiet)
-    SVN_ERR(svn_cl__print_conflict_stats(ctx->notify_baton2, scratch_pool));
+    SVN_ERR(svn_cl__print_conflict_stats(nwb.wrapped_baton, scratch_pool));
+
+  if (nwb.had_externals_error)
+    return svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL,
+                            _("Failure occured processing one or more "
+                              "externals definitions"));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c Sun Nov 21 00:48:20 2010
@@ -27,6 +27,7 @@
 
 /*** Includes. ***/
 
+#include "svn_path.h"
 #include "svn_pools.h"
 #include "svn_client.h"
 #include "svn_error_codes.h"
@@ -48,6 +49,8 @@ svn_cl__unlock(apr_getopt_t *os,
   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
+  svn_boolean_t wc_present = FALSE, url_present = FALSE;
+  int i;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -59,6 +62,23 @@ svn_cl__unlock(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
 
+  /* Check to see if at least one of our paths is a working copy
+   * path or a repository url. */
+  for (i = 0; i < targets->nelts; ++i)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+      if (! svn_path_is_url(target))
+        wc_present = TRUE;
+      else
+        url_present = TRUE;
+    }
+
+  if (url_present && wc_present)
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("Cannot mix repository and working copy "
+                               "targets"));
+
   return svn_error_return(
     svn_client_unlock(targets, opt_state->force, ctx, scratch_pool));
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c Sun Nov 21 00:48:20 2010
@@ -50,6 +50,7 @@ svn_cl__update(apr_getopt_t *os,
   apr_array_header_t *targets;
   svn_depth_t depth;
   svn_boolean_t depth_is_sticky;
+  struct svn_cl__check_externals_failed_notify_baton nwb;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -85,15 +86,26 @@ svn_cl__update(apr_getopt_t *os,
       depth_is_sticky = FALSE;
     }
 
-  SVN_ERR(svn_client_update3(NULL, targets,
+  nwb.wrapped_func = ctx->notify_func2;
+  nwb.wrapped_baton = ctx->notify_baton2;
+  nwb.had_externals_error = FALSE;
+  ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper;
+  ctx->notify_baton2 = &nwb;
+  
+  SVN_ERR(svn_client_update4(NULL, targets,
                              &(opt_state->start_revision),
                              depth, depth_is_sticky,
                              opt_state->ignore_externals,
-                             opt_state->force,
+                             opt_state->force, opt_state->parents,
                              ctx, scratch_pool));
 
   if (! opt_state->quiet)
-    SVN_ERR(svn_cl__print_conflict_stats(ctx->notify_baton2, scratch_pool));
+    SVN_ERR(svn_cl__print_conflict_stats(nwb.wrapped_baton, scratch_pool));
+
+  if (nwb.had_externals_error)
+    return svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL,
+                            _("Failure occured processing one or more "
+                              "externals definitions"));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/upgrade-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/upgrade-cmd.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/upgrade-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/upgrade-cmd.c Sun Nov 21 00:48:20 2010
@@ -67,10 +67,8 @@ svn_cl__upgrade(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
       if (svn_path_is_url(target))
-        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  target));
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
     }
 
   iterpool = svn_pool_create(scratch_pool);

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/util.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/util.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/util.c Sun Nov 21 00:48:20 2010
@@ -71,8 +71,13 @@ svn_cl__print_commit_info(const svn_comm
                           apr_pool_t *pool)
 {
   if (SVN_IS_VALID_REVNUM(commit_info->revision))
-    SVN_ERR(svn_cmdline_printf(pool, _("\nCommitted revision %ld.\n"),
-                               commit_info->revision));
+    SVN_ERR(svn_cmdline_printf(pool, _("\nCommitted revision %ld%s.\n"),
+                               commit_info->revision,
+                               commit_info->revision == 42 &&
+                               getenv("SVN_I_LOVE_PANGALACTIC_GARGLE_BLASTERS")
+                                 ?  _(" (the answer to life, the universe, "
+                                      "and everything)")
+                                 : ""));
 
   /* Writing to stdout, as there maybe systems that consider the
    * presence of stderr as an indication of commit failure.
@@ -1324,3 +1329,19 @@ svn_cl__eat_peg_revisions(apr_array_head
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_cl__opt_parse_path(svn_opt_revision_t *rev,
+                       const char **truepath,
+                       const char *path /* UTF-8! */,
+                       apr_pool_t *pool)
+{
+  SVN_ERR(svn_opt_parse_path(rev, truepath, path, pool));
+  
+  if (svn_path_is_url(*truepath))
+    *truepath = svn_uri_canonicalize(*truepath, pool);
+  else
+    *truepath = svn_dirent_canonicalize(*truepath, pool);
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c Sun Nov 21 00:48:20 2010
@@ -843,6 +843,8 @@ svn_error_t *
 get_dump_editor(const svn_delta_editor_t **editor,
                 void **edit_baton,
                 svn_stream_t *stream,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
                 apr_pool_t *pool)
 {
   struct dump_edit_baton *eb;
@@ -878,5 +880,7 @@ get_dump_editor(const svn_delta_editor_t
   *edit_baton = eb;
   *editor = de;
 
-  return SVN_NO_ERROR;
+  /* Wrap this editor in a cancellation editor. */
+  return svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
+                                           de, eb, editor, edit_baton, pool);
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.h?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.h Sun Nov 21 00:48:20 2010
@@ -68,12 +68,16 @@ struct handler_baton
 
 /**
  * Get a dump editor @a editor along with a @a edit_baton allocated in
- * @a pool. The editor will write output to @a stream.
+ * @a pool.  The editor will write output to @a stream.  Use @a
+ * cancel_func and @a cancel_baton to check for user cancellation of
+ * the operation (for timely-but-safe termination).
  */
 svn_error_t *
 get_dump_editor(const svn_delta_editor_t **editor,
                 void **edit_baton,
                 svn_stream_t *stream,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
                 apr_pool_t *pool);
 
 /**

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.c Sun Nov 21 00:48:20 2010
@@ -73,6 +73,8 @@ static svn_boolean_t is_atomicity_error(
 static svn_error_t *
 get_lock(const svn_string_t **lock_string_p,
          svn_ra_session_t *session,
+         svn_cancel_func_t cancel_func,
+         void *cancel_baton,
          apr_pool_t *pool)
 {
   char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
@@ -87,16 +89,11 @@ get_lock(const svn_string_t **lock_strin
                                 pool));
   if (! be_atomic)
     {
-      /* Pre-1.7 server.  Can't lock without a race condition.
-         See issue #3546.
-       */
-      svn_error_t *err;
-
-      err = svn_error_create(
-              SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-              _("Target server does not support atomic revision property "
-                "edits; consider upgrading it to 1.7 or using an external "
-                "locking program"));
+      /* Pre-1.7 servers can't lock without a race condition.  (Issue #3546) */
+      svn_error_t *err =
+        svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                         _("Target server does not support atomic revision "
+                           "property edits; consider upgrading it to 1.7."));
       svn_handle_warning2(stderr, err, "svnrdump: ");
       svn_error_clear(err);
     }
@@ -119,23 +116,24 @@ get_lock(const svn_string_t **lock_strin
 
       svn_pool_clear(subpool);
 
+      SVN_ERR(cancel_func(cancel_baton));
       SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, &reposlocktoken,
                               subpool));
 
       if (reposlocktoken)
         {
-          /* Did we get it? If so, we're done, otherwise we sleep. */
+          /* Did we get it? If so, we're done. */
           if (strcmp(reposlocktoken->data, mylocktoken->data) == 0)
             return SVN_NO_ERROR;
-          else
-            {
-              SVN_ERR(svn_cmdline_printf
-                      (pool, _("Failed to get lock on destination "
-                               "repos, currently held by '%s'\n"),
-                       reposlocktoken->data));
 
-              apr_sleep(apr_time_from_sec(1));
-            }
+          /* ...otherwise, tell the user that someone else has the
+             lock and sleep before retrying. */
+          SVN_ERR(svn_cmdline_printf
+                  (pool, _("Failed to get lock on destination "
+                           "repos, currently held by '%s'\n"),
+                   reposlocktoken->data));
+          
+          apr_sleep(apr_time_from_sec(1));
         }
       else if (i < LOCK_RETRIES - 1)
         {
@@ -147,19 +145,23 @@ get_lock(const svn_string_t **lock_strin
                                         mylocktoken, subpool);
 
           if (be_atomic && err && is_atomicity_error(err))
-            /* Someone else has the lock.  Let's loop. */
-            svn_error_clear(err);
+            {
+              /* Someone else has the lock.  Let's loop. */
+              svn_error_clear(err);
+            }
           else if (be_atomic && err == SVN_NO_ERROR)
-            /* We have the lock. 
-
-               However, for compatibility with concurrent svnsync's that don't
-               support atomicity, loop anyway to double-check that they haven't
-               overwritten our lock.
-             */
-            continue;
+            {
+              /* We have the lock.  However, for compatibility with
+                 concurrent svnrdumps that don't support atomicity, loop
+                 anyway to double-check that they haven't overwritten
+                 our lock. */
+              continue;
+            }
           else
-            /* Genuine error, or we aren't atomic and need to loop. */
-            SVN_ERR(err);
+            {
+              /* Genuine error, or we aren't atomic and need to loop. */
+              SVN_ERR(err);
+            }
         }
     }
 
@@ -168,6 +170,33 @@ get_lock(const svn_string_t **lock_strin
                              "after %d attempts"), i);
 }
 
+/* Remove the lock on SESSION iff the lock is owned by MYLOCKTOKEN. */
+static svn_error_t *
+maybe_unlock(svn_ra_session_t *session,
+             const svn_string_t *mylocktoken,
+             apr_pool_t *scratch_pool)
+{
+  svn_string_t *reposlocktoken;
+  svn_boolean_t be_atomic;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                scratch_pool));
+  SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK,
+                          &reposlocktoken, scratch_pool));
+  if (reposlocktoken && strcmp(reposlocktoken->data, mylocktoken->data) == 0)
+    {
+      svn_error_t *err =
+        svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                be_atomic ? &mylocktoken : NULL, NULL,
+                                scratch_pool);
+      if (is_atomicity_error(err))
+        return svn_error_quick_wrap(err, _("svnrdump's lock was stolen; "
+                                           "can't remove it"));
+    }
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 new_revision_record(void **revision_baton,
 		    apr_hash_t *headers,
@@ -590,7 +619,9 @@ close_revision(void *baton)
           SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
           rb->db = rb->db->parent;
         }
+      /* root dir's baton */
       LDR_DBG(("Closing edit on %p\n", commit_edit_baton));
+      SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
       SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pool));
     }
   else
@@ -606,6 +637,7 @@ close_revision(void *baton)
 
       LDR_DBG(("Opened root %p\n", child_baton));
       LDR_DBG(("Closing edit on %p\n", commit_edit_baton));
+      SVN_ERR(commit_editor->close_directory(child_baton, rb->pool));
       SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pool));
     }
 
@@ -659,6 +691,8 @@ drive_dumpstream_loader(svn_stream_t *st
                         const svn_repos_parse_fns2_t *parser,
                         void *parse_baton,
                         svn_ra_session_t *session,
+                        svn_cancel_func_t cancel_func,
+                        void *cancel_baton,
                         apr_pool_t *pool)
 {
   struct parse_baton *pb = parse_baton;
@@ -669,17 +703,16 @@ drive_dumpstream_loader(svn_stream_t *st
   SVN_ERR(svn_ra_has_capability(session, &be_atomic,
                                 SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
                                 pool));
-
-  SVN_ERR(get_lock(&lock_string, session, pool));
+  SVN_ERR(get_lock(&lock_string, session, cancel_func, cancel_baton, pool));
   SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
-  SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
-                                      NULL, NULL, pool));
-  err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
-                                 be_atomic ? &lock_string : NULL, NULL, pool);
-  if (is_atomicity_error(err))
-    return svn_error_quick_wrap(err,
-                                _("\"svnrdump load\"'s lock was stolen; "
-                                  "can't remove it"));
+  err = svn_repos_parse_dumpstream2(stream, parser, parse_baton,
+                                    cancel_func, cancel_baton, pool);
 
-  return SVN_NO_ERROR;
+  /* If all goes well, or if we're cancelled cleanly, don't leave a
+     stray lock behind. */
+  if ((! err) 
+      || (err && (err->apr_err == SVN_ERR_CANCELLED)))
+    err = svn_error_compose_create(maybe_unlock(session, lock_string, pool),
+                                   err);
+  return err;
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.h?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/load_editor.h Sun Nov 21 00:48:20 2010
@@ -104,13 +104,17 @@ get_dumpstream_loader(const svn_repos_pa
  * Drive the dumpstream loader described by @a parser and @a
  * parse_baton to parse and commit the stream @a stream to the
  * location described by @a session. Use @a pool for all memory
- * allocations.
+ * allocations.  Use @a cancel_func and @a cancel_baton to check for
+ * user cancellation of the operation (for timely-but-safe
+ * termination).
  */
 svn_error_t *
 drive_dumpstream_loader(svn_stream_t *stream,
                         const svn_repos_parse_fns2_t *parser,
                         void *parse_baton,
                         svn_ra_session_t *session,
+                        svn_cancel_func_t cancel_func,
+                        void *cancel_baton,
                         apr_pool_t *pool);
 
 #endif

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c Sun Nov 21 00:48:20 2010
@@ -1,6 +1,6 @@
 /*
  *  svnrdump.c: Produce a dumpfile of a local or remote repository
- *  without touching the filesystem, but for temporary files.
+ *              without touching the filesystem, but for temporary files.
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -22,6 +22,8 @@
  * ====================================================================
  */
 
+#include <apr_signal.h>
+
 #include "svn_pools.h"
 #include "svn_cmdline.h"
 #include "svn_client.h"
@@ -39,6 +41,34 @@
 
 #include "private/svn_cmdline_private.h"
 
+
+
+/*** Cancellation ***/
+
+/* A flag to see if we've been cancelled by the client or not. */
+static volatile sig_atomic_t cancelled = FALSE;
+
+/* A signal handler to support cancellation. */
+static void
+signal_handler(int signum)
+{
+  apr_signal(signum, SIG_IGN);
+  cancelled = TRUE;
+}
+
+/* Our cancellation callback. */
+static svn_error_t *
+check_cancel(void *baton)
+{
+  if (cancelled)
+    return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal"));
+  else
+    return SVN_NO_ERROR;
+}
+
+
+
+
 static svn_opt_subcommand_t dump_cmd, load_cmd;
 
 enum svn_svnrdump__longopt_t
@@ -74,28 +104,33 @@ static const svn_opt_subcommand_desc2_t 
 
 static const apr_getopt_option_t svnrdump__options[] =
   {
-    {"revision",     'r', 1, N_("specify revision number ARG (or X:Y range)")},
-    {"quiet",         'q', 0, N_("no progress (only errors) to stderr")},
-    {"config-dir",    opt_config_dir, 1, N_("read user configuration files from"
-                                            " directory ARG") },
-    {"username",      opt_auth_username, 1, N_("specify a username ARG")},
-    {"password",      opt_auth_password, 1, N_("specify a password ARG")},
-    {"non-interactive", opt_non_interactive, 0, N_("do no interactive"
-                                                   " prompting")},
-    {"no-auth-cache", opt_auth_nocache, 0, N_("do not cache authentication"
-                                              " tokens")},
-  
-    {"help",          'h', 0, N_("display this help")},
-    {"version",       opt_version, 0, N_("show program version information")},
+    {"revision",     'r', 1, 
+                      N_("specify revision number ARG (or X:Y range)")},
+    {"quiet",         'q', 0,
+                      N_("no progress (only errors) to stderr")},
+    {"config-dir",    opt_config_dir, 1,
+                      N_("read user configuration files from directory ARG")},
+    {"username",      opt_auth_username, 1,
+                      N_("specify a username ARG")},
+    {"password",      opt_auth_password, 1,
+                      N_("specify a password ARG")},
+    {"non-interactive", opt_non_interactive, 0,
+                      N_("do no interactive prompting")},
+    {"no-auth-cache", opt_auth_nocache, 0,
+                      N_("do not cache authentication tokens")},
+    {"help",          'h', 0,
+                      N_("display this help")},
+    {"version",       opt_version, 0,
+                      N_("show program version information")},
     {"config-option", opt_config_option, 1,
-                    N_("set user configuration option in the format:\n"
-                       "                             "
-                       "    FILE:SECTION:OPTION=[VALUE]\n"
-                       "                             "
-                       "For example:\n"
-                       "                             "
-                       "    servers:global:http-library=serf")},
-    {0,                  0,   0, 0}
+                      N_("set user configuration option in the format:\n"
+                         "                             "
+                         "    FILE:SECTION:OPTION=[VALUE]\n"
+                         "                             "
+                         "For example:\n"
+                         "                             "
+                         "    servers:global:http-library=serf")},
+    {0, 0, 0, 0}
   };
 
 /* Baton for the RA replay session. */
@@ -110,6 +145,7 @@ struct replay_baton {
   svn_boolean_t quiet;
 };
 
+/* Option set */
 typedef struct opt_baton_t {
   svn_ra_session_t *session;
   const char *url;
@@ -118,6 +154,9 @@ typedef struct opt_baton_t {
   svn_boolean_t quiet;
 } opt_baton_t;
 
+/* Print dumpstream-formatted information about REVISION.
+ * Implements the `svn_ra_replay_revstart_callback_t' interface.
+ */
 static svn_error_t *
 replay_revstart(svn_revnum_t revision,
                 void *replay_baton,
@@ -168,6 +207,8 @@ replay_revstart(svn_revnum_t revision,
   return SVN_NO_ERROR;
 }
 
+/* Print progress information about the dump of REVISION.
+   Implements the `svn_ra_replay_revfinish_callback_t' interface. */
 static svn_error_t *
 replay_revend(svn_revnum_t revision,
               void *replay_baton,
@@ -183,11 +224,12 @@ replay_revend(svn_revnum_t revision,
   return SVN_NO_ERROR;
 }
 
-/* Return in *SESSION a new RA session to URL.
- * Allocate *SESSION and related data structures in POOL.
- * Use CONFIG_DIR and pass USERNAME, PASSWORD, CONFIG_DIR and
- * NO_AUTH_CACHE to initialize the authorization baton.
- * CONFIG_OPTIONS (if not NULL) is a list of configuration overrides. */
+/* Set *SESSION to a new RA session opened to URL.  Allocate *SESSION
+ * and related data structures in POOL.  Use CONFIG_DIR and pass
+ * USERNAME, PASSWORD, CONFIG_DIR and NO_AUTH_CACHE to initialize the
+ * authorization baton.  CONFIG_OPTIONS (if not NULL) is a list of
+ * configuration overrides.
+ */
 static svn_error_t *
 open_connection(svn_ra_session_t **session,
                 const char *url,
@@ -216,6 +258,9 @@ open_connection(svn_ra_session_t **sessi
   cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
                             APR_HASH_KEY_STRING);
 
+  /* Set up our cancellation support. */
+  ctx->cancel_func = check_cancel;
+
   /* Default authentication providers for non-interactive use */
   SVN_ERR(svn_cmdline_create_auth_baton(&(ctx->auth_baton), non_interactive,
                                         username, password, config_dir,
@@ -226,10 +271,19 @@ open_connection(svn_ra_session_t **sessi
   return SVN_NO_ERROR;
 }
 
+/* Replay revisions START_REVISION thru END_REVISION (inclusive) of
+ * the repository located at URL, using callbacks which generate
+ * Subversion repository dumpstreams describing the changes made in
+ * those revisions.  If QUIET is set, don't generate progress
+ * messages.
+ */
 static svn_error_t *
-replay_revisions(svn_ra_session_t *session, const char *url,
-                 svn_revnum_t start_revision, svn_revnum_t end_revision,
-                 svn_boolean_t quiet, apr_pool_t *pool)
+replay_revisions(svn_ra_session_t *session,
+                 const char *url,
+                 svn_revnum_t start_revision,
+                 svn_revnum_t end_revision,
+                 svn_boolean_t quiet,
+                 apr_pool_t *pool)
 {
   const svn_delta_editor_t *dump_editor;
   struct replay_baton *replay_baton;
@@ -239,7 +293,8 @@ replay_revisions(svn_ra_session_t *sessi
 
   SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
 
-  SVN_ERR(get_dump_editor(&dump_editor, &dump_baton, stdout_stream, pool));
+  SVN_ERR(get_dump_editor(&dump_editor, &dump_baton, stdout_stream, 
+                          check_cancel, NULL, pool));
 
   replay_baton = apr_pcalloc(pool, sizeof(*replay_baton));
   replay_baton->editor = dump_editor;
@@ -288,7 +343,8 @@ replay_revisions(svn_ra_session_t *sessi
                                &(propstring->len)));
       SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));
       if (! quiet)
-        svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n", start_revision);
+        svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+                            start_revision);
 
       start_revision++;
     }
@@ -300,9 +356,15 @@ replay_revisions(svn_ra_session_t *sessi
   return SVN_NO_ERROR;
 }
 
+/* Read a dumpstream from stdin, and use it to feed a loader capable
+ * of transmitting that information to the repository located at URL
+ * (to which SESSION has been opened).
+ */
 static svn_error_t *
-load_revisions(svn_ra_session_t *session, const char *url,
-               svn_boolean_t quiet, apr_pool_t *pool)
+load_revisions(svn_ra_session_t *session,
+               const char *url,
+               svn_boolean_t quiet,
+               apr_pool_t *pool)
 {
   apr_file_t *stdin_file;
   svn_stream_t *stdin_stream;
@@ -313,104 +375,111 @@ load_revisions(svn_ra_session_t *session
   stdin_stream = svn_stream_from_aprfile2(stdin_file, FALSE, pool);
 
   SVN_ERR(get_dumpstream_loader(&parser, &parse_baton, session, pool));
-  SVN_ERR(drive_dumpstream_loader(stdin_stream, parser, parse_baton, session, pool));
+  SVN_ERR(drive_dumpstream_loader(stdin_stream, parser, parse_baton,
+                                  session, check_cancel, NULL, pool));
 
   svn_stream_close(stdin_stream);
 
   return SVN_NO_ERROR;
 }
 
-
+/* Return a program name for this program, the basename of the path
+ * represented by PROGNAME if not NULL; use "svnrdump" otherwise.
+ */
 static const char *
-ensure_appname(const char *progname, apr_pool_t *pool)
+ensure_appname(const char *progname,
+               apr_pool_t *pool)
 {
   if (!progname)
     return "svnrdump";
-  
-  progname = svn_dirent_internal_style(progname, pool);
-  return svn_dirent_basename(progname, NULL);
+
+  return svn_dirent_basename(svn_dirent_internal_style(progname, pool), NULL);
 }
 
+/* Print a simple usage string. */
 static svn_error_t *
-usage(const char *progname, apr_pool_t *pool)
+usage(const char *progname,
+      apr_pool_t *pool)
 {
-  progname = ensure_appname(progname, pool);
-
-  SVN_ERR(svn_cmdline_fprintf(stderr, pool,
-                              _("Type '%s help' for usage.\n"),
-                              progname));
-  return SVN_NO_ERROR;
+  return svn_cmdline_fprintf(stderr, pool,
+                             _("Type '%s help' for usage.\n"),
+                             ensure_appname(progname, pool));
 }
 
+/* Print information about the version of this program and dependent
+ * modules.
+ */
 static svn_error_t *
-version(const char *progname, apr_pool_t *pool)
+version(const char *progname,
+        apr_pool_t *pool)
 {
-  const char *ra_desc_start
-    = _("The following repository access (RA) modules are available:\n\n");
-
-  svn_stringbuf_t *version_footer = svn_stringbuf_create(ra_desc_start,
-                                                         pool);
+  svn_stringbuf_t *version_footer = 
+    svn_stringbuf_create(_("The following repository access (RA) modules "
+                           "are available:\n\n"),
+                         pool);
 
   SVN_ERR(svn_ra_print_modules(version_footer, pool));
-
-  progname = ensure_appname(progname, pool);
-
-  return svn_opt_print_help3(NULL, progname, TRUE, FALSE,
-                             version_footer->data, NULL, NULL,
-                             NULL, NULL, NULL, pool);
+  return svn_opt_print_help3(NULL, ensure_appname(progname, pool),
+                             TRUE, FALSE, version_footer->data,
+                             NULL, NULL, NULL, NULL, NULL, pool);
 }
 
 
-/** A statement macro, similar to @c SVN_ERR, but returns an integer.
- *
+/* A statement macro, similar to @c SVN_ERR, but returns an integer.
  * Evaluate @a expr. If it yields an error, handle that error and
  * return @c EXIT_FAILURE.
  */
-#define SVNRDUMP_ERR(expr)                                              \
-  do                                                                    \
-    {                                                                   \
-      svn_error_t *svn_err__temp = (expr);                              \
-      if (svn_err__temp)                                                \
-        {                                                               \
+#define SVNRDUMP_ERR(expr)                                               \
+  do                                                                     \
+    {                                                                    \
+      svn_error_t *svn_err__temp = (expr);                               \
+      if (svn_err__temp)                                                 \
+        {                                                                \
           svn_handle_error2(svn_err__temp, stderr, FALSE, "svnrdump: "); \
-          svn_error_clear(svn_err__temp);                               \
-          return EXIT_FAILURE;                                          \
-        }                                                               \
-    }                                                                   \
+          svn_error_clear(svn_err__temp);                                \
+          return EXIT_FAILURE;                                           \
+        }                                                                \
+    }                                                                    \
   while (0)
 
+/* Handle the "dump" subcommand.  Implements `svn_opt_subcommand_t'.  */
 static svn_error_t *
-dump_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+dump_cmd(apr_getopt_t *os,
+         void *baton,
+         apr_pool_t *pool)
 {
   opt_baton_t *opt_baton = baton;
-  SVN_ERR(replay_revisions(opt_baton->session, opt_baton->url,
-                           opt_baton->start_revision, opt_baton->end_revision,
-                           opt_baton->quiet, pool));
-  return SVN_NO_ERROR;
+  return replay_revisions(opt_baton->session, opt_baton->url,
+                          opt_baton->start_revision, opt_baton->end_revision,
+                          opt_baton->quiet, pool);
 }
 
+/* Handle the "load" subcommand.  Implements `svn_opt_subcommand_t'.  */
 static svn_error_t *
-load_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+load_cmd(apr_getopt_t *os,
+         void *baton,
+         apr_pool_t *pool)
 {
   opt_baton_t *opt_baton = baton;
-  SVN_ERR(load_revisions(opt_baton->session, opt_baton->url,
-                         opt_baton->quiet, pool));  
-  return SVN_NO_ERROR;
+  return load_revisions(opt_baton->session, opt_baton->url,
+                        opt_baton->quiet, pool);
 }
 
+/* Handle the "help" subcommand.  Implements `svn_opt_subcommand_t'.  */
 static svn_error_t *
-help_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+help_cmd(apr_getopt_t *os,
+         void *baton,
+         apr_pool_t *pool)
 {
   const char *header =
     _("general usage: svnrdump SUBCOMMAND URL [-r LOWER[:UPPER]]\n"
-      "Type 'svnrdump help <subcommand>' for help on a specific subcommand.\n\n"
+      "Type 'svnrdump help <subcommand>' for help on a specific subcommand.\n"
+      "\n"
       "Available subcommands:\n");
 
-  SVN_ERR(svn_opt_print_help3(os, "svnrdump", FALSE, FALSE, NULL, header,
-                              svnrdump__cmd_table, svnrdump__options, NULL,
-                              NULL, pool));
-
-  return SVN_NO_ERROR;
+  return svn_opt_print_help3(os, "svnrdump", FALSE, FALSE, NULL, header,
+                             svnrdump__cmd_table, svnrdump__options, NULL,
+                             NULL, pool);
 }
 
 int
@@ -443,6 +512,29 @@ main(int argc, const char **argv)
 
   os->interleave = TRUE; /* Options and arguments can be interleaved */
 
+  /* Set up our cancellation support. */
+  apr_signal(SIGINT, signal_handler);
+#ifdef SIGBREAK
+  /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */
+  apr_signal(SIGBREAK, signal_handler);
+#endif
+#ifdef SIGHUP
+  apr_signal(SIGHUP, signal_handler);
+#endif
+#ifdef SIGTERM
+  apr_signal(SIGTERM, signal_handler);
+#endif
+#ifdef SIGPIPE
+  /* Disable SIGPIPE generation for the platforms that have it. */
+  apr_signal(SIGPIPE, SIG_IGN);
+#endif
+#ifdef SIGXFSZ
+  /* Disable SIGXFSZ generation for the platforms that have it, otherwise
+   * working with large files when compiled against an APR that doesn't have
+   * large file support will crash the program, which is uncool. */
+  apr_signal(SIGXFSZ, SIG_IGN);
+#endif
+
   while (1)
     {
       int opt;
@@ -465,14 +557,15 @@ main(int argc, const char **argv)
             revision_cut = strchr(opt_arg, ':');
             if (revision_cut)
               {
-                opt_baton->start_revision = (svn_revnum_t)strtoul(opt_arg,
-                                                                  &revision_cut, 10);
-                opt_baton->end_revision = (svn_revnum_t)strtoul(revision_cut + 1,
-                                                                NULL, 10);
+                opt_baton->start_revision =
+                  (svn_revnum_t)strtoul(opt_arg, &revision_cut, 10);
+                opt_baton->end_revision =
+                  (svn_revnum_t)strtoul(revision_cut + 1, NULL, 10);
               }
             else
               {
-                opt_baton->start_revision = (svn_revnum_t)strtoul(opt_arg, NULL, 10);
+                opt_baton->start_revision =
+                  (svn_revnum_t)strtoul(opt_arg, NULL, 10);
                 opt_baton->end_revision = opt_baton->start_revision;
               }
           }
@@ -517,9 +610,8 @@ main(int argc, const char **argv)
 
   if (os->ind >= os->argc)
     {
-      svn_error_clear
-                (svn_cmdline_fprintf(stderr, pool,
-                                     _("Subcommand argument required\n")));
+      svn_error_clear(svn_cmdline_fprintf(stderr, pool,
+                                          _("Subcommand argument required\n")));
       SVNRDUMP_ERR(help_cmd(NULL, NULL, pool));
       svn_pool_destroy(pool);
       exit(EXIT_FAILURE);
@@ -559,7 +651,8 @@ main(int argc, const char **argv)
       exit(EXIT_FAILURE);
     }
 
-  SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&(opt_baton->url), os->argv[os->ind], pool));
+  SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&(opt_baton->url),
+                                       os->argv[os->ind], pool));
 
   opt_baton->url = svn_uri_canonicalize(os->argv[os->ind], pool);
 
@@ -573,8 +666,10 @@ main(int argc, const char **argv)
                                config_options,
                                pool));
 
-  /* Have sane opt_baton->start_revision and end_revision defaults if unspecified */
-  SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session, &latest_revision, pool));
+  /* Have sane opt_baton->start_revision and end_revision defaults if
+     unspecified.  */
+  SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session,
+                                        &latest_revision, pool));
   if (opt_baton->start_revision == svn_opt_revision_unspecified)
     opt_baton->start_revision = 0;
   if (opt_baton->end_revision == svn_opt_revision_unspecified)
@@ -599,5 +694,5 @@ main(int argc, const char **argv)
 
   svn_pool_destroy(pool);
 
-  return 0;
+  return EXIT_SUCCESS;
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnserve/serve.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnserve/serve.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnserve/serve.c Sun Nov 21 00:48:20 2010
@@ -1838,11 +1838,14 @@ static svn_error_t *get_mergeinfo(svn_ra
   apr_hash_index_t *hi;
   const char *inherit_word;
   svn_mergeinfo_inheritance_t inherit;
+  svn_boolean_t validate_inherited_mergeinfo;
   svn_boolean_t include_descendants;
   apr_pool_t *iterpool;
 
-  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)wb", &paths, &rev,
-                                 &inherit_word, &include_descendants));
+  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)wb?b", &paths, &rev,
+                                 &inherit_word,
+                                 &include_descendants,
+                                 &validate_inherited_mergeinfo));
   inherit = svn_inheritance_from_word(inherit_word);
 
   /* Canonicalize the paths which mergeinfo has been requested for. */
@@ -1868,12 +1871,13 @@ static svn_error_t *get_mergeinfo(svn_ra
                                              pool)));
 
   SVN_ERR(trivial_auth_request(conn, pool, b));
-  SVN_CMD_ERR(svn_repos_fs_get_mergeinfo(&mergeinfo, b->repos,
-                                         canonical_paths, rev,
-                                         inherit,
-                                         include_descendants,
-                                         authz_check_access_cb_func(b), b,
-                                         pool));
+  SVN_CMD_ERR(svn_repos_fs_get_mergeinfo2(&mergeinfo, b->repos,
+                                          canonical_paths, rev,
+                                          inherit,
+                                          validate_inherited_mergeinfo,
+                                          include_descendants,
+                                          authz_check_access_cb_func(b), b,
+                                          pool));
   SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(&mergeinfo, mergeinfo,
                                                     b->fs_path->data, pool));
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "success"));
@@ -1891,7 +1895,8 @@ static svn_error_t *get_mergeinfo(svn_ra
                                      mergeinfo_string));
     }
   svn_pool_destroy(iterpool);
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)b)",
+    validate_inherited_mergeinfo));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnsync/main.c?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnsync/main.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnsync/main.c Sun Nov 21 00:48:20 2010
@@ -530,6 +530,8 @@ check_if_session_is_at_repos_root(svn_ra
 /* Remove the properties in TARGET_PROPS but not in SOURCE_PROPS from
  * revision REV of the repository associated with RA session SESSION.
  *
+ * For REV zero, don't remove properties with the "svn:sync-" prefix.
+ * 
  * All allocations will be done in a subpool of POOL.
  */
 static svn_error_t *
@@ -550,6 +552,10 @@ remove_props_not_in_source(svn_ra_sessio
 
       svn_pool_clear(subpool);
 
+      if (rev == 0 && !strncmp(propname, SVNSYNC_PROP_PREFIX,
+                               sizeof(SVNSYNC_PROP_PREFIX) - 1))
+        continue;
+
       /* Delete property if the name can't be found in SOURCE_PROPS. */
       if (! apr_hash_get(source_props, propname, APR_HASH_KEY_STRING))
         SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL,
@@ -1487,7 +1493,7 @@ do_copy_revprops(svn_ra_session_t *to_se
     {
       int normalized_count;
       SVN_ERR(check_cancel(NULL));
-      SVN_ERR(copy_revprops(from_session, to_session, i, FALSE,
+      SVN_ERR(copy_revprops(from_session, to_session, i, TRUE,
                             baton->quiet, &normalized_count, pool));
       normalized_rev_props_count += normalized_count;
     }

Modified: subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/authz_tests.py?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/authz_tests.py Sun Nov 21 00:48:20 2010
@@ -1090,9 +1090,10 @@ test_list = [ None,
               Skip(authz_recursive_ls,
                    svntest.main.is_ra_type_file),
              ]
+serial_only = True
 
 if __name__ == '__main__':
-  svntest.main.run_tests(test_list, serial_only = True)
+  svntest.main.run_tests(test_list, serial_only = serial_only)
   # NOTREACHED
 
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/basic_tests.py?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/basic_tests.py Sun Nov 21 00:48:20 2010
@@ -2500,9 +2500,9 @@ def delete_from_url_with_spaces(sbox):
   "delete a directory with ' ' using its url"
   
   sbox.build()
-  sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With Spaces'))
-  sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With'))
-  sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With/Spaces'))
+  sbox.simple_mkdir('Dir With Spaces')
+  sbox.simple_mkdir('Dir With')
+  sbox.simple_mkdir('Dir With/Spaces')
 
   svntest.actions.run_and_verify_svn(None, None, [],
                                       'ci', sbox.wc_dir, '-m', 'Added dir')
@@ -2671,6 +2671,19 @@ def delete_urls_with_spaces(sbox):
                                      sbox.repo_url + '/C spaced',
                                      '-m', 'Deleted B and C') 
 
+def ls_url_special_characters(sbox):
+  """special characters in svn ls URL"""
+  sbox.build(create_wc = False)
+
+  special_urls = [sbox.repo_url + '/A' + '/%2E',
+                  sbox.repo_url + '%2F' + 'A']
+
+  for url in special_urls:
+    svntest.actions.run_and_verify_svn('ls URL with special characters',
+                                       ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
+                                       [], 'ls', 
+                                       url)
+
 ########################################################################
 # Run the tests
 
@@ -2732,6 +2745,7 @@ test_list = [ None,
               delete_child_parent_update,
               basic_relocate,
               delete_urls_with_spaces,
+              ls_url_special_characters,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/cat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/cat_tests.py?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/cat_tests.py (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/cat_tests.py Sun Nov 21 00:48:20 2010
@@ -196,6 +196,20 @@ def cat_keywords(sbox):
                                      ["This is the file 'iota'.\n", "$Revision: 2 $\n"],
                                      [], 'cat', iota_path)
 
+def cat_url_special_characters(sbox):
+  """special characters in svn cat URL"""
+  sbox.build(create_wc = False)
+  wc_dir = sbox.wc_dir
+
+  special_urls = [sbox.repo_url + '/A' + '/%2E',
+                  sbox.repo_url + '%2F' + 'A']
+
+  expected_err = ["svn: warning: URL '" + sbox.repo_url + '/A'  + "'"
+                   + " refers to a directory\n"]
+
+  for url in special_urls:
+    svntest.actions.run_and_verify_svn2(None, None, expected_err, 0,
+                                        'cat', url)
 
 ########################################################################
 # Run the tests
@@ -210,6 +224,7 @@ test_list = [ None,
               cat_skip_uncattable,
               cat_unversioned_file,
               cat_keywords,
+              cat_url_special_characters,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/copy_tests.py?rev=1037363&r1=1037362&r2=1037363&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/tests/cmdline/copy_tests.py Sun Nov 21 00:48:20 2010
@@ -4332,6 +4332,8 @@ def nonrecursive_commit_of_copy(sbox):
                                         None,
                                         wc_dir, '--depth', 'immediates')
 
+# Regression test for issue #3474 - making a new subdir, moving files into it
+# and then renaming the subdir, breaks history of the moved files.
 def copy_added_dir_with_copy(sbox):
   """copy of new dir with copied file keeps history"""
 
@@ -4358,8 +4360,6 @@ def copy_added_dir_with_copy(sbox):
       'NewDir2/mu'        : Item(status='A ', copied='+', wc_rev='-'),
     })
 
-  # Currently this fails because NewDir2/mu loses its history in the copy
-  # from NewDir to NewDir2
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 
@@ -4588,7 +4588,7 @@ def changed_data_should_match_checkout(s
 
   svntest.actions.run_and_verify_svn(None, None, [], 'copy', A_B_E, E_new)
 
-  sbox.simple_commit(wc_dir)
+  sbox.simple_commit()
 
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
@@ -4618,7 +4618,7 @@ def changed_dir_data_should_match_checko
 
   svntest.actions.run_and_verify_svn(None, None, [], 'copy', A_B, B_new)
 
-  sbox.simple_commit(wc_dir)
+  sbox.simple_commit()
 
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
@@ -4835,6 +4835,92 @@ def delete_replace_delete(sbox):
   # Currently fails because pi, rho, tau get left behind
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
+A_B_children = ['A/B/lambda', 'A/B/F', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/E']
+A_D_children = ['A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
+                'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega']
+
+def copy_repos_over_deleted_same_kind(sbox):
+  "copy repos node over deleted node, same kind"
+  sbox.build(read_only = True)
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+  # Set up some deleted paths
+  sbox.simple_rm('iota', 'A/B')
+  for path in ['iota', 'A/B'] + A_B_children:
+    expected_status.tweak(path, status='D ')
+
+  # Test copying
+  main.run_svn(None, 'cp', sbox.repo_url + '/A/mu', sbox.ospath('iota'))
+  expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+  main.run_svn(None, 'cp', sbox.repo_url + '/A/D', sbox.ospath('A/B'))
+  expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+  for child in A_D_children:
+    expected_status.add({ child.replace('A/D', 'A/B'):
+                          Item(status='  ', wc_rev='-', copied='+')})
+  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+def copy_repos_over_deleted_other_kind(sbox):
+  "copy repos node over deleted node, other kind"
+  sbox.build(read_only = True)
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+  # Set up some deleted paths
+  sbox.simple_rm('iota', 'A/B')
+  for path in ['iota', 'A/B'] + A_B_children:
+    expected_status.tweak(path, status='D ')
+
+  # Test copying
+  main.run_svn(None, 'cp', sbox.repo_url + '/iota', sbox.ospath('A/B'))
+  expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+  expected_status.remove(*A_B_children)
+  main.run_svn(None, 'cp', sbox.repo_url + '/A/B', sbox.ospath('iota'))
+  expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+  for child in A_B_children:
+    expected_status.add({ child.replace('A/B', 'iota'):
+                          Item(status='  ', wc_rev='-', copied='+')})
+  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+def copy_wc_over_deleted_same_kind(sbox):
+  "copy WC node over a deleted node, same kind"
+  sbox.build(read_only = True)
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+  # Set up some deleted paths
+  sbox.simple_rm('iota', 'A/B')
+  for path in ['iota', 'A/B'] + A_B_children:
+    expected_status.tweak(path, status='D ')
+
+  # Test copying
+  main.run_svn(None, 'cp', sbox.ospath('A/mu'), sbox.ospath('iota'))
+  expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+  main.run_svn(None, 'cp', sbox.ospath('A/D'), sbox.ospath('A/B'))
+  expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+  for child in A_D_children:
+    expected_status.add({ child.replace('A/D', 'A/B'):
+                          Item(status='  ', wc_rev='-', copied='+')})
+  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+def copy_wc_over_deleted_other_kind(sbox):
+  "copy WC node over deleted node, other kind"
+  sbox.build(read_only = True)
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+  # Set up some deleted paths
+  sbox.simple_rm('iota', 'A/B')
+  for path in ['iota', 'A/B'] + A_B_children:
+    expected_status.tweak(path, status='D ')
+
+  # Test copying
+  main.run_svn(None, 'cp', sbox.ospath('A/mu'), sbox.ospath('A/B'))
+  expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+  expected_status.remove(*A_B_children)
+  main.run_svn(None, 'cp', sbox.ospath('A/D'), sbox.ospath('iota'))
+  expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+  for child in A_D_children:
+    expected_status.add({ child.replace('A/D', 'iota'):
+                          Item(status='  ', wc_rev='-', copied='+')})
+  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
 
 ########################################################################
 # Run the tests
@@ -4934,6 +5020,10 @@ test_list = [ None,
               copy_delete_delete,
               XFail(copy_delete_revert),
               delete_replace_delete,
+              copy_repos_over_deleted_same_kind,
+              copy_repos_over_deleted_other_kind,
+              copy_wc_over_deleted_same_kind,
+              copy_wc_over_deleted_other_kind,
              ]
 
 if __name__ == '__main__':