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

svn commit: r1413258 [30/33] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/ notes/ notes/directory-index/ subversion/ subv...

Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/help-cmd.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/help-cmd.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/help-cmd.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,94 @@
+/*
+ * help-cmd.c -- Provide help
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include "svn_string.h"
+#include "svn_error.h"
+#include "svn_version.h"
+#include "cl.h"
+
+#include "svn_private_config.h"
+
+
+/*** Code. ***/
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__help(apr_getopt_t *os,
+             void *baton,
+             apr_pool_t *pool)
+{
+  svn_cl__opt_state_t *opt_state;
+
+  /* xgettext: the %s is for SVN_VER_NUMBER. */
+  char help_header_template[] =
+  N_("usage: svn-bench <subcommand> [options] [args]\n"
+     "Subversion command-line client, version %s.\n"
+     "Type 'svn-bench help <subcommand>' for help on a specific subcommand.\n"
+     "Type 'svn-bench --version' to see the program version and RA modules\n"
+     "  or 'svn-bench --version --quiet' to see just the version number.\n"
+     "\n"
+     "Most subcommands take file and/or directory arguments, recursing\n"
+     "on the directories.  If no arguments are supplied to such a\n"
+     "command, it recurses on the current directory (inclusive) by default.\n"
+     "\n"
+     "Available subcommands:\n");
+
+  char help_footer[] =
+  N_("Subversion is a tool for version control.\n"
+     "For additional information, see http://subversion.apache.org/\n");
+
+  char *help_header =
+    apr_psprintf(pool, _(help_header_template), SVN_VER_NUMBER);
+
+  const char *ra_desc_start
+    = _("The following repository access (RA) modules are available:\n\n");
+
+  svn_stringbuf_t *version_footer;
+
+  if (baton)
+    opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+  else
+    opt_state = NULL;
+
+  version_footer = svn_stringbuf_create(ra_desc_start, pool);
+  SVN_ERR(svn_ra_print_modules(version_footer, pool));
+
+  return svn_opt_print_help4(os,
+                             "svn",   /* ### erm, derive somehow? */
+                             opt_state ? opt_state->version : FALSE,
+                             opt_state ? opt_state->quiet : FALSE,
+                             opt_state ? opt_state->verbose : FALSE,
+                             version_footer->data,
+                             help_header,   /* already gettext()'d */
+                             svn_cl__cmd_table,
+                             svn_cl__options,
+                             svn_cl__global_options,
+                             _(help_footer),
+                             pool);
+}

Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/main.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/main.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/main.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,954 @@
+/*
+ * main.c:  Subversion command line client.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include <string.h>
+#include <assert.h>
+
+#include <apr_signal.h>
+
+#include "svn_cmdline.h"
+#include "svn_dirent_uri.h"
+#include "svn_pools.h"
+#include "svn_utf.h"
+#include "svn_version.h"
+
+#include "cl.h"
+
+#include "private/svn_opt_private.h"
+#include "private/svn_cmdline_private.h"
+
+#include "svn_private_config.h"
+
+
+/*** Option Processing ***/
+
+/* Add an identifier here for long options that don't have a short
+   option. Options that have both long and short options should just
+   use the short option letter as identifier.  */
+typedef enum svn_cl__longopt_t {
+  opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID,
+  opt_auth_username,
+  opt_config_dir,
+  opt_config_options,
+  opt_depth,
+  opt_no_auth_cache,
+  opt_non_interactive,
+  opt_stop_on_copy,
+  opt_strict,
+  opt_targets,
+  opt_version,
+  opt_with_revprop,
+  opt_with_all_revprops,
+  opt_with_no_revprops,
+  opt_trust_server_cert,
+} svn_cl__longopt_t;
+
+
+/* Option codes and descriptions for the command line client.
+ *
+ * The entire list must be terminated with an entry of nulls.
+ */
+const apr_getopt_option_t svn_cl__options[] =
+{
+  {"help",          'h', 0, N_("show help on a subcommand")},
+  {NULL,            '?', 0, N_("show help on a subcommand")},
+  {"quiet",         'q', 0, N_("print nothing, or only summary information")},
+  {"recursive",     'R', 0, N_("descend recursively, same as --depth=infinity")},
+  {"non-recursive", 'N', 0, N_("obsolete; try --depth=files or --depth=immediates")},
+  {"change",        'c', 1,
+                    N_("the change made by revision ARG (like -r ARG-1:ARG)\n"
+                       "                             "
+                       "If ARG is negative this is like -r ARG:ARG-1\n"
+                       "                             "
+                       "If ARG is of the form ARG1-ARG2 then this is like\n"
+                       "                             "
+                       "ARG1:ARG2, where ARG1 is inclusive")},
+  {"revision",      'r', 1,
+                    N_("ARG (some commands also take ARG1:ARG2 range)\n"
+                       "                             "
+                       "A revision argument can be one of:\n"
+                       "                             "
+                       "   NUMBER       revision number\n"
+                       "                             "
+                       "   '{' DATE '}' revision at start of the date\n"
+                       "                             "
+                       "   'HEAD'       latest in repository\n"
+                       "                             "
+                       "   'BASE'       base rev of item's working copy\n"
+                       "                             "
+                       "   'COMMITTED'  last commit at or before BASE\n"
+                       "                             "
+                       "   'PREV'       revision just before COMMITTED")},
+  {"version",       opt_version, 0, N_("show program version information")},
+  {"verbose",       'v', 0, N_("print extra information")},
+  {"username",      opt_auth_username, 1, N_("specify a username ARG")},
+  {"password",      opt_auth_password, 1, N_("specify a password ARG")},
+  {"targets",       opt_targets, 1,
+                    N_("pass contents of file ARG as additional args")},
+  {"depth",         opt_depth, 1,
+                    N_("limit operation by depth ARG ('empty', 'files',\n"
+                       "                             "
+                       "'immediates', or 'infinity')")},
+  {"strict",        opt_strict, 0, N_("use strict semantics")},
+  {"stop-on-copy",  opt_stop_on_copy, 0,
+                    N_("do not cross copies while traversing history")},
+  {"no-auth-cache", opt_no_auth_cache, 0,
+                    N_("do not cache authentication tokens")},
+  {"trust-server-cert", opt_trust_server_cert, 0,
+                    N_("accept SSL server certificates from unknown\n"
+                       "                             "
+                       "certificate authorities without prompting (but only\n"
+                       "                             "
+                       "with '--non-interactive')") },
+  {"non-interactive", opt_non_interactive, 0,
+                    N_("do no interactive prompting")},
+  {"config-dir",    opt_config_dir, 1,
+                    N_("read user configuration files from directory ARG")},
+  {"config-option", opt_config_options, 1,
+                    N_("set user configuration option in the format:\n"
+                       "                             "
+                       "    FILE:SECTION:OPTION=[VALUE]\n"
+                       "                             "
+                       "For example:\n"
+                       "                             "
+                       "    servers:global:http-library=serf")},
+  {"limit",         'l', 1, N_("maximum number of log entries")},
+  {"with-all-revprops",  opt_with_all_revprops, 0,
+                    N_("retrieve all revision properties")},
+  {"with-no-revprops",  opt_with_no_revprops, 0,
+                    N_("retrieve no revision properties")},
+  {"with-revprop",  opt_with_revprop, 1,
+                    N_("set revision property ARG in new revision\n"
+                       "                             "
+                       "using the name[=value] format")},
+  {"use-merge-history", 'g', 0,
+                    N_("use/display additional information from merge\n"
+                       "                             "
+                       "history")},
+
+  /* Long-opt Aliases
+   *
+   * These have NULL desriptions, but an option code that matches some
+   * other option (whose description should probably mention its aliases).
+  */
+
+  {0,               0, 0, 0},
+};
+
+
+
+/*** Command dispatch. ***/
+
+/* Our array of available subcommands.
+ *
+ * The entire list must be terminated with an entry of nulls.
+ *
+ * In most of the help text "PATH" is used where a working copy path is
+ * required, "URL" where a repository URL is required and "TARGET" when
+ * either a path or a url can be used.  Hmm, should this be part of the
+ * help text?
+ */
+
+/* Options that apply to all commands.  (While not every command may
+   currently require authentication or be interactive, allowing every
+   command to take these arguments allows scripts to just pass them
+   willy-nilly to every invocation of 'svn') . */
+const int svn_cl__global_options[] =
+{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive,
+  opt_trust_server_cert, opt_config_dir, opt_config_options, 0
+};
+
+const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
+{
+  { "help", svn_cl__help, {"?", "h"}, N_
+    ("Describe the usage of this program or its subcommands.\n"
+     "usage: help [SUBCOMMAND...]\n"),
+    {0} },
+  /* This command is also invoked if we see option "--help", "-h" or "-?". */
+
+  { "null-export", svn_cl__null_export, {0}, N_
+    ("Create an unversioned copy of a tree.\n"
+     "usage: null-export [-r REV] URL[@PEGREV]\n"
+     "\n"
+     "  Exports a clean directory tree from the repository specified by\n"
+     "  URL, at revision REV if it is given, otherwise at HEAD.\n"
+     "\n"
+     "  If specified, PEGREV determines in which revision the target is first\n"
+     "  looked up.\n"),
+    {'r', 'q', 'N', opt_depth} },
+
+  { "null-list", svn_cl__null_list, {"ls"}, N_
+    ("List directory entries in the repository.\n"
+     "usage: list [TARGET[@REV]...]\n"
+     "\n"
+     "  List each TARGET file and the contents of each TARGET directory as\n"
+     "  they exist in the repository.  If TARGET is a working copy path, the\n"
+     "  corresponding repository URL will be used. If specified, REV determines\n"
+     "  in which revision the target is first looked up.\n"
+     "\n"
+     "  The default TARGET is '.', meaning the repository URL of the current\n"
+     "  working directory.\n"
+     "\n"
+     "  With --verbose, the following fields will be fetched for each item:\n"
+     "\n"
+     "    Revision number of the last commit\n"
+     "    Author of the last commit\n"
+     "    If locked, the letter 'O'.  (Use 'svn info URL' to see details)\n"
+     "    Size (in bytes)\n"
+     "    Date and time of the last commit\n"),
+    {'r', 'v', 'R', opt_depth} },
+
+  { "null-log", svn_cl__null_log, {0}, N_
+    ("Fetch the log messages for a set of revision(s) and/or path(s).\n"
+     "usage: 1. null-log [PATH][@REV]\n"
+     "       2. null-log URL[@REV] [PATH...]\n"
+     "\n"
+     "  1. Fetch the log messages for the URL corresponding to PATH\n"
+     "     (default: '.'). If specified, REV is the revision in which the\n"
+     "     URL is first looked up, and the default revision range is REV:1.\n"
+     "     If REV is not specified, the default revision range is BASE:1,\n"
+     "     since the URL might not exist in the HEAD revision.\n"
+     "\n"
+     "  2. Fetch the log messages for the PATHs (default: '.') under URL.\n"
+     "     If specified, REV is the revision in which the URL is first\n"
+     "     looked up, and the default revision range is REV:1; otherwise,\n"
+     "     the URL is looked up in HEAD, and the default revision range is\n"
+     "     HEAD:1.\n"
+     "\n"
+     "  Multiple '-c' or '-r' options may be specified (but not a\n"
+     "  combination of '-c' and '-r' options), and mixing of forward and\n"
+     "  reverse ranges is allowed.\n"
+     "\n"
+     "  With -v, also print all affected paths with each log message.\n"
+     "  With -q, don't print the log message body itself (note that this is\n"
+     "  compatible with -v).\n"
+     "\n"
+     "  Each log message is printed just once, even if more than one of the\n"
+     "  affected paths for that revision were explicitly requested.  Logs\n"
+     "  follow copy history by default.  Use --stop-on-copy to disable this\n"
+     "  behavior, which can be useful for determining branchpoints.\n"),
+    {'r', 'q', 'v', 'g', 'c', opt_targets, opt_stop_on_copy, 
+     'l', opt_with_all_revprops, opt_with_no_revprops, opt_with_revprop,
+     'x',},
+    {{opt_with_revprop, N_("retrieve revision property ARG")},
+     {'c', N_("the change made in revision ARG")}} },
+
+  { NULL, NULL, {0}, NULL, {0} }
+};
+
+
+/* Version compatibility check */
+static svn_error_t *
+check_lib_versions(void)
+{
+  static const svn_version_checklist_t checklist[] =
+    {
+      { "svn_subr",   svn_subr_version },
+      { "svn_client", svn_client_version },
+      { "svn_wc",     svn_wc_version },
+      { "svn_ra",     svn_ra_version },
+      { "svn_delta",  svn_delta_version },
+      { NULL, NULL }
+    };
+  SVN_VERSION_DEFINE(my_version);
+
+  return svn_ver_check_list(&my_version, checklist);
+}
+
+
+/* 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. */
+svn_error_t *
+svn_cl__check_cancel(void *baton)
+{
+  if (cancelled)
+    return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal"));
+  else
+    return SVN_NO_ERROR;
+}
+
+
+/*** Main. ***/
+
+/* Report and clear the error ERR, and return EXIT_FAILURE. */
+#define EXIT_ERROR(err)                                                 \
+  svn_cmdline_handle_exit_error(err, NULL, "svn: ")
+
+/* A redefinition of the public SVN_INT_ERR macro, that suppresses the
+ * error message if it is SVN_ERR_IO_PIPE_WRITE_ERROR. */
+#undef SVN_INT_ERR
+#define SVN_INT_ERR(expr)                                        \
+  do {                                                           \
+    svn_error_t *svn_err__temp = (expr);                         \
+    if (svn_err__temp)                                           \
+      return EXIT_ERROR(svn_err__temp);                          \
+  } while (0)
+
+static int
+sub_main(int argc, const char *argv[], apr_pool_t *pool)
+{
+  svn_error_t *err;
+  int opt_id;
+  apr_getopt_t *os;
+  svn_cl__opt_state_t opt_state = { 0, { 0 } };
+  svn_client_ctx_t *ctx;
+  apr_array_header_t *received_opts;
+  int i;
+  const svn_opt_subcommand_desc2_t *subcommand = NULL;
+  svn_cl__cmd_baton_t command_baton;
+  svn_auth_baton_t *ab;
+  svn_config_t *cfg_config;
+  svn_boolean_t descend = TRUE;
+  svn_boolean_t use_notifier = TRUE;
+
+  received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
+
+  /* Check library versions */
+  SVN_INT_ERR(check_lib_versions());
+
+#if defined(WIN32) || defined(__CYGWIN__)
+  /* Set the working copy administrative directory name. */
+  if (getenv("SVN_ASP_DOT_NET_HACK"))
+    {
+      SVN_INT_ERR(svn_wc_set_adm_dir("_svn", pool));
+    }
+#endif
+
+  /* Initialize the RA library. */
+  SVN_INT_ERR(svn_ra_initialize(pool));
+
+  /* Begin processing arguments. */
+  opt_state.start_revision.kind = svn_opt_revision_unspecified;
+  opt_state.end_revision.kind = svn_opt_revision_unspecified;
+  opt_state.revision_ranges =
+    apr_array_make(pool, 0, sizeof(svn_opt_revision_range_t *));
+  opt_state.depth = svn_depth_unknown;
+
+  /* No args?  Show usage. */
+  if (argc <= 1)
+    {
+      svn_cl__help(NULL, NULL, pool);
+      return EXIT_FAILURE;
+    }
+
+  /* Else, parse options. */
+  SVN_INT_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
+
+  os->interleave = 1;
+  while (1)
+    {
+      const char *opt_arg;
+      const char *utf8_opt_arg;
+
+      /* Parse the next option. */
+      apr_status_t apr_err = apr_getopt_long(os, svn_cl__options, &opt_id,
+                                             &opt_arg);
+      if (APR_STATUS_IS_EOF(apr_err))
+        break;
+      else if (apr_err)
+        {
+          svn_cl__help(NULL, NULL, pool);
+          return EXIT_FAILURE;
+        }
+
+      /* Stash the option code in an array before parsing it. */
+      APR_ARRAY_PUSH(received_opts, int) = opt_id;
+
+      switch (opt_id) {
+      case 'l':
+        {
+          err = svn_cstring_atoi(&opt_state.limit, opt_arg);
+          if (err)
+            {
+              err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+                                     _("Non-numeric limit argument given"));
+              return EXIT_ERROR(err);
+            }
+          if (opt_state.limit <= 0)
+            {
+              err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                    _("Argument to --limit must be positive"));
+              return EXIT_ERROR(err);
+            }
+        }
+        break;
+      case 'c':
+        {
+          apr_array_header_t *change_revs =
+            svn_cstring_split(opt_arg, ", \n\r\t\v", TRUE, pool);
+
+          for (i = 0; i < change_revs->nelts; i++)
+            {
+              char *end;
+              svn_revnum_t changeno, changeno_end;
+              const char *change_str =
+                APR_ARRAY_IDX(change_revs, i, const char *);
+              const char *s = change_str;
+              svn_boolean_t is_negative;
+
+              /* 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 || is_negative)
+                    {
+                      err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+                                              NULL,
+                                              _("Negative number in range (%s)"
+                                                " not supported with -c"),
+                                              change_str);
+                      return EXIT_ERROR(err);
+                    }
+                  s = end + 1;
+                  while (*s == 'r')
+                    s++;
+                  changeno_end = strtol(s, &end, 10);
+                }
+              if (end == change_str || *end != '\0')
+                {
+                  err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                          _("Non-numeric change argument (%s) "
+                                            "given to -c"), change_str);
+                  return EXIT_ERROR(err);
+                }
+
+              if (changeno == 0)
+                {
+                  err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                         _("There is no change 0"));
+                  return EXIT_ERROR(err);
+                }
+
+              if (is_negative)
+                changeno = -changeno;
+
+              /* Figure out the range:
+                    -c N  -> -r N-1:N
+                    -c -N -> -r N:N-1
+                    -c M-N -> -r M-1:N for M < N
+                    -c M-N -> -r M:N-1 for M > N
+                    -c -M-N -> error (too confusing/no valid use case)
+              */
+              if (changeno > 0)
+                {
+                  if (changeno <= changeno_end)
+                    changeno--;
+                  else
+                    changeno_end--;
+                }
+              else
+                {
+                  changeno = -changeno;
+                  changeno_end = changeno - 1;
+                }
+
+              opt_state.used_change_arg = TRUE;
+              APR_ARRAY_PUSH(opt_state.revision_ranges,
+                             svn_opt_revision_range_t *)
+                = svn_opt__revision_range_from_revnums(changeno, changeno_end,
+                                                       pool);
+            }
+        }
+        break;
+      case 'r':
+        opt_state.used_revision_arg = TRUE;
+        if (svn_opt_parse_revision_to_range(opt_state.revision_ranges,
+                                            opt_arg, pool) != 0)
+          {
+            SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+            err = svn_error_createf
+                (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                 _("Syntax error in revision argument '%s'"),
+                 utf8_opt_arg);
+            return EXIT_ERROR(err);
+          }
+        break;
+      case 'v':
+        opt_state.verbose = TRUE;
+        break;
+      case 'h':
+      case '?':
+        opt_state.help = TRUE;
+        break;
+      case 'q':
+        opt_state.quiet = TRUE;
+        break;
+      case opt_targets:
+        {
+          svn_stringbuf_t *buffer, *buffer_utf8;
+
+          /* We need to convert to UTF-8 now, even before we divide
+             the targets into an array, because otherwise we wouldn't
+             know what delimiter to use for svn_cstring_split().  */
+
+          SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+          SVN_INT_ERR(svn_stringbuf_from_file2(&buffer, utf8_opt_arg, pool));
+          SVN_INT_ERR(svn_utf_stringbuf_to_utf8(&buffer_utf8, buffer, pool));
+          opt_state.targets = svn_cstring_split(buffer_utf8->data, "\n\r",
+                                                TRUE, pool);
+        }
+        break;
+      case 'N':
+        descend = FALSE;
+        break;
+      case opt_depth:
+        err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
+        if (err)
+          return EXIT_ERROR
+            (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+                               _("Error converting depth "
+                                 "from locale to UTF-8")));
+        opt_state.depth = svn_depth_from_word(utf8_opt_arg);
+        if (opt_state.depth == svn_depth_unknown
+            || opt_state.depth == svn_depth_exclude)
+          {
+            return EXIT_ERROR
+              (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a valid depth; try "
+                                   "'empty', 'files', 'immediates', "
+                                   "or 'infinity'"),
+                                 utf8_opt_arg));
+          }
+        break;
+      case opt_version:
+        opt_state.version = TRUE;
+        break;
+      case opt_auth_username:
+        SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_username,
+                                            opt_arg, pool));
+        break;
+      case opt_auth_password:
+        SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password,
+                                            opt_arg, pool));
+        break;
+      case opt_stop_on_copy:
+        opt_state.stop_on_copy = TRUE;
+        break;
+      case opt_strict:
+        opt_state.strict = TRUE;
+        break;
+      case opt_no_auth_cache:
+        opt_state.no_auth_cache = TRUE;
+        break;
+      case opt_non_interactive:
+        opt_state.non_interactive = TRUE;
+        break;
+      case opt_trust_server_cert:
+        opt_state.trust_server_cert = TRUE;
+        break;
+      case 'x':
+        SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.extensions,
+                                            opt_arg, pool));
+        break;
+      case opt_config_dir:
+        {
+          const char *path_utf8;
+          SVN_INT_ERR(svn_utf_cstring_to_utf8(&path_utf8, opt_arg, pool));
+          opt_state.config_dir = svn_dirent_internal_style(path_utf8, pool);
+        }
+        break;
+      case opt_config_options:
+        if (!opt_state.config_options)
+          opt_state.config_options =
+                   apr_array_make(pool, 1,
+                                  sizeof(svn_cmdline__config_argument_t*));
+
+        SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+        SVN_INT_ERR(svn_cmdline__parse_config_option(opt_state.config_options,
+                                                     opt_arg, pool));
+        break;
+      case opt_with_all_revprops:
+        /* If --with-all-revprops is specified along with one or more
+         * --with-revprops options, --with-all-revprops takes precedence. */
+        opt_state.all_revprops = TRUE;
+        break;
+      case opt_with_no_revprops:
+        opt_state.no_revprops = TRUE;
+        break;
+      case opt_with_revprop:
+        SVN_INT_ERR(svn_opt_parse_revprop(&opt_state.revprop_table,
+                                          opt_arg, pool));
+        break;
+      case 'g':
+        opt_state.use_merge_history = TRUE;
+        break;
+      default:
+        /* Hmmm. Perhaps this would be a good place to squirrel away
+           opts that commands like svn diff might need. Hmmm indeed. */
+        break;
+      }
+    }
+
+  /* ### This really belongs in libsvn_client.  The trouble is,
+     there's no one place there to run it from, no
+     svn_client_init().  We'd have to add it to all the public
+     functions that a client might call.  It's unmaintainable to do
+     initialization from within libsvn_client itself, but it seems
+     burdensome to demand that all clients call svn_client_init()
+     before calling any other libsvn_client function... On the other
+     hand, the alternative is effectively to demand that they call
+     svn_config_ensure() instead, so maybe we should have a generic
+     init function anyway.  Thoughts?  */
+  SVN_INT_ERR(svn_config_ensure(opt_state.config_dir, pool));
+
+  /* If the user asked for help, then the rest of the arguments are
+     the names of subcommands to get help on (if any), or else they're
+     just typos/mistakes.  Whatever the case, the subcommand to
+     actually run is svn_cl__help(). */
+  if (opt_state.help)
+    subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table, "help");
+
+  /* If we're not running the `help' subcommand, then look for a
+     subcommand in the first argument. */
+  if (subcommand == NULL)
+    {
+      if (os->ind >= os->argc)
+        {
+          if (opt_state.version)
+            {
+              /* Use the "help" subcommand to handle the "--version" option. */
+              static const svn_opt_subcommand_desc2_t pseudo_cmd =
+                { "--version", svn_cl__help, {0}, "",
+                  {opt_version,    /* must accept its own option */
+                   'q',            /* brief output */
+                   'v',            /* verbose output */
+                   opt_config_dir  /* all commands accept this */
+                  } };
+
+              subcommand = &pseudo_cmd;
+            }
+          else
+            {
+              svn_error_clear
+                (svn_cmdline_fprintf(stderr, pool,
+                                     _("Subcommand argument required\n")));
+              svn_cl__help(NULL, NULL, pool);
+              return EXIT_FAILURE;
+            }
+        }
+      else
+        {
+          const char *first_arg = os->argv[os->ind++];
+          subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table,
+                                                         first_arg);
+          if (subcommand == NULL)
+            {
+              const char *first_arg_utf8;
+              SVN_INT_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8,
+                                                  first_arg, pool));
+              svn_error_clear
+                (svn_cmdline_fprintf(stderr, pool,
+                                     _("Unknown command: '%s'\n"),
+                                     first_arg_utf8));
+              svn_cl__help(NULL, NULL, pool);
+              return EXIT_FAILURE;
+            }
+        }
+    }
+
+  /* Check that the subcommand wasn't passed any inappropriate options. */
+  for (i = 0; i < received_opts->nelts; i++)
+    {
+      opt_id = APR_ARRAY_IDX(received_opts, i, int);
+
+      /* All commands implicitly accept --help, so just skip over this
+         when we see it. Note that we don't want to include this option
+         in their "accepted options" list because it would be awfully
+         redundant to display it in every commands' help text. */
+      if (opt_id == 'h' || opt_id == '?')
+        continue;
+
+      if (! svn_opt_subcommand_takes_option3(subcommand, opt_id,
+                                             svn_cl__global_options))
+        {
+          const char *optstr;
+          const apr_getopt_option_t *badopt =
+            svn_opt_get_option_from_code2(opt_id, svn_cl__options,
+                                          subcommand, pool);
+          svn_opt_format_option(&optstr, badopt, FALSE, pool);
+          if (subcommand->name[0] == '-')
+            svn_cl__help(NULL, NULL, pool);
+          else
+            svn_error_clear
+              (svn_cmdline_fprintf
+               (stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n"
+                                "Type 'svn-bench help %s' for usage.\n"),
+                subcommand->name, optstr, subcommand->name));
+          return EXIT_FAILURE;
+        }
+    }
+
+  /* Only merge and log support multiple revisions/revision ranges. */
+  if (subcommand->cmd_func != svn_cl__null_log)
+    {
+      if (opt_state.revision_ranges->nelts > 1)
+        {
+          err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("Multiple revision arguments "
+                                   "encountered; can't specify -c twice, "
+                                   "or both -c and -r"));
+          return EXIT_ERROR(err);
+        }
+    }
+
+  /* Disallow simultaneous use of both --with-all-revprops and
+     --with-no-revprops.  */
+  if (opt_state.all_revprops && opt_state.no_revprops)
+    {
+      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("--with-all-revprops and --with-no-revprops "
+                               "are mutually exclusive"));
+      return EXIT_ERROR(err);
+    }
+
+  /* Disallow simultaneous use of both --with-revprop and
+     --with-no-revprops.  */
+  if (opt_state.revprop_table && opt_state.no_revprops)
+    {
+      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("--with-revprop and --with-no-revprops "
+                               "are mutually exclusive"));
+      return EXIT_ERROR(err);
+    }
+
+  /* --trust-server-cert can only be used with --non-interactive */
+  if (opt_state.trust_server_cert && !opt_state.non_interactive)
+    {
+      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("--trust-server-cert requires "
+                               "--non-interactive"));
+      return EXIT_ERROR(err);
+    }
+
+  /* Ensure that 'revision_ranges' has at least one item, and make
+     'start_revision' and 'end_revision' match that item. */
+  if (opt_state.revision_ranges->nelts == 0)
+    {
+      svn_opt_revision_range_t *range = apr_palloc(pool, sizeof(*range));
+      range->start.kind = svn_opt_revision_unspecified;
+      range->end.kind = svn_opt_revision_unspecified;
+      APR_ARRAY_PUSH(opt_state.revision_ranges,
+                     svn_opt_revision_range_t *) = range;
+    }
+  opt_state.start_revision = APR_ARRAY_IDX(opt_state.revision_ranges, 0,
+                                           svn_opt_revision_range_t *)->start;
+  opt_state.end_revision = APR_ARRAY_IDX(opt_state.revision_ranges, 0,
+                                         svn_opt_revision_range_t *)->end;
+
+  /* Create a client context object. */
+  command_baton.opt_state = &opt_state;
+  SVN_INT_ERR(svn_client_create_context2(&ctx, NULL, pool));
+  command_baton.ctx = ctx;
+
+  /* Only a few commands can accept a revision range; the rest can take at
+     most one revision number. */
+  if (subcommand->cmd_func != svn_cl__null_log)
+    {
+      if (opt_state.end_revision.kind != svn_opt_revision_unspecified)
+        {
+          err = svn_error_create(SVN_ERR_CLIENT_REVISION_RANGE, NULL, NULL);
+          return EXIT_ERROR(err);
+        }
+    }
+
+  /* -N has a different meaning depending on the command */
+  if (descend == FALSE)
+    opt_state.depth = svn_depth_files;
+
+  err = svn_config_get_config(&(ctx->config),
+                              opt_state.config_dir, pool);
+  if (err)
+    {
+      /* Fallback to default config if the config directory isn't readable
+         or is not a directory. */
+      if (APR_STATUS_IS_EACCES(err->apr_err)
+          || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err))
+        {
+          svn_handle_warning2(stderr, err, "svn: ");
+          svn_error_clear(err);
+        }
+      else
+        return EXIT_ERROR(err);
+    }
+
+  cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
+                            APR_HASH_KEY_STRING);
+
+  /* Update the options in the config */
+  if (opt_state.config_options)
+    {
+      svn_error_clear(
+          svn_cmdline__apply_config_options(ctx->config,
+                                            opt_state.config_options,
+                                            "svn: ", "--config-option"));
+    }
+
+  /* Set up the notifier.
+
+     In general, we use it any time we aren't in --quiet mode.  'svn
+     status' is unique, though, in that we don't want it in --quiet mode
+     unless we're also in --verbose mode.  When in --xml mode,
+     though, we never want it.  */
+  if (opt_state.quiet)
+    use_notifier = FALSE;
+  if (use_notifier)
+    {
+      SVN_INT_ERR(svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2,
+                                       pool));
+    }
+
+  /* Set up our cancellation support. */
+  ctx->cancel_func = svn_cl__check_cancel;
+  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
+
+  /* Set up Authentication stuff. */
+  SVN_INT_ERR(svn_cmdline_create_auth_baton(&ab,
+                                            opt_state.non_interactive,
+                                            opt_state.auth_username,
+                                            opt_state.auth_password,
+                                            opt_state.config_dir,
+                                            opt_state.no_auth_cache,
+                                            opt_state.trust_server_cert,
+                                            cfg_config,
+                                            ctx->cancel_func,
+                                            ctx->cancel_baton,
+                                            pool));
+
+  ctx->auth_baton = ab;
+
+  /* The new svn behavior is to postpone everything until after the operation
+     completed */
+  ctx->conflict_func = NULL;
+  ctx->conflict_baton = NULL;
+  ctx->conflict_func2 = NULL;
+  ctx->conflict_baton2 = NULL;
+
+  /* And now we finally run the subcommand. */
+  err = (*subcommand->cmd_func)(os, &command_baton, pool);
+  if (err)
+    {
+      /* For argument-related problems, suggest using the 'help'
+         subcommand. */
+      if (err->apr_err == SVN_ERR_CL_INSUFFICIENT_ARGS
+          || err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR)
+        {
+          err = svn_error_quick_wrap(
+                  err, apr_psprintf(pool,
+                                    _("Try 'svn-bench help %s' for more information"),
+                                    subcommand->name));
+        }
+      if (err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+        {
+          err = svn_error_quick_wrap(err,
+                                     _("Please see the 'svn upgrade' command"));
+        }
+
+      /* Tell the user about 'svn cleanup' if any error on the stack
+         was about locked working copies. */
+      if (svn_error_find_cause(err, SVN_ERR_WC_LOCKED))
+        {
+          err = svn_error_quick_wrap(
+                  err, _("Run 'svn cleanup' to remove locks "
+                         "(type 'svn help cleanup' for details)"));
+        }
+
+      return EXIT_ERROR(err);
+    }
+  else
+    {
+      /* Ensure that stdout is flushed, so the user will see any write errors.
+         This makes sure that output is not silently lost. */
+      SVN_INT_ERR(svn_cmdline_fflush(stdout));
+
+      return EXIT_SUCCESS;
+    }
+}
+
+int
+main(int argc, const char *argv[])
+{
+  apr_pool_t *pool;
+  int exit_code;
+
+  /* Initialize the app. */
+  if (svn_cmdline_init("svn", stderr) != EXIT_SUCCESS)
+    return EXIT_FAILURE;
+
+  /* Create our top-level pool.  Use a separate mutexless allocator,
+   * given this application is single threaded.
+   */
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+
+  exit_code = sub_main(argc, argv, pool);
+
+  svn_pool_destroy(pool);
+  return exit_code;
+}

Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/notify.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/notify.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/notify.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/notify.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,1045 @@
+/*
+ * notify.c:  feedback handlers for cmdline client.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
+#include <apr_want.h>
+
+#include "svn_cmdline.h"
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_sorts.h"
+#include "cl.h"
+
+#include "svn_private_config.h"
+
+
+/* Baton for notify and friends. */
+struct notify_baton
+{
+  svn_boolean_t received_some_change;
+  svn_boolean_t is_checkout;
+  svn_boolean_t is_export;
+  svn_boolean_t is_wc_to_repos_copy;
+  svn_boolean_t sent_first_txdelta;
+  svn_boolean_t in_external;
+  svn_boolean_t had_print_error; /* Used to not keep printing error messages
+                                    when we've already had one print error. */
+
+  /* Conflict stats for update and merge. */
+  unsigned int text_conflicts;
+  unsigned int prop_conflicts;
+  unsigned int tree_conflicts;
+  unsigned int skipped_paths;
+  apr_hash_t *conflicted_paths;
+
+  /* The cwd, for use in decomposing absolute paths. */
+  const char *path_prefix;
+};
+
+
+/* Add a conflicted path to the list of conflicted paths stored
+ * in the notify baton. */
+static void
+add_conflicted_path(struct notify_baton *nb, const char *path)
+{
+  apr_hash_set(nb->conflicted_paths,
+               apr_pstrdup(apr_hash_pool_get(nb->conflicted_paths), path),
+               APR_HASH_KEY_STRING, "");
+}
+
+/* This implements `svn_wc_notify_func2_t'.
+ * NOTE: This function can't fail, so we just ignore any print errors. */
+static void
+notify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool)
+{
+  struct notify_baton *nb = baton;
+  char statchar_buf[5] = "    ";
+  const char *path_local;
+  svn_error_t *err;
+
+  if (n->url)
+    path_local = n->url;
+  else
+    {
+      if (n->path_prefix)
+        path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path,
+                                                       pool);
+      else /* skip nb->path_prefix, if it's non-null */
+        path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path,
+                                                       pool);
+    }
+
+  switch (n->action)
+    {
+    case svn_wc_notify_skip:
+      nb->skipped_paths++;
+      if (n->content_state == svn_wc_notify_state_missing)
+        {
+          if ((err = svn_cmdline_printf
+               (pool, _("Skipped missing target: '%s'\n"),
+                path_local)))
+            goto print_error;
+        }
+      else if (n->content_state == svn_wc_notify_state_source_missing)
+        {
+          if ((err = svn_cmdline_printf
+               (pool, _("Skipped target: '%s' -- copy-source is missing\n"),
+                path_local)))
+            goto print_error;
+        }
+      else
+        {
+          if ((err = svn_cmdline_printf
+               (pool, _("Skipped '%s'\n"), path_local)))
+            goto print_error;
+        }
+      break;
+    case svn_wc_notify_update_skip_obstruction:
+      nb->skipped_paths++;
+      if ((err = svn_cmdline_printf(
+            pool, _("Skipped '%s' -- An obstructing working copy was found\n"),
+            path_local)))
+        goto print_error;
+      break;
+    case svn_wc_notify_update_skip_working_only:
+      nb->skipped_paths++;
+      if ((err = svn_cmdline_printf(
+            pool, _("Skipped '%s' -- Has no versioned parent\n"),
+            path_local)))
+        goto print_error;
+      break;
+    case svn_wc_notify_update_skip_access_denied:
+      nb->skipped_paths++;
+      if ((err = svn_cmdline_printf(
+            pool, _("Skipped '%s' -- Access denied\n"),
+            path_local)))
+        goto print_error;
+      break;
+    case svn_wc_notify_skip_conflicted:
+      nb->skipped_paths++;
+      if ((err = svn_cmdline_printf(
+            pool, _("Skipped '%s' -- Node remains in conflict\n"),
+            path_local)))
+        goto print_error;
+      break;
+    case svn_wc_notify_update_delete:
+    case svn_wc_notify_exclude:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool, "D    %s\n", path_local)))
+        goto print_error;
+      break;
+    case svn_wc_notify_update_broken_lock:
+      if ((err = svn_cmdline_printf(pool, "B    %s\n", path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_external_removed:
+      nb->received_some_change = TRUE;
+      if (n->err && n->err->message)
+        {
+          if ((err = svn_cmdline_printf(pool, "Removed external '%s': %s\n",
+              path_local, n->err->message)))
+            goto print_error;
+        }
+      else
+        {
+          if ((err = svn_cmdline_printf(pool, "Removed external '%s'\n",
+                                        path_local)))
+            goto print_error;
+        }
+      break;
+
+    case svn_wc_notify_left_local_modifications:
+      if ((err = svn_cmdline_printf(pool, "Left local modifications as '%s'\n",
+                                        path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_replace:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool, "R    %s\n", path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_add:
+      nb->received_some_change = TRUE;
+      if (n->content_state == svn_wc_notify_state_conflicted)
+        {
+          nb->text_conflicts++;
+          add_conflicted_path(nb, n->path);
+          if ((err = svn_cmdline_printf(pool, "C    %s\n", path_local)))
+            goto print_error;
+        }
+      else
+        {
+          if ((err = svn_cmdline_printf(pool, "A    %s\n", path_local)))
+            goto print_error;
+        }
+      break;
+
+    case svn_wc_notify_exists:
+      nb->received_some_change = TRUE;
+      if (n->content_state == svn_wc_notify_state_conflicted)
+        {
+          nb->text_conflicts++;
+          add_conflicted_path(nb, n->path);
+          statchar_buf[0] = 'C';
+        }
+      else
+        statchar_buf[0] = 'E';
+
+      if (n->prop_state == svn_wc_notify_state_conflicted)
+        {
+          nb->prop_conflicts++;
+          add_conflicted_path(nb, n->path);
+          statchar_buf[1] = 'C';
+        }
+      else if (n->prop_state == svn_wc_notify_state_merged)
+        statchar_buf[1] = 'G';
+
+      if ((err = svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_restore:
+      if ((err = svn_cmdline_printf(pool, _("Restored '%s'\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_revert:
+      if ((err = svn_cmdline_printf(pool, _("Reverted '%s'\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_failed_revert:
+      if (( err = svn_cmdline_printf(pool, _("Failed to revert '%s' -- "
+                                             "try updating instead.\n"),
+                                     path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_resolved:
+      if ((err = svn_cmdline_printf(pool,
+                                    _("Resolved conflicted state of '%s'\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_add:
+      /* We *should* only get the MIME_TYPE if PATH is a file.  If we
+         do get it, and the mime-type is not textual, note that this
+         is a binary addition. */
+      if (n->mime_type && (svn_mime_type_is_binary(n->mime_type)))
+        {
+          if ((err = svn_cmdline_printf(pool, "A  (bin)  %s\n",
+                                        path_local)))
+            goto print_error;
+        }
+      else
+        {
+          if ((err = svn_cmdline_printf(pool, "A         %s\n",
+                                        path_local)))
+            goto print_error;
+        }
+      break;
+
+    case svn_wc_notify_delete:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool, "D         %s\n",
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_patch:
+      {
+        nb->received_some_change = TRUE;
+        if (n->content_state == svn_wc_notify_state_conflicted)
+          {
+            nb->text_conflicts++;
+            add_conflicted_path(nb, n->path);
+            statchar_buf[0] = 'C';
+          }
+        else if (n->kind == svn_node_file)
+          {
+            if (n->content_state == svn_wc_notify_state_merged)
+              statchar_buf[0] = 'G';
+            else if (n->content_state == svn_wc_notify_state_changed)
+              statchar_buf[0] = 'U';
+          }
+
+        if (n->prop_state == svn_wc_notify_state_conflicted)
+          {
+            nb->prop_conflicts++;
+            add_conflicted_path(nb, n->path);
+            statchar_buf[1] = 'C';
+          }
+        else if (n->prop_state == svn_wc_notify_state_changed)
+              statchar_buf[1] = 'U';
+
+        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
+          {
+            if ((err = svn_cmdline_printf(pool, "%s      %s\n",
+                                          statchar_buf, path_local)))
+              goto print_error;
+          }
+      }
+      break;
+
+    case svn_wc_notify_patch_applied_hunk:
+      nb->received_some_change = TRUE;
+      if (n->hunk_original_start != n->hunk_matched_line)
+        {
+          apr_uint64_t off;
+          const char *s;
+          const char *minus;
+
+          if (n->hunk_matched_line > n->hunk_original_start)
+            {
+              off = n->hunk_matched_line - n->hunk_original_start;
+              minus = "";
+            }
+          else
+            {
+              off = n->hunk_original_start - n->hunk_matched_line;
+              minus = "-";
+            }
+
+          /* ### We're creating the localized strings without
+           * ### APR_INT64_T_FMT since it isn't translator-friendly */
+          if (n->hunk_fuzz)
+            {
+
+              if (n->prop_name)
+                {
+                  s = _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
+                        "with offset %s");
+
+                  err = svn_cmdline_printf(pool,
+                                           apr_pstrcat(pool, s,
+                                                       "%"APR_UINT64_T_FMT
+                                                       " and fuzz %lu (%s)\n",
+                                                       (char *)NULL),
+                                           n->hunk_original_start,
+                                           n->hunk_original_length,
+                                           n->hunk_modified_start,
+                                           n->hunk_modified_length,
+                                           minus, off, n->hunk_fuzz,
+                                           n->prop_name);
+                }
+              else
+                {
+                  s = _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
+                        "with offset %s");
+
+                  err = svn_cmdline_printf(pool,
+                                           apr_pstrcat(pool, s,
+                                                       "%"APR_UINT64_T_FMT
+                                                       " and fuzz %lu\n",
+                                                       (char *)NULL),
+                                           n->hunk_original_start,
+                                           n->hunk_original_length,
+                                           n->hunk_modified_start,
+                                           n->hunk_modified_length,
+                                           minus, off, n->hunk_fuzz);
+                }
+
+              if (err)
+                goto print_error;
+            }
+          else
+            {
+
+              if (n->prop_name)
+                {
+                  s = _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
+                        "with offset %s");
+                  err = svn_cmdline_printf(pool,
+                                            apr_pstrcat(pool, s,
+                                                        "%"APR_UINT64_T_FMT" (%s)\n",
+                                                        (char *)NULL),
+                                            n->hunk_original_start,
+                                            n->hunk_original_length,
+                                            n->hunk_modified_start,
+                                            n->hunk_modified_length,
+                                            minus, off, n->prop_name);
+                }
+              else
+                {
+                  s = _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
+                        "with offset %s");
+                  err = svn_cmdline_printf(pool,
+                                           apr_pstrcat(pool, s,
+                                                       "%"APR_UINT64_T_FMT"\n",
+                                                       (char *)NULL),
+                                           n->hunk_original_start,
+                                           n->hunk_original_length,
+                                           n->hunk_modified_start,
+                                           n->hunk_modified_length,
+                                           minus, off);
+                }
+
+              if (err)
+                goto print_error;
+            }
+        }
+      else if (n->hunk_fuzz)
+        {
+          if (n->prop_name)
+            err = svn_cmdline_printf(pool,
+                          _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
+                                        "with fuzz %lu (%s)\n"),
+                                        n->hunk_original_start,
+                                        n->hunk_original_length,
+                                        n->hunk_modified_start,
+                                        n->hunk_modified_length,
+                                        n->hunk_fuzz,
+                                        n->prop_name);
+          else
+            err = svn_cmdline_printf(pool,
+                          _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
+                                        "with fuzz %lu\n"),
+                                        n->hunk_original_start,
+                                        n->hunk_original_length,
+                                        n->hunk_modified_start,
+                                        n->hunk_modified_length,
+                                        n->hunk_fuzz);
+          if (err)
+            goto print_error;
+
+        }
+      break;
+
+    case svn_wc_notify_patch_rejected_hunk:
+      nb->received_some_change = TRUE;
+
+      if (n->prop_name)
+        err = svn_cmdline_printf(pool,
+                                 _(">         rejected hunk "
+                                   "## -%lu,%lu +%lu,%lu ## (%s)\n"),
+                                 n->hunk_original_start,
+                                 n->hunk_original_length,
+                                 n->hunk_modified_start,
+                                 n->hunk_modified_length,
+                                 n->prop_name);
+      else
+        err = svn_cmdline_printf(pool,
+                                 _(">         rejected hunk "
+                                   "@@ -%lu,%lu +%lu,%lu @@\n"),
+                                 n->hunk_original_start,
+                                 n->hunk_original_length,
+                                 n->hunk_modified_start,
+                                 n->hunk_modified_length);
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_patch_hunk_already_applied:
+      nb->received_some_change = TRUE;
+      if (n->prop_name)
+        err = svn_cmdline_printf(pool,
+                                 _(">         hunk "
+                                   "## -%lu,%lu +%lu,%lu ## "
+                                   "already applied (%s)\n"),
+                                 n->hunk_original_start,
+                                 n->hunk_original_length,
+                                 n->hunk_modified_start,
+                                 n->hunk_modified_length,
+                                 n->prop_name);
+      else
+        err = svn_cmdline_printf(pool,
+                                 _(">         hunk "
+                                   "@@ -%lu,%lu +%lu,%lu @@ "
+                                   "already applied\n"),
+                                 n->hunk_original_start,
+                                 n->hunk_original_length,
+                                 n->hunk_modified_start,
+                                 n->hunk_modified_length);
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_update:
+    case svn_wc_notify_merge_record_info:
+      {
+        if (n->content_state == svn_wc_notify_state_conflicted)
+          {
+            nb->text_conflicts++;
+            add_conflicted_path(nb, n->path);
+            statchar_buf[0] = 'C';
+          }
+        else if (n->kind == svn_node_file)
+          {
+            if (n->content_state == svn_wc_notify_state_merged)
+              statchar_buf[0] = 'G';
+            else if (n->content_state == svn_wc_notify_state_changed)
+              statchar_buf[0] = 'U';
+          }
+
+        if (n->prop_state == svn_wc_notify_state_conflicted)
+          {
+            nb->prop_conflicts++;
+            add_conflicted_path(nb, n->path);
+            statchar_buf[1] = 'C';
+          }
+        else if (n->prop_state == svn_wc_notify_state_merged)
+          statchar_buf[1] = 'G';
+        else if (n->prop_state == svn_wc_notify_state_changed)
+          statchar_buf[1] = 'U';
+
+        if (n->lock_state == svn_wc_notify_lock_state_unlocked)
+          statchar_buf[2] = 'B';
+
+        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
+          nb->received_some_change = TRUE;
+
+        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
+            || statchar_buf[2] != ' ')
+          {
+            if ((err = svn_cmdline_printf(pool, "%s %s\n",
+                                          statchar_buf, path_local)))
+              goto print_error;
+          }
+      }
+      break;
+
+    case svn_wc_notify_update_external:
+      /* Remember that we're now "inside" an externals definition. */
+      nb->in_external = TRUE;
+
+      /* Currently this is used for checkouts and switches too.  If we
+         want different output, we'll have to add new actions. */
+      if ((err = svn_cmdline_printf(pool,
+                                    _("\nFetching external item into '%s':\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_failed_external:
+      /* If we are currently inside the handling of an externals
+         definition, then we can simply present n->err as a warning
+         and feel confident that after this, we aren't handling that
+         externals definition any longer. */
+      if (nb->in_external)
+        {
+          svn_handle_warning2(stderr, n->err, "svn: ");
+          nb->in_external = FALSE;
+          if ((err = svn_cmdline_printf(pool, "\n")))
+            goto print_error;
+        }
+      /* Otherwise, we'll just print two warnings.  Why?  Because
+         svn_handle_warning2() only shows the single "best message",
+         but we have two pretty important ones: that the external at
+         '/some/path' didn't pan out, and then the more specific
+         reason why (from n->err). */
+      else
+        {
+          svn_error_t *warn_err =
+            svn_error_createf(SVN_ERR_BASE, NULL,
+                              _("Error handling externals definition for '%s':"),
+                              path_local);
+          svn_handle_warning2(stderr, warn_err, "svn: ");
+          svn_error_clear(warn_err);
+          svn_handle_warning2(stderr, n->err, "svn: ");
+        }
+      break;
+
+    case svn_wc_notify_update_started:
+      if (! (nb->in_external ||
+             nb->is_checkout ||
+             nb->is_export))
+        {
+          if ((err = svn_cmdline_printf(pool, _("Updating '%s':\n"),
+                                        path_local)))
+            goto print_error;
+        }
+      break;
+
+    case svn_wc_notify_update_completed:
+      {
+        if (SVN_IS_VALID_REVNUM(n->revision))
+          {
+            if (nb->is_export)
+              {
+                if ((err = svn_cmdline_printf
+                     (pool, nb->in_external
+                      ? _("Exported external at revision %ld.\n")
+                      : _("Exported revision %ld.\n"),
+                      n->revision)))
+                  goto print_error;
+              }
+            else if (nb->is_checkout)
+              {
+                if ((err = svn_cmdline_printf
+                     (pool, nb->in_external
+                      ? _("Checked out external at revision %ld.\n")
+                      : _("Checked out revision %ld.\n"),
+                      n->revision)))
+                  goto print_error;
+              }
+            else
+              {
+                if (nb->received_some_change)
+                  {
+                    nb->received_some_change = FALSE;
+                    if ((err = svn_cmdline_printf
+                         (pool, nb->in_external
+                          ? _("Updated external to revision %ld.\n")
+                          : _("Updated to revision %ld.\n"),
+                          n->revision)))
+                      goto print_error;
+                  }
+                else
+                  {
+                    if ((err = svn_cmdline_printf
+                         (pool, nb->in_external
+                          ? _("External at revision %ld.\n")
+                          : _("At revision %ld.\n"),
+                          n->revision)))
+                      goto print_error;
+                  }
+              }
+          }
+        else  /* no revision */
+          {
+            if (nb->is_export)
+              {
+                if ((err = svn_cmdline_printf
+                     (pool, nb->in_external
+                      ? _("External export complete.\n")
+                      : _("Export complete.\n"))))
+                  goto print_error;
+              }
+            else if (nb->is_checkout)
+              {
+                if ((err = svn_cmdline_printf
+                     (pool, nb->in_external
+                      ? _("External checkout complete.\n")
+                      : _("Checkout complete.\n"))))
+                  goto print_error;
+              }
+            else
+              {
+                if ((err = svn_cmdline_printf
+                     (pool, nb->in_external
+                      ? _("External update complete.\n")
+                      : _("Update complete.\n"))))
+                  goto print_error;
+              }
+          }
+      }
+
+      if (nb->in_external)
+        {
+          nb->in_external = FALSE;
+          if ((err = svn_cmdline_printf(pool, "\n")))
+            goto print_error;
+        }
+      break;
+
+    case svn_wc_notify_status_external:
+      if ((err = svn_cmdline_printf
+           (pool, _("\nPerforming status on external item at '%s':\n"),
+            path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_status_completed:
+      if (SVN_IS_VALID_REVNUM(n->revision))
+        if ((err = svn_cmdline_printf(pool,
+                                      _("Status against revision: %6ld\n"),
+                                      n->revision)))
+          goto print_error;
+      break;
+
+    case svn_wc_notify_commit_modified:
+      /* xgettext: Align the %s's on this and the following 4 messages */
+      if ((err = svn_cmdline_printf(pool,
+                                    nb->is_wc_to_repos_copy
+                                      ? _("Sending copy of       %s\n")
+                                      : _("Sending        %s\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_commit_added:
+    case svn_wc_notify_commit_copied:
+      if (n->mime_type && svn_mime_type_is_binary(n->mime_type))
+        {
+          if ((err = svn_cmdline_printf(pool,
+                                        nb->is_wc_to_repos_copy
+                                          ? _("Adding copy of (bin)  %s\n")
+                                          : _("Adding  (bin)  %s\n"),
+                                        path_local)))
+          goto print_error;
+        }
+      else
+        {
+          if ((err = svn_cmdline_printf(pool,
+                                        nb->is_wc_to_repos_copy
+                                          ? _("Adding copy of        %s\n")
+                                          : _("Adding         %s\n"),
+                                        path_local)))
+            goto print_error;
+        }
+      break;
+
+    case svn_wc_notify_commit_deleted:
+      if ((err = svn_cmdline_printf(pool,
+                                    nb->is_wc_to_repos_copy
+                                      ? _("Deleting copy of      %s\n")
+                                      : _("Deleting       %s\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_commit_replaced:
+    case svn_wc_notify_commit_copied_replaced:
+      if ((err = svn_cmdline_printf(pool,
+                                    nb->is_wc_to_repos_copy
+                                      ? _("Replacing copy of     %s\n")
+                                      : _("Replacing      %s\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_commit_postfix_txdelta:
+      if (! nb->sent_first_txdelta)
+        {
+          nb->sent_first_txdelta = TRUE;
+          if ((err = svn_cmdline_printf(pool,
+                                        _("Transmitting file data "))))
+            goto print_error;
+        }
+
+      if ((err = svn_cmdline_printf(pool, ".")))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_locked:
+      if ((err = svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"),
+                                    path_local, n->lock->owner)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_unlocked:
+      if ((err = svn_cmdline_printf(pool, _("'%s' unlocked.\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_failed_lock:
+    case svn_wc_notify_failed_unlock:
+      svn_handle_warning2(stderr, n->err, "svn: ");
+      break;
+
+    case svn_wc_notify_changelist_set:
+      if ((err = svn_cmdline_printf(pool, "A [%s] %s\n",
+                                    n->changelist_name, path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_changelist_clear:
+    case svn_wc_notify_changelist_moved:
+      if ((err = svn_cmdline_printf(pool,
+                                    "D [%s] %s\n",
+                                    n->changelist_name, path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_merge_begin:
+      if (n->merge_range == NULL)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Merging differences between "
+                                   "repository URLs into '%s':\n"),
+                                 path_local);
+      else if (n->merge_range->start == n->merge_range->end - 1
+          || n->merge_range->start == n->merge_range->end)
+        err = svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"),
+                                 n->merge_range->end, path_local);
+      else if (n->merge_range->start - 1 == n->merge_range->end)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Reverse-merging r%ld into '%s':\n"),
+                                 n->merge_range->start, path_local);
+      else if (n->merge_range->start < n->merge_range->end)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Merging r%ld through r%ld into "
+                                   "'%s':\n"),
+                                 n->merge_range->start + 1,
+                                 n->merge_range->end, path_local);
+      else /* n->merge_range->start > n->merge_range->end - 1 */
+        err = svn_cmdline_printf(pool,
+                                 _("--- Reverse-merging r%ld through r%ld "
+                                   "into '%s':\n"),
+                                 n->merge_range->start,
+                                 n->merge_range->end + 1, path_local);
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_merge_record_info_begin:
+      if (!n->merge_range)
+        {
+          err = svn_cmdline_printf(pool,
+                                   _("--- Recording mergeinfo for merge "
+                                     "between repository URLs into '%s':\n"),
+                                   path_local);
+        }
+      else
+        {
+          if (n->merge_range->start == n->merge_range->end - 1
+              || n->merge_range->start == n->merge_range->end)
+            err = svn_cmdline_printf(
+              pool,
+              _("--- Recording mergeinfo for merge of r%ld into '%s':\n"),
+              n->merge_range->end, path_local);
+          else if (n->merge_range->start - 1 == n->merge_range->end)
+            err = svn_cmdline_printf(
+              pool,
+              _("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"),
+              n->merge_range->start, path_local);
+           else if (n->merge_range->start < n->merge_range->end)
+             err = svn_cmdline_printf(
+               pool,
+               _("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"),
+               n->merge_range->start + 1, n->merge_range->end, path_local);
+           else /* n->merge_range->start > n->merge_range->end - 1 */
+             err = svn_cmdline_printf(
+               pool,
+               _("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"),
+               n->merge_range->start, n->merge_range->end + 1, path_local);
+        }
+
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_merge_elide_info:
+      if ((err = svn_cmdline_printf(pool,
+                                    _("--- Eliding mergeinfo from '%s':\n"),
+                                    path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_foreign_merge_begin:
+      if (n->merge_range == NULL)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Merging differences between "
+                                   "foreign repository URLs into '%s':\n"),
+                                 path_local);
+      else if (n->merge_range->start == n->merge_range->end - 1
+          || n->merge_range->start == n->merge_range->end)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Merging (from foreign repository) "
+                                   "r%ld into '%s':\n"),
+                                 n->merge_range->end, path_local);
+      else if (n->merge_range->start - 1 == n->merge_range->end)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Reverse-merging (from foreign "
+                                   "repository) r%ld into '%s':\n"),
+                                 n->merge_range->start, path_local);
+      else if (n->merge_range->start < n->merge_range->end)
+        err = svn_cmdline_printf(pool,
+                                 _("--- Merging (from foreign repository) "
+                                   "r%ld through r%ld into '%s':\n"),
+                                 n->merge_range->start + 1,
+                                 n->merge_range->end, path_local);
+      else /* n->merge_range->start > n->merge_range->end - 1 */
+        err = svn_cmdline_printf(pool,
+                                 _("--- Reverse-merging (from foreign "
+                                   "repository) r%ld through r%ld into "
+                                   "'%s':\n"),
+                                 n->merge_range->start,
+                                 n->merge_range->end + 1, path_local);
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_tree_conflict:
+      nb->tree_conflicts++;
+      add_conflicted_path(nb, n->path);
+      if ((err = svn_cmdline_printf(pool, "   C %s\n", path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_shadowed_add:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool, "   A %s\n", path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_shadowed_update:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool, "   U %s\n", path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_update_shadowed_delete:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool, "   D %s\n", path_local)))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_property_modified:
+    case svn_wc_notify_property_added:
+        err = svn_cmdline_printf(pool,
+                                 _("property '%s' set on '%s'\n"),
+                                 n->prop_name, path_local);
+        if (err)
+          goto print_error;
+      break;
+
+    case svn_wc_notify_property_deleted:
+        err = svn_cmdline_printf(pool,
+                                 _("property '%s' deleted from '%s'.\n"),
+                                 n->prop_name, path_local);
+        if (err)
+          goto print_error;
+      break;
+
+    case svn_wc_notify_property_deleted_nonexistent:
+        err = svn_cmdline_printf(pool,
+                                 _("Attempting to delete nonexistent "
+                                   "property '%s' on '%s'\n"), n->prop_name,
+                                   path_local);
+        if (err)
+          goto print_error;
+      break;
+
+    case svn_wc_notify_revprop_set:
+        err = svn_cmdline_printf(pool,
+                          _("property '%s' set on repository revision %ld\n"),
+                          n->prop_name, n->revision);
+        if (err)
+          goto print_error;
+      break;
+
+    case svn_wc_notify_revprop_deleted:
+        err = svn_cmdline_printf(pool,
+                     _("property '%s' deleted from repository revision %ld\n"),
+                     n->prop_name, n->revision);
+        if (err)
+          goto print_error;
+      break;
+
+    case svn_wc_notify_upgraded_path:
+        err = svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local);
+        if (err)
+          goto print_error;
+      break;
+
+    case svn_wc_notify_url_redirect:
+      err = svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"),
+                               n->url);
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_path_nonexistent:
+      err = svn_cmdline_printf(pool, _("'%s' is not under version control"),
+                               path_local);
+      if (err)
+        goto print_error;
+      break;
+
+    case svn_wc_notify_conflict_resolver_starting:
+      /* Once all operations invoke the interactive conflict resolution after
+       * they've completed, we can run svn_cl__print_conflict_stats() here. */
+      break;
+
+    case svn_wc_notify_conflict_resolver_done:
+      break;
+
+    default:
+      break;
+    }
+
+  if ((err = svn_cmdline_fflush(stdout)))
+    goto print_error;
+
+  return;
+
+ print_error:
+  /* If we had no errors before, print this error to stderr. Else, don't print
+     anything.  The user already knows there were some output errors,
+     so there is no point in flooding her with an error per notification. */
+  if (!nb->had_print_error)
+    {
+      nb->had_print_error = TRUE;
+      /* Issue #3014:
+       * Don't print anything on broken pipes. The pipe was likely
+       * closed by the process at the other end. We expect that
+       * process to perform error reporting as necessary.
+       *
+       * ### This assumes that there is only one error in a chain for
+       * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
+      if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
+        svn_handle_error2(err, stderr, FALSE, "svn: ");
+    }
+  svn_error_clear(err);
+}
+
+
+svn_error_t *
+svn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p,
+                     void **notify_baton_p,
+                     apr_pool_t *pool)
+{
+  struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb));
+
+  nb->received_some_change = FALSE;
+  nb->sent_first_txdelta = FALSE;
+  nb->is_checkout = FALSE;
+  nb->is_export = FALSE;
+  nb->is_wc_to_repos_copy = FALSE;
+  nb->in_external = FALSE;
+  nb->had_print_error = FALSE;
+  nb->text_conflicts = 0;
+  nb->prop_conflicts = 0;
+  nb->tree_conflicts = 0;
+  nb->skipped_paths = 0;
+  nb->conflicted_paths = apr_hash_make(pool);
+  SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool));
+
+  *notify_func_p = notify;
+  *notify_baton_p = nb;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cl__notifier_mark_export(void *baton)
+{
+  struct notify_baton *nb = baton;
+
+  nb->is_export = TRUE;
+  return SVN_NO_ERROR;
+}