notify.c revision 289180
1251881Speter/*
2251881Speter * notify.c:  feedback handlers for cmdline client.
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter/* ==================================================================== */
25251881Speter
26251881Speter
27251881Speter
28251881Speter/*** Includes. ***/
29251881Speter
30251881Speter#define APR_WANT_STDIO
31251881Speter#define APR_WANT_STRFUNC
32251881Speter#include <apr_want.h>
33251881Speter
34251881Speter#include "svn_cmdline.h"
35251881Speter#include "svn_pools.h"
36251881Speter#include "svn_dirent_uri.h"
37251881Speter#include "svn_path.h"
38251881Speter#include "svn_sorts.h"
39251881Speter#include "svn_hash.h"
40251881Speter#include "cl.h"
41251881Speter#include "private/svn_subr_private.h"
42251881Speter#include "private/svn_dep_compat.h"
43251881Speter
44251881Speter#include "svn_private_config.h"
45251881Speter
46251881Speter
47251881Speter/* Baton for notify and friends. */
48251881Speterstruct notify_baton
49251881Speter{
50251881Speter  svn_boolean_t received_some_change;
51251881Speter  svn_boolean_t is_checkout;
52251881Speter  svn_boolean_t is_export;
53251881Speter  svn_boolean_t is_wc_to_repos_copy;
54251881Speter  svn_boolean_t sent_first_txdelta;
55289180Speter  int in_external;
56251881Speter  svn_boolean_t had_print_error; /* Used to not keep printing error messages
57251881Speter                                    when we've already had one print error. */
58251881Speter
59251881Speter  svn_cl__conflict_stats_t *conflict_stats;
60251881Speter
61251881Speter  /* The cwd, for use in decomposing absolute paths. */
62251881Speter  const char *path_prefix;
63251881Speter};
64251881Speter
65251881Speter/* Conflict stats for operations such as update and merge. */
66251881Speterstruct svn_cl__conflict_stats_t
67251881Speter{
68251881Speter  apr_pool_t *stats_pool;
69251881Speter  apr_hash_t *text_conflicts, *prop_conflicts, *tree_conflicts;
70251881Speter  int text_conflicts_resolved, prop_conflicts_resolved, tree_conflicts_resolved;
71251881Speter  int skipped_paths;
72251881Speter};
73251881Speter
74251881Spetersvn_cl__conflict_stats_t *
75251881Spetersvn_cl__conflict_stats_create(apr_pool_t *pool)
76251881Speter{
77251881Speter  svn_cl__conflict_stats_t *conflict_stats
78251881Speter    = apr_palloc(pool, sizeof(*conflict_stats));
79251881Speter
80251881Speter  conflict_stats->stats_pool = pool;
81251881Speter  conflict_stats->text_conflicts = apr_hash_make(pool);
82251881Speter  conflict_stats->prop_conflicts = apr_hash_make(pool);
83251881Speter  conflict_stats->tree_conflicts = apr_hash_make(pool);
84251881Speter  conflict_stats->text_conflicts_resolved = 0;
85251881Speter  conflict_stats->prop_conflicts_resolved = 0;
86251881Speter  conflict_stats->tree_conflicts_resolved = 0;
87251881Speter  conflict_stats->skipped_paths = 0;
88251881Speter  return conflict_stats;
89251881Speter}
90251881Speter
91251881Speter/* Add the PATH (as a key, with a meaningless value) into the HASH in NB. */
92251881Speterstatic void
93251881Speterstore_path(struct notify_baton *nb, apr_hash_t *hash, const char *path)
94251881Speter{
95251881Speter  svn_hash_sets(hash, apr_pstrdup(nb->conflict_stats->stats_pool, path), "");
96251881Speter}
97251881Speter
98251881Spetervoid
99251881Spetersvn_cl__conflict_stats_resolved(svn_cl__conflict_stats_t *conflict_stats,
100251881Speter                                const char *path_local,
101251881Speter                                svn_wc_conflict_kind_t conflict_kind)
102251881Speter{
103251881Speter  switch (conflict_kind)
104251881Speter    {
105251881Speter      case svn_wc_conflict_kind_text:
106251881Speter        if (svn_hash_gets(conflict_stats->text_conflicts, path_local))
107251881Speter          {
108251881Speter            svn_hash_sets(conflict_stats->text_conflicts, path_local, NULL);
109251881Speter            conflict_stats->text_conflicts_resolved++;
110251881Speter          }
111251881Speter        break;
112251881Speter      case svn_wc_conflict_kind_property:
113251881Speter        if (svn_hash_gets(conflict_stats->prop_conflicts, path_local))
114251881Speter          {
115251881Speter            svn_hash_sets(conflict_stats->prop_conflicts, path_local, NULL);
116251881Speter            conflict_stats->prop_conflicts_resolved++;
117251881Speter          }
118251881Speter        break;
119251881Speter      case svn_wc_conflict_kind_tree:
120251881Speter        if (svn_hash_gets(conflict_stats->tree_conflicts, path_local))
121251881Speter          {
122251881Speter            svn_hash_sets(conflict_stats->tree_conflicts, path_local, NULL);
123251881Speter            conflict_stats->tree_conflicts_resolved++;
124251881Speter          }
125251881Speter        break;
126251881Speter    }
127251881Speter}
128251881Speter
129251881Speterstatic const char *
130251881Speterremaining_str(apr_pool_t *pool, int n_remaining)
131251881Speter{
132289180Speter  return apr_psprintf(pool, Q_("%d remaining",
133251881Speter                               "%d remaining",
134251881Speter                               n_remaining),
135251881Speter                      n_remaining);
136251881Speter}
137251881Speter
138251881Speterstatic const char *
139251881Speterresolved_str(apr_pool_t *pool, int n_resolved)
140251881Speter{
141251881Speter  return apr_psprintf(pool, Q_("and %d already resolved",
142251881Speter                               "and %d already resolved",
143251881Speter                               n_resolved),
144251881Speter                      n_resolved);
145251881Speter}
146251881Speter
147251881Spetersvn_error_t *
148289180Spetersvn_cl__print_conflict_stats(svn_cl__conflict_stats_t *conflict_stats,
149289180Speter                             apr_pool_t *scratch_pool)
150251881Speter{
151289180Speter  int n_text = apr_hash_count(conflict_stats->text_conflicts);
152289180Speter  int n_prop = apr_hash_count(conflict_stats->prop_conflicts);
153289180Speter  int n_tree = apr_hash_count(conflict_stats->tree_conflicts);
154289180Speter  int n_text_r = conflict_stats->text_conflicts_resolved;
155289180Speter  int n_prop_r = conflict_stats->prop_conflicts_resolved;
156289180Speter  int n_tree_r = conflict_stats->tree_conflicts_resolved;
157251881Speter
158251881Speter  if (n_text > 0 || n_text_r > 0
159251881Speter      || n_prop > 0 || n_prop_r > 0
160251881Speter      || n_tree > 0 || n_tree_r > 0
161289180Speter      || conflict_stats->skipped_paths > 0)
162251881Speter    SVN_ERR(svn_cmdline_printf(scratch_pool,
163251881Speter                               _("Summary of conflicts:\n")));
164251881Speter
165251881Speter  if (n_text_r == 0 && n_prop_r == 0 && n_tree_r == 0)
166251881Speter    {
167251881Speter      if (n_text > 0)
168251881Speter        SVN_ERR(svn_cmdline_printf(scratch_pool,
169251881Speter          _("  Text conflicts: %d\n"),
170251881Speter          n_text));
171251881Speter      if (n_prop > 0)
172251881Speter        SVN_ERR(svn_cmdline_printf(scratch_pool,
173251881Speter          _("  Property conflicts: %d\n"),
174251881Speter          n_prop));
175251881Speter      if (n_tree > 0)
176251881Speter        SVN_ERR(svn_cmdline_printf(scratch_pool,
177251881Speter          _("  Tree conflicts: %d\n"),
178251881Speter          n_tree));
179251881Speter    }
180251881Speter  else
181251881Speter    {
182251881Speter      if (n_text > 0 || n_text_r > 0)
183251881Speter        SVN_ERR(svn_cmdline_printf(scratch_pool,
184251881Speter                                   _("  Text conflicts: %s (%s)\n"),
185251881Speter                                   remaining_str(scratch_pool, n_text),
186251881Speter                                   resolved_str(scratch_pool, n_text_r)));
187251881Speter      if (n_prop > 0 || n_prop_r > 0)
188251881Speter        SVN_ERR(svn_cmdline_printf(scratch_pool,
189251881Speter                                   _("  Property conflicts: %s (%s)\n"),
190251881Speter                                   remaining_str(scratch_pool, n_prop),
191251881Speter                                   resolved_str(scratch_pool, n_prop_r)));
192251881Speter      if (n_tree > 0 || n_tree_r > 0)
193251881Speter        SVN_ERR(svn_cmdline_printf(scratch_pool,
194251881Speter                                   _("  Tree conflicts: %s (%s)\n"),
195251881Speter                                   remaining_str(scratch_pool, n_tree),
196251881Speter                                   resolved_str(scratch_pool, n_tree_r)));
197251881Speter    }
198289180Speter  if (conflict_stats->skipped_paths > 0)
199251881Speter    SVN_ERR(svn_cmdline_printf(scratch_pool,
200251881Speter                               _("  Skipped paths: %d\n"),
201289180Speter                               conflict_stats->skipped_paths));
202251881Speter
203251881Speter  return SVN_NO_ERROR;
204251881Speter}
205251881Speter
206289180Spetersvn_error_t *
207289180Spetersvn_cl__notifier_print_conflict_stats(void *baton, apr_pool_t *scratch_pool)
208251881Speter{
209251881Speter  struct notify_baton *nb = baton;
210289180Speter
211289180Speter  SVN_ERR(svn_cl__print_conflict_stats(nb->conflict_stats, scratch_pool));
212289180Speter  return SVN_NO_ERROR;
213289180Speter}
214289180Speter
215289180Speter/* The body for notify() function with standard error handling semantic.
216289180Speter * Handling of errors implemented at caller side. */
217289180Speterstatic svn_error_t *
218289180Speternotify_body(struct notify_baton *nb,
219289180Speter            const svn_wc_notify_t *n,
220289180Speter            apr_pool_t *pool)
221289180Speter{
222251881Speter  char statchar_buf[5] = "    ";
223251881Speter  const char *path_local;
224251881Speter
225251881Speter  if (n->url)
226251881Speter    path_local = n->url;
227251881Speter  else
228251881Speter    {
229289180Speter      /* Skip the path prefix in N, if supplied, or else the path prefix
230289180Speter         in NB (which was set to the current working directory). */
231251881Speter      if (n->path_prefix)
232251881Speter        path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path,
233251881Speter                                                       pool);
234289180Speter      else
235251881Speter        path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path,
236251881Speter                                                       pool);
237251881Speter    }
238251881Speter
239251881Speter  switch (n->action)
240251881Speter    {
241251881Speter    case svn_wc_notify_skip:
242251881Speter      nb->conflict_stats->skipped_paths++;
243251881Speter      if (n->content_state == svn_wc_notify_state_missing)
244251881Speter        {
245289180Speter          SVN_ERR(svn_cmdline_printf(pool,
246289180Speter                                     _("Skipped missing target: '%s'\n"),
247289180Speter                                     path_local));
248251881Speter        }
249251881Speter      else if (n->content_state == svn_wc_notify_state_source_missing)
250251881Speter        {
251289180Speter          SVN_ERR(svn_cmdline_printf(
252289180Speter                    pool,
253289180Speter                    _("Skipped target: '%s' -- copy-source is missing\n"),
254289180Speter                    path_local));
255251881Speter        }
256251881Speter      else
257251881Speter        {
258289180Speter          SVN_ERR(svn_cmdline_printf(pool, _("Skipped '%s'\n"), path_local));
259251881Speter        }
260251881Speter      break;
261251881Speter    case svn_wc_notify_update_skip_obstruction:
262251881Speter      nb->conflict_stats->skipped_paths++;
263289180Speter      SVN_ERR(svn_cmdline_printf(
264289180Speter                pool,
265289180Speter                _("Skipped '%s' -- An obstructing working copy was found\n"),
266289180Speter                path_local));
267251881Speter      break;
268251881Speter    case svn_wc_notify_update_skip_working_only:
269251881Speter      nb->conflict_stats->skipped_paths++;
270289180Speter      SVN_ERR(svn_cmdline_printf(
271289180Speter                pool, _("Skipped '%s' -- Has no versioned parent\n"),
272289180Speter                path_local));
273251881Speter      break;
274251881Speter    case svn_wc_notify_update_skip_access_denied:
275251881Speter      nb->conflict_stats->skipped_paths++;
276289180Speter      SVN_ERR(svn_cmdline_printf(
277289180Speter                pool, _("Skipped '%s' -- Access denied\n"),
278289180Speter                path_local));
279251881Speter      break;
280251881Speter    case svn_wc_notify_skip_conflicted:
281251881Speter      nb->conflict_stats->skipped_paths++;
282289180Speter      SVN_ERR(svn_cmdline_printf(
283289180Speter                pool, _("Skipped '%s' -- Node remains in conflict\n"),
284289180Speter                path_local));
285251881Speter      break;
286251881Speter    case svn_wc_notify_update_delete:
287251881Speter    case svn_wc_notify_exclude:
288251881Speter      nb->received_some_change = TRUE;
289289180Speter      SVN_ERR(svn_cmdline_printf(pool, "D    %s\n", path_local));
290251881Speter      break;
291251881Speter    case svn_wc_notify_update_broken_lock:
292289180Speter      SVN_ERR(svn_cmdline_printf(pool, "B    %s\n", path_local));
293251881Speter      break;
294251881Speter
295251881Speter    case svn_wc_notify_update_external_removed:
296251881Speter      nb->received_some_change = TRUE;
297251881Speter      if (n->err && n->err->message)
298251881Speter        {
299289180Speter          SVN_ERR(svn_cmdline_printf(pool, _("Removed external '%s': %s\n"),
300289180Speter                                     path_local, n->err->message));
301251881Speter        }
302251881Speter      else
303251881Speter        {
304289180Speter          SVN_ERR(svn_cmdline_printf(pool, _("Removed external '%s'\n"),
305289180Speter                                     path_local));
306251881Speter        }
307251881Speter      break;
308251881Speter
309251881Speter    case svn_wc_notify_left_local_modifications:
310289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Left local modifications as '%s'\n"),
311289180Speter                                 path_local));
312251881Speter      break;
313251881Speter
314251881Speter    case svn_wc_notify_update_replace:
315251881Speter      nb->received_some_change = TRUE;
316289180Speter      SVN_ERR(svn_cmdline_printf(pool, "R    %s\n", path_local));
317251881Speter      break;
318251881Speter
319251881Speter    case svn_wc_notify_update_add:
320251881Speter      nb->received_some_change = TRUE;
321251881Speter      if (n->content_state == svn_wc_notify_state_conflicted)
322251881Speter        {
323251881Speter          store_path(nb, nb->conflict_stats->text_conflicts, path_local);
324289180Speter          SVN_ERR(svn_cmdline_printf(pool, "C    %s\n", path_local));
325251881Speter        }
326251881Speter      else
327251881Speter        {
328289180Speter          SVN_ERR(svn_cmdline_printf(pool, "A    %s\n", path_local));
329251881Speter        }
330251881Speter      break;
331251881Speter
332251881Speter    case svn_wc_notify_exists:
333251881Speter      nb->received_some_change = TRUE;
334251881Speter      if (n->content_state == svn_wc_notify_state_conflicted)
335251881Speter        {
336251881Speter          store_path(nb, nb->conflict_stats->text_conflicts, path_local);
337251881Speter          statchar_buf[0] = 'C';
338251881Speter        }
339251881Speter      else
340251881Speter        statchar_buf[0] = 'E';
341251881Speter
342251881Speter      if (n->prop_state == svn_wc_notify_state_conflicted)
343251881Speter        {
344251881Speter          store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
345251881Speter          statchar_buf[1] = 'C';
346251881Speter        }
347251881Speter      else if (n->prop_state == svn_wc_notify_state_merged)
348251881Speter        statchar_buf[1] = 'G';
349251881Speter
350289180Speter      SVN_ERR(svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local));
351251881Speter      break;
352251881Speter
353251881Speter    case svn_wc_notify_restore:
354289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Restored '%s'\n"),
355289180Speter                                 path_local));
356251881Speter      break;
357251881Speter
358251881Speter    case svn_wc_notify_revert:
359289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Reverted '%s'\n"),
360289180Speter                                 path_local));
361251881Speter      break;
362251881Speter
363251881Speter    case svn_wc_notify_failed_revert:
364289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Failed to revert '%s' -- "
365289180Speter                                         "try updating instead.\n"),
366289180Speter                                 path_local));
367251881Speter      break;
368251881Speter
369251881Speter    case svn_wc_notify_resolved:
370289180Speter      SVN_ERR(svn_cmdline_printf(pool,
371289180Speter                                 _("Resolved conflicted state of '%s'\n"),
372289180Speter                                 path_local));
373251881Speter      break;
374251881Speter
375251881Speter    case svn_wc_notify_add:
376251881Speter      /* We *should* only get the MIME_TYPE if PATH is a file.  If we
377251881Speter         do get it, and the mime-type is not textual, note that this
378251881Speter         is a binary addition. */
379251881Speter      if (n->mime_type && (svn_mime_type_is_binary(n->mime_type)))
380251881Speter        {
381289180Speter          SVN_ERR(svn_cmdline_printf(pool, "A  (bin)  %s\n",
382289180Speter                                     path_local));
383251881Speter        }
384251881Speter      else
385251881Speter        {
386289180Speter          SVN_ERR(svn_cmdline_printf(pool, "A         %s\n",
387289180Speter                                     path_local));
388251881Speter        }
389251881Speter      break;
390251881Speter
391251881Speter    case svn_wc_notify_delete:
392251881Speter      nb->received_some_change = TRUE;
393289180Speter      SVN_ERR(svn_cmdline_printf(pool, "D         %s\n",
394289180Speter                                 path_local));
395251881Speter      break;
396251881Speter
397251881Speter    case svn_wc_notify_patch:
398251881Speter      {
399251881Speter        nb->received_some_change = TRUE;
400251881Speter        if (n->content_state == svn_wc_notify_state_conflicted)
401251881Speter          {
402251881Speter            store_path(nb, nb->conflict_stats->text_conflicts, path_local);
403251881Speter            statchar_buf[0] = 'C';
404251881Speter          }
405251881Speter        else if (n->kind == svn_node_file)
406251881Speter          {
407251881Speter            if (n->content_state == svn_wc_notify_state_merged)
408251881Speter              statchar_buf[0] = 'G';
409251881Speter            else if (n->content_state == svn_wc_notify_state_changed)
410251881Speter              statchar_buf[0] = 'U';
411251881Speter          }
412251881Speter
413251881Speter        if (n->prop_state == svn_wc_notify_state_conflicted)
414251881Speter          {
415251881Speter            store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
416251881Speter            statchar_buf[1] = 'C';
417251881Speter          }
418251881Speter        else if (n->prop_state == svn_wc_notify_state_changed)
419251881Speter              statchar_buf[1] = 'U';
420251881Speter
421251881Speter        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
422251881Speter          {
423289180Speter            SVN_ERR(svn_cmdline_printf(pool, "%s      %s\n",
424289180Speter                                       statchar_buf, path_local));
425251881Speter          }
426251881Speter      }
427251881Speter      break;
428251881Speter
429251881Speter    case svn_wc_notify_patch_applied_hunk:
430251881Speter      nb->received_some_change = TRUE;
431251881Speter      if (n->hunk_original_start != n->hunk_matched_line)
432251881Speter        {
433251881Speter          apr_uint64_t off;
434251881Speter          const char *s;
435251881Speter          const char *minus;
436251881Speter
437251881Speter          if (n->hunk_matched_line > n->hunk_original_start)
438251881Speter            {
439251881Speter              /* If we are patching from the start of an empty file,
440251881Speter                 it is nicer to show offset 0 */
441251881Speter              if (n->hunk_original_start == 0 && n->hunk_matched_line == 1)
442251881Speter                off = 0; /* No offset, just adding */
443251881Speter              else
444251881Speter                off = n->hunk_matched_line - n->hunk_original_start;
445251881Speter
446251881Speter              minus = "";
447251881Speter            }
448251881Speter          else
449251881Speter            {
450251881Speter              off = n->hunk_original_start - n->hunk_matched_line;
451251881Speter              minus = "-";
452251881Speter            }
453251881Speter
454251881Speter          /* ### We're creating the localized strings without
455251881Speter           * ### APR_INT64_T_FMT since it isn't translator-friendly */
456251881Speter          if (n->hunk_fuzz)
457251881Speter            {
458251881Speter
459251881Speter              if (n->prop_name)
460251881Speter                {
461251881Speter                  s = _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
462251881Speter                        "with offset %s");
463251881Speter
464289180Speter                  SVN_ERR(svn_cmdline_printf(pool,
465289180Speter                                             apr_pstrcat(pool, s,
466289180Speter                                                         "%"APR_UINT64_T_FMT
467289180Speter                                                         " and fuzz %lu (%s)\n",
468289180Speter                                                         SVN_VA_NULL),
469289180Speter                                             n->hunk_original_start,
470289180Speter                                             n->hunk_original_length,
471289180Speter                                             n->hunk_modified_start,
472289180Speter                                             n->hunk_modified_length,
473289180Speter                                             minus, off, n->hunk_fuzz,
474289180Speter                                             n->prop_name));
475251881Speter                }
476251881Speter              else
477251881Speter                {
478251881Speter                  s = _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
479251881Speter                        "with offset %s");
480251881Speter
481289180Speter                  SVN_ERR(svn_cmdline_printf(pool,
482289180Speter                                             apr_pstrcat(pool, s,
483289180Speter                                                         "%"APR_UINT64_T_FMT
484289180Speter                                                         " and fuzz %lu\n",
485289180Speter                                                         SVN_VA_NULL),
486289180Speter                                             n->hunk_original_start,
487289180Speter                                             n->hunk_original_length,
488289180Speter                                             n->hunk_modified_start,
489289180Speter                                             n->hunk_modified_length,
490289180Speter                                             minus, off, n->hunk_fuzz));
491251881Speter                }
492251881Speter            }
493251881Speter          else
494251881Speter            {
495251881Speter
496251881Speter              if (n->prop_name)
497251881Speter                {
498251881Speter                  s = _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
499251881Speter                        "with offset %s");
500289180Speter                  SVN_ERR(svn_cmdline_printf(pool,
501289180Speter                                              apr_pstrcat(pool, s,
502289180Speter                                                          "%"APR_UINT64_T_FMT" (%s)\n",
503289180Speter                                                          SVN_VA_NULL),
504289180Speter                                              n->hunk_original_start,
505289180Speter                                              n->hunk_original_length,
506289180Speter                                              n->hunk_modified_start,
507289180Speter                                              n->hunk_modified_length,
508289180Speter                                              minus, off, n->prop_name));
509251881Speter                }
510251881Speter              else
511251881Speter                {
512251881Speter                  s = _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
513251881Speter                        "with offset %s");
514289180Speter                  SVN_ERR(svn_cmdline_printf(pool,
515289180Speter                                             apr_pstrcat(pool, s,
516289180Speter                                                         "%"APR_UINT64_T_FMT"\n",
517289180Speter                                                         SVN_VA_NULL),
518289180Speter                                             n->hunk_original_start,
519289180Speter                                             n->hunk_original_length,
520289180Speter                                             n->hunk_modified_start,
521289180Speter                                             n->hunk_modified_length,
522289180Speter                                             minus, off));
523251881Speter                }
524251881Speter            }
525251881Speter        }
526251881Speter      else if (n->hunk_fuzz)
527251881Speter        {
528251881Speter          if (n->prop_name)
529289180Speter            SVN_ERR(svn_cmdline_printf(pool,
530251881Speter                          _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
531251881Speter                                        "with fuzz %lu (%s)\n"),
532251881Speter                                        n->hunk_original_start,
533251881Speter                                        n->hunk_original_length,
534251881Speter                                        n->hunk_modified_start,
535251881Speter                                        n->hunk_modified_length,
536251881Speter                                        n->hunk_fuzz,
537289180Speter                                        n->prop_name));
538251881Speter          else
539289180Speter            SVN_ERR(svn_cmdline_printf(pool,
540251881Speter                          _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
541251881Speter                                        "with fuzz %lu\n"),
542251881Speter                                        n->hunk_original_start,
543251881Speter                                        n->hunk_original_length,
544251881Speter                                        n->hunk_modified_start,
545251881Speter                                        n->hunk_modified_length,
546289180Speter                                        n->hunk_fuzz));
547251881Speter
548251881Speter        }
549251881Speter      break;
550251881Speter
551251881Speter    case svn_wc_notify_patch_rejected_hunk:
552251881Speter      nb->received_some_change = TRUE;
553251881Speter
554251881Speter      if (n->prop_name)
555289180Speter        SVN_ERR(svn_cmdline_printf(pool,
556289180Speter                                   _(">         rejected hunk "
557289180Speter                                     "## -%lu,%lu +%lu,%lu ## (%s)\n"),
558289180Speter                                   n->hunk_original_start,
559289180Speter                                   n->hunk_original_length,
560289180Speter                                   n->hunk_modified_start,
561289180Speter                                   n->hunk_modified_length,
562289180Speter                                   n->prop_name));
563251881Speter      else
564289180Speter        SVN_ERR(svn_cmdline_printf(pool,
565289180Speter                                   _(">         rejected hunk "
566289180Speter                                     "@@ -%lu,%lu +%lu,%lu @@\n"),
567289180Speter                                   n->hunk_original_start,
568289180Speter                                   n->hunk_original_length,
569289180Speter                                   n->hunk_modified_start,
570289180Speter                                   n->hunk_modified_length));
571251881Speter      break;
572251881Speter
573251881Speter    case svn_wc_notify_patch_hunk_already_applied:
574251881Speter      nb->received_some_change = TRUE;
575251881Speter      if (n->prop_name)
576289180Speter        SVN_ERR(svn_cmdline_printf(pool,
577289180Speter                                   _(">         hunk "
578289180Speter                                     "## -%lu,%lu +%lu,%lu ## "
579289180Speter                                     "already applied (%s)\n"),
580289180Speter                                   n->hunk_original_start,
581289180Speter                                   n->hunk_original_length,
582289180Speter                                   n->hunk_modified_start,
583289180Speter                                   n->hunk_modified_length,
584289180Speter                                   n->prop_name));
585251881Speter      else
586289180Speter        SVN_ERR(svn_cmdline_printf(pool,
587289180Speter                                   _(">         hunk "
588289180Speter                                     "@@ -%lu,%lu +%lu,%lu @@ "
589289180Speter                                     "already applied\n"),
590289180Speter                                   n->hunk_original_start,
591289180Speter                                   n->hunk_original_length,
592289180Speter                                   n->hunk_modified_start,
593289180Speter                                   n->hunk_modified_length));
594251881Speter      break;
595251881Speter
596251881Speter    case svn_wc_notify_update_update:
597251881Speter    case svn_wc_notify_merge_record_info:
598251881Speter      {
599251881Speter        if (n->content_state == svn_wc_notify_state_conflicted)
600251881Speter          {
601251881Speter            store_path(nb, nb->conflict_stats->text_conflicts, path_local);
602251881Speter            statchar_buf[0] = 'C';
603251881Speter          }
604251881Speter        else if (n->kind == svn_node_file)
605251881Speter          {
606251881Speter            if (n->content_state == svn_wc_notify_state_merged)
607251881Speter              statchar_buf[0] = 'G';
608251881Speter            else if (n->content_state == svn_wc_notify_state_changed)
609251881Speter              statchar_buf[0] = 'U';
610251881Speter          }
611251881Speter
612251881Speter        if (n->prop_state == svn_wc_notify_state_conflicted)
613251881Speter          {
614251881Speter            store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
615251881Speter            statchar_buf[1] = 'C';
616251881Speter          }
617251881Speter        else if (n->prop_state == svn_wc_notify_state_merged)
618251881Speter          statchar_buf[1] = 'G';
619251881Speter        else if (n->prop_state == svn_wc_notify_state_changed)
620251881Speter          statchar_buf[1] = 'U';
621251881Speter
622251881Speter        if (n->lock_state == svn_wc_notify_lock_state_unlocked)
623251881Speter          statchar_buf[2] = 'B';
624251881Speter
625251881Speter        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
626251881Speter          nb->received_some_change = TRUE;
627251881Speter
628251881Speter        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
629251881Speter            || statchar_buf[2] != ' ')
630251881Speter          {
631289180Speter            SVN_ERR(svn_cmdline_printf(pool, "%s %s\n",
632289180Speter                                       statchar_buf, path_local));
633251881Speter          }
634251881Speter      }
635251881Speter      break;
636251881Speter
637251881Speter    case svn_wc_notify_update_external:
638251881Speter      /* Remember that we're now "inside" an externals definition. */
639289180Speter      ++nb->in_external;
640251881Speter
641251881Speter      /* Currently this is used for checkouts and switches too.  If we
642251881Speter         want different output, we'll have to add new actions. */
643289180Speter      SVN_ERR(svn_cmdline_printf(pool,
644289180Speter                                 _("\nFetching external item into '%s':\n"),
645289180Speter                                 path_local));
646251881Speter      break;
647251881Speter
648251881Speter    case svn_wc_notify_failed_external:
649251881Speter      /* If we are currently inside the handling of an externals
650251881Speter         definition, then we can simply present n->err as a warning
651251881Speter         and feel confident that after this, we aren't handling that
652251881Speter         externals definition any longer. */
653251881Speter      if (nb->in_external)
654251881Speter        {
655251881Speter          svn_handle_warning2(stderr, n->err, "svn: ");
656289180Speter          --nb->in_external;
657289180Speter          SVN_ERR(svn_cmdline_printf(pool, "\n"));
658251881Speter        }
659251881Speter      /* Otherwise, we'll just print two warnings.  Why?  Because
660251881Speter         svn_handle_warning2() only shows the single "best message",
661251881Speter         but we have two pretty important ones: that the external at
662251881Speter         '/some/path' didn't pan out, and then the more specific
663251881Speter         reason why (from n->err). */
664251881Speter      else
665251881Speter        {
666251881Speter          svn_error_t *warn_err =
667289180Speter            svn_error_createf(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL,
668251881Speter                              _("Error handling externals definition for '%s':"),
669251881Speter                              path_local);
670251881Speter          svn_handle_warning2(stderr, warn_err, "svn: ");
671251881Speter          svn_error_clear(warn_err);
672251881Speter          svn_handle_warning2(stderr, n->err, "svn: ");
673251881Speter        }
674251881Speter      break;
675251881Speter
676251881Speter    case svn_wc_notify_update_started:
677251881Speter      if (! (nb->in_external ||
678251881Speter             nb->is_checkout ||
679251881Speter             nb->is_export))
680251881Speter        {
681289180Speter          SVN_ERR(svn_cmdline_printf(pool, _("Updating '%s':\n"),
682289180Speter                                     path_local));
683251881Speter        }
684251881Speter      break;
685251881Speter
686251881Speter    case svn_wc_notify_update_completed:
687251881Speter      {
688251881Speter        if (SVN_IS_VALID_REVNUM(n->revision))
689251881Speter          {
690251881Speter            if (nb->is_export)
691251881Speter              {
692289180Speter                SVN_ERR(svn_cmdline_printf(
693289180Speter                          pool, nb->in_external
694289180Speter                            ? _("Exported external at revision %ld.\n")
695289180Speter                            : _("Exported revision %ld.\n"),
696289180Speter                          n->revision));
697251881Speter              }
698251881Speter            else if (nb->is_checkout)
699251881Speter              {
700289180Speter                SVN_ERR(svn_cmdline_printf(
701289180Speter                          pool, nb->in_external
702289180Speter                            ? _("Checked out external at revision %ld.\n")
703289180Speter                            : _("Checked out revision %ld.\n"),
704289180Speter                          n->revision));
705251881Speter              }
706251881Speter            else
707251881Speter              {
708251881Speter                if (nb->received_some_change)
709251881Speter                  {
710251881Speter                    nb->received_some_change = FALSE;
711289180Speter                    SVN_ERR(svn_cmdline_printf(
712289180Speter                              pool, nb->in_external
713289180Speter                                ? _("Updated external to revision %ld.\n")
714289180Speter                                : _("Updated to revision %ld.\n"),
715289180Speter                              n->revision));
716251881Speter                  }
717251881Speter                else
718251881Speter                  {
719289180Speter                    SVN_ERR(svn_cmdline_printf(
720289180Speter                              pool, nb->in_external
721289180Speter                                ? _("External at revision %ld.\n")
722289180Speter                                : _("At revision %ld.\n"),
723289180Speter                               n->revision));
724251881Speter                  }
725251881Speter              }
726251881Speter          }
727251881Speter        else  /* no revision */
728251881Speter          {
729251881Speter            if (nb->is_export)
730251881Speter              {
731289180Speter                SVN_ERR(svn_cmdline_printf(
732289180Speter                          pool, nb->in_external
733289180Speter                            ? _("External export complete.\n")
734289180Speter                            : _("Export complete.\n")));
735251881Speter              }
736251881Speter            else if (nb->is_checkout)
737251881Speter              {
738289180Speter                SVN_ERR(svn_cmdline_printf(
739289180Speter                          pool, nb->in_external
740289180Speter                            ? _("External checkout complete.\n")
741289180Speter                            : _("Checkout complete.\n")));
742251881Speter              }
743251881Speter            else
744251881Speter              {
745289180Speter                SVN_ERR(svn_cmdline_printf(
746289180Speter                          pool, nb->in_external
747289180Speter                            ? _("External update complete.\n")
748289180Speter                            : _("Update complete.\n")));
749251881Speter              }
750251881Speter          }
751251881Speter      }
752251881Speter
753251881Speter      if (nb->in_external)
754251881Speter        {
755289180Speter          --nb->in_external;
756289180Speter          SVN_ERR(svn_cmdline_printf(pool, "\n"));
757251881Speter        }
758251881Speter      break;
759251881Speter
760251881Speter    case svn_wc_notify_status_external:
761289180Speter      SVN_ERR(svn_cmdline_printf(
762289180Speter        pool, _("\nPerforming status on external item at '%s':\n"),
763289180Speter        path_local));
764251881Speter      break;
765251881Speter
766289180Speter    case svn_wc_notify_info_external:
767289180Speter      SVN_ERR(svn_cmdline_printf(
768289180Speter         pool, _("\nPerforming info on external item at '%s':\n"),
769289180Speter         path_local));
770289180Speter      break;
771289180Speter
772251881Speter    case svn_wc_notify_status_completed:
773251881Speter      if (SVN_IS_VALID_REVNUM(n->revision))
774289180Speter        SVN_ERR(svn_cmdline_printf(pool,
775289180Speter                                   _("Status against revision: %6ld\n"),
776289180Speter                                   n->revision));
777251881Speter      break;
778251881Speter
779251881Speter    case svn_wc_notify_commit_modified:
780251881Speter      /* xgettext: Align the %s's on this and the following 4 messages */
781289180Speter      SVN_ERR(svn_cmdline_printf(pool,
782289180Speter                                 nb->is_wc_to_repos_copy
783289180Speter                                   ? _("Sending copy of       %s\n")
784289180Speter                                   : _("Sending        %s\n"),
785289180Speter                                 path_local));
786251881Speter      break;
787251881Speter
788251881Speter    case svn_wc_notify_commit_added:
789251881Speter    case svn_wc_notify_commit_copied:
790251881Speter      if (n->mime_type && svn_mime_type_is_binary(n->mime_type))
791251881Speter        {
792289180Speter          SVN_ERR(svn_cmdline_printf(pool,
793289180Speter                                     nb->is_wc_to_repos_copy
794289180Speter                                       ? _("Adding copy of (bin)  %s\n")
795289180Speter                                       : _("Adding  (bin)  %s\n"),
796289180Speter                                     path_local));
797251881Speter        }
798251881Speter      else
799251881Speter        {
800289180Speter          SVN_ERR(svn_cmdline_printf(pool,
801289180Speter                                     nb->is_wc_to_repos_copy
802289180Speter                                       ? _("Adding copy of        %s\n")
803289180Speter                                       : _("Adding         %s\n"),
804289180Speter                                     path_local));
805251881Speter        }
806251881Speter      break;
807251881Speter
808251881Speter    case svn_wc_notify_commit_deleted:
809289180Speter      SVN_ERR(svn_cmdline_printf(pool,
810289180Speter                                 nb->is_wc_to_repos_copy
811289180Speter                                   ? _("Deleting copy of      %s\n")
812289180Speter                                   : _("Deleting       %s\n"),
813289180Speter                                 path_local));
814251881Speter      break;
815251881Speter
816251881Speter    case svn_wc_notify_commit_replaced:
817251881Speter    case svn_wc_notify_commit_copied_replaced:
818289180Speter      SVN_ERR(svn_cmdline_printf(pool,
819289180Speter                                 nb->is_wc_to_repos_copy
820289180Speter                                   ? _("Replacing copy of     %s\n")
821289180Speter                                   : _("Replacing      %s\n"),
822289180Speter                                 path_local));
823251881Speter      break;
824251881Speter
825251881Speter    case svn_wc_notify_commit_postfix_txdelta:
826251881Speter      if (! nb->sent_first_txdelta)
827251881Speter        {
828251881Speter          nb->sent_first_txdelta = TRUE;
829289180Speter          SVN_ERR(svn_cmdline_printf(pool,
830289180Speter                                     _("Transmitting file data ")));
831251881Speter        }
832251881Speter
833289180Speter      SVN_ERR(svn_cmdline_printf(pool, "."));
834251881Speter      break;
835251881Speter
836251881Speter    case svn_wc_notify_locked:
837289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"),
838289180Speter                                 path_local, n->lock->owner));
839251881Speter      break;
840251881Speter
841251881Speter    case svn_wc_notify_unlocked:
842289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("'%s' unlocked.\n"),
843289180Speter                                 path_local));
844251881Speter      break;
845251881Speter
846251881Speter    case svn_wc_notify_failed_lock:
847251881Speter    case svn_wc_notify_failed_unlock:
848251881Speter      svn_handle_warning2(stderr, n->err, "svn: ");
849251881Speter      break;
850251881Speter
851251881Speter    case svn_wc_notify_changelist_set:
852289180Speter      SVN_ERR(svn_cmdline_printf(pool, "A [%s] %s\n",
853289180Speter                                 n->changelist_name, path_local));
854251881Speter      break;
855251881Speter
856251881Speter    case svn_wc_notify_changelist_clear:
857251881Speter    case svn_wc_notify_changelist_moved:
858289180Speter      SVN_ERR(svn_cmdline_printf(pool,
859289180Speter                                 "D [%s] %s\n",
860289180Speter                                 n->changelist_name, path_local));
861251881Speter      break;
862251881Speter
863251881Speter    case svn_wc_notify_merge_begin:
864251881Speter      if (n->merge_range == NULL)
865289180Speter        SVN_ERR(svn_cmdline_printf(pool,
866289180Speter                                   _("--- Merging differences between "
867289180Speter                                     "repository URLs into '%s':\n"),
868289180Speter                                   path_local));
869251881Speter      else if (n->merge_range->start == n->merge_range->end - 1
870251881Speter          || n->merge_range->start == n->merge_range->end)
871289180Speter        SVN_ERR(svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"),
872289180Speter                                   n->merge_range->end, path_local));
873251881Speter      else if (n->merge_range->start - 1 == n->merge_range->end)
874289180Speter        SVN_ERR(svn_cmdline_printf(pool,
875289180Speter                                   _("--- Reverse-merging r%ld into '%s':\n"),
876289180Speter                                   n->merge_range->start, path_local));
877251881Speter      else if (n->merge_range->start < n->merge_range->end)
878289180Speter        SVN_ERR(svn_cmdline_printf(pool,
879289180Speter                                   _("--- Merging r%ld through r%ld into "
880289180Speter                                     "'%s':\n"),
881289180Speter                                   n->merge_range->start + 1,
882289180Speter                                   n->merge_range->end, path_local));
883251881Speter      else /* n->merge_range->start > n->merge_range->end - 1 */
884289180Speter        SVN_ERR(svn_cmdline_printf(pool,
885289180Speter                                   _("--- Reverse-merging r%ld through r%ld "
886289180Speter                                     "into '%s':\n"),
887289180Speter                                   n->merge_range->start,
888289180Speter                                   n->merge_range->end + 1, path_local));
889251881Speter      break;
890251881Speter
891251881Speter    case svn_wc_notify_merge_record_info_begin:
892251881Speter      if (!n->merge_range)
893251881Speter        {
894289180Speter          SVN_ERR(svn_cmdline_printf(pool,
895289180Speter                                     _("--- Recording mergeinfo for merge "
896289180Speter                                       "between repository URLs into '%s':\n"),
897289180Speter                                     path_local));
898251881Speter        }
899251881Speter      else
900251881Speter        {
901251881Speter          if (n->merge_range->start == n->merge_range->end - 1
902251881Speter              || n->merge_range->start == n->merge_range->end)
903289180Speter            SVN_ERR(svn_cmdline_printf(
904251881Speter              pool,
905251881Speter              _("--- Recording mergeinfo for merge of r%ld into '%s':\n"),
906289180Speter              n->merge_range->end, path_local));
907251881Speter          else if (n->merge_range->start - 1 == n->merge_range->end)
908289180Speter            SVN_ERR(svn_cmdline_printf(
909251881Speter              pool,
910251881Speter              _("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"),
911289180Speter              n->merge_range->start, path_local));
912251881Speter           else if (n->merge_range->start < n->merge_range->end)
913289180Speter             SVN_ERR(svn_cmdline_printf(
914251881Speter               pool,
915251881Speter               _("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"),
916289180Speter               n->merge_range->start + 1, n->merge_range->end, path_local));
917251881Speter           else /* n->merge_range->start > n->merge_range->end - 1 */
918289180Speter             SVN_ERR(svn_cmdline_printf(
919251881Speter               pool,
920251881Speter               _("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"),
921289180Speter               n->merge_range->start, n->merge_range->end + 1, path_local));
922251881Speter        }
923251881Speter      break;
924251881Speter
925251881Speter    case svn_wc_notify_merge_elide_info:
926289180Speter      SVN_ERR(svn_cmdline_printf(pool,
927289180Speter                                 _("--- Eliding mergeinfo from '%s':\n"),
928289180Speter                                 path_local));
929251881Speter      break;
930251881Speter
931251881Speter    case svn_wc_notify_foreign_merge_begin:
932251881Speter      if (n->merge_range == NULL)
933289180Speter        SVN_ERR(svn_cmdline_printf(pool,
934289180Speter                                   _("--- Merging differences between "
935289180Speter                                     "foreign repository URLs into '%s':\n"),
936289180Speter                                   path_local));
937251881Speter      else if (n->merge_range->start == n->merge_range->end - 1
938251881Speter          || n->merge_range->start == n->merge_range->end)
939289180Speter        SVN_ERR(svn_cmdline_printf(pool,
940289180Speter                                   _("--- Merging (from foreign repository) "
941289180Speter                                     "r%ld into '%s':\n"),
942289180Speter                                   n->merge_range->end, path_local));
943251881Speter      else if (n->merge_range->start - 1 == n->merge_range->end)
944289180Speter        SVN_ERR(svn_cmdline_printf(pool,
945289180Speter                                   _("--- Reverse-merging (from foreign "
946289180Speter                                     "repository) r%ld into '%s':\n"),
947289180Speter                                   n->merge_range->start, path_local));
948251881Speter      else if (n->merge_range->start < n->merge_range->end)
949289180Speter        SVN_ERR(svn_cmdline_printf(pool,
950289180Speter                                   _("--- Merging (from foreign repository) "
951289180Speter                                     "r%ld through r%ld into '%s':\n"),
952289180Speter                                   n->merge_range->start + 1,
953289180Speter                                   n->merge_range->end, path_local));
954251881Speter      else /* n->merge_range->start > n->merge_range->end - 1 */
955289180Speter        SVN_ERR(svn_cmdline_printf(pool,
956289180Speter                                   _("--- Reverse-merging (from foreign "
957289180Speter                                     "repository) r%ld through r%ld into "
958289180Speter                                     "'%s':\n"),
959289180Speter                                   n->merge_range->start,
960289180Speter                                   n->merge_range->end + 1, path_local));
961251881Speter      break;
962251881Speter
963251881Speter    case svn_wc_notify_tree_conflict:
964251881Speter      store_path(nb, nb->conflict_stats->tree_conflicts, path_local);
965289180Speter      SVN_ERR(svn_cmdline_printf(pool, "   C %s\n", path_local));
966251881Speter      break;
967251881Speter
968251881Speter    case svn_wc_notify_update_shadowed_add:
969251881Speter      nb->received_some_change = TRUE;
970289180Speter      SVN_ERR(svn_cmdline_printf(pool, "   A %s\n", path_local));
971251881Speter      break;
972251881Speter
973251881Speter    case svn_wc_notify_update_shadowed_update:
974251881Speter      nb->received_some_change = TRUE;
975289180Speter      SVN_ERR(svn_cmdline_printf(pool, "   U %s\n", path_local));
976251881Speter      break;
977251881Speter
978251881Speter    case svn_wc_notify_update_shadowed_delete:
979251881Speter      nb->received_some_change = TRUE;
980289180Speter      SVN_ERR(svn_cmdline_printf(pool, "   D %s\n", path_local));
981251881Speter      break;
982251881Speter
983251881Speter    case svn_wc_notify_property_modified:
984251881Speter    case svn_wc_notify_property_added:
985289180Speter      SVN_ERR(svn_cmdline_printf(pool,
986289180Speter                                 _("property '%s' set on '%s'\n"),
987289180Speter                                 n->prop_name, path_local));
988251881Speter      break;
989251881Speter
990251881Speter    case svn_wc_notify_property_deleted:
991289180Speter      SVN_ERR(svn_cmdline_printf(pool,
992289180Speter                                 _("property '%s' deleted from '%s'.\n"),
993289180Speter                                 n->prop_name, path_local));
994251881Speter      break;
995251881Speter
996251881Speter    case svn_wc_notify_property_deleted_nonexistent:
997289180Speter      SVN_ERR(svn_cmdline_printf(pool,
998289180Speter                                 _("Attempting to delete nonexistent "
999289180Speter                                   "property '%s' on '%s'\n"), n->prop_name,
1000289180Speter                                 path_local));
1001251881Speter      break;
1002251881Speter
1003251881Speter    case svn_wc_notify_revprop_set:
1004289180Speter      SVN_ERR(svn_cmdline_printf(pool,
1005251881Speter                           _("property '%s' set on repository revision %ld\n"),
1006289180Speter                           n->prop_name, n->revision));
1007251881Speter      break;
1008251881Speter
1009251881Speter    case svn_wc_notify_revprop_deleted:
1010289180Speter      SVN_ERR(svn_cmdline_printf(pool,
1011251881Speter                     _("property '%s' deleted from repository revision %ld\n"),
1012289180Speter                     n->prop_name, n->revision));
1013251881Speter      break;
1014251881Speter
1015251881Speter    case svn_wc_notify_upgraded_path:
1016289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local));
1017251881Speter      break;
1018251881Speter
1019251881Speter    case svn_wc_notify_url_redirect:
1020289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"),
1021289180Speter                                 n->url));
1022251881Speter      break;
1023251881Speter
1024251881Speter    case svn_wc_notify_path_nonexistent:
1025289180Speter      SVN_ERR(svn_cmdline_printf(pool, "%s\n",
1026289180Speter                apr_psprintf(pool, _("'%s' is not under version control"),
1027289180Speter                             path_local)));
1028251881Speter      break;
1029251881Speter
1030251881Speter    case svn_wc_notify_conflict_resolver_starting:
1031251881Speter      /* Once all operations invoke the interactive conflict resolution after
1032251881Speter       * they've completed, we can run svn_cl__notifier_print_conflict_stats()
1033251881Speter       * here. */
1034251881Speter      break;
1035251881Speter
1036251881Speter    case svn_wc_notify_conflict_resolver_done:
1037251881Speter      break;
1038251881Speter
1039251881Speter    case svn_wc_notify_foreign_copy_begin:
1040251881Speter      if (n->merge_range == NULL)
1041251881Speter        {
1042289180Speter          SVN_ERR(svn_cmdline_printf(
1043251881Speter                           pool,
1044251881Speter                           _("--- Copying from foreign repository URL '%s':\n"),
1045289180Speter                           n->url));
1046251881Speter        }
1047251881Speter      break;
1048251881Speter
1049251881Speter    case svn_wc_notify_move_broken:
1050289180Speter      SVN_ERR(svn_cmdline_printf(pool,
1051289180Speter                                 _("Breaking move with source path '%s'\n"),
1052289180Speter                                 path_local));
1053251881Speter      break;
1054251881Speter
1055289180Speter    case svn_wc_notify_cleanup_external:
1056289180Speter      SVN_ERR(svn_cmdline_printf
1057289180Speter                (pool, _("Performing cleanup on external item at '%s'.\n"),
1058289180Speter                 path_local));
1059289180Speter      break;
1060289180Speter
1061289180Speter    case svn_wc_notify_commit_finalizing:
1062289180Speter      if (nb->sent_first_txdelta)
1063289180Speter        {
1064289180Speter          SVN_ERR(svn_cmdline_printf(pool, _("done\n")));
1065289180Speter        }
1066289180Speter      SVN_ERR(svn_cmdline_printf(pool, _("Committing transaction...\n")));
1067289180Speter      break;
1068289180Speter
1069251881Speter    default:
1070251881Speter      break;
1071251881Speter    }
1072251881Speter
1073289180Speter  SVN_ERR(svn_cmdline_fflush(stdout));
1074251881Speter
1075289180Speter  return SVN_NO_ERROR;
1076289180Speter}
1077251881Speter
1078289180Speter/* This implements `svn_wc_notify_func2_t'.
1079289180Speter * NOTE: This function can't fail, so we just ignore any print errors. */
1080289180Speterstatic void
1081289180Speternotify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool)
1082289180Speter{
1083289180Speter  struct notify_baton *nb = baton;
1084289180Speter  svn_error_t *err;
1085289180Speter
1086289180Speter  err = notify_body(nb, n, pool);
1087289180Speter
1088251881Speter  /* If we had no errors before, print this error to stderr. Else, don't print
1089251881Speter     anything.  The user already knows there were some output errors,
1090251881Speter     so there is no point in flooding her with an error per notification. */
1091289180Speter  if (err && !nb->had_print_error)
1092251881Speter    {
1093251881Speter      nb->had_print_error = TRUE;
1094251881Speter      /* Issue #3014:
1095251881Speter       * Don't print anything on broken pipes. The pipe was likely
1096251881Speter       * closed by the process at the other end. We expect that
1097251881Speter       * process to perform error reporting as necessary.
1098251881Speter       *
1099251881Speter       * ### This assumes that there is only one error in a chain for
1100251881Speter       * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
1101251881Speter      if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
1102251881Speter        svn_handle_error2(err, stderr, FALSE, "svn: ");
1103251881Speter    }
1104251881Speter  svn_error_clear(err);
1105251881Speter}
1106251881Speter
1107251881Spetersvn_error_t *
1108251881Spetersvn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p,
1109251881Speter                     void **notify_baton_p,
1110251881Speter                     svn_cl__conflict_stats_t *conflict_stats,
1111251881Speter                     apr_pool_t *pool)
1112251881Speter{
1113251881Speter  struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb));
1114251881Speter
1115251881Speter  nb->received_some_change = FALSE;
1116251881Speter  nb->sent_first_txdelta = FALSE;
1117251881Speter  nb->is_checkout = FALSE;
1118251881Speter  nb->is_export = FALSE;
1119251881Speter  nb->is_wc_to_repos_copy = FALSE;
1120289180Speter  nb->in_external = 0;
1121251881Speter  nb->had_print_error = FALSE;
1122251881Speter  nb->conflict_stats = conflict_stats;
1123251881Speter  SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool));
1124251881Speter
1125251881Speter  *notify_func_p = notify;
1126251881Speter  *notify_baton_p = nb;
1127251881Speter  return SVN_NO_ERROR;
1128251881Speter}
1129251881Speter
1130251881Spetersvn_error_t *
1131251881Spetersvn_cl__notifier_mark_checkout(void *baton)
1132251881Speter{
1133251881Speter  struct notify_baton *nb = baton;
1134251881Speter
1135251881Speter  nb->is_checkout = TRUE;
1136251881Speter  return SVN_NO_ERROR;
1137251881Speter}
1138251881Speter
1139251881Spetersvn_error_t *
1140251881Spetersvn_cl__notifier_mark_export(void *baton)
1141251881Speter{
1142251881Speter  struct notify_baton *nb = baton;
1143251881Speter
1144251881Speter  nb->is_export = TRUE;
1145251881Speter  return SVN_NO_ERROR;
1146251881Speter}
1147251881Speter
1148251881Spetersvn_error_t *
1149251881Spetersvn_cl__notifier_mark_wc_to_repos_copy(void *baton)
1150251881Speter{
1151251881Speter  struct notify_baton *nb = baton;
1152251881Speter
1153251881Speter  nb->is_wc_to_repos_copy = TRUE;
1154251881Speter  return SVN_NO_ERROR;
1155251881Speter}
1156251881Speter
1157251881Spetervoid
1158251881Spetersvn_cl__check_externals_failed_notify_wrapper(void *baton,
1159251881Speter                                              const svn_wc_notify_t *n,
1160251881Speter                                              apr_pool_t *pool)
1161251881Speter{
1162251881Speter  struct svn_cl__check_externals_failed_notify_baton *nwb = baton;
1163251881Speter
1164251881Speter  if (n->action == svn_wc_notify_failed_external)
1165251881Speter    nwb->had_externals_error = TRUE;
1166251881Speter
1167251881Speter  if (nwb->wrapped_func)
1168251881Speter    nwb->wrapped_func(nwb->wrapped_baton, n, pool);
1169251881Speter}
1170