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" 42362181Sdim#include "private/svn_sorts_private.h" 43251881Speter#include "private/svn_dep_compat.h" 44251881Speter 45251881Speter#include "svn_private_config.h" 46251881Speter 47251881Speter 48251881Speter/* Baton for notify and friends. */ 49251881Speterstruct notify_baton 50251881Speter{ 51251881Speter svn_boolean_t received_some_change; 52251881Speter svn_boolean_t is_checkout; 53251881Speter svn_boolean_t is_export; 54251881Speter svn_boolean_t is_wc_to_repos_copy; 55251881Speter svn_boolean_t sent_first_txdelta; 56289180Speter int in_external; 57362181Sdim svn_revnum_t progress_revision; 58251881Speter svn_boolean_t had_print_error; /* Used to not keep printing error messages 59251881Speter when we've already had one print error. */ 60251881Speter 61251881Speter svn_cl__conflict_stats_t *conflict_stats; 62251881Speter 63251881Speter /* The cwd, for use in decomposing absolute paths. */ 64251881Speter const char *path_prefix; 65251881Speter}; 66251881Speter 67251881Speter/* Conflict stats for operations such as update and merge. */ 68251881Speterstruct svn_cl__conflict_stats_t 69251881Speter{ 70251881Speter apr_pool_t *stats_pool; 71251881Speter apr_hash_t *text_conflicts, *prop_conflicts, *tree_conflicts; 72251881Speter int text_conflicts_resolved, prop_conflicts_resolved, tree_conflicts_resolved; 73251881Speter int skipped_paths; 74251881Speter}; 75251881Speter 76251881Spetersvn_cl__conflict_stats_t * 77251881Spetersvn_cl__conflict_stats_create(apr_pool_t *pool) 78251881Speter{ 79251881Speter svn_cl__conflict_stats_t *conflict_stats 80251881Speter = apr_palloc(pool, sizeof(*conflict_stats)); 81251881Speter 82251881Speter conflict_stats->stats_pool = pool; 83251881Speter conflict_stats->text_conflicts = apr_hash_make(pool); 84251881Speter conflict_stats->prop_conflicts = apr_hash_make(pool); 85251881Speter conflict_stats->tree_conflicts = apr_hash_make(pool); 86251881Speter conflict_stats->text_conflicts_resolved = 0; 87251881Speter conflict_stats->prop_conflicts_resolved = 0; 88251881Speter conflict_stats->tree_conflicts_resolved = 0; 89251881Speter conflict_stats->skipped_paths = 0; 90251881Speter return conflict_stats; 91251881Speter} 92251881Speter 93251881Speter/* Add the PATH (as a key, with a meaningless value) into the HASH in NB. */ 94251881Speterstatic void 95251881Speterstore_path(struct notify_baton *nb, apr_hash_t *hash, const char *path) 96251881Speter{ 97251881Speter svn_hash_sets(hash, apr_pstrdup(nb->conflict_stats->stats_pool, path), ""); 98251881Speter} 99251881Speter 100251881Spetervoid 101251881Spetersvn_cl__conflict_stats_resolved(svn_cl__conflict_stats_t *conflict_stats, 102251881Speter const char *path_local, 103251881Speter svn_wc_conflict_kind_t conflict_kind) 104251881Speter{ 105251881Speter switch (conflict_kind) 106251881Speter { 107251881Speter case svn_wc_conflict_kind_text: 108251881Speter if (svn_hash_gets(conflict_stats->text_conflicts, path_local)) 109251881Speter { 110251881Speter svn_hash_sets(conflict_stats->text_conflicts, path_local, NULL); 111251881Speter conflict_stats->text_conflicts_resolved++; 112251881Speter } 113251881Speter break; 114251881Speter case svn_wc_conflict_kind_property: 115251881Speter if (svn_hash_gets(conflict_stats->prop_conflicts, path_local)) 116251881Speter { 117251881Speter svn_hash_sets(conflict_stats->prop_conflicts, path_local, NULL); 118251881Speter conflict_stats->prop_conflicts_resolved++; 119251881Speter } 120251881Speter break; 121251881Speter case svn_wc_conflict_kind_tree: 122251881Speter if (svn_hash_gets(conflict_stats->tree_conflicts, path_local)) 123251881Speter { 124251881Speter svn_hash_sets(conflict_stats->tree_conflicts, path_local, NULL); 125251881Speter conflict_stats->tree_conflicts_resolved++; 126251881Speter } 127251881Speter break; 128251881Speter } 129251881Speter} 130251881Speter 131251881Speterstatic const char * 132251881Speterremaining_str(apr_pool_t *pool, int n_remaining) 133251881Speter{ 134289180Speter return apr_psprintf(pool, Q_("%d remaining", 135251881Speter "%d remaining", 136251881Speter n_remaining), 137251881Speter n_remaining); 138251881Speter} 139251881Speter 140251881Speterstatic const char * 141251881Speterresolved_str(apr_pool_t *pool, int n_resolved) 142251881Speter{ 143251881Speter return apr_psprintf(pool, Q_("and %d already resolved", 144251881Speter "and %d already resolved", 145251881Speter n_resolved), 146251881Speter n_resolved); 147251881Speter} 148251881Speter 149251881Spetersvn_error_t * 150362181Sdimsvn_cl__conflict_stats_get_paths(apr_array_header_t **conflicted_paths, 151362181Sdim svn_cl__conflict_stats_t *conflict_stats, 152362181Sdim apr_pool_t *result_pool, 153362181Sdim apr_pool_t *scratch_pool) 154362181Sdim{ 155362181Sdim 156362181Sdim int n_text = apr_hash_count(conflict_stats->text_conflicts); 157362181Sdim int n_prop = apr_hash_count(conflict_stats->prop_conflicts); 158362181Sdim int n_tree = apr_hash_count(conflict_stats->tree_conflicts); 159362181Sdim apr_hash_t *all_conflicts; 160362181Sdim 161362181Sdim *conflicted_paths = NULL; 162362181Sdim if (n_text == 0 && n_prop == 0 && n_tree == 0) 163362181Sdim return SVN_NO_ERROR; 164362181Sdim 165362181Sdim /* Use a hash table to ensure paths with multiple conflicts are 166362181Sdim * returned just once. */ 167362181Sdim all_conflicts = apr_hash_make(result_pool); 168362181Sdim if (n_text > 0) 169362181Sdim { 170362181Sdim apr_array_header_t *k_text; 171362181Sdim int i; 172362181Sdim 173362181Sdim SVN_ERR(svn_hash_keys(&k_text, conflict_stats->text_conflicts, 174362181Sdim scratch_pool)); 175362181Sdim for (i = 0; i < k_text->nelts; i++) 176362181Sdim { 177362181Sdim const char *path = APR_ARRAY_IDX(k_text, i, const char *); 178362181Sdim 179362181Sdim svn_hash_sets(all_conflicts, path, ""); 180362181Sdim } 181362181Sdim } 182362181Sdim 183362181Sdim if (n_prop > 0) 184362181Sdim { 185362181Sdim apr_array_header_t *k_prop; 186362181Sdim int i; 187362181Sdim 188362181Sdim SVN_ERR(svn_hash_keys(&k_prop, conflict_stats->prop_conflicts, 189362181Sdim scratch_pool)); 190362181Sdim for (i = 0; i < k_prop->nelts; i++) 191362181Sdim { 192362181Sdim const char *path = APR_ARRAY_IDX(k_prop, i, const char *); 193362181Sdim 194362181Sdim svn_hash_sets(all_conflicts, path, ""); 195362181Sdim } 196362181Sdim } 197362181Sdim 198362181Sdim if (n_tree > 0) 199362181Sdim { 200362181Sdim apr_array_header_t *k_tree; 201362181Sdim int i; 202362181Sdim 203362181Sdim SVN_ERR(svn_hash_keys(&k_tree, conflict_stats->tree_conflicts, 204362181Sdim scratch_pool)); 205362181Sdim for (i = 0; i < k_tree->nelts; i++) 206362181Sdim { 207362181Sdim const char *path = APR_ARRAY_IDX(k_tree, i, const char *); 208362181Sdim 209362181Sdim svn_hash_sets(all_conflicts, path, ""); 210362181Sdim } 211362181Sdim } 212362181Sdim 213362181Sdim SVN_ERR(svn_hash_keys(conflicted_paths, all_conflicts, result_pool)); 214362181Sdim svn_sort__array(*conflicted_paths, svn_sort_compare_paths); 215362181Sdim 216362181Sdim return SVN_NO_ERROR; 217362181Sdim} 218362181Sdim 219362181Sdimsvn_error_t * 220289180Spetersvn_cl__print_conflict_stats(svn_cl__conflict_stats_t *conflict_stats, 221289180Speter apr_pool_t *scratch_pool) 222251881Speter{ 223289180Speter int n_text = apr_hash_count(conflict_stats->text_conflicts); 224289180Speter int n_prop = apr_hash_count(conflict_stats->prop_conflicts); 225289180Speter int n_tree = apr_hash_count(conflict_stats->tree_conflicts); 226289180Speter int n_text_r = conflict_stats->text_conflicts_resolved; 227289180Speter int n_prop_r = conflict_stats->prop_conflicts_resolved; 228289180Speter int n_tree_r = conflict_stats->tree_conflicts_resolved; 229251881Speter 230251881Speter if (n_text > 0 || n_text_r > 0 231251881Speter || n_prop > 0 || n_prop_r > 0 232251881Speter || n_tree > 0 || n_tree_r > 0 233289180Speter || conflict_stats->skipped_paths > 0) 234251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 235251881Speter _("Summary of conflicts:\n"))); 236251881Speter 237251881Speter if (n_text_r == 0 && n_prop_r == 0 && n_tree_r == 0) 238251881Speter { 239251881Speter if (n_text > 0) 240251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 241251881Speter _(" Text conflicts: %d\n"), 242251881Speter n_text)); 243251881Speter if (n_prop > 0) 244251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 245251881Speter _(" Property conflicts: %d\n"), 246251881Speter n_prop)); 247251881Speter if (n_tree > 0) 248251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 249251881Speter _(" Tree conflicts: %d\n"), 250251881Speter n_tree)); 251251881Speter } 252251881Speter else 253251881Speter { 254251881Speter if (n_text > 0 || n_text_r > 0) 255251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 256251881Speter _(" Text conflicts: %s (%s)\n"), 257251881Speter remaining_str(scratch_pool, n_text), 258251881Speter resolved_str(scratch_pool, n_text_r))); 259251881Speter if (n_prop > 0 || n_prop_r > 0) 260251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 261251881Speter _(" Property conflicts: %s (%s)\n"), 262251881Speter remaining_str(scratch_pool, n_prop), 263251881Speter resolved_str(scratch_pool, n_prop_r))); 264251881Speter if (n_tree > 0 || n_tree_r > 0) 265251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 266251881Speter _(" Tree conflicts: %s (%s)\n"), 267251881Speter remaining_str(scratch_pool, n_tree), 268251881Speter resolved_str(scratch_pool, n_tree_r))); 269251881Speter } 270289180Speter if (conflict_stats->skipped_paths > 0) 271251881Speter SVN_ERR(svn_cmdline_printf(scratch_pool, 272251881Speter _(" Skipped paths: %d\n"), 273289180Speter conflict_stats->skipped_paths)); 274251881Speter 275251881Speter return SVN_NO_ERROR; 276251881Speter} 277251881Speter 278289180Spetersvn_error_t * 279289180Spetersvn_cl__notifier_print_conflict_stats(void *baton, apr_pool_t *scratch_pool) 280251881Speter{ 281251881Speter struct notify_baton *nb = baton; 282289180Speter 283289180Speter SVN_ERR(svn_cl__print_conflict_stats(nb->conflict_stats, scratch_pool)); 284289180Speter return SVN_NO_ERROR; 285289180Speter} 286289180Speter 287289180Speter/* The body for notify() function with standard error handling semantic. 288289180Speter * Handling of errors implemented at caller side. */ 289289180Speterstatic svn_error_t * 290289180Speternotify_body(struct notify_baton *nb, 291289180Speter const svn_wc_notify_t *n, 292289180Speter apr_pool_t *pool) 293289180Speter{ 294251881Speter char statchar_buf[5] = " "; 295251881Speter const char *path_local; 296251881Speter 297251881Speter if (n->url) 298251881Speter path_local = n->url; 299251881Speter else 300251881Speter { 301289180Speter /* Skip the path prefix in N, if supplied, or else the path prefix 302289180Speter in NB (which was set to the current working directory). */ 303251881Speter if (n->path_prefix) 304251881Speter path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path, 305251881Speter pool); 306289180Speter else 307251881Speter path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path, 308251881Speter pool); 309251881Speter } 310251881Speter 311251881Speter switch (n->action) 312251881Speter { 313251881Speter case svn_wc_notify_skip: 314251881Speter nb->conflict_stats->skipped_paths++; 315251881Speter if (n->content_state == svn_wc_notify_state_missing) 316251881Speter { 317289180Speter SVN_ERR(svn_cmdline_printf(pool, 318289180Speter _("Skipped missing target: '%s'\n"), 319289180Speter path_local)); 320251881Speter } 321251881Speter else if (n->content_state == svn_wc_notify_state_source_missing) 322251881Speter { 323289180Speter SVN_ERR(svn_cmdline_printf( 324289180Speter pool, 325289180Speter _("Skipped target: '%s' -- copy-source is missing\n"), 326289180Speter path_local)); 327251881Speter } 328362181Sdim else if (n->content_state == svn_wc_notify_state_obstructed) 329362181Sdim { 330362181Sdim SVN_ERR(svn_cmdline_printf( 331362181Sdim pool, 332362181Sdim _("Skipped '%s' -- obstructed by unversioned node\n"), 333362181Sdim path_local)); 334362181Sdim } 335251881Speter else 336251881Speter { 337289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Skipped '%s'\n"), path_local)); 338251881Speter } 339251881Speter break; 340251881Speter case svn_wc_notify_update_skip_obstruction: 341251881Speter nb->conflict_stats->skipped_paths++; 342289180Speter SVN_ERR(svn_cmdline_printf( 343289180Speter pool, 344289180Speter _("Skipped '%s' -- An obstructing working copy was found\n"), 345289180Speter path_local)); 346251881Speter break; 347251881Speter case svn_wc_notify_update_skip_working_only: 348251881Speter nb->conflict_stats->skipped_paths++; 349289180Speter SVN_ERR(svn_cmdline_printf( 350289180Speter pool, _("Skipped '%s' -- Has no versioned parent\n"), 351289180Speter path_local)); 352251881Speter break; 353251881Speter case svn_wc_notify_update_skip_access_denied: 354251881Speter nb->conflict_stats->skipped_paths++; 355289180Speter SVN_ERR(svn_cmdline_printf( 356289180Speter pool, _("Skipped '%s' -- Access denied\n"), 357289180Speter path_local)); 358251881Speter break; 359251881Speter case svn_wc_notify_skip_conflicted: 360251881Speter nb->conflict_stats->skipped_paths++; 361289180Speter SVN_ERR(svn_cmdline_printf( 362289180Speter pool, _("Skipped '%s' -- Node remains in conflict\n"), 363289180Speter path_local)); 364251881Speter break; 365251881Speter case svn_wc_notify_update_delete: 366251881Speter case svn_wc_notify_exclude: 367251881Speter nb->received_some_change = TRUE; 368289180Speter SVN_ERR(svn_cmdline_printf(pool, "D %s\n", path_local)); 369251881Speter break; 370251881Speter case svn_wc_notify_update_broken_lock: 371289180Speter SVN_ERR(svn_cmdline_printf(pool, "B %s\n", path_local)); 372251881Speter break; 373251881Speter 374251881Speter case svn_wc_notify_update_external_removed: 375251881Speter nb->received_some_change = TRUE; 376251881Speter if (n->err && n->err->message) 377251881Speter { 378289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Removed external '%s': %s\n"), 379289180Speter path_local, n->err->message)); 380251881Speter } 381251881Speter else 382251881Speter { 383289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Removed external '%s'\n"), 384289180Speter path_local)); 385251881Speter } 386251881Speter break; 387251881Speter 388251881Speter case svn_wc_notify_left_local_modifications: 389289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Left local modifications as '%s'\n"), 390289180Speter path_local)); 391251881Speter break; 392251881Speter 393251881Speter case svn_wc_notify_update_replace: 394251881Speter nb->received_some_change = TRUE; 395289180Speter SVN_ERR(svn_cmdline_printf(pool, "R %s\n", path_local)); 396251881Speter break; 397251881Speter 398251881Speter case svn_wc_notify_update_add: 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); 403289180Speter SVN_ERR(svn_cmdline_printf(pool, "C %s\n", path_local)); 404251881Speter } 405251881Speter else 406251881Speter { 407289180Speter SVN_ERR(svn_cmdline_printf(pool, "A %s\n", path_local)); 408251881Speter } 409251881Speter break; 410251881Speter 411251881Speter case svn_wc_notify_exists: 412251881Speter nb->received_some_change = TRUE; 413251881Speter if (n->content_state == svn_wc_notify_state_conflicted) 414251881Speter { 415251881Speter store_path(nb, nb->conflict_stats->text_conflicts, path_local); 416251881Speter statchar_buf[0] = 'C'; 417251881Speter } 418251881Speter else 419251881Speter statchar_buf[0] = 'E'; 420251881Speter 421251881Speter if (n->prop_state == svn_wc_notify_state_conflicted) 422251881Speter { 423251881Speter store_path(nb, nb->conflict_stats->prop_conflicts, path_local); 424251881Speter statchar_buf[1] = 'C'; 425251881Speter } 426251881Speter else if (n->prop_state == svn_wc_notify_state_merged) 427251881Speter statchar_buf[1] = 'G'; 428251881Speter 429289180Speter SVN_ERR(svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local)); 430251881Speter break; 431251881Speter 432251881Speter case svn_wc_notify_restore: 433289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Restored '%s'\n"), 434289180Speter path_local)); 435251881Speter break; 436251881Speter 437251881Speter case svn_wc_notify_revert: 438289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Reverted '%s'\n"), 439289180Speter path_local)); 440251881Speter break; 441251881Speter 442251881Speter case svn_wc_notify_failed_revert: 443289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Failed to revert '%s' -- " 444289180Speter "try updating instead.\n"), 445289180Speter path_local)); 446251881Speter break; 447251881Speter 448251881Speter case svn_wc_notify_resolved: 449289180Speter SVN_ERR(svn_cmdline_printf(pool, 450289180Speter _("Resolved conflicted state of '%s'\n"), 451289180Speter path_local)); 452251881Speter break; 453251881Speter 454362181Sdim case svn_wc_notify_resolved_text: 455362181Sdim SVN_ERR(svn_cmdline_printf(pool, 456362181Sdim _("Merge conflicts in '%s' marked as " 457362181Sdim "resolved.\n"), 458362181Sdim path_local)); 459362181Sdim break; 460362181Sdim 461362181Sdim case svn_wc_notify_resolved_prop: 462362181Sdim SVN_ERR_ASSERT(n->prop_name && strlen(n->prop_name) > 0); 463362181Sdim SVN_ERR(svn_cmdline_printf(pool, 464362181Sdim _("Conflict in property '%s' at '%s' marked " 465362181Sdim "as resolved.\n"), 466362181Sdim n->prop_name, path_local)); 467362181Sdim break; 468362181Sdim 469362181Sdim case svn_wc_notify_resolved_tree: 470362181Sdim SVN_ERR(svn_cmdline_printf(pool, 471362181Sdim _("Tree conflict at '%s' marked as " 472362181Sdim "resolved.\n"), 473362181Sdim path_local)); 474362181Sdim break; 475362181Sdim 476362181Sdim case svn_wc_notify_begin_search_tree_conflict_details: 477362181Sdim SVN_ERR(svn_cmdline_printf(pool, 478362181Sdim _("Searching tree conflict details for '%s' " 479362181Sdim "in repository:\n"), 480362181Sdim path_local)); 481362181Sdim nb->progress_revision = 0; 482362181Sdim break; 483362181Sdim 484362181Sdim case svn_wc_notify_tree_conflict_details_progress: 485362181Sdim /* First printf is to obliterate any previous progress printf, 486362181Sdim assuming no more than 10 digit revisions. Avoid i18n so the 487362181Sdim text length is known. We only need to do this if the new 488362181Sdim revision is 4 digits less than the previous revision but that 489362181Sdim requires counting digits. Dividing by 1000 works well 490362181Sdim enough: it triggers when needed, it sometimes triggers when 491362181Sdim not needed, but in typical cases it doesn't trigger as the 492362181Sdim revisions don't vary much. */ 493362181Sdim if (n->revision < nb->progress_revision / 1000) 494362181Sdim SVN_ERR(svn_cmdline_printf(pool, "\rChecking r ")); 495362181Sdim SVN_ERR(svn_cmdline_printf(pool, "\rChecking r%ld...", n->revision)); 496362181Sdim nb->progress_revision = n->revision; 497362181Sdim break; 498362181Sdim 499362181Sdim case svn_wc_notify_end_search_tree_conflict_details: 500362181Sdim SVN_ERR(svn_cmdline_printf(pool, _(" done\n"))); 501362181Sdim nb->progress_revision = 0; 502362181Sdim break; 503362181Sdim 504251881Speter case svn_wc_notify_add: 505251881Speter /* We *should* only get the MIME_TYPE if PATH is a file. If we 506251881Speter do get it, and the mime-type is not textual, note that this 507251881Speter is a binary addition. */ 508251881Speter if (n->mime_type && (svn_mime_type_is_binary(n->mime_type))) 509251881Speter { 510289180Speter SVN_ERR(svn_cmdline_printf(pool, "A (bin) %s\n", 511289180Speter path_local)); 512251881Speter } 513251881Speter else 514251881Speter { 515289180Speter SVN_ERR(svn_cmdline_printf(pool, "A %s\n", 516289180Speter path_local)); 517251881Speter } 518251881Speter break; 519251881Speter 520251881Speter case svn_wc_notify_delete: 521251881Speter nb->received_some_change = TRUE; 522289180Speter SVN_ERR(svn_cmdline_printf(pool, "D %s\n", 523289180Speter path_local)); 524251881Speter break; 525251881Speter 526251881Speter case svn_wc_notify_patch: 527251881Speter { 528251881Speter nb->received_some_change = TRUE; 529251881Speter if (n->content_state == svn_wc_notify_state_conflicted) 530251881Speter { 531251881Speter store_path(nb, nb->conflict_stats->text_conflicts, path_local); 532251881Speter statchar_buf[0] = 'C'; 533251881Speter } 534251881Speter else if (n->kind == svn_node_file) 535251881Speter { 536251881Speter if (n->content_state == svn_wc_notify_state_merged) 537251881Speter statchar_buf[0] = 'G'; 538251881Speter else if (n->content_state == svn_wc_notify_state_changed) 539251881Speter statchar_buf[0] = 'U'; 540251881Speter } 541251881Speter 542251881Speter if (n->prop_state == svn_wc_notify_state_conflicted) 543251881Speter { 544251881Speter store_path(nb, nb->conflict_stats->prop_conflicts, path_local); 545251881Speter statchar_buf[1] = 'C'; 546251881Speter } 547362181Sdim else if (n->prop_state == svn_wc_notify_state_merged) 548362181Sdim statchar_buf[1] = 'G'; 549251881Speter else if (n->prop_state == svn_wc_notify_state_changed) 550362181Sdim statchar_buf[1] = 'U'; 551251881Speter 552251881Speter if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ') 553251881Speter { 554289180Speter SVN_ERR(svn_cmdline_printf(pool, "%s %s\n", 555289180Speter statchar_buf, path_local)); 556251881Speter } 557251881Speter } 558251881Speter break; 559251881Speter 560251881Speter case svn_wc_notify_patch_applied_hunk: 561251881Speter nb->received_some_change = TRUE; 562251881Speter if (n->hunk_original_start != n->hunk_matched_line) 563251881Speter { 564251881Speter apr_uint64_t off; 565251881Speter const char *s; 566251881Speter const char *minus; 567251881Speter 568251881Speter if (n->hunk_matched_line > n->hunk_original_start) 569251881Speter { 570251881Speter /* If we are patching from the start of an empty file, 571251881Speter it is nicer to show offset 0 */ 572251881Speter if (n->hunk_original_start == 0 && n->hunk_matched_line == 1) 573251881Speter off = 0; /* No offset, just adding */ 574251881Speter else 575251881Speter off = n->hunk_matched_line - n->hunk_original_start; 576251881Speter 577251881Speter minus = ""; 578251881Speter } 579251881Speter else 580251881Speter { 581251881Speter off = n->hunk_original_start - n->hunk_matched_line; 582251881Speter minus = "-"; 583251881Speter } 584251881Speter 585251881Speter /* ### We're creating the localized strings without 586251881Speter * ### APR_INT64_T_FMT since it isn't translator-friendly */ 587251881Speter if (n->hunk_fuzz) 588251881Speter { 589251881Speter 590251881Speter if (n->prop_name) 591251881Speter { 592251881Speter s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## " 593251881Speter "with offset %s"); 594251881Speter 595289180Speter SVN_ERR(svn_cmdline_printf(pool, 596289180Speter apr_pstrcat(pool, s, 597289180Speter "%"APR_UINT64_T_FMT 598289180Speter " and fuzz %lu (%s)\n", 599289180Speter SVN_VA_NULL), 600289180Speter n->hunk_original_start, 601289180Speter n->hunk_original_length, 602289180Speter n->hunk_modified_start, 603289180Speter n->hunk_modified_length, 604289180Speter minus, off, n->hunk_fuzz, 605289180Speter n->prop_name)); 606251881Speter } 607251881Speter else 608251881Speter { 609251881Speter s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ " 610251881Speter "with offset %s"); 611251881Speter 612289180Speter SVN_ERR(svn_cmdline_printf(pool, 613289180Speter apr_pstrcat(pool, s, 614289180Speter "%"APR_UINT64_T_FMT 615289180Speter " and fuzz %lu\n", 616289180Speter SVN_VA_NULL), 617289180Speter n->hunk_original_start, 618289180Speter n->hunk_original_length, 619289180Speter n->hunk_modified_start, 620289180Speter n->hunk_modified_length, 621289180Speter minus, off, n->hunk_fuzz)); 622251881Speter } 623251881Speter } 624251881Speter else 625251881Speter { 626251881Speter 627251881Speter if (n->prop_name) 628251881Speter { 629251881Speter s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## " 630251881Speter "with offset %s"); 631289180Speter SVN_ERR(svn_cmdline_printf(pool, 632289180Speter apr_pstrcat(pool, s, 633289180Speter "%"APR_UINT64_T_FMT" (%s)\n", 634289180Speter SVN_VA_NULL), 635289180Speter n->hunk_original_start, 636289180Speter n->hunk_original_length, 637289180Speter n->hunk_modified_start, 638289180Speter n->hunk_modified_length, 639289180Speter minus, off, n->prop_name)); 640251881Speter } 641251881Speter else 642251881Speter { 643251881Speter s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ " 644251881Speter "with offset %s"); 645289180Speter SVN_ERR(svn_cmdline_printf(pool, 646289180Speter apr_pstrcat(pool, s, 647289180Speter "%"APR_UINT64_T_FMT"\n", 648289180Speter SVN_VA_NULL), 649289180Speter n->hunk_original_start, 650289180Speter n->hunk_original_length, 651289180Speter n->hunk_modified_start, 652289180Speter n->hunk_modified_length, 653289180Speter minus, off)); 654251881Speter } 655251881Speter } 656251881Speter } 657251881Speter else if (n->hunk_fuzz) 658251881Speter { 659251881Speter if (n->prop_name) 660289180Speter SVN_ERR(svn_cmdline_printf(pool, 661251881Speter _("> applied hunk ## -%lu,%lu +%lu,%lu ## " 662251881Speter "with fuzz %lu (%s)\n"), 663251881Speter n->hunk_original_start, 664251881Speter n->hunk_original_length, 665251881Speter n->hunk_modified_start, 666251881Speter n->hunk_modified_length, 667251881Speter n->hunk_fuzz, 668289180Speter n->prop_name)); 669251881Speter else 670289180Speter SVN_ERR(svn_cmdline_printf(pool, 671251881Speter _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ " 672251881Speter "with fuzz %lu\n"), 673251881Speter n->hunk_original_start, 674251881Speter n->hunk_original_length, 675251881Speter n->hunk_modified_start, 676251881Speter n->hunk_modified_length, 677289180Speter n->hunk_fuzz)); 678251881Speter 679251881Speter } 680251881Speter break; 681251881Speter 682251881Speter case svn_wc_notify_patch_rejected_hunk: 683251881Speter nb->received_some_change = TRUE; 684251881Speter 685251881Speter if (n->prop_name) 686289180Speter SVN_ERR(svn_cmdline_printf(pool, 687289180Speter _("> rejected hunk " 688289180Speter "## -%lu,%lu +%lu,%lu ## (%s)\n"), 689289180Speter n->hunk_original_start, 690289180Speter n->hunk_original_length, 691289180Speter n->hunk_modified_start, 692289180Speter n->hunk_modified_length, 693289180Speter n->prop_name)); 694251881Speter else 695289180Speter SVN_ERR(svn_cmdline_printf(pool, 696289180Speter _("> rejected hunk " 697289180Speter "@@ -%lu,%lu +%lu,%lu @@\n"), 698289180Speter n->hunk_original_start, 699289180Speter n->hunk_original_length, 700289180Speter n->hunk_modified_start, 701289180Speter n->hunk_modified_length)); 702251881Speter break; 703251881Speter 704251881Speter case svn_wc_notify_patch_hunk_already_applied: 705251881Speter nb->received_some_change = TRUE; 706251881Speter if (n->prop_name) 707289180Speter SVN_ERR(svn_cmdline_printf(pool, 708289180Speter _("> hunk " 709289180Speter "## -%lu,%lu +%lu,%lu ## " 710289180Speter "already applied (%s)\n"), 711289180Speter n->hunk_original_start, 712289180Speter n->hunk_original_length, 713289180Speter n->hunk_modified_start, 714289180Speter n->hunk_modified_length, 715289180Speter n->prop_name)); 716251881Speter else 717289180Speter SVN_ERR(svn_cmdline_printf(pool, 718289180Speter _("> hunk " 719289180Speter "@@ -%lu,%lu +%lu,%lu @@ " 720289180Speter "already applied\n"), 721289180Speter n->hunk_original_start, 722289180Speter n->hunk_original_length, 723289180Speter n->hunk_modified_start, 724289180Speter n->hunk_modified_length)); 725251881Speter break; 726251881Speter 727251881Speter case svn_wc_notify_update_update: 728251881Speter case svn_wc_notify_merge_record_info: 729251881Speter { 730251881Speter if (n->content_state == svn_wc_notify_state_conflicted) 731251881Speter { 732251881Speter store_path(nb, nb->conflict_stats->text_conflicts, path_local); 733251881Speter statchar_buf[0] = 'C'; 734251881Speter } 735251881Speter else if (n->kind == svn_node_file) 736251881Speter { 737251881Speter if (n->content_state == svn_wc_notify_state_merged) 738251881Speter statchar_buf[0] = 'G'; 739251881Speter else if (n->content_state == svn_wc_notify_state_changed) 740251881Speter statchar_buf[0] = 'U'; 741251881Speter } 742251881Speter 743251881Speter if (n->prop_state == svn_wc_notify_state_conflicted) 744251881Speter { 745251881Speter store_path(nb, nb->conflict_stats->prop_conflicts, path_local); 746251881Speter statchar_buf[1] = 'C'; 747251881Speter } 748251881Speter else if (n->prop_state == svn_wc_notify_state_merged) 749251881Speter statchar_buf[1] = 'G'; 750251881Speter else if (n->prop_state == svn_wc_notify_state_changed) 751251881Speter statchar_buf[1] = 'U'; 752251881Speter 753251881Speter if (n->lock_state == svn_wc_notify_lock_state_unlocked) 754251881Speter statchar_buf[2] = 'B'; 755251881Speter 756251881Speter if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ') 757251881Speter nb->received_some_change = TRUE; 758251881Speter 759251881Speter if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ' 760251881Speter || statchar_buf[2] != ' ') 761251881Speter { 762289180Speter SVN_ERR(svn_cmdline_printf(pool, "%s %s\n", 763289180Speter statchar_buf, path_local)); 764251881Speter } 765251881Speter } 766251881Speter break; 767251881Speter 768251881Speter case svn_wc_notify_update_external: 769251881Speter /* Remember that we're now "inside" an externals definition. */ 770289180Speter ++nb->in_external; 771251881Speter 772251881Speter /* Currently this is used for checkouts and switches too. If we 773251881Speter want different output, we'll have to add new actions. */ 774289180Speter SVN_ERR(svn_cmdline_printf(pool, 775289180Speter _("\nFetching external item into '%s':\n"), 776289180Speter path_local)); 777251881Speter break; 778251881Speter 779251881Speter case svn_wc_notify_failed_external: 780251881Speter /* If we are currently inside the handling of an externals 781251881Speter definition, then we can simply present n->err as a warning 782251881Speter and feel confident that after this, we aren't handling that 783251881Speter externals definition any longer. */ 784251881Speter if (nb->in_external) 785251881Speter { 786251881Speter svn_handle_warning2(stderr, n->err, "svn: "); 787289180Speter --nb->in_external; 788289180Speter SVN_ERR(svn_cmdline_printf(pool, "\n")); 789251881Speter } 790251881Speter /* Otherwise, we'll just print two warnings. Why? Because 791251881Speter svn_handle_warning2() only shows the single "best message", 792251881Speter but we have two pretty important ones: that the external at 793251881Speter '/some/path' didn't pan out, and then the more specific 794251881Speter reason why (from n->err). */ 795251881Speter else 796251881Speter { 797251881Speter svn_error_t *warn_err = 798289180Speter svn_error_createf(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL, 799251881Speter _("Error handling externals definition for '%s':"), 800251881Speter path_local); 801251881Speter svn_handle_warning2(stderr, warn_err, "svn: "); 802251881Speter svn_error_clear(warn_err); 803251881Speter svn_handle_warning2(stderr, n->err, "svn: "); 804251881Speter } 805251881Speter break; 806251881Speter 807251881Speter case svn_wc_notify_update_started: 808251881Speter if (! (nb->in_external || 809251881Speter nb->is_checkout || 810251881Speter nb->is_export)) 811251881Speter { 812289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Updating '%s':\n"), 813289180Speter path_local)); 814251881Speter } 815251881Speter break; 816251881Speter 817251881Speter case svn_wc_notify_update_completed: 818251881Speter { 819251881Speter if (SVN_IS_VALID_REVNUM(n->revision)) 820251881Speter { 821251881Speter if (nb->is_export) 822251881Speter { 823289180Speter SVN_ERR(svn_cmdline_printf( 824289180Speter pool, nb->in_external 825289180Speter ? _("Exported external at revision %ld.\n") 826289180Speter : _("Exported revision %ld.\n"), 827289180Speter n->revision)); 828251881Speter } 829251881Speter else if (nb->is_checkout) 830251881Speter { 831289180Speter SVN_ERR(svn_cmdline_printf( 832289180Speter pool, nb->in_external 833289180Speter ? _("Checked out external at revision %ld.\n") 834289180Speter : _("Checked out revision %ld.\n"), 835289180Speter n->revision)); 836251881Speter } 837251881Speter else 838251881Speter { 839251881Speter if (nb->received_some_change) 840251881Speter { 841251881Speter nb->received_some_change = FALSE; 842289180Speter SVN_ERR(svn_cmdline_printf( 843289180Speter pool, nb->in_external 844289180Speter ? _("Updated external to revision %ld.\n") 845289180Speter : _("Updated to revision %ld.\n"), 846289180Speter n->revision)); 847251881Speter } 848251881Speter else 849251881Speter { 850289180Speter SVN_ERR(svn_cmdline_printf( 851289180Speter pool, nb->in_external 852289180Speter ? _("External at revision %ld.\n") 853289180Speter : _("At revision %ld.\n"), 854289180Speter n->revision)); 855251881Speter } 856251881Speter } 857251881Speter } 858251881Speter else /* no revision */ 859251881Speter { 860251881Speter if (nb->is_export) 861251881Speter { 862289180Speter SVN_ERR(svn_cmdline_printf( 863289180Speter pool, nb->in_external 864289180Speter ? _("External export complete.\n") 865289180Speter : _("Export complete.\n"))); 866251881Speter } 867251881Speter else if (nb->is_checkout) 868251881Speter { 869289180Speter SVN_ERR(svn_cmdline_printf( 870289180Speter pool, nb->in_external 871289180Speter ? _("External checkout complete.\n") 872289180Speter : _("Checkout complete.\n"))); 873251881Speter } 874251881Speter else 875251881Speter { 876289180Speter SVN_ERR(svn_cmdline_printf( 877289180Speter pool, nb->in_external 878289180Speter ? _("External update complete.\n") 879289180Speter : _("Update complete.\n"))); 880251881Speter } 881251881Speter } 882251881Speter } 883251881Speter 884251881Speter if (nb->in_external) 885251881Speter { 886289180Speter --nb->in_external; 887289180Speter SVN_ERR(svn_cmdline_printf(pool, "\n")); 888251881Speter } 889251881Speter break; 890251881Speter 891251881Speter case svn_wc_notify_status_external: 892289180Speter SVN_ERR(svn_cmdline_printf( 893289180Speter pool, _("\nPerforming status on external item at '%s':\n"), 894289180Speter path_local)); 895251881Speter break; 896251881Speter 897289180Speter case svn_wc_notify_info_external: 898289180Speter SVN_ERR(svn_cmdline_printf( 899289180Speter pool, _("\nPerforming info on external item at '%s':\n"), 900289180Speter path_local)); 901289180Speter break; 902289180Speter 903251881Speter case svn_wc_notify_status_completed: 904251881Speter if (SVN_IS_VALID_REVNUM(n->revision)) 905289180Speter SVN_ERR(svn_cmdline_printf(pool, 906289180Speter _("Status against revision: %6ld\n"), 907289180Speter n->revision)); 908251881Speter break; 909251881Speter 910251881Speter case svn_wc_notify_commit_modified: 911251881Speter /* xgettext: Align the %s's on this and the following 4 messages */ 912289180Speter SVN_ERR(svn_cmdline_printf(pool, 913289180Speter nb->is_wc_to_repos_copy 914289180Speter ? _("Sending copy of %s\n") 915289180Speter : _("Sending %s\n"), 916289180Speter path_local)); 917251881Speter break; 918251881Speter 919251881Speter case svn_wc_notify_commit_added: 920251881Speter case svn_wc_notify_commit_copied: 921251881Speter if (n->mime_type && svn_mime_type_is_binary(n->mime_type)) 922251881Speter { 923289180Speter SVN_ERR(svn_cmdline_printf(pool, 924289180Speter nb->is_wc_to_repos_copy 925289180Speter ? _("Adding copy of (bin) %s\n") 926289180Speter : _("Adding (bin) %s\n"), 927289180Speter path_local)); 928251881Speter } 929251881Speter else 930251881Speter { 931289180Speter SVN_ERR(svn_cmdline_printf(pool, 932289180Speter nb->is_wc_to_repos_copy 933289180Speter ? _("Adding copy of %s\n") 934289180Speter : _("Adding %s\n"), 935289180Speter path_local)); 936251881Speter } 937251881Speter break; 938251881Speter 939251881Speter case svn_wc_notify_commit_deleted: 940289180Speter SVN_ERR(svn_cmdline_printf(pool, 941289180Speter nb->is_wc_to_repos_copy 942289180Speter ? _("Deleting copy of %s\n") 943289180Speter : _("Deleting %s\n"), 944289180Speter path_local)); 945251881Speter break; 946251881Speter 947251881Speter case svn_wc_notify_commit_replaced: 948251881Speter case svn_wc_notify_commit_copied_replaced: 949289180Speter SVN_ERR(svn_cmdline_printf(pool, 950289180Speter nb->is_wc_to_repos_copy 951289180Speter ? _("Replacing copy of %s\n") 952289180Speter : _("Replacing %s\n"), 953289180Speter path_local)); 954251881Speter break; 955251881Speter 956251881Speter case svn_wc_notify_commit_postfix_txdelta: 957251881Speter if (! nb->sent_first_txdelta) 958251881Speter { 959251881Speter nb->sent_first_txdelta = TRUE; 960289180Speter SVN_ERR(svn_cmdline_printf(pool, 961289180Speter _("Transmitting file data "))); 962251881Speter } 963251881Speter 964289180Speter SVN_ERR(svn_cmdline_printf(pool, ".")); 965251881Speter break; 966251881Speter 967251881Speter case svn_wc_notify_locked: 968289180Speter SVN_ERR(svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"), 969289180Speter path_local, n->lock->owner)); 970251881Speter break; 971251881Speter 972251881Speter case svn_wc_notify_unlocked: 973289180Speter SVN_ERR(svn_cmdline_printf(pool, _("'%s' unlocked.\n"), 974289180Speter path_local)); 975251881Speter break; 976251881Speter 977251881Speter case svn_wc_notify_failed_lock: 978251881Speter case svn_wc_notify_failed_unlock: 979251881Speter svn_handle_warning2(stderr, n->err, "svn: "); 980251881Speter break; 981251881Speter 982251881Speter case svn_wc_notify_changelist_set: 983289180Speter SVN_ERR(svn_cmdline_printf(pool, "A [%s] %s\n", 984289180Speter n->changelist_name, path_local)); 985251881Speter break; 986251881Speter 987251881Speter case svn_wc_notify_changelist_clear: 988251881Speter case svn_wc_notify_changelist_moved: 989289180Speter SVN_ERR(svn_cmdline_printf(pool, 990289180Speter "D [%s] %s\n", 991289180Speter n->changelist_name, path_local)); 992251881Speter break; 993251881Speter 994251881Speter case svn_wc_notify_merge_begin: 995251881Speter if (n->merge_range == NULL) 996289180Speter SVN_ERR(svn_cmdline_printf(pool, 997289180Speter _("--- Merging differences between " 998289180Speter "repository URLs into '%s':\n"), 999289180Speter path_local)); 1000251881Speter else if (n->merge_range->start == n->merge_range->end - 1 1001251881Speter || n->merge_range->start == n->merge_range->end) 1002289180Speter SVN_ERR(svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"), 1003289180Speter n->merge_range->end, path_local)); 1004251881Speter else if (n->merge_range->start - 1 == n->merge_range->end) 1005289180Speter SVN_ERR(svn_cmdline_printf(pool, 1006289180Speter _("--- Reverse-merging r%ld into '%s':\n"), 1007289180Speter n->merge_range->start, path_local)); 1008251881Speter else if (n->merge_range->start < n->merge_range->end) 1009289180Speter SVN_ERR(svn_cmdline_printf(pool, 1010289180Speter _("--- Merging r%ld through r%ld into " 1011289180Speter "'%s':\n"), 1012289180Speter n->merge_range->start + 1, 1013289180Speter n->merge_range->end, path_local)); 1014251881Speter else /* n->merge_range->start > n->merge_range->end - 1 */ 1015289180Speter SVN_ERR(svn_cmdline_printf(pool, 1016289180Speter _("--- Reverse-merging r%ld through r%ld " 1017289180Speter "into '%s':\n"), 1018289180Speter n->merge_range->start, 1019289180Speter n->merge_range->end + 1, path_local)); 1020251881Speter break; 1021251881Speter 1022251881Speter case svn_wc_notify_merge_record_info_begin: 1023251881Speter if (!n->merge_range) 1024251881Speter { 1025289180Speter SVN_ERR(svn_cmdline_printf(pool, 1026289180Speter _("--- Recording mergeinfo for merge " 1027289180Speter "between repository URLs into '%s':\n"), 1028289180Speter path_local)); 1029251881Speter } 1030251881Speter else 1031251881Speter { 1032251881Speter if (n->merge_range->start == n->merge_range->end - 1 1033251881Speter || n->merge_range->start == n->merge_range->end) 1034289180Speter SVN_ERR(svn_cmdline_printf( 1035251881Speter pool, 1036251881Speter _("--- Recording mergeinfo for merge of r%ld into '%s':\n"), 1037289180Speter n->merge_range->end, path_local)); 1038251881Speter else if (n->merge_range->start - 1 == n->merge_range->end) 1039289180Speter SVN_ERR(svn_cmdline_printf( 1040251881Speter pool, 1041251881Speter _("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"), 1042289180Speter n->merge_range->start, path_local)); 1043251881Speter else if (n->merge_range->start < n->merge_range->end) 1044289180Speter SVN_ERR(svn_cmdline_printf( 1045251881Speter pool, 1046251881Speter _("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"), 1047289180Speter n->merge_range->start + 1, n->merge_range->end, path_local)); 1048251881Speter else /* n->merge_range->start > n->merge_range->end - 1 */ 1049289180Speter SVN_ERR(svn_cmdline_printf( 1050251881Speter pool, 1051251881Speter _("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"), 1052289180Speter n->merge_range->start, n->merge_range->end + 1, path_local)); 1053251881Speter } 1054251881Speter break; 1055251881Speter 1056251881Speter case svn_wc_notify_merge_elide_info: 1057289180Speter SVN_ERR(svn_cmdline_printf(pool, 1058289180Speter _("--- Eliding mergeinfo from '%s':\n"), 1059289180Speter path_local)); 1060251881Speter break; 1061251881Speter 1062251881Speter case svn_wc_notify_foreign_merge_begin: 1063251881Speter if (n->merge_range == NULL) 1064289180Speter SVN_ERR(svn_cmdline_printf(pool, 1065289180Speter _("--- Merging differences between " 1066289180Speter "foreign repository URLs into '%s':\n"), 1067289180Speter path_local)); 1068251881Speter else if (n->merge_range->start == n->merge_range->end - 1 1069251881Speter || n->merge_range->start == n->merge_range->end) 1070289180Speter SVN_ERR(svn_cmdline_printf(pool, 1071289180Speter _("--- Merging (from foreign repository) " 1072289180Speter "r%ld into '%s':\n"), 1073289180Speter n->merge_range->end, path_local)); 1074251881Speter else if (n->merge_range->start - 1 == n->merge_range->end) 1075289180Speter SVN_ERR(svn_cmdline_printf(pool, 1076289180Speter _("--- Reverse-merging (from foreign " 1077289180Speter "repository) r%ld into '%s':\n"), 1078289180Speter n->merge_range->start, path_local)); 1079251881Speter else if (n->merge_range->start < n->merge_range->end) 1080289180Speter SVN_ERR(svn_cmdline_printf(pool, 1081289180Speter _("--- Merging (from foreign repository) " 1082289180Speter "r%ld through r%ld into '%s':\n"), 1083289180Speter n->merge_range->start + 1, 1084289180Speter n->merge_range->end, path_local)); 1085251881Speter else /* n->merge_range->start > n->merge_range->end - 1 */ 1086289180Speter SVN_ERR(svn_cmdline_printf(pool, 1087289180Speter _("--- Reverse-merging (from foreign " 1088289180Speter "repository) r%ld through r%ld into " 1089289180Speter "'%s':\n"), 1090289180Speter n->merge_range->start, 1091289180Speter n->merge_range->end + 1, path_local)); 1092251881Speter break; 1093251881Speter 1094251881Speter case svn_wc_notify_tree_conflict: 1095251881Speter store_path(nb, nb->conflict_stats->tree_conflicts, path_local); 1096289180Speter SVN_ERR(svn_cmdline_printf(pool, " C %s\n", path_local)); 1097251881Speter break; 1098251881Speter 1099251881Speter case svn_wc_notify_update_shadowed_add: 1100251881Speter nb->received_some_change = TRUE; 1101289180Speter SVN_ERR(svn_cmdline_printf(pool, " A %s\n", path_local)); 1102251881Speter break; 1103251881Speter 1104251881Speter case svn_wc_notify_update_shadowed_update: 1105251881Speter nb->received_some_change = TRUE; 1106289180Speter SVN_ERR(svn_cmdline_printf(pool, " U %s\n", path_local)); 1107251881Speter break; 1108251881Speter 1109251881Speter case svn_wc_notify_update_shadowed_delete: 1110251881Speter nb->received_some_change = TRUE; 1111289180Speter SVN_ERR(svn_cmdline_printf(pool, " D %s\n", path_local)); 1112251881Speter break; 1113251881Speter 1114251881Speter case svn_wc_notify_property_modified: 1115251881Speter case svn_wc_notify_property_added: 1116289180Speter SVN_ERR(svn_cmdline_printf(pool, 1117289180Speter _("property '%s' set on '%s'\n"), 1118289180Speter n->prop_name, path_local)); 1119251881Speter break; 1120251881Speter 1121251881Speter case svn_wc_notify_property_deleted: 1122289180Speter SVN_ERR(svn_cmdline_printf(pool, 1123289180Speter _("property '%s' deleted from '%s'.\n"), 1124289180Speter n->prop_name, path_local)); 1125251881Speter break; 1126251881Speter 1127251881Speter case svn_wc_notify_property_deleted_nonexistent: 1128289180Speter SVN_ERR(svn_cmdline_printf(pool, 1129289180Speter _("Attempting to delete nonexistent " 1130289180Speter "property '%s' on '%s'\n"), n->prop_name, 1131289180Speter path_local)); 1132251881Speter break; 1133251881Speter 1134251881Speter case svn_wc_notify_revprop_set: 1135289180Speter SVN_ERR(svn_cmdline_printf(pool, 1136251881Speter _("property '%s' set on repository revision %ld\n"), 1137289180Speter n->prop_name, n->revision)); 1138251881Speter break; 1139251881Speter 1140251881Speter case svn_wc_notify_revprop_deleted: 1141289180Speter SVN_ERR(svn_cmdline_printf(pool, 1142251881Speter _("property '%s' deleted from repository revision %ld\n"), 1143289180Speter n->prop_name, n->revision)); 1144251881Speter break; 1145251881Speter 1146251881Speter case svn_wc_notify_upgraded_path: 1147289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local)); 1148251881Speter break; 1149251881Speter 1150251881Speter case svn_wc_notify_url_redirect: 1151289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"), 1152289180Speter n->url)); 1153251881Speter break; 1154251881Speter 1155251881Speter case svn_wc_notify_path_nonexistent: 1156289180Speter SVN_ERR(svn_cmdline_printf(pool, "%s\n", 1157289180Speter apr_psprintf(pool, _("'%s' is not under version control"), 1158289180Speter path_local))); 1159251881Speter break; 1160251881Speter 1161251881Speter case svn_wc_notify_conflict_resolver_starting: 1162251881Speter /* Once all operations invoke the interactive conflict resolution after 1163251881Speter * they've completed, we can run svn_cl__notifier_print_conflict_stats() 1164251881Speter * here. */ 1165251881Speter break; 1166251881Speter 1167251881Speter case svn_wc_notify_conflict_resolver_done: 1168251881Speter break; 1169251881Speter 1170251881Speter case svn_wc_notify_foreign_copy_begin: 1171251881Speter if (n->merge_range == NULL) 1172251881Speter { 1173289180Speter SVN_ERR(svn_cmdline_printf( 1174251881Speter pool, 1175251881Speter _("--- Copying from foreign repository URL '%s':\n"), 1176289180Speter n->url)); 1177251881Speter } 1178251881Speter break; 1179251881Speter 1180251881Speter case svn_wc_notify_move_broken: 1181289180Speter SVN_ERR(svn_cmdline_printf(pool, 1182289180Speter _("Breaking move with source path '%s'\n"), 1183289180Speter path_local)); 1184251881Speter break; 1185251881Speter 1186289180Speter case svn_wc_notify_cleanup_external: 1187289180Speter SVN_ERR(svn_cmdline_printf 1188289180Speter (pool, _("Performing cleanup on external item at '%s'.\n"), 1189289180Speter path_local)); 1190289180Speter break; 1191289180Speter 1192289180Speter case svn_wc_notify_commit_finalizing: 1193289180Speter if (nb->sent_first_txdelta) 1194289180Speter { 1195289180Speter SVN_ERR(svn_cmdline_printf(pool, _("done\n"))); 1196289180Speter } 1197289180Speter SVN_ERR(svn_cmdline_printf(pool, _("Committing transaction...\n"))); 1198289180Speter break; 1199289180Speter 1200251881Speter default: 1201251881Speter break; 1202251881Speter } 1203251881Speter 1204289180Speter SVN_ERR(svn_cmdline_fflush(stdout)); 1205251881Speter 1206289180Speter return SVN_NO_ERROR; 1207289180Speter} 1208251881Speter 1209289180Speter/* This implements `svn_wc_notify_func2_t'. 1210289180Speter * NOTE: This function can't fail, so we just ignore any print errors. */ 1211289180Speterstatic void 1212289180Speternotify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool) 1213289180Speter{ 1214289180Speter struct notify_baton *nb = baton; 1215289180Speter svn_error_t *err; 1216289180Speter 1217289180Speter err = notify_body(nb, n, pool); 1218289180Speter 1219251881Speter /* If we had no errors before, print this error to stderr. Else, don't print 1220251881Speter anything. The user already knows there were some output errors, 1221251881Speter so there is no point in flooding her with an error per notification. */ 1222289180Speter if (err && !nb->had_print_error) 1223251881Speter { 1224251881Speter nb->had_print_error = TRUE; 1225251881Speter /* Issue #3014: 1226251881Speter * Don't print anything on broken pipes. The pipe was likely 1227251881Speter * closed by the process at the other end. We expect that 1228251881Speter * process to perform error reporting as necessary. 1229251881Speter * 1230251881Speter * ### This assumes that there is only one error in a chain for 1231251881Speter * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */ 1232251881Speter if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR) 1233251881Speter svn_handle_error2(err, stderr, FALSE, "svn: "); 1234251881Speter } 1235251881Speter svn_error_clear(err); 1236251881Speter} 1237251881Speter 1238251881Spetersvn_error_t * 1239251881Spetersvn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p, 1240251881Speter void **notify_baton_p, 1241251881Speter svn_cl__conflict_stats_t *conflict_stats, 1242251881Speter apr_pool_t *pool) 1243251881Speter{ 1244251881Speter struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb)); 1245251881Speter 1246251881Speter nb->received_some_change = FALSE; 1247251881Speter nb->sent_first_txdelta = FALSE; 1248251881Speter nb->is_checkout = FALSE; 1249251881Speter nb->is_export = FALSE; 1250251881Speter nb->is_wc_to_repos_copy = FALSE; 1251289180Speter nb->in_external = 0; 1252362181Sdim nb->progress_revision = 0; 1253251881Speter nb->had_print_error = FALSE; 1254251881Speter nb->conflict_stats = conflict_stats; 1255251881Speter SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool)); 1256251881Speter 1257251881Speter *notify_func_p = notify; 1258251881Speter *notify_baton_p = nb; 1259251881Speter return SVN_NO_ERROR; 1260251881Speter} 1261251881Speter 1262251881Spetersvn_error_t * 1263251881Spetersvn_cl__notifier_mark_checkout(void *baton) 1264251881Speter{ 1265251881Speter struct notify_baton *nb = baton; 1266251881Speter 1267251881Speter nb->is_checkout = TRUE; 1268251881Speter return SVN_NO_ERROR; 1269251881Speter} 1270251881Speter 1271251881Spetersvn_error_t * 1272251881Spetersvn_cl__notifier_mark_export(void *baton) 1273251881Speter{ 1274251881Speter struct notify_baton *nb = baton; 1275251881Speter 1276251881Speter nb->is_export = TRUE; 1277251881Speter return SVN_NO_ERROR; 1278251881Speter} 1279251881Speter 1280251881Spetersvn_error_t * 1281251881Spetersvn_cl__notifier_mark_wc_to_repos_copy(void *baton) 1282251881Speter{ 1283251881Speter struct notify_baton *nb = baton; 1284251881Speter 1285251881Speter nb->is_wc_to_repos_copy = TRUE; 1286251881Speter return SVN_NO_ERROR; 1287251881Speter} 1288251881Speter 1289251881Spetervoid 1290251881Spetersvn_cl__check_externals_failed_notify_wrapper(void *baton, 1291251881Speter const svn_wc_notify_t *n, 1292251881Speter apr_pool_t *pool) 1293251881Speter{ 1294251881Speter struct svn_cl__check_externals_failed_notify_baton *nwb = baton; 1295251881Speter 1296251881Speter if (n->action == svn_wc_notify_failed_external) 1297251881Speter nwb->had_externals_error = TRUE; 1298251881Speter 1299251881Speter if (nwb->wrapped_func) 1300251881Speter nwb->wrapped_func(nwb->wrapped_baton, n, pool); 1301251881Speter} 1302