2 * notify.c: feedback handlers for cmdline client.
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
24 /* ==================================================================== */
30 #define APR_WANT_STDIO
31 #define APR_WANT_STRFUNC
34 #include "svn_cmdline.h"
35 #include "svn_pools.h"
36 #include "svn_dirent_uri.h"
38 #include "svn_sorts.h"
41 #include "svn_private_config.h"
44 /* Baton for notify and friends. */
47 svn_boolean_t received_some_change;
48 svn_boolean_t is_checkout;
49 svn_boolean_t is_export;
50 svn_boolean_t is_wc_to_repos_copy;
51 svn_boolean_t sent_first_txdelta;
52 svn_boolean_t in_external;
53 svn_boolean_t had_print_error; /* Used to not keep printing error messages
54 when we've already had one print error. */
56 /* Conflict stats for update and merge. */
57 unsigned int text_conflicts;
58 unsigned int prop_conflicts;
59 unsigned int tree_conflicts;
60 unsigned int skipped_paths;
61 apr_hash_t *conflicted_paths;
63 /* The cwd, for use in decomposing absolute paths. */
64 const char *path_prefix;
68 /* Add a conflicted path to the list of conflicted paths stored
69 * in the notify baton. */
71 add_conflicted_path(struct notify_baton *nb, const char *path)
73 apr_hash_set(nb->conflicted_paths,
74 apr_pstrdup(apr_hash_pool_get(nb->conflicted_paths), path),
75 APR_HASH_KEY_STRING, "");
78 /* This implements `svn_wc_notify_func2_t'.
79 * NOTE: This function can't fail, so we just ignore any print errors. */
81 notify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool)
83 struct notify_baton *nb = baton;
84 char statchar_buf[5] = " ";
85 const char *path_local;
93 path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path,
95 else /* skip nb->path_prefix, if it's non-null */
96 path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path,
102 case svn_wc_notify_skip:
104 if (n->content_state == svn_wc_notify_state_missing)
106 if ((err = svn_cmdline_printf
107 (pool, _("Skipped missing target: '%s'\n"),
111 else if (n->content_state == svn_wc_notify_state_source_missing)
113 if ((err = svn_cmdline_printf
114 (pool, _("Skipped target: '%s' -- copy-source is missing\n"),
120 if ((err = svn_cmdline_printf
121 (pool, _("Skipped '%s'\n"), path_local)))
125 case svn_wc_notify_update_skip_obstruction:
127 if ((err = svn_cmdline_printf(
128 pool, _("Skipped '%s' -- An obstructing working copy was found\n"),
132 case svn_wc_notify_update_skip_working_only:
134 if ((err = svn_cmdline_printf(
135 pool, _("Skipped '%s' -- Has no versioned parent\n"),
139 case svn_wc_notify_update_skip_access_denied:
141 if ((err = svn_cmdline_printf(
142 pool, _("Skipped '%s' -- Access denied\n"),
146 case svn_wc_notify_skip_conflicted:
148 if ((err = svn_cmdline_printf(
149 pool, _("Skipped '%s' -- Node remains in conflict\n"),
153 case svn_wc_notify_update_delete:
154 case svn_wc_notify_exclude:
155 nb->received_some_change = TRUE;
156 if ((err = svn_cmdline_printf(pool, "D %s\n", path_local)))
159 case svn_wc_notify_update_broken_lock:
160 if ((err = svn_cmdline_printf(pool, "B %s\n", path_local)))
164 case svn_wc_notify_update_external_removed:
165 nb->received_some_change = TRUE;
166 if (n->err && n->err->message)
168 if ((err = svn_cmdline_printf(pool, "Removed external '%s': %s\n",
169 path_local, n->err->message)))
174 if ((err = svn_cmdline_printf(pool, "Removed external '%s'\n",
180 case svn_wc_notify_left_local_modifications:
181 if ((err = svn_cmdline_printf(pool, "Left local modifications as '%s'\n",
186 case svn_wc_notify_update_replace:
187 nb->received_some_change = TRUE;
188 if ((err = svn_cmdline_printf(pool, "R %s\n", path_local)))
192 case svn_wc_notify_update_add:
193 nb->received_some_change = TRUE;
194 if (n->content_state == svn_wc_notify_state_conflicted)
196 nb->text_conflicts++;
197 add_conflicted_path(nb, n->path);
198 if ((err = svn_cmdline_printf(pool, "C %s\n", path_local)))
203 if ((err = svn_cmdline_printf(pool, "A %s\n", path_local)))
208 case svn_wc_notify_exists:
209 nb->received_some_change = TRUE;
210 if (n->content_state == svn_wc_notify_state_conflicted)
212 nb->text_conflicts++;
213 add_conflicted_path(nb, n->path);
214 statchar_buf[0] = 'C';
217 statchar_buf[0] = 'E';
219 if (n->prop_state == svn_wc_notify_state_conflicted)
221 nb->prop_conflicts++;
222 add_conflicted_path(nb, n->path);
223 statchar_buf[1] = 'C';
225 else if (n->prop_state == svn_wc_notify_state_merged)
226 statchar_buf[1] = 'G';
228 if ((err = svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local)))
232 case svn_wc_notify_restore:
233 if ((err = svn_cmdline_printf(pool, _("Restored '%s'\n"),
238 case svn_wc_notify_revert:
239 if ((err = svn_cmdline_printf(pool, _("Reverted '%s'\n"),
244 case svn_wc_notify_failed_revert:
245 if (( err = svn_cmdline_printf(pool, _("Failed to revert '%s' -- "
246 "try updating instead.\n"),
251 case svn_wc_notify_resolved:
252 if ((err = svn_cmdline_printf(pool,
253 _("Resolved conflicted state of '%s'\n"),
258 case svn_wc_notify_add:
259 /* We *should* only get the MIME_TYPE if PATH is a file. If we
260 do get it, and the mime-type is not textual, note that this
261 is a binary addition. */
262 if (n->mime_type && (svn_mime_type_is_binary(n->mime_type)))
264 if ((err = svn_cmdline_printf(pool, "A (bin) %s\n",
270 if ((err = svn_cmdline_printf(pool, "A %s\n",
276 case svn_wc_notify_delete:
277 nb->received_some_change = TRUE;
278 if ((err = svn_cmdline_printf(pool, "D %s\n",
283 case svn_wc_notify_patch:
285 nb->received_some_change = TRUE;
286 if (n->content_state == svn_wc_notify_state_conflicted)
288 nb->text_conflicts++;
289 add_conflicted_path(nb, n->path);
290 statchar_buf[0] = 'C';
292 else if (n->kind == svn_node_file)
294 if (n->content_state == svn_wc_notify_state_merged)
295 statchar_buf[0] = 'G';
296 else if (n->content_state == svn_wc_notify_state_changed)
297 statchar_buf[0] = 'U';
300 if (n->prop_state == svn_wc_notify_state_conflicted)
302 nb->prop_conflicts++;
303 add_conflicted_path(nb, n->path);
304 statchar_buf[1] = 'C';
306 else if (n->prop_state == svn_wc_notify_state_changed)
307 statchar_buf[1] = 'U';
309 if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
311 if ((err = svn_cmdline_printf(pool, "%s %s\n",
312 statchar_buf, path_local)))
318 case svn_wc_notify_patch_applied_hunk:
319 nb->received_some_change = TRUE;
320 if (n->hunk_original_start != n->hunk_matched_line)
326 if (n->hunk_matched_line > n->hunk_original_start)
328 off = n->hunk_matched_line - n->hunk_original_start;
333 off = n->hunk_original_start - n->hunk_matched_line;
337 /* ### We're creating the localized strings without
338 * ### APR_INT64_T_FMT since it isn't translator-friendly */
344 s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## "
347 err = svn_cmdline_printf(pool,
350 " and fuzz %lu (%s)\n",
352 n->hunk_original_start,
353 n->hunk_original_length,
354 n->hunk_modified_start,
355 n->hunk_modified_length,
356 minus, off, n->hunk_fuzz,
361 s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ "
364 err = svn_cmdline_printf(pool,
369 n->hunk_original_start,
370 n->hunk_original_length,
371 n->hunk_modified_start,
372 n->hunk_modified_length,
373 minus, off, n->hunk_fuzz);
384 s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## "
386 err = svn_cmdline_printf(pool,
388 "%"APR_UINT64_T_FMT" (%s)\n",
390 n->hunk_original_start,
391 n->hunk_original_length,
392 n->hunk_modified_start,
393 n->hunk_modified_length,
394 minus, off, n->prop_name);
398 s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ "
400 err = svn_cmdline_printf(pool,
402 "%"APR_UINT64_T_FMT"\n",
404 n->hunk_original_start,
405 n->hunk_original_length,
406 n->hunk_modified_start,
407 n->hunk_modified_length,
415 else if (n->hunk_fuzz)
418 err = svn_cmdline_printf(pool,
419 _("> applied hunk ## -%lu,%lu +%lu,%lu ## "
420 "with fuzz %lu (%s)\n"),
421 n->hunk_original_start,
422 n->hunk_original_length,
423 n->hunk_modified_start,
424 n->hunk_modified_length,
428 err = svn_cmdline_printf(pool,
429 _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ "
431 n->hunk_original_start,
432 n->hunk_original_length,
433 n->hunk_modified_start,
434 n->hunk_modified_length,
442 case svn_wc_notify_patch_rejected_hunk:
443 nb->received_some_change = TRUE;
446 err = svn_cmdline_printf(pool,
448 "## -%lu,%lu +%lu,%lu ## (%s)\n"),
449 n->hunk_original_start,
450 n->hunk_original_length,
451 n->hunk_modified_start,
452 n->hunk_modified_length,
455 err = svn_cmdline_printf(pool,
457 "@@ -%lu,%lu +%lu,%lu @@\n"),
458 n->hunk_original_start,
459 n->hunk_original_length,
460 n->hunk_modified_start,
461 n->hunk_modified_length);
466 case svn_wc_notify_patch_hunk_already_applied:
467 nb->received_some_change = TRUE;
469 err = svn_cmdline_printf(pool,
471 "## -%lu,%lu +%lu,%lu ## "
472 "already applied (%s)\n"),
473 n->hunk_original_start,
474 n->hunk_original_length,
475 n->hunk_modified_start,
476 n->hunk_modified_length,
479 err = svn_cmdline_printf(pool,
481 "@@ -%lu,%lu +%lu,%lu @@ "
482 "already applied\n"),
483 n->hunk_original_start,
484 n->hunk_original_length,
485 n->hunk_modified_start,
486 n->hunk_modified_length);
491 case svn_wc_notify_update_update:
492 case svn_wc_notify_merge_record_info:
494 if (n->content_state == svn_wc_notify_state_conflicted)
496 nb->text_conflicts++;
497 add_conflicted_path(nb, n->path);
498 statchar_buf[0] = 'C';
500 else if (n->kind == svn_node_file)
502 if (n->content_state == svn_wc_notify_state_merged)
503 statchar_buf[0] = 'G';
504 else if (n->content_state == svn_wc_notify_state_changed)
505 statchar_buf[0] = 'U';
508 if (n->prop_state == svn_wc_notify_state_conflicted)
510 nb->prop_conflicts++;
511 add_conflicted_path(nb, n->path);
512 statchar_buf[1] = 'C';
514 else if (n->prop_state == svn_wc_notify_state_merged)
515 statchar_buf[1] = 'G';
516 else if (n->prop_state == svn_wc_notify_state_changed)
517 statchar_buf[1] = 'U';
519 if (n->lock_state == svn_wc_notify_lock_state_unlocked)
520 statchar_buf[2] = 'B';
522 if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
523 nb->received_some_change = TRUE;
525 if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
526 || statchar_buf[2] != ' ')
528 if ((err = svn_cmdline_printf(pool, "%s %s\n",
529 statchar_buf, path_local)))
535 case svn_wc_notify_update_external:
536 /* Remember that we're now "inside" an externals definition. */
537 nb->in_external = TRUE;
539 /* Currently this is used for checkouts and switches too. If we
540 want different output, we'll have to add new actions. */
541 if ((err = svn_cmdline_printf(pool,
542 _("\nFetching external item into '%s':\n"),
547 case svn_wc_notify_failed_external:
548 /* If we are currently inside the handling of an externals
549 definition, then we can simply present n->err as a warning
550 and feel confident that after this, we aren't handling that
551 externals definition any longer. */
554 svn_handle_warning2(stderr, n->err, "svn: ");
555 nb->in_external = FALSE;
556 if ((err = svn_cmdline_printf(pool, "\n")))
559 /* Otherwise, we'll just print two warnings. Why? Because
560 svn_handle_warning2() only shows the single "best message",
561 but we have two pretty important ones: that the external at
562 '/some/path' didn't pan out, and then the more specific
563 reason why (from n->err). */
566 svn_error_t *warn_err =
567 svn_error_createf(SVN_ERR_BASE, NULL,
568 _("Error handling externals definition for '%s':"),
570 svn_handle_warning2(stderr, warn_err, "svn: ");
571 svn_error_clear(warn_err);
572 svn_handle_warning2(stderr, n->err, "svn: ");
576 case svn_wc_notify_update_started:
577 if (! (nb->in_external ||
581 if ((err = svn_cmdline_printf(pool, _("Updating '%s':\n"),
587 case svn_wc_notify_update_completed:
589 if (SVN_IS_VALID_REVNUM(n->revision))
593 if ((err = svn_cmdline_printf
594 (pool, nb->in_external
595 ? _("Exported external at revision %ld.\n")
596 : _("Exported revision %ld.\n"),
600 else if (nb->is_checkout)
602 if ((err = svn_cmdline_printf
603 (pool, nb->in_external
604 ? _("Checked out external at revision %ld.\n")
605 : _("Checked out revision %ld.\n"),
611 if (nb->received_some_change)
613 nb->received_some_change = FALSE;
614 if ((err = svn_cmdline_printf
615 (pool, nb->in_external
616 ? _("Updated external to revision %ld.\n")
617 : _("Updated to revision %ld.\n"),
623 if ((err = svn_cmdline_printf
624 (pool, nb->in_external
625 ? _("External at revision %ld.\n")
626 : _("At revision %ld.\n"),
632 else /* no revision */
636 if ((err = svn_cmdline_printf
637 (pool, nb->in_external
638 ? _("External export complete.\n")
639 : _("Export complete.\n"))))
642 else if (nb->is_checkout)
644 if ((err = svn_cmdline_printf
645 (pool, nb->in_external
646 ? _("External checkout complete.\n")
647 : _("Checkout complete.\n"))))
652 if ((err = svn_cmdline_printf
653 (pool, nb->in_external
654 ? _("External update complete.\n")
655 : _("Update complete.\n"))))
663 nb->in_external = FALSE;
664 if ((err = svn_cmdline_printf(pool, "\n")))
669 case svn_wc_notify_status_external:
670 if ((err = svn_cmdline_printf
671 (pool, _("\nPerforming status on external item at '%s':\n"),
676 case svn_wc_notify_status_completed:
677 if (SVN_IS_VALID_REVNUM(n->revision))
678 if ((err = svn_cmdline_printf(pool,
679 _("Status against revision: %6ld\n"),
684 case svn_wc_notify_commit_modified:
685 /* xgettext: Align the %s's on this and the following 4 messages */
686 if ((err = svn_cmdline_printf(pool,
687 nb->is_wc_to_repos_copy
688 ? _("Sending copy of %s\n")
694 case svn_wc_notify_commit_added:
695 case svn_wc_notify_commit_copied:
696 if (n->mime_type && svn_mime_type_is_binary(n->mime_type))
698 if ((err = svn_cmdline_printf(pool,
699 nb->is_wc_to_repos_copy
700 ? _("Adding copy of (bin) %s\n")
701 : _("Adding (bin) %s\n"),
707 if ((err = svn_cmdline_printf(pool,
708 nb->is_wc_to_repos_copy
709 ? _("Adding copy of %s\n")
716 case svn_wc_notify_commit_deleted:
717 if ((err = svn_cmdline_printf(pool,
718 nb->is_wc_to_repos_copy
719 ? _("Deleting copy of %s\n")
720 : _("Deleting %s\n"),
725 case svn_wc_notify_commit_replaced:
726 case svn_wc_notify_commit_copied_replaced:
727 if ((err = svn_cmdline_printf(pool,
728 nb->is_wc_to_repos_copy
729 ? _("Replacing copy of %s\n")
730 : _("Replacing %s\n"),
735 case svn_wc_notify_commit_postfix_txdelta:
736 if (! nb->sent_first_txdelta)
738 nb->sent_first_txdelta = TRUE;
739 if ((err = svn_cmdline_printf(pool,
740 _("Transmitting file data "))))
744 if ((err = svn_cmdline_printf(pool, ".")))
748 case svn_wc_notify_locked:
749 if ((err = svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"),
750 path_local, n->lock->owner)))
754 case svn_wc_notify_unlocked:
755 if ((err = svn_cmdline_printf(pool, _("'%s' unlocked.\n"),
760 case svn_wc_notify_failed_lock:
761 case svn_wc_notify_failed_unlock:
762 svn_handle_warning2(stderr, n->err, "svn: ");
765 case svn_wc_notify_changelist_set:
766 if ((err = svn_cmdline_printf(pool, "A [%s] %s\n",
767 n->changelist_name, path_local)))
771 case svn_wc_notify_changelist_clear:
772 case svn_wc_notify_changelist_moved:
773 if ((err = svn_cmdline_printf(pool,
775 n->changelist_name, path_local)))
779 case svn_wc_notify_merge_begin:
780 if (n->merge_range == NULL)
781 err = svn_cmdline_printf(pool,
782 _("--- Merging differences between "
783 "repository URLs into '%s':\n"),
785 else if (n->merge_range->start == n->merge_range->end - 1
786 || n->merge_range->start == n->merge_range->end)
787 err = svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"),
788 n->merge_range->end, path_local);
789 else if (n->merge_range->start - 1 == n->merge_range->end)
790 err = svn_cmdline_printf(pool,
791 _("--- Reverse-merging r%ld into '%s':\n"),
792 n->merge_range->start, path_local);
793 else if (n->merge_range->start < n->merge_range->end)
794 err = svn_cmdline_printf(pool,
795 _("--- Merging r%ld through r%ld into "
797 n->merge_range->start + 1,
798 n->merge_range->end, path_local);
799 else /* n->merge_range->start > n->merge_range->end - 1 */
800 err = svn_cmdline_printf(pool,
801 _("--- Reverse-merging r%ld through r%ld "
803 n->merge_range->start,
804 n->merge_range->end + 1, path_local);
809 case svn_wc_notify_merge_record_info_begin:
812 err = svn_cmdline_printf(pool,
813 _("--- Recording mergeinfo for merge "
814 "between repository URLs into '%s':\n"),
819 if (n->merge_range->start == n->merge_range->end - 1
820 || n->merge_range->start == n->merge_range->end)
821 err = svn_cmdline_printf(
823 _("--- Recording mergeinfo for merge of r%ld into '%s':\n"),
824 n->merge_range->end, path_local);
825 else if (n->merge_range->start - 1 == n->merge_range->end)
826 err = svn_cmdline_printf(
828 _("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"),
829 n->merge_range->start, path_local);
830 else if (n->merge_range->start < n->merge_range->end)
831 err = svn_cmdline_printf(
833 _("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"),
834 n->merge_range->start + 1, n->merge_range->end, path_local);
835 else /* n->merge_range->start > n->merge_range->end - 1 */
836 err = svn_cmdline_printf(
838 _("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"),
839 n->merge_range->start, n->merge_range->end + 1, path_local);
846 case svn_wc_notify_merge_elide_info:
847 if ((err = svn_cmdline_printf(pool,
848 _("--- Eliding mergeinfo from '%s':\n"),
853 case svn_wc_notify_foreign_merge_begin:
854 if (n->merge_range == NULL)
855 err = svn_cmdline_printf(pool,
856 _("--- Merging differences between "
857 "foreign repository URLs into '%s':\n"),
859 else if (n->merge_range->start == n->merge_range->end - 1
860 || n->merge_range->start == n->merge_range->end)
861 err = svn_cmdline_printf(pool,
862 _("--- Merging (from foreign repository) "
863 "r%ld into '%s':\n"),
864 n->merge_range->end, path_local);
865 else if (n->merge_range->start - 1 == n->merge_range->end)
866 err = svn_cmdline_printf(pool,
867 _("--- Reverse-merging (from foreign "
868 "repository) r%ld into '%s':\n"),
869 n->merge_range->start, path_local);
870 else if (n->merge_range->start < n->merge_range->end)
871 err = svn_cmdline_printf(pool,
872 _("--- Merging (from foreign repository) "
873 "r%ld through r%ld into '%s':\n"),
874 n->merge_range->start + 1,
875 n->merge_range->end, path_local);
876 else /* n->merge_range->start > n->merge_range->end - 1 */
877 err = svn_cmdline_printf(pool,
878 _("--- Reverse-merging (from foreign "
879 "repository) r%ld through r%ld into "
881 n->merge_range->start,
882 n->merge_range->end + 1, path_local);
887 case svn_wc_notify_tree_conflict:
888 nb->tree_conflicts++;
889 add_conflicted_path(nb, n->path);
890 if ((err = svn_cmdline_printf(pool, " C %s\n", path_local)))
894 case svn_wc_notify_update_shadowed_add:
895 nb->received_some_change = TRUE;
896 if ((err = svn_cmdline_printf(pool, " A %s\n", path_local)))
900 case svn_wc_notify_update_shadowed_update:
901 nb->received_some_change = TRUE;
902 if ((err = svn_cmdline_printf(pool, " U %s\n", path_local)))
906 case svn_wc_notify_update_shadowed_delete:
907 nb->received_some_change = TRUE;
908 if ((err = svn_cmdline_printf(pool, " D %s\n", path_local)))
912 case svn_wc_notify_property_modified:
913 case svn_wc_notify_property_added:
914 err = svn_cmdline_printf(pool,
915 _("property '%s' set on '%s'\n"),
916 n->prop_name, path_local);
921 case svn_wc_notify_property_deleted:
922 err = svn_cmdline_printf(pool,
923 _("property '%s' deleted from '%s'.\n"),
924 n->prop_name, path_local);
929 case svn_wc_notify_property_deleted_nonexistent:
930 err = svn_cmdline_printf(pool,
931 _("Attempting to delete nonexistent "
932 "property '%s' on '%s'\n"), n->prop_name,
938 case svn_wc_notify_revprop_set:
939 err = svn_cmdline_printf(pool,
940 _("property '%s' set on repository revision %ld\n"),
941 n->prop_name, n->revision);
946 case svn_wc_notify_revprop_deleted:
947 err = svn_cmdline_printf(pool,
948 _("property '%s' deleted from repository revision %ld\n"),
949 n->prop_name, n->revision);
954 case svn_wc_notify_upgraded_path:
955 err = svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local);
960 case svn_wc_notify_url_redirect:
961 err = svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"),
967 case svn_wc_notify_path_nonexistent:
968 err = svn_cmdline_printf(pool, _("'%s' is not under version control"),
974 case svn_wc_notify_conflict_resolver_starting:
975 /* Once all operations invoke the interactive conflict resolution after
976 * they've completed, we can run svn_cl__print_conflict_stats() here. */
979 case svn_wc_notify_conflict_resolver_done:
986 if ((err = svn_cmdline_fflush(stdout)))
992 /* If we had no errors before, print this error to stderr. Else, don't print
993 anything. The user already knows there were some output errors,
994 so there is no point in flooding her with an error per notification. */
995 if (!nb->had_print_error)
997 nb->had_print_error = TRUE;
999 * Don't print anything on broken pipes. The pipe was likely
1000 * closed by the process at the other end. We expect that
1001 * process to perform error reporting as necessary.
1003 * ### This assumes that there is only one error in a chain for
1004 * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
1005 if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
1006 svn_handle_error2(err, stderr, FALSE, "svn: ");
1008 svn_error_clear(err);
1013 svn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p,
1014 void **notify_baton_p,
1017 struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb));
1019 nb->received_some_change = FALSE;
1020 nb->sent_first_txdelta = FALSE;
1021 nb->is_checkout = FALSE;
1022 nb->is_export = FALSE;
1023 nb->is_wc_to_repos_copy = FALSE;
1024 nb->in_external = FALSE;
1025 nb->had_print_error = FALSE;
1026 nb->text_conflicts = 0;
1027 nb->prop_conflicts = 0;
1028 nb->tree_conflicts = 0;
1029 nb->skipped_paths = 0;
1030 nb->conflicted_paths = apr_hash_make(pool);
1031 SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool));
1033 *notify_func_p = notify;
1034 *notify_baton_p = nb;
1035 return SVN_NO_ERROR;
1039 svn_cl__notifier_mark_export(void *baton)
1041 struct notify_baton *nb = baton;
1043 nb->is_export = TRUE;
1044 return SVN_NO_ERROR;