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;
55251881Speter  svn_boolean_t 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{
132251881Speter  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 *
148251881Spetersvn_cl__notifier_print_conflict_stats(void *baton, apr_pool_t *scratch_pool)
149251881Speter{
150251881Speter  struct notify_baton *nb = baton;
151251881Speter  int n_text = apr_hash_count(nb->conflict_stats->text_conflicts);
152251881Speter  int n_prop = apr_hash_count(nb->conflict_stats->prop_conflicts);
153251881Speter  int n_tree = apr_hash_count(nb->conflict_stats->tree_conflicts);
154251881Speter  int n_text_r = nb->conflict_stats->text_conflicts_resolved;
155251881Speter  int n_prop_r = nb->conflict_stats->prop_conflicts_resolved;
156251881Speter  int n_tree_r = nb->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
161251881Speter      || nb->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    }
198251881Speter  if (nb->conflict_stats->skipped_paths > 0)
199251881Speter    SVN_ERR(svn_cmdline_printf(scratch_pool,
200251881Speter                               _("  Skipped paths: %d\n"),
201251881Speter                               nb->conflict_stats->skipped_paths));
202251881Speter
203251881Speter  return SVN_NO_ERROR;
204251881Speter}
205251881Speter
206251881Speter/* This implements `svn_wc_notify_func2_t'.
207251881Speter * NOTE: This function can't fail, so we just ignore any print errors. */
208251881Speterstatic void
209251881Speternotify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool)
210251881Speter{
211251881Speter  struct notify_baton *nb = baton;
212251881Speter  char statchar_buf[5] = "    ";
213251881Speter  const char *path_local;
214251881Speter  svn_error_t *err;
215251881Speter
216251881Speter  if (n->url)
217251881Speter    path_local = n->url;
218251881Speter  else
219251881Speter    {
220251881Speter      if (n->path_prefix)
221251881Speter        path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path,
222251881Speter                                                       pool);
223251881Speter      else /* skip nb->path_prefix, if it's non-null */
224251881Speter        path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path,
225251881Speter                                                       pool);
226251881Speter    }
227251881Speter
228251881Speter  switch (n->action)
229251881Speter    {
230251881Speter    case svn_wc_notify_skip:
231251881Speter      nb->conflict_stats->skipped_paths++;
232251881Speter      if (n->content_state == svn_wc_notify_state_missing)
233251881Speter        {
234251881Speter          if ((err = svn_cmdline_printf
235251881Speter               (pool, _("Skipped missing target: '%s'\n"),
236251881Speter                path_local)))
237251881Speter            goto print_error;
238251881Speter        }
239251881Speter      else if (n->content_state == svn_wc_notify_state_source_missing)
240251881Speter        {
241251881Speter          if ((err = svn_cmdline_printf
242251881Speter               (pool, _("Skipped target: '%s' -- copy-source is missing\n"),
243251881Speter                path_local)))
244251881Speter            goto print_error;
245251881Speter        }
246251881Speter      else
247251881Speter        {
248251881Speter          if ((err = svn_cmdline_printf
249251881Speter               (pool, _("Skipped '%s'\n"), path_local)))
250251881Speter            goto print_error;
251251881Speter        }
252251881Speter      break;
253251881Speter    case svn_wc_notify_update_skip_obstruction:
254251881Speter      nb->conflict_stats->skipped_paths++;
255251881Speter      if ((err = svn_cmdline_printf(
256251881Speter            pool, _("Skipped '%s' -- An obstructing working copy was found\n"),
257251881Speter            path_local)))
258251881Speter        goto print_error;
259251881Speter      break;
260251881Speter    case svn_wc_notify_update_skip_working_only:
261251881Speter      nb->conflict_stats->skipped_paths++;
262251881Speter      if ((err = svn_cmdline_printf(
263251881Speter            pool, _("Skipped '%s' -- Has no versioned parent\n"),
264251881Speter            path_local)))
265251881Speter        goto print_error;
266251881Speter      break;
267251881Speter    case svn_wc_notify_update_skip_access_denied:
268251881Speter      nb->conflict_stats->skipped_paths++;
269251881Speter      if ((err = svn_cmdline_printf(
270251881Speter            pool, _("Skipped '%s' -- Access denied\n"),
271251881Speter            path_local)))
272251881Speter        goto print_error;
273251881Speter      break;
274251881Speter    case svn_wc_notify_skip_conflicted:
275251881Speter      nb->conflict_stats->skipped_paths++;
276251881Speter      if ((err = svn_cmdline_printf(
277251881Speter            pool, _("Skipped '%s' -- Node remains in conflict\n"),
278251881Speter            path_local)))
279251881Speter        goto print_error;
280251881Speter      break;
281251881Speter    case svn_wc_notify_update_delete:
282251881Speter    case svn_wc_notify_exclude:
283251881Speter      nb->received_some_change = TRUE;
284251881Speter      if ((err = svn_cmdline_printf(pool, "D    %s\n", path_local)))
285251881Speter        goto print_error;
286251881Speter      break;
287251881Speter    case svn_wc_notify_update_broken_lock:
288251881Speter      if ((err = svn_cmdline_printf(pool, "B    %s\n", path_local)))
289251881Speter        goto print_error;
290251881Speter      break;
291251881Speter
292251881Speter    case svn_wc_notify_update_external_removed:
293251881Speter      nb->received_some_change = TRUE;
294251881Speter      if (n->err && n->err->message)
295251881Speter        {
296251881Speter          if ((err = svn_cmdline_printf(pool, "Removed external '%s': %s\n",
297251881Speter              path_local, n->err->message)))
298251881Speter            goto print_error;
299251881Speter        }
300251881Speter      else
301251881Speter        {
302251881Speter          if ((err = svn_cmdline_printf(pool, "Removed external '%s'\n",
303251881Speter                                        path_local)))
304251881Speter            goto print_error;
305251881Speter        }
306251881Speter      break;
307251881Speter
308251881Speter    case svn_wc_notify_left_local_modifications:
309251881Speter      if ((err = svn_cmdline_printf(pool, "Left local modifications as '%s'\n",
310251881Speter                                        path_local)))
311251881Speter        goto print_error;
312251881Speter      break;
313251881Speter
314251881Speter    case svn_wc_notify_update_replace:
315251881Speter      nb->received_some_change = TRUE;
316251881Speter      if ((err = svn_cmdline_printf(pool, "R    %s\n", path_local)))
317251881Speter        goto print_error;
318251881Speter      break;
319251881Speter
320251881Speter    case svn_wc_notify_update_add:
321251881Speter      nb->received_some_change = TRUE;
322251881Speter      if (n->content_state == svn_wc_notify_state_conflicted)
323251881Speter        {
324251881Speter          store_path(nb, nb->conflict_stats->text_conflicts, path_local);
325251881Speter          if ((err = svn_cmdline_printf(pool, "C    %s\n", path_local)))
326251881Speter            goto print_error;
327251881Speter        }
328251881Speter      else
329251881Speter        {
330251881Speter          if ((err = svn_cmdline_printf(pool, "A    %s\n", path_local)))
331251881Speter            goto print_error;
332251881Speter        }
333251881Speter      break;
334251881Speter
335251881Speter    case svn_wc_notify_exists:
336251881Speter      nb->received_some_change = TRUE;
337251881Speter      if (n->content_state == svn_wc_notify_state_conflicted)
338251881Speter        {
339251881Speter          store_path(nb, nb->conflict_stats->text_conflicts, path_local);
340251881Speter          statchar_buf[0] = 'C';
341251881Speter        }
342251881Speter      else
343251881Speter        statchar_buf[0] = 'E';
344251881Speter
345251881Speter      if (n->prop_state == svn_wc_notify_state_conflicted)
346251881Speter        {
347251881Speter          store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
348251881Speter          statchar_buf[1] = 'C';
349251881Speter        }
350251881Speter      else if (n->prop_state == svn_wc_notify_state_merged)
351251881Speter        statchar_buf[1] = 'G';
352251881Speter
353251881Speter      if ((err = svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local)))
354251881Speter        goto print_error;
355251881Speter      break;
356251881Speter
357251881Speter    case svn_wc_notify_restore:
358251881Speter      if ((err = svn_cmdline_printf(pool, _("Restored '%s'\n"),
359251881Speter                                    path_local)))
360251881Speter        goto print_error;
361251881Speter      break;
362251881Speter
363251881Speter    case svn_wc_notify_revert:
364251881Speter      if ((err = svn_cmdline_printf(pool, _("Reverted '%s'\n"),
365251881Speter                                    path_local)))
366251881Speter        goto print_error;
367251881Speter      break;
368251881Speter
369251881Speter    case svn_wc_notify_failed_revert:
370251881Speter      if (( err = svn_cmdline_printf(pool, _("Failed to revert '%s' -- "
371251881Speter                                             "try updating instead.\n"),
372251881Speter                                     path_local)))
373251881Speter        goto print_error;
374251881Speter      break;
375251881Speter
376251881Speter    case svn_wc_notify_resolved:
377251881Speter      if ((err = svn_cmdline_printf(pool,
378251881Speter                                    _("Resolved conflicted state of '%s'\n"),
379251881Speter                                    path_local)))
380251881Speter        goto print_error;
381251881Speter      break;
382251881Speter
383251881Speter    case svn_wc_notify_add:
384251881Speter      /* We *should* only get the MIME_TYPE if PATH is a file.  If we
385251881Speter         do get it, and the mime-type is not textual, note that this
386251881Speter         is a binary addition. */
387251881Speter      if (n->mime_type && (svn_mime_type_is_binary(n->mime_type)))
388251881Speter        {
389251881Speter          if ((err = svn_cmdline_printf(pool, "A  (bin)  %s\n",
390251881Speter                                        path_local)))
391251881Speter            goto print_error;
392251881Speter        }
393251881Speter      else
394251881Speter        {
395251881Speter          if ((err = svn_cmdline_printf(pool, "A         %s\n",
396251881Speter                                        path_local)))
397251881Speter            goto print_error;
398251881Speter        }
399251881Speter      break;
400251881Speter
401251881Speter    case svn_wc_notify_delete:
402251881Speter      nb->received_some_change = TRUE;
403251881Speter      if ((err = svn_cmdline_printf(pool, "D         %s\n",
404251881Speter                                    path_local)))
405251881Speter        goto print_error;
406251881Speter      break;
407251881Speter
408251881Speter    case svn_wc_notify_patch:
409251881Speter      {
410251881Speter        nb->received_some_change = TRUE;
411251881Speter        if (n->content_state == svn_wc_notify_state_conflicted)
412251881Speter          {
413251881Speter            store_path(nb, nb->conflict_stats->text_conflicts, path_local);
414251881Speter            statchar_buf[0] = 'C';
415251881Speter          }
416251881Speter        else if (n->kind == svn_node_file)
417251881Speter          {
418251881Speter            if (n->content_state == svn_wc_notify_state_merged)
419251881Speter              statchar_buf[0] = 'G';
420251881Speter            else if (n->content_state == svn_wc_notify_state_changed)
421251881Speter              statchar_buf[0] = 'U';
422251881Speter          }
423251881Speter
424251881Speter        if (n->prop_state == svn_wc_notify_state_conflicted)
425251881Speter          {
426251881Speter            store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
427251881Speter            statchar_buf[1] = 'C';
428251881Speter          }
429251881Speter        else if (n->prop_state == svn_wc_notify_state_changed)
430251881Speter              statchar_buf[1] = 'U';
431251881Speter
432251881Speter        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
433251881Speter          {
434251881Speter            if ((err = svn_cmdline_printf(pool, "%s      %s\n",
435251881Speter                                          statchar_buf, path_local)))
436251881Speter              goto print_error;
437251881Speter          }
438251881Speter      }
439251881Speter      break;
440251881Speter
441251881Speter    case svn_wc_notify_patch_applied_hunk:
442251881Speter      nb->received_some_change = TRUE;
443251881Speter      if (n->hunk_original_start != n->hunk_matched_line)
444251881Speter        {
445251881Speter          apr_uint64_t off;
446251881Speter          const char *s;
447251881Speter          const char *minus;
448251881Speter
449251881Speter          if (n->hunk_matched_line > n->hunk_original_start)
450251881Speter            {
451251881Speter              /* If we are patching from the start of an empty file,
452251881Speter                 it is nicer to show offset 0 */
453251881Speter              if (n->hunk_original_start == 0 && n->hunk_matched_line == 1)
454251881Speter                off = 0; /* No offset, just adding */
455251881Speter              else
456251881Speter                off = n->hunk_matched_line - n->hunk_original_start;
457251881Speter
458251881Speter              minus = "";
459251881Speter            }
460251881Speter          else
461251881Speter            {
462251881Speter              off = n->hunk_original_start - n->hunk_matched_line;
463251881Speter              minus = "-";
464251881Speter            }
465251881Speter
466251881Speter          /* ### We're creating the localized strings without
467251881Speter           * ### APR_INT64_T_FMT since it isn't translator-friendly */
468251881Speter          if (n->hunk_fuzz)
469251881Speter            {
470251881Speter
471251881Speter              if (n->prop_name)
472251881Speter                {
473251881Speter                  s = _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
474251881Speter                        "with offset %s");
475251881Speter
476251881Speter                  err = svn_cmdline_printf(pool,
477251881Speter                                           apr_pstrcat(pool, s,
478251881Speter                                                       "%"APR_UINT64_T_FMT
479251881Speter                                                       " and fuzz %lu (%s)\n",
480251881Speter                                                       (char *)NULL),
481251881Speter                                           n->hunk_original_start,
482251881Speter                                           n->hunk_original_length,
483251881Speter                                           n->hunk_modified_start,
484251881Speter                                           n->hunk_modified_length,
485251881Speter                                           minus, off, n->hunk_fuzz,
486251881Speter                                           n->prop_name);
487251881Speter                }
488251881Speter              else
489251881Speter                {
490251881Speter                  s = _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
491251881Speter                        "with offset %s");
492251881Speter
493251881Speter                  err = svn_cmdline_printf(pool,
494251881Speter                                           apr_pstrcat(pool, s,
495251881Speter                                                       "%"APR_UINT64_T_FMT
496251881Speter                                                       " and fuzz %lu\n",
497251881Speter                                                       (char *)NULL),
498251881Speter                                           n->hunk_original_start,
499251881Speter                                           n->hunk_original_length,
500251881Speter                                           n->hunk_modified_start,
501251881Speter                                           n->hunk_modified_length,
502251881Speter                                           minus, off, n->hunk_fuzz);
503251881Speter                }
504251881Speter
505251881Speter              if (err)
506251881Speter                goto print_error;
507251881Speter            }
508251881Speter          else
509251881Speter            {
510251881Speter
511251881Speter              if (n->prop_name)
512251881Speter                {
513251881Speter                  s = _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
514251881Speter                        "with offset %s");
515251881Speter                  err = svn_cmdline_printf(pool,
516251881Speter                                            apr_pstrcat(pool, s,
517251881Speter                                                        "%"APR_UINT64_T_FMT" (%s)\n",
518251881Speter                                                        (char *)NULL),
519251881Speter                                            n->hunk_original_start,
520251881Speter                                            n->hunk_original_length,
521251881Speter                                            n->hunk_modified_start,
522251881Speter                                            n->hunk_modified_length,
523251881Speter                                            minus, off, n->prop_name);
524251881Speter                }
525251881Speter              else
526251881Speter                {
527251881Speter                  s = _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
528251881Speter                        "with offset %s");
529251881Speter                  err = svn_cmdline_printf(pool,
530251881Speter                                           apr_pstrcat(pool, s,
531251881Speter                                                       "%"APR_UINT64_T_FMT"\n",
532251881Speter                                                       (char *)NULL),
533251881Speter                                           n->hunk_original_start,
534251881Speter                                           n->hunk_original_length,
535251881Speter                                           n->hunk_modified_start,
536251881Speter                                           n->hunk_modified_length,
537251881Speter                                           minus, off);
538251881Speter                }
539251881Speter
540251881Speter              if (err)
541251881Speter                goto print_error;
542251881Speter            }
543251881Speter        }
544251881Speter      else if (n->hunk_fuzz)
545251881Speter        {
546251881Speter          if (n->prop_name)
547251881Speter            err = svn_cmdline_printf(pool,
548251881Speter                          _(">         applied hunk ## -%lu,%lu +%lu,%lu ## "
549251881Speter                                        "with fuzz %lu (%s)\n"),
550251881Speter                                        n->hunk_original_start,
551251881Speter                                        n->hunk_original_length,
552251881Speter                                        n->hunk_modified_start,
553251881Speter                                        n->hunk_modified_length,
554251881Speter                                        n->hunk_fuzz,
555251881Speter                                        n->prop_name);
556251881Speter          else
557251881Speter            err = svn_cmdline_printf(pool,
558251881Speter                          _(">         applied hunk @@ -%lu,%lu +%lu,%lu @@ "
559251881Speter                                        "with fuzz %lu\n"),
560251881Speter                                        n->hunk_original_start,
561251881Speter                                        n->hunk_original_length,
562251881Speter                                        n->hunk_modified_start,
563251881Speter                                        n->hunk_modified_length,
564251881Speter                                        n->hunk_fuzz);
565251881Speter          if (err)
566251881Speter            goto print_error;
567251881Speter
568251881Speter        }
569251881Speter      break;
570251881Speter
571251881Speter    case svn_wc_notify_patch_rejected_hunk:
572251881Speter      nb->received_some_change = TRUE;
573251881Speter
574251881Speter      if (n->prop_name)
575251881Speter        err = svn_cmdline_printf(pool,
576251881Speter                                 _(">         rejected hunk "
577251881Speter                                   "## -%lu,%lu +%lu,%lu ## (%s)\n"),
578251881Speter                                 n->hunk_original_start,
579251881Speter                                 n->hunk_original_length,
580251881Speter                                 n->hunk_modified_start,
581251881Speter                                 n->hunk_modified_length,
582251881Speter                                 n->prop_name);
583251881Speter      else
584251881Speter        err = svn_cmdline_printf(pool,
585251881Speter                                 _(">         rejected hunk "
586251881Speter                                   "@@ -%lu,%lu +%lu,%lu @@\n"),
587251881Speter                                 n->hunk_original_start,
588251881Speter                                 n->hunk_original_length,
589251881Speter                                 n->hunk_modified_start,
590251881Speter                                 n->hunk_modified_length);
591251881Speter      if (err)
592251881Speter        goto print_error;
593251881Speter      break;
594251881Speter
595251881Speter    case svn_wc_notify_patch_hunk_already_applied:
596251881Speter      nb->received_some_change = TRUE;
597251881Speter      if (n->prop_name)
598251881Speter        err = svn_cmdline_printf(pool,
599251881Speter                                 _(">         hunk "
600251881Speter                                   "## -%lu,%lu +%lu,%lu ## "
601251881Speter                                   "already applied (%s)\n"),
602251881Speter                                 n->hunk_original_start,
603251881Speter                                 n->hunk_original_length,
604251881Speter                                 n->hunk_modified_start,
605251881Speter                                 n->hunk_modified_length,
606251881Speter                                 n->prop_name);
607251881Speter      else
608251881Speter        err = svn_cmdline_printf(pool,
609251881Speter                                 _(">         hunk "
610251881Speter                                   "@@ -%lu,%lu +%lu,%lu @@ "
611251881Speter                                   "already applied\n"),
612251881Speter                                 n->hunk_original_start,
613251881Speter                                 n->hunk_original_length,
614251881Speter                                 n->hunk_modified_start,
615251881Speter                                 n->hunk_modified_length);
616251881Speter      if (err)
617251881Speter        goto print_error;
618251881Speter      break;
619251881Speter
620251881Speter    case svn_wc_notify_update_update:
621251881Speter    case svn_wc_notify_merge_record_info:
622251881Speter      {
623251881Speter        if (n->content_state == svn_wc_notify_state_conflicted)
624251881Speter          {
625251881Speter            store_path(nb, nb->conflict_stats->text_conflicts, path_local);
626251881Speter            statchar_buf[0] = 'C';
627251881Speter          }
628251881Speter        else if (n->kind == svn_node_file)
629251881Speter          {
630251881Speter            if (n->content_state == svn_wc_notify_state_merged)
631251881Speter              statchar_buf[0] = 'G';
632251881Speter            else if (n->content_state == svn_wc_notify_state_changed)
633251881Speter              statchar_buf[0] = 'U';
634251881Speter          }
635251881Speter
636251881Speter        if (n->prop_state == svn_wc_notify_state_conflicted)
637251881Speter          {
638251881Speter            store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
639251881Speter            statchar_buf[1] = 'C';
640251881Speter          }
641251881Speter        else if (n->prop_state == svn_wc_notify_state_merged)
642251881Speter          statchar_buf[1] = 'G';
643251881Speter        else if (n->prop_state == svn_wc_notify_state_changed)
644251881Speter          statchar_buf[1] = 'U';
645251881Speter
646251881Speter        if (n->lock_state == svn_wc_notify_lock_state_unlocked)
647251881Speter          statchar_buf[2] = 'B';
648251881Speter
649251881Speter        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
650251881Speter          nb->received_some_change = TRUE;
651251881Speter
652251881Speter        if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
653251881Speter            || statchar_buf[2] != ' ')
654251881Speter          {
655251881Speter            if ((err = svn_cmdline_printf(pool, "%s %s\n",
656251881Speter                                          statchar_buf, path_local)))
657251881Speter              goto print_error;
658251881Speter          }
659251881Speter      }
660251881Speter      break;
661251881Speter
662251881Speter    case svn_wc_notify_update_external:
663251881Speter      /* Remember that we're now "inside" an externals definition. */
664251881Speter      nb->in_external = TRUE;
665251881Speter
666251881Speter      /* Currently this is used for checkouts and switches too.  If we
667251881Speter         want different output, we'll have to add new actions. */
668251881Speter      if ((err = svn_cmdline_printf(pool,
669251881Speter                                    _("\nFetching external item into '%s':\n"),
670251881Speter                                    path_local)))
671251881Speter        goto print_error;
672251881Speter      break;
673251881Speter
674251881Speter    case svn_wc_notify_failed_external:
675251881Speter      /* If we are currently inside the handling of an externals
676251881Speter         definition, then we can simply present n->err as a warning
677251881Speter         and feel confident that after this, we aren't handling that
678251881Speter         externals definition any longer. */
679251881Speter      if (nb->in_external)
680251881Speter        {
681251881Speter          svn_handle_warning2(stderr, n->err, "svn: ");
682251881Speter          nb->in_external = FALSE;
683251881Speter          if ((err = svn_cmdline_printf(pool, "\n")))
684251881Speter            goto print_error;
685251881Speter        }
686251881Speter      /* Otherwise, we'll just print two warnings.  Why?  Because
687251881Speter         svn_handle_warning2() only shows the single "best message",
688251881Speter         but we have two pretty important ones: that the external at
689251881Speter         '/some/path' didn't pan out, and then the more specific
690251881Speter         reason why (from n->err). */
691251881Speter      else
692251881Speter        {
693251881Speter          svn_error_t *warn_err =
694251881Speter            svn_error_createf(SVN_ERR_BASE, NULL,
695251881Speter                              _("Error handling externals definition for '%s':"),
696251881Speter                              path_local);
697251881Speter          svn_handle_warning2(stderr, warn_err, "svn: ");
698251881Speter          svn_error_clear(warn_err);
699251881Speter          svn_handle_warning2(stderr, n->err, "svn: ");
700251881Speter        }
701251881Speter      break;
702251881Speter
703251881Speter    case svn_wc_notify_update_started:
704251881Speter      if (! (nb->in_external ||
705251881Speter             nb->is_checkout ||
706251881Speter             nb->is_export))
707251881Speter        {
708251881Speter          if ((err = svn_cmdline_printf(pool, _("Updating '%s':\n"),
709251881Speter                                        path_local)))
710251881Speter            goto print_error;
711251881Speter        }
712251881Speter      break;
713251881Speter
714251881Speter    case svn_wc_notify_update_completed:
715251881Speter      {
716251881Speter        if (SVN_IS_VALID_REVNUM(n->revision))
717251881Speter          {
718251881Speter            if (nb->is_export)
719251881Speter              {
720251881Speter                if ((err = svn_cmdline_printf
721251881Speter                     (pool, nb->in_external
722251881Speter                      ? _("Exported external at revision %ld.\n")
723251881Speter                      : _("Exported revision %ld.\n"),
724251881Speter                      n->revision)))
725251881Speter                  goto print_error;
726251881Speter              }
727251881Speter            else if (nb->is_checkout)
728251881Speter              {
729251881Speter                if ((err = svn_cmdline_printf
730251881Speter                     (pool, nb->in_external
731251881Speter                      ? _("Checked out external at revision %ld.\n")
732251881Speter                      : _("Checked out revision %ld.\n"),
733251881Speter                      n->revision)))
734251881Speter                  goto print_error;
735251881Speter              }
736251881Speter            else
737251881Speter              {
738251881Speter                if (nb->received_some_change)
739251881Speter                  {
740251881Speter                    nb->received_some_change = FALSE;
741251881Speter                    if ((err = svn_cmdline_printf
742251881Speter                         (pool, nb->in_external
743251881Speter                          ? _("Updated external to revision %ld.\n")
744251881Speter                          : _("Updated to revision %ld.\n"),
745251881Speter                          n->revision)))
746251881Speter                      goto print_error;
747251881Speter                  }
748251881Speter                else
749251881Speter                  {
750251881Speter                    if ((err = svn_cmdline_printf
751251881Speter                         (pool, nb->in_external
752251881Speter                          ? _("External at revision %ld.\n")
753251881Speter                          : _("At revision %ld.\n"),
754251881Speter                          n->revision)))
755251881Speter                      goto print_error;
756251881Speter                  }
757251881Speter              }
758251881Speter          }
759251881Speter        else  /* no revision */
760251881Speter          {
761251881Speter            if (nb->is_export)
762251881Speter              {
763251881Speter                if ((err = svn_cmdline_printf
764251881Speter                     (pool, nb->in_external
765251881Speter                      ? _("External export complete.\n")
766251881Speter                      : _("Export complete.\n"))))
767251881Speter                  goto print_error;
768251881Speter              }
769251881Speter            else if (nb->is_checkout)
770251881Speter              {
771251881Speter                if ((err = svn_cmdline_printf
772251881Speter                     (pool, nb->in_external
773251881Speter                      ? _("External checkout complete.\n")
774251881Speter                      : _("Checkout complete.\n"))))
775251881Speter                  goto print_error;
776251881Speter              }
777251881Speter            else
778251881Speter              {
779251881Speter                if ((err = svn_cmdline_printf
780251881Speter                     (pool, nb->in_external
781251881Speter                      ? _("External update complete.\n")
782251881Speter                      : _("Update complete.\n"))))
783251881Speter                  goto print_error;
784251881Speter              }
785251881Speter          }
786251881Speter      }
787251881Speter
788251881Speter      if (nb->in_external)
789251881Speter        {
790251881Speter          nb->in_external = FALSE;
791251881Speter          if ((err = svn_cmdline_printf(pool, "\n")))
792251881Speter            goto print_error;
793251881Speter        }
794251881Speter      break;
795251881Speter
796251881Speter    case svn_wc_notify_status_external:
797251881Speter      if ((err = svn_cmdline_printf
798251881Speter           (pool, _("\nPerforming status on external item at '%s':\n"),
799251881Speter            path_local)))
800251881Speter        goto print_error;
801251881Speter      break;
802251881Speter
803251881Speter    case svn_wc_notify_status_completed:
804251881Speter      if (SVN_IS_VALID_REVNUM(n->revision))
805251881Speter        if ((err = svn_cmdline_printf(pool,
806251881Speter                                      _("Status against revision: %6ld\n"),
807251881Speter                                      n->revision)))
808251881Speter          goto print_error;
809251881Speter      break;
810251881Speter
811251881Speter    case svn_wc_notify_commit_modified:
812251881Speter      /* xgettext: Align the %s's on this and the following 4 messages */
813251881Speter      if ((err = svn_cmdline_printf(pool,
814251881Speter                                    nb->is_wc_to_repos_copy
815251881Speter                                      ? _("Sending copy of       %s\n")
816251881Speter                                      : _("Sending        %s\n"),
817251881Speter                                    path_local)))
818251881Speter        goto print_error;
819251881Speter      break;
820251881Speter
821251881Speter    case svn_wc_notify_commit_added:
822251881Speter    case svn_wc_notify_commit_copied:
823251881Speter      if (n->mime_type && svn_mime_type_is_binary(n->mime_type))
824251881Speter        {
825251881Speter          if ((err = svn_cmdline_printf(pool,
826251881Speter                                        nb->is_wc_to_repos_copy
827251881Speter                                          ? _("Adding copy of (bin)  %s\n")
828251881Speter                                          : _("Adding  (bin)  %s\n"),
829251881Speter                                        path_local)))
830251881Speter          goto print_error;
831251881Speter        }
832251881Speter      else
833251881Speter        {
834251881Speter          if ((err = svn_cmdline_printf(pool,
835251881Speter                                        nb->is_wc_to_repos_copy
836251881Speter                                          ? _("Adding copy of        %s\n")
837251881Speter                                          : _("Adding         %s\n"),
838251881Speter                                        path_local)))
839251881Speter            goto print_error;
840251881Speter        }
841251881Speter      break;
842251881Speter
843251881Speter    case svn_wc_notify_commit_deleted:
844251881Speter      if ((err = svn_cmdline_printf(pool,
845251881Speter                                    nb->is_wc_to_repos_copy
846251881Speter                                      ? _("Deleting copy of      %s\n")
847251881Speter                                      : _("Deleting       %s\n"),
848251881Speter                                    path_local)))
849251881Speter        goto print_error;
850251881Speter      break;
851251881Speter
852251881Speter    case svn_wc_notify_commit_replaced:
853251881Speter    case svn_wc_notify_commit_copied_replaced:
854251881Speter      if ((err = svn_cmdline_printf(pool,
855251881Speter                                    nb->is_wc_to_repos_copy
856251881Speter                                      ? _("Replacing copy of     %s\n")
857251881Speter                                      : _("Replacing      %s\n"),
858251881Speter                                    path_local)))
859251881Speter        goto print_error;
860251881Speter      break;
861251881Speter
862251881Speter    case svn_wc_notify_commit_postfix_txdelta:
863251881Speter      if (! nb->sent_first_txdelta)
864251881Speter        {
865251881Speter          nb->sent_first_txdelta = TRUE;
866251881Speter          if ((err = svn_cmdline_printf(pool,
867251881Speter                                        _("Transmitting file data "))))
868251881Speter            goto print_error;
869251881Speter        }
870251881Speter
871251881Speter      if ((err = svn_cmdline_printf(pool, ".")))
872251881Speter        goto print_error;
873251881Speter      break;
874251881Speter
875251881Speter    case svn_wc_notify_locked:
876251881Speter      if ((err = svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"),
877251881Speter                                    path_local, n->lock->owner)))
878251881Speter        goto print_error;
879251881Speter      break;
880251881Speter
881251881Speter    case svn_wc_notify_unlocked:
882251881Speter      if ((err = svn_cmdline_printf(pool, _("'%s' unlocked.\n"),
883251881Speter                                    path_local)))
884251881Speter        goto print_error;
885251881Speter      break;
886251881Speter
887251881Speter    case svn_wc_notify_failed_lock:
888251881Speter    case svn_wc_notify_failed_unlock:
889251881Speter      svn_handle_warning2(stderr, n->err, "svn: ");
890251881Speter      break;
891251881Speter
892251881Speter    case svn_wc_notify_changelist_set:
893251881Speter      if ((err = svn_cmdline_printf(pool, "A [%s] %s\n",
894251881Speter                                    n->changelist_name, path_local)))
895251881Speter        goto print_error;
896251881Speter      break;
897251881Speter
898251881Speter    case svn_wc_notify_changelist_clear:
899251881Speter    case svn_wc_notify_changelist_moved:
900251881Speter      if ((err = svn_cmdline_printf(pool,
901251881Speter                                    "D [%s] %s\n",
902251881Speter                                    n->changelist_name, path_local)))
903251881Speter        goto print_error;
904251881Speter      break;
905251881Speter
906251881Speter    case svn_wc_notify_merge_begin:
907251881Speter      if (n->merge_range == NULL)
908251881Speter        err = svn_cmdline_printf(pool,
909251881Speter                                 _("--- Merging differences between "
910251881Speter                                   "repository URLs into '%s':\n"),
911251881Speter                                 path_local);
912251881Speter      else if (n->merge_range->start == n->merge_range->end - 1
913251881Speter          || n->merge_range->start == n->merge_range->end)
914251881Speter        err = svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"),
915251881Speter                                 n->merge_range->end, path_local);
916251881Speter      else if (n->merge_range->start - 1 == n->merge_range->end)
917251881Speter        err = svn_cmdline_printf(pool,
918251881Speter                                 _("--- Reverse-merging r%ld into '%s':\n"),
919251881Speter                                 n->merge_range->start, path_local);
920251881Speter      else if (n->merge_range->start < n->merge_range->end)
921251881Speter        err = svn_cmdline_printf(pool,
922251881Speter                                 _("--- Merging r%ld through r%ld into "
923251881Speter                                   "'%s':\n"),
924251881Speter                                 n->merge_range->start + 1,
925251881Speter                                 n->merge_range->end, path_local);
926251881Speter      else /* n->merge_range->start > n->merge_range->end - 1 */
927251881Speter        err = svn_cmdline_printf(pool,
928251881Speter                                 _("--- Reverse-merging r%ld through r%ld "
929251881Speter                                   "into '%s':\n"),
930251881Speter                                 n->merge_range->start,
931251881Speter                                 n->merge_range->end + 1, path_local);
932251881Speter      if (err)
933251881Speter        goto print_error;
934251881Speter      break;
935251881Speter
936251881Speter    case svn_wc_notify_merge_record_info_begin:
937251881Speter      if (!n->merge_range)
938251881Speter        {
939251881Speter          err = svn_cmdline_printf(pool,
940251881Speter                                   _("--- Recording mergeinfo for merge "
941251881Speter                                     "between repository URLs into '%s':\n"),
942251881Speter                                   path_local);
943251881Speter        }
944251881Speter      else
945251881Speter        {
946251881Speter          if (n->merge_range->start == n->merge_range->end - 1
947251881Speter              || n->merge_range->start == n->merge_range->end)
948251881Speter            err = svn_cmdline_printf(
949251881Speter              pool,
950251881Speter              _("--- Recording mergeinfo for merge of r%ld into '%s':\n"),
951251881Speter              n->merge_range->end, path_local);
952251881Speter          else if (n->merge_range->start - 1 == n->merge_range->end)
953251881Speter            err = svn_cmdline_printf(
954251881Speter              pool,
955251881Speter              _("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"),
956251881Speter              n->merge_range->start, path_local);
957251881Speter           else if (n->merge_range->start < n->merge_range->end)
958251881Speter             err = svn_cmdline_printf(
959251881Speter               pool,
960251881Speter               _("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"),
961251881Speter               n->merge_range->start + 1, n->merge_range->end, path_local);
962251881Speter           else /* n->merge_range->start > n->merge_range->end - 1 */
963251881Speter             err = svn_cmdline_printf(
964251881Speter               pool,
965251881Speter               _("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"),
966251881Speter               n->merge_range->start, n->merge_range->end + 1, path_local);
967251881Speter        }
968251881Speter
969251881Speter      if (err)
970251881Speter        goto print_error;
971251881Speter      break;
972251881Speter
973251881Speter    case svn_wc_notify_merge_elide_info:
974251881Speter      if ((err = svn_cmdline_printf(pool,
975251881Speter                                    _("--- Eliding mergeinfo from '%s':\n"),
976251881Speter                                    path_local)))
977251881Speter        goto print_error;
978251881Speter      break;
979251881Speter
980251881Speter    case svn_wc_notify_foreign_merge_begin:
981251881Speter      if (n->merge_range == NULL)
982251881Speter        err = svn_cmdline_printf(pool,
983251881Speter                                 _("--- Merging differences between "
984251881Speter                                   "foreign repository URLs into '%s':\n"),
985251881Speter                                 path_local);
986251881Speter      else if (n->merge_range->start == n->merge_range->end - 1
987251881Speter          || n->merge_range->start == n->merge_range->end)
988251881Speter        err = svn_cmdline_printf(pool,
989251881Speter                                 _("--- Merging (from foreign repository) "
990251881Speter                                   "r%ld into '%s':\n"),
991251881Speter                                 n->merge_range->end, path_local);
992251881Speter      else if (n->merge_range->start - 1 == n->merge_range->end)
993251881Speter        err = svn_cmdline_printf(pool,
994251881Speter                                 _("--- Reverse-merging (from foreign "
995251881Speter                                   "repository) r%ld into '%s':\n"),
996251881Speter                                 n->merge_range->start, path_local);
997251881Speter      else if (n->merge_range->start < n->merge_range->end)
998251881Speter        err = svn_cmdline_printf(pool,
999251881Speter                                 _("--- Merging (from foreign repository) "
1000251881Speter                                   "r%ld through r%ld into '%s':\n"),
1001251881Speter                                 n->merge_range->start + 1,
1002251881Speter                                 n->merge_range->end, path_local);
1003251881Speter      else /* n->merge_range->start > n->merge_range->end - 1 */
1004251881Speter        err = svn_cmdline_printf(pool,
1005251881Speter                                 _("--- Reverse-merging (from foreign "
1006251881Speter                                   "repository) r%ld through r%ld into "
1007251881Speter                                   "'%s':\n"),
1008251881Speter                                 n->merge_range->start,
1009251881Speter                                 n->merge_range->end + 1, path_local);
1010251881Speter      if (err)
1011251881Speter        goto print_error;
1012251881Speter      break;
1013251881Speter
1014251881Speter    case svn_wc_notify_tree_conflict:
1015251881Speter      store_path(nb, nb->conflict_stats->tree_conflicts, path_local);
1016251881Speter      if ((err = svn_cmdline_printf(pool, "   C %s\n", path_local)))
1017251881Speter        goto print_error;
1018251881Speter      break;
1019251881Speter
1020251881Speter    case svn_wc_notify_update_shadowed_add:
1021251881Speter      nb->received_some_change = TRUE;
1022251881Speter      if ((err = svn_cmdline_printf(pool, "   A %s\n", path_local)))
1023251881Speter        goto print_error;
1024251881Speter      break;
1025251881Speter
1026251881Speter    case svn_wc_notify_update_shadowed_update:
1027251881Speter      nb->received_some_change = TRUE;
1028251881Speter      if ((err = svn_cmdline_printf(pool, "   U %s\n", path_local)))
1029251881Speter        goto print_error;
1030251881Speter      break;
1031251881Speter
1032251881Speter    case svn_wc_notify_update_shadowed_delete:
1033251881Speter      nb->received_some_change = TRUE;
1034251881Speter      if ((err = svn_cmdline_printf(pool, "   D %s\n", path_local)))
1035251881Speter        goto print_error;
1036251881Speter      break;
1037251881Speter
1038251881Speter    case svn_wc_notify_property_modified:
1039251881Speter    case svn_wc_notify_property_added:
1040251881Speter      err = svn_cmdline_printf(pool,
1041251881Speter                               _("property '%s' set on '%s'\n"),
1042251881Speter                               n->prop_name, path_local);
1043251881Speter      if (err)
1044251881Speter        goto print_error;
1045251881Speter      break;
1046251881Speter
1047251881Speter    case svn_wc_notify_property_deleted:
1048251881Speter      err = svn_cmdline_printf(pool,
1049251881Speter                               _("property '%s' deleted from '%s'.\n"),
1050251881Speter                               n->prop_name, path_local);
1051251881Speter      if (err)
1052251881Speter        goto print_error;
1053251881Speter      break;
1054251881Speter
1055251881Speter    case svn_wc_notify_property_deleted_nonexistent:
1056251881Speter      err = svn_cmdline_printf(pool,
1057251881Speter                               _("Attempting to delete nonexistent "
1058251881Speter                                 "property '%s' on '%s'\n"), n->prop_name,
1059251881Speter                               path_local);
1060251881Speter      if (err)
1061251881Speter        goto print_error;
1062251881Speter      break;
1063251881Speter
1064251881Speter    case svn_wc_notify_revprop_set:
1065251881Speter      err = svn_cmdline_printf(pool,
1066251881Speter                           _("property '%s' set on repository revision %ld\n"),
1067251881Speter                           n->prop_name, n->revision);
1068251881Speter        if (err)
1069251881Speter          goto print_error;
1070251881Speter      break;
1071251881Speter
1072251881Speter    case svn_wc_notify_revprop_deleted:
1073251881Speter      err = svn_cmdline_printf(pool,
1074251881Speter                     _("property '%s' deleted from repository revision %ld\n"),
1075251881Speter                     n->prop_name, n->revision);
1076251881Speter      if (err)
1077251881Speter        goto print_error;
1078251881Speter      break;
1079251881Speter
1080251881Speter    case svn_wc_notify_upgraded_path:
1081251881Speter      err = svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local);
1082251881Speter      if (err)
1083251881Speter        goto print_error;
1084251881Speter      break;
1085251881Speter
1086251881Speter    case svn_wc_notify_url_redirect:
1087251881Speter      err = svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"),
1088251881Speter                               n->url);
1089251881Speter      if (err)
1090251881Speter        goto print_error;
1091251881Speter      break;
1092251881Speter
1093251881Speter    case svn_wc_notify_path_nonexistent:
1094251881Speter      err = svn_cmdline_printf(pool, "%s\n",
1095251881Speter               apr_psprintf(pool, _("'%s' is not under version control"),
1096251881Speter                            path_local));
1097251881Speter      if (err)
1098251881Speter        goto print_error;
1099251881Speter      break;
1100251881Speter
1101251881Speter    case svn_wc_notify_conflict_resolver_starting:
1102251881Speter      /* Once all operations invoke the interactive conflict resolution after
1103251881Speter       * they've completed, we can run svn_cl__notifier_print_conflict_stats()
1104251881Speter       * here. */
1105251881Speter      break;
1106251881Speter
1107251881Speter    case svn_wc_notify_conflict_resolver_done:
1108251881Speter      break;
1109251881Speter
1110251881Speter    case svn_wc_notify_foreign_copy_begin:
1111251881Speter      if (n->merge_range == NULL)
1112251881Speter        {
1113251881Speter          err = svn_cmdline_printf(
1114251881Speter                           pool,
1115251881Speter                           _("--- Copying from foreign repository URL '%s':\n"),
1116251881Speter                           n->url);
1117251881Speter          if (err)
1118251881Speter            goto print_error;
1119251881Speter        }
1120251881Speter      break;
1121251881Speter
1122251881Speter    case svn_wc_notify_move_broken:
1123251881Speter      err = svn_cmdline_printf(pool,
1124251881Speter                               _("Breaking move with source path '%s'\n"),
1125251881Speter                               path_local);
1126251881Speter      if (err)
1127251881Speter        goto print_error;
1128251881Speter      break;
1129251881Speter
1130251881Speter    default:
1131251881Speter      break;
1132251881Speter    }
1133251881Speter
1134251881Speter  if ((err = svn_cmdline_fflush(stdout)))
1135251881Speter    goto print_error;
1136251881Speter
1137251881Speter  return;
1138251881Speter
1139251881Speter print_error:
1140251881Speter  /* If we had no errors before, print this error to stderr. Else, don't print
1141251881Speter     anything.  The user already knows there were some output errors,
1142251881Speter     so there is no point in flooding her with an error per notification. */
1143251881Speter  if (!nb->had_print_error)
1144251881Speter    {
1145251881Speter      nb->had_print_error = TRUE;
1146251881Speter      /* Issue #3014:
1147251881Speter       * Don't print anything on broken pipes. The pipe was likely
1148251881Speter       * closed by the process at the other end. We expect that
1149251881Speter       * process to perform error reporting as necessary.
1150251881Speter       *
1151251881Speter       * ### This assumes that there is only one error in a chain for
1152251881Speter       * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
1153251881Speter      if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
1154251881Speter        svn_handle_error2(err, stderr, FALSE, "svn: ");
1155251881Speter    }
1156251881Speter  svn_error_clear(err);
1157251881Speter}
1158251881Speter
1159251881Speter
1160251881Spetersvn_error_t *
1161251881Spetersvn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p,
1162251881Speter                     void **notify_baton_p,
1163251881Speter                     svn_cl__conflict_stats_t *conflict_stats,
1164251881Speter                     apr_pool_t *pool)
1165251881Speter{
1166251881Speter  struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb));
1167251881Speter
1168251881Speter  nb->received_some_change = FALSE;
1169251881Speter  nb->sent_first_txdelta = FALSE;
1170251881Speter  nb->is_checkout = FALSE;
1171251881Speter  nb->is_export = FALSE;
1172251881Speter  nb->is_wc_to_repos_copy = FALSE;
1173251881Speter  nb->in_external = FALSE;
1174251881Speter  nb->had_print_error = FALSE;
1175251881Speter  nb->conflict_stats = conflict_stats;
1176251881Speter  SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool));
1177251881Speter
1178251881Speter  *notify_func_p = notify;
1179251881Speter  *notify_baton_p = nb;
1180251881Speter  return SVN_NO_ERROR;
1181251881Speter}
1182251881Speter
1183251881Spetersvn_error_t *
1184251881Spetersvn_cl__notifier_mark_checkout(void *baton)
1185251881Speter{
1186251881Speter  struct notify_baton *nb = baton;
1187251881Speter
1188251881Speter  nb->is_checkout = TRUE;
1189251881Speter  return SVN_NO_ERROR;
1190251881Speter}
1191251881Speter
1192251881Spetersvn_error_t *
1193251881Spetersvn_cl__notifier_mark_export(void *baton)
1194251881Speter{
1195251881Speter  struct notify_baton *nb = baton;
1196251881Speter
1197251881Speter  nb->is_export = TRUE;
1198251881Speter  return SVN_NO_ERROR;
1199251881Speter}
1200251881Speter
1201251881Spetersvn_error_t *
1202251881Spetersvn_cl__notifier_mark_wc_to_repos_copy(void *baton)
1203251881Speter{
1204251881Speter  struct notify_baton *nb = baton;
1205251881Speter
1206251881Speter  nb->is_wc_to_repos_copy = TRUE;
1207251881Speter  return SVN_NO_ERROR;
1208251881Speter}
1209251881Speter
1210251881Spetervoid
1211251881Spetersvn_cl__check_externals_failed_notify_wrapper(void *baton,
1212251881Speter                                              const svn_wc_notify_t *n,
1213251881Speter                                              apr_pool_t *pool)
1214251881Speter{
1215251881Speter  struct svn_cl__check_externals_failed_notify_baton *nwb = baton;
1216251881Speter
1217251881Speter  if (n->action == svn_wc_notify_failed_external)
1218251881Speter    nwb->had_externals_error = TRUE;
1219251881Speter
1220251881Speter  if (nwb->wrapped_func)
1221251881Speter    nwb->wrapped_func(nwb->wrapped_baton, n, pool);
1222251881Speter}
1223