1289177Speter/* 2289177Speter * notify.c: feedback handlers for cmdline client. 3289177Speter * 4289177Speter * ==================================================================== 5289177Speter * Licensed to the Apache Software Foundation (ASF) under one 6289177Speter * or more contributor license agreements. See the NOTICE file 7289177Speter * distributed with this work for additional information 8289177Speter * regarding copyright ownership. The ASF licenses this file 9289177Speter * to you under the Apache License, Version 2.0 (the 10289177Speter * "License"); you may not use this file except in compliance 11289177Speter * with the License. You may obtain a copy of the License at 12289177Speter * 13289177Speter * http://www.apache.org/licenses/LICENSE-2.0 14289177Speter * 15289177Speter * Unless required by applicable law or agreed to in writing, 16289177Speter * software distributed under the License is distributed on an 17289177Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18289177Speter * KIND, either express or implied. See the License for the 19289177Speter * specific language governing permissions and limitations 20289177Speter * under the License. 21289177Speter * ==================================================================== 22289177Speter */ 23289177Speter 24289177Speter/* ==================================================================== */ 25289177Speter 26289177Speter 27289177Speter 28289177Speter/*** Includes. ***/ 29289177Speter 30289177Speter#define APR_WANT_STDIO 31289177Speter#define APR_WANT_STRFUNC 32289177Speter#include <apr_want.h> 33289177Speter 34289177Speter#include "svn_cmdline.h" 35289177Speter#include "svn_pools.h" 36289177Speter#include "svn_dirent_uri.h" 37289177Speter#include "svn_path.h" 38289177Speter#include "svn_sorts.h" 39289177Speter#include "cl.h" 40289177Speter 41289177Speter#include "svn_private_config.h" 42289177Speter 43289177Speter 44289177Speter/* Baton for notify and friends. */ 45289177Speterstruct notify_baton 46289177Speter{ 47289177Speter svn_boolean_t received_some_change; 48289177Speter svn_boolean_t is_checkout; 49289177Speter svn_boolean_t is_export; 50289177Speter svn_boolean_t is_wc_to_repos_copy; 51289177Speter svn_boolean_t sent_first_txdelta; 52289177Speter svn_boolean_t in_external; 53289177Speter svn_boolean_t had_print_error; /* Used to not keep printing error messages 54289177Speter when we've already had one print error. */ 55289177Speter 56289177Speter /* Conflict stats for update and merge. */ 57289177Speter unsigned int text_conflicts; 58289177Speter unsigned int prop_conflicts; 59289177Speter unsigned int tree_conflicts; 60289177Speter unsigned int skipped_paths; 61289177Speter apr_hash_t *conflicted_paths; 62289177Speter 63289177Speter /* The cwd, for use in decomposing absolute paths. */ 64289177Speter const char *path_prefix; 65289177Speter}; 66289177Speter 67289177Speter 68289177Speter/* Add a conflicted path to the list of conflicted paths stored 69289177Speter * in the notify baton. */ 70289177Speterstatic void 71289177Speteradd_conflicted_path(struct notify_baton *nb, const char *path) 72289177Speter{ 73289177Speter apr_hash_set(nb->conflicted_paths, 74289177Speter apr_pstrdup(apr_hash_pool_get(nb->conflicted_paths), path), 75289177Speter APR_HASH_KEY_STRING, ""); 76289177Speter} 77289177Speter 78289177Speter/* This implements `svn_wc_notify_func2_t'. 79289177Speter * NOTE: This function can't fail, so we just ignore any print errors. */ 80289177Speterstatic void 81289177Speternotify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool) 82289177Speter{ 83289177Speter struct notify_baton *nb = baton; 84289177Speter char statchar_buf[5] = " "; 85289177Speter const char *path_local; 86289177Speter svn_error_t *err; 87289177Speter 88289177Speter if (n->url) 89289177Speter path_local = n->url; 90289177Speter else 91289177Speter { 92289177Speter if (n->path_prefix) 93289177Speter path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path, 94289177Speter pool); 95289177Speter else /* skip nb->path_prefix, if it's non-null */ 96289177Speter path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path, 97289177Speter pool); 98289177Speter } 99289177Speter 100289177Speter switch (n->action) 101289177Speter { 102289177Speter case svn_wc_notify_skip: 103289177Speter nb->skipped_paths++; 104289177Speter if (n->content_state == svn_wc_notify_state_missing) 105289177Speter { 106289177Speter if ((err = svn_cmdline_printf 107289177Speter (pool, _("Skipped missing target: '%s'\n"), 108289177Speter path_local))) 109289177Speter goto print_error; 110289177Speter } 111289177Speter else if (n->content_state == svn_wc_notify_state_source_missing) 112289177Speter { 113289177Speter if ((err = svn_cmdline_printf 114289177Speter (pool, _("Skipped target: '%s' -- copy-source is missing\n"), 115289177Speter path_local))) 116289177Speter goto print_error; 117289177Speter } 118289177Speter else 119289177Speter { 120289177Speter if ((err = svn_cmdline_printf 121289177Speter (pool, _("Skipped '%s'\n"), path_local))) 122289177Speter goto print_error; 123289177Speter } 124289177Speter break; 125289177Speter case svn_wc_notify_update_skip_obstruction: 126289177Speter nb->skipped_paths++; 127289177Speter if ((err = svn_cmdline_printf( 128289177Speter pool, _("Skipped '%s' -- An obstructing working copy was found\n"), 129289177Speter path_local))) 130289177Speter goto print_error; 131289177Speter break; 132289177Speter case svn_wc_notify_update_skip_working_only: 133289177Speter nb->skipped_paths++; 134289177Speter if ((err = svn_cmdline_printf( 135289177Speter pool, _("Skipped '%s' -- Has no versioned parent\n"), 136289177Speter path_local))) 137289177Speter goto print_error; 138289177Speter break; 139289177Speter case svn_wc_notify_update_skip_access_denied: 140289177Speter nb->skipped_paths++; 141289177Speter if ((err = svn_cmdline_printf( 142289177Speter pool, _("Skipped '%s' -- Access denied\n"), 143289177Speter path_local))) 144289177Speter goto print_error; 145289177Speter break; 146289177Speter case svn_wc_notify_skip_conflicted: 147289177Speter nb->skipped_paths++; 148289177Speter if ((err = svn_cmdline_printf( 149289177Speter pool, _("Skipped '%s' -- Node remains in conflict\n"), 150289177Speter path_local))) 151289177Speter goto print_error; 152289177Speter break; 153289177Speter case svn_wc_notify_update_delete: 154289177Speter case svn_wc_notify_exclude: 155289177Speter nb->received_some_change = TRUE; 156289177Speter if ((err = svn_cmdline_printf(pool, "D %s\n", path_local))) 157289177Speter goto print_error; 158289177Speter break; 159289177Speter case svn_wc_notify_update_broken_lock: 160289177Speter if ((err = svn_cmdline_printf(pool, "B %s\n", path_local))) 161289177Speter goto print_error; 162289177Speter break; 163289177Speter 164289177Speter case svn_wc_notify_update_external_removed: 165289177Speter nb->received_some_change = TRUE; 166289177Speter if (n->err && n->err->message) 167289177Speter { 168289177Speter if ((err = svn_cmdline_printf(pool, "Removed external '%s': %s\n", 169289177Speter path_local, n->err->message))) 170289177Speter goto print_error; 171289177Speter } 172289177Speter else 173289177Speter { 174289177Speter if ((err = svn_cmdline_printf(pool, "Removed external '%s'\n", 175289177Speter path_local))) 176289177Speter goto print_error; 177289177Speter } 178289177Speter break; 179289177Speter 180289177Speter case svn_wc_notify_left_local_modifications: 181289177Speter if ((err = svn_cmdline_printf(pool, "Left local modifications as '%s'\n", 182289177Speter path_local))) 183289177Speter goto print_error; 184289177Speter break; 185289177Speter 186289177Speter case svn_wc_notify_update_replace: 187289177Speter nb->received_some_change = TRUE; 188289177Speter if ((err = svn_cmdline_printf(pool, "R %s\n", path_local))) 189289177Speter goto print_error; 190289177Speter break; 191289177Speter 192289177Speter case svn_wc_notify_update_add: 193289177Speter nb->received_some_change = TRUE; 194289177Speter if (n->content_state == svn_wc_notify_state_conflicted) 195289177Speter { 196289177Speter nb->text_conflicts++; 197289177Speter add_conflicted_path(nb, n->path); 198289177Speter if ((err = svn_cmdline_printf(pool, "C %s\n", path_local))) 199289177Speter goto print_error; 200289177Speter } 201289177Speter else 202289177Speter { 203289177Speter if ((err = svn_cmdline_printf(pool, "A %s\n", path_local))) 204289177Speter goto print_error; 205289177Speter } 206289177Speter break; 207289177Speter 208289177Speter case svn_wc_notify_exists: 209289177Speter nb->received_some_change = TRUE; 210289177Speter if (n->content_state == svn_wc_notify_state_conflicted) 211289177Speter { 212289177Speter nb->text_conflicts++; 213289177Speter add_conflicted_path(nb, n->path); 214289177Speter statchar_buf[0] = 'C'; 215289177Speter } 216289177Speter else 217289177Speter statchar_buf[0] = 'E'; 218289177Speter 219289177Speter if (n->prop_state == svn_wc_notify_state_conflicted) 220289177Speter { 221289177Speter nb->prop_conflicts++; 222289177Speter add_conflicted_path(nb, n->path); 223289177Speter statchar_buf[1] = 'C'; 224289177Speter } 225289177Speter else if (n->prop_state == svn_wc_notify_state_merged) 226289177Speter statchar_buf[1] = 'G'; 227289177Speter 228289177Speter if ((err = svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local))) 229289177Speter goto print_error; 230289177Speter break; 231289177Speter 232289177Speter case svn_wc_notify_restore: 233289177Speter if ((err = svn_cmdline_printf(pool, _("Restored '%s'\n"), 234289177Speter path_local))) 235289177Speter goto print_error; 236289177Speter break; 237289177Speter 238289177Speter case svn_wc_notify_revert: 239289177Speter if ((err = svn_cmdline_printf(pool, _("Reverted '%s'\n"), 240289177Speter path_local))) 241289177Speter goto print_error; 242289177Speter break; 243289177Speter 244289177Speter case svn_wc_notify_failed_revert: 245289177Speter if (( err = svn_cmdline_printf(pool, _("Failed to revert '%s' -- " 246289177Speter "try updating instead.\n"), 247289177Speter path_local))) 248289177Speter goto print_error; 249289177Speter break; 250289177Speter 251289177Speter case svn_wc_notify_resolved: 252289177Speter if ((err = svn_cmdline_printf(pool, 253289177Speter _("Resolved conflicted state of '%s'\n"), 254289177Speter path_local))) 255289177Speter goto print_error; 256289177Speter break; 257289177Speter 258289177Speter case svn_wc_notify_add: 259289177Speter /* We *should* only get the MIME_TYPE if PATH is a file. If we 260289177Speter do get it, and the mime-type is not textual, note that this 261289177Speter is a binary addition. */ 262289177Speter if (n->mime_type && (svn_mime_type_is_binary(n->mime_type))) 263289177Speter { 264289177Speter if ((err = svn_cmdline_printf(pool, "A (bin) %s\n", 265289177Speter path_local))) 266289177Speter goto print_error; 267289177Speter } 268289177Speter else 269289177Speter { 270289177Speter if ((err = svn_cmdline_printf(pool, "A %s\n", 271289177Speter path_local))) 272289177Speter goto print_error; 273289177Speter } 274289177Speter break; 275289177Speter 276289177Speter case svn_wc_notify_delete: 277289177Speter nb->received_some_change = TRUE; 278289177Speter if ((err = svn_cmdline_printf(pool, "D %s\n", 279289177Speter path_local))) 280289177Speter goto print_error; 281289177Speter break; 282289177Speter 283289177Speter case svn_wc_notify_patch: 284289177Speter { 285289177Speter nb->received_some_change = TRUE; 286289177Speter if (n->content_state == svn_wc_notify_state_conflicted) 287289177Speter { 288289177Speter nb->text_conflicts++; 289289177Speter add_conflicted_path(nb, n->path); 290289177Speter statchar_buf[0] = 'C'; 291289177Speter } 292289177Speter else if (n->kind == svn_node_file) 293289177Speter { 294289177Speter if (n->content_state == svn_wc_notify_state_merged) 295289177Speter statchar_buf[0] = 'G'; 296289177Speter else if (n->content_state == svn_wc_notify_state_changed) 297289177Speter statchar_buf[0] = 'U'; 298289177Speter } 299289177Speter 300289177Speter if (n->prop_state == svn_wc_notify_state_conflicted) 301289177Speter { 302289177Speter nb->prop_conflicts++; 303289177Speter add_conflicted_path(nb, n->path); 304289177Speter statchar_buf[1] = 'C'; 305289177Speter } 306289177Speter else if (n->prop_state == svn_wc_notify_state_changed) 307289177Speter statchar_buf[1] = 'U'; 308289177Speter 309289177Speter if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ') 310289177Speter { 311289177Speter if ((err = svn_cmdline_printf(pool, "%s %s\n", 312289177Speter statchar_buf, path_local))) 313289177Speter goto print_error; 314289177Speter } 315289177Speter } 316289177Speter break; 317289177Speter 318289177Speter case svn_wc_notify_patch_applied_hunk: 319289177Speter nb->received_some_change = TRUE; 320289177Speter if (n->hunk_original_start != n->hunk_matched_line) 321289177Speter { 322289177Speter apr_uint64_t off; 323289177Speter const char *s; 324289177Speter const char *minus; 325289177Speter 326289177Speter if (n->hunk_matched_line > n->hunk_original_start) 327289177Speter { 328289177Speter off = n->hunk_matched_line - n->hunk_original_start; 329289177Speter minus = ""; 330289177Speter } 331289177Speter else 332289177Speter { 333289177Speter off = n->hunk_original_start - n->hunk_matched_line; 334289177Speter minus = "-"; 335289177Speter } 336289177Speter 337289177Speter /* ### We're creating the localized strings without 338289177Speter * ### APR_INT64_T_FMT since it isn't translator-friendly */ 339289177Speter if (n->hunk_fuzz) 340289177Speter { 341289177Speter 342289177Speter if (n->prop_name) 343289177Speter { 344289177Speter s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## " 345289177Speter "with offset %s"); 346289177Speter 347289177Speter err = svn_cmdline_printf(pool, 348289177Speter apr_pstrcat(pool, s, 349289177Speter "%"APR_UINT64_T_FMT 350289177Speter " and fuzz %lu (%s)\n", 351289177Speter SVN_VA_NULL), 352289177Speter n->hunk_original_start, 353289177Speter n->hunk_original_length, 354289177Speter n->hunk_modified_start, 355289177Speter n->hunk_modified_length, 356289177Speter minus, off, n->hunk_fuzz, 357289177Speter n->prop_name); 358289177Speter } 359289177Speter else 360289177Speter { 361289177Speter s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ " 362289177Speter "with offset %s"); 363289177Speter 364289177Speter err = svn_cmdline_printf(pool, 365289177Speter apr_pstrcat(pool, s, 366289177Speter "%"APR_UINT64_T_FMT 367289177Speter " and fuzz %lu\n", 368289177Speter SVN_VA_NULL), 369289177Speter n->hunk_original_start, 370289177Speter n->hunk_original_length, 371289177Speter n->hunk_modified_start, 372289177Speter n->hunk_modified_length, 373289177Speter minus, off, n->hunk_fuzz); 374289177Speter } 375289177Speter 376289177Speter if (err) 377289177Speter goto print_error; 378289177Speter } 379289177Speter else 380289177Speter { 381289177Speter 382289177Speter if (n->prop_name) 383289177Speter { 384289177Speter s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## " 385289177Speter "with offset %s"); 386289177Speter err = svn_cmdline_printf(pool, 387289177Speter apr_pstrcat(pool, s, 388289177Speter "%"APR_UINT64_T_FMT" (%s)\n", 389289177Speter SVN_VA_NULL), 390289177Speter n->hunk_original_start, 391289177Speter n->hunk_original_length, 392289177Speter n->hunk_modified_start, 393289177Speter n->hunk_modified_length, 394289177Speter minus, off, n->prop_name); 395289177Speter } 396289177Speter else 397289177Speter { 398289177Speter s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ " 399289177Speter "with offset %s"); 400289177Speter err = svn_cmdline_printf(pool, 401289177Speter apr_pstrcat(pool, s, 402289177Speter "%"APR_UINT64_T_FMT"\n", 403289177Speter SVN_VA_NULL), 404289177Speter n->hunk_original_start, 405289177Speter n->hunk_original_length, 406289177Speter n->hunk_modified_start, 407289177Speter n->hunk_modified_length, 408289177Speter minus, off); 409289177Speter } 410289177Speter 411289177Speter if (err) 412289177Speter goto print_error; 413289177Speter } 414289177Speter } 415289177Speter else if (n->hunk_fuzz) 416289177Speter { 417289177Speter if (n->prop_name) 418289177Speter err = svn_cmdline_printf(pool, 419289177Speter _("> applied hunk ## -%lu,%lu +%lu,%lu ## " 420289177Speter "with fuzz %lu (%s)\n"), 421289177Speter n->hunk_original_start, 422289177Speter n->hunk_original_length, 423289177Speter n->hunk_modified_start, 424289177Speter n->hunk_modified_length, 425289177Speter n->hunk_fuzz, 426289177Speter n->prop_name); 427289177Speter else 428289177Speter err = svn_cmdline_printf(pool, 429289177Speter _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ " 430289177Speter "with fuzz %lu\n"), 431289177Speter n->hunk_original_start, 432289177Speter n->hunk_original_length, 433289177Speter n->hunk_modified_start, 434289177Speter n->hunk_modified_length, 435289177Speter n->hunk_fuzz); 436289177Speter if (err) 437289177Speter goto print_error; 438289177Speter 439289177Speter } 440289177Speter break; 441289177Speter 442289177Speter case svn_wc_notify_patch_rejected_hunk: 443289177Speter nb->received_some_change = TRUE; 444289177Speter 445289177Speter if (n->prop_name) 446289177Speter err = svn_cmdline_printf(pool, 447289177Speter _("> rejected hunk " 448289177Speter "## -%lu,%lu +%lu,%lu ## (%s)\n"), 449289177Speter n->hunk_original_start, 450289177Speter n->hunk_original_length, 451289177Speter n->hunk_modified_start, 452289177Speter n->hunk_modified_length, 453289177Speter n->prop_name); 454289177Speter else 455289177Speter err = svn_cmdline_printf(pool, 456289177Speter _("> rejected hunk " 457289177Speter "@@ -%lu,%lu +%lu,%lu @@\n"), 458289177Speter n->hunk_original_start, 459289177Speter n->hunk_original_length, 460289177Speter n->hunk_modified_start, 461289177Speter n->hunk_modified_length); 462289177Speter if (err) 463289177Speter goto print_error; 464289177Speter break; 465289177Speter 466289177Speter case svn_wc_notify_patch_hunk_already_applied: 467289177Speter nb->received_some_change = TRUE; 468289177Speter if (n->prop_name) 469289177Speter err = svn_cmdline_printf(pool, 470289177Speter _("> hunk " 471289177Speter "## -%lu,%lu +%lu,%lu ## " 472289177Speter "already applied (%s)\n"), 473289177Speter n->hunk_original_start, 474289177Speter n->hunk_original_length, 475289177Speter n->hunk_modified_start, 476289177Speter n->hunk_modified_length, 477289177Speter n->prop_name); 478289177Speter else 479289177Speter err = svn_cmdline_printf(pool, 480289177Speter _("> hunk " 481289177Speter "@@ -%lu,%lu +%lu,%lu @@ " 482289177Speter "already applied\n"), 483289177Speter n->hunk_original_start, 484289177Speter n->hunk_original_length, 485289177Speter n->hunk_modified_start, 486289177Speter n->hunk_modified_length); 487289177Speter if (err) 488289177Speter goto print_error; 489289177Speter break; 490289177Speter 491289177Speter case svn_wc_notify_update_update: 492289177Speter case svn_wc_notify_merge_record_info: 493289177Speter { 494289177Speter if (n->content_state == svn_wc_notify_state_conflicted) 495289177Speter { 496289177Speter nb->text_conflicts++; 497289177Speter add_conflicted_path(nb, n->path); 498289177Speter statchar_buf[0] = 'C'; 499289177Speter } 500289177Speter else if (n->kind == svn_node_file) 501289177Speter { 502289177Speter if (n->content_state == svn_wc_notify_state_merged) 503289177Speter statchar_buf[0] = 'G'; 504289177Speter else if (n->content_state == svn_wc_notify_state_changed) 505289177Speter statchar_buf[0] = 'U'; 506289177Speter } 507289177Speter 508289177Speter if (n->prop_state == svn_wc_notify_state_conflicted) 509289177Speter { 510289177Speter nb->prop_conflicts++; 511289177Speter add_conflicted_path(nb, n->path); 512289177Speter statchar_buf[1] = 'C'; 513289177Speter } 514289177Speter else if (n->prop_state == svn_wc_notify_state_merged) 515289177Speter statchar_buf[1] = 'G'; 516289177Speter else if (n->prop_state == svn_wc_notify_state_changed) 517289177Speter statchar_buf[1] = 'U'; 518289177Speter 519289177Speter if (n->lock_state == svn_wc_notify_lock_state_unlocked) 520289177Speter statchar_buf[2] = 'B'; 521289177Speter 522289177Speter if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ') 523289177Speter nb->received_some_change = TRUE; 524289177Speter 525289177Speter if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ' 526289177Speter || statchar_buf[2] != ' ') 527289177Speter { 528289177Speter if ((err = svn_cmdline_printf(pool, "%s %s\n", 529289177Speter statchar_buf, path_local))) 530289177Speter goto print_error; 531289177Speter } 532289177Speter } 533289177Speter break; 534289177Speter 535289177Speter case svn_wc_notify_update_external: 536289177Speter /* Remember that we're now "inside" an externals definition. */ 537289177Speter nb->in_external = TRUE; 538289177Speter 539289177Speter /* Currently this is used for checkouts and switches too. If we 540289177Speter want different output, we'll have to add new actions. */ 541289177Speter if ((err = svn_cmdline_printf(pool, 542289177Speter _("\nFetching external item into '%s':\n"), 543289177Speter path_local))) 544289177Speter goto print_error; 545289177Speter break; 546289177Speter 547289177Speter case svn_wc_notify_failed_external: 548289177Speter /* If we are currently inside the handling of an externals 549289177Speter definition, then we can simply present n->err as a warning 550289177Speter and feel confident that after this, we aren't handling that 551289177Speter externals definition any longer. */ 552289177Speter if (nb->in_external) 553289177Speter { 554289177Speter svn_handle_warning2(stderr, n->err, "svn: "); 555289177Speter nb->in_external = FALSE; 556289177Speter if ((err = svn_cmdline_printf(pool, "\n"))) 557289177Speter goto print_error; 558289177Speter } 559289177Speter /* Otherwise, we'll just print two warnings. Why? Because 560289177Speter svn_handle_warning2() only shows the single "best message", 561289177Speter but we have two pretty important ones: that the external at 562289177Speter '/some/path' didn't pan out, and then the more specific 563289177Speter reason why (from n->err). */ 564289177Speter else 565289177Speter { 566289177Speter svn_error_t *warn_err = 567289177Speter svn_error_createf(SVN_ERR_BASE, NULL, 568289177Speter _("Error handling externals definition for '%s':"), 569289177Speter path_local); 570289177Speter svn_handle_warning2(stderr, warn_err, "svn: "); 571289177Speter svn_error_clear(warn_err); 572289177Speter svn_handle_warning2(stderr, n->err, "svn: "); 573289177Speter } 574289177Speter break; 575289177Speter 576289177Speter case svn_wc_notify_update_started: 577289177Speter if (! (nb->in_external || 578289177Speter nb->is_checkout || 579289177Speter nb->is_export)) 580289177Speter { 581289177Speter if ((err = svn_cmdline_printf(pool, _("Updating '%s':\n"), 582289177Speter path_local))) 583289177Speter goto print_error; 584289177Speter } 585289177Speter break; 586289177Speter 587289177Speter case svn_wc_notify_update_completed: 588289177Speter { 589289177Speter if (SVN_IS_VALID_REVNUM(n->revision)) 590289177Speter { 591289177Speter if (nb->is_export) 592289177Speter { 593289177Speter if ((err = svn_cmdline_printf 594289177Speter (pool, nb->in_external 595289177Speter ? _("Exported external at revision %ld.\n") 596289177Speter : _("Exported revision %ld.\n"), 597289177Speter n->revision))) 598289177Speter goto print_error; 599289177Speter } 600289177Speter else if (nb->is_checkout) 601289177Speter { 602289177Speter if ((err = svn_cmdline_printf 603289177Speter (pool, nb->in_external 604289177Speter ? _("Checked out external at revision %ld.\n") 605289177Speter : _("Checked out revision %ld.\n"), 606289177Speter n->revision))) 607289177Speter goto print_error; 608289177Speter } 609289177Speter else 610289177Speter { 611289177Speter if (nb->received_some_change) 612289177Speter { 613289177Speter nb->received_some_change = FALSE; 614289177Speter if ((err = svn_cmdline_printf 615289177Speter (pool, nb->in_external 616289177Speter ? _("Updated external to revision %ld.\n") 617289177Speter : _("Updated to revision %ld.\n"), 618289177Speter n->revision))) 619289177Speter goto print_error; 620289177Speter } 621289177Speter else 622289177Speter { 623289177Speter if ((err = svn_cmdline_printf 624289177Speter (pool, nb->in_external 625289177Speter ? _("External at revision %ld.\n") 626289177Speter : _("At revision %ld.\n"), 627289177Speter n->revision))) 628289177Speter goto print_error; 629289177Speter } 630289177Speter } 631289177Speter } 632289177Speter else /* no revision */ 633289177Speter { 634289177Speter if (nb->is_export) 635289177Speter { 636289177Speter if ((err = svn_cmdline_printf 637289177Speter (pool, nb->in_external 638289177Speter ? _("External export complete.\n") 639289177Speter : _("Export complete.\n")))) 640289177Speter goto print_error; 641289177Speter } 642289177Speter else if (nb->is_checkout) 643289177Speter { 644289177Speter if ((err = svn_cmdline_printf 645289177Speter (pool, nb->in_external 646289177Speter ? _("External checkout complete.\n") 647289177Speter : _("Checkout complete.\n")))) 648289177Speter goto print_error; 649289177Speter } 650289177Speter else 651289177Speter { 652289177Speter if ((err = svn_cmdline_printf 653289177Speter (pool, nb->in_external 654289177Speter ? _("External update complete.\n") 655289177Speter : _("Update complete.\n")))) 656289177Speter goto print_error; 657289177Speter } 658289177Speter } 659289177Speter } 660289177Speter 661289177Speter if (nb->in_external) 662289177Speter { 663289177Speter nb->in_external = FALSE; 664289177Speter if ((err = svn_cmdline_printf(pool, "\n"))) 665289177Speter goto print_error; 666289177Speter } 667289177Speter break; 668289177Speter 669289177Speter case svn_wc_notify_status_external: 670289177Speter if ((err = svn_cmdline_printf 671289177Speter (pool, _("\nPerforming status on external item at '%s':\n"), 672289177Speter path_local))) 673289177Speter goto print_error; 674289177Speter break; 675289177Speter 676289177Speter case svn_wc_notify_status_completed: 677289177Speter if (SVN_IS_VALID_REVNUM(n->revision)) 678289177Speter if ((err = svn_cmdline_printf(pool, 679289177Speter _("Status against revision: %6ld\n"), 680289177Speter n->revision))) 681289177Speter goto print_error; 682289177Speter break; 683289177Speter 684289177Speter case svn_wc_notify_commit_modified: 685289177Speter /* xgettext: Align the %s's on this and the following 4 messages */ 686289177Speter if ((err = svn_cmdline_printf(pool, 687289177Speter nb->is_wc_to_repos_copy 688289177Speter ? _("Sending copy of %s\n") 689289177Speter : _("Sending %s\n"), 690289177Speter path_local))) 691289177Speter goto print_error; 692289177Speter break; 693289177Speter 694289177Speter case svn_wc_notify_commit_added: 695289177Speter case svn_wc_notify_commit_copied: 696289177Speter if (n->mime_type && svn_mime_type_is_binary(n->mime_type)) 697289177Speter { 698289177Speter if ((err = svn_cmdline_printf(pool, 699289177Speter nb->is_wc_to_repos_copy 700289177Speter ? _("Adding copy of (bin) %s\n") 701289177Speter : _("Adding (bin) %s\n"), 702289177Speter path_local))) 703289177Speter goto print_error; 704289177Speter } 705289177Speter else 706289177Speter { 707289177Speter if ((err = svn_cmdline_printf(pool, 708289177Speter nb->is_wc_to_repos_copy 709289177Speter ? _("Adding copy of %s\n") 710289177Speter : _("Adding %s\n"), 711289177Speter path_local))) 712289177Speter goto print_error; 713289177Speter } 714289177Speter break; 715289177Speter 716289177Speter case svn_wc_notify_commit_deleted: 717289177Speter if ((err = svn_cmdline_printf(pool, 718289177Speter nb->is_wc_to_repos_copy 719289177Speter ? _("Deleting copy of %s\n") 720289177Speter : _("Deleting %s\n"), 721289177Speter path_local))) 722289177Speter goto print_error; 723289177Speter break; 724289177Speter 725289177Speter case svn_wc_notify_commit_replaced: 726289177Speter case svn_wc_notify_commit_copied_replaced: 727289177Speter if ((err = svn_cmdline_printf(pool, 728289177Speter nb->is_wc_to_repos_copy 729289177Speter ? _("Replacing copy of %s\n") 730289177Speter : _("Replacing %s\n"), 731289177Speter path_local))) 732289177Speter goto print_error; 733289177Speter break; 734289177Speter 735289177Speter case svn_wc_notify_commit_postfix_txdelta: 736289177Speter if (! nb->sent_first_txdelta) 737289177Speter { 738289177Speter nb->sent_first_txdelta = TRUE; 739289177Speter if ((err = svn_cmdline_printf(pool, 740289177Speter _("Transmitting file data ")))) 741289177Speter goto print_error; 742289177Speter } 743289177Speter 744289177Speter if ((err = svn_cmdline_printf(pool, "."))) 745289177Speter goto print_error; 746289177Speter break; 747289177Speter 748289177Speter case svn_wc_notify_locked: 749289177Speter if ((err = svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"), 750289177Speter path_local, n->lock->owner))) 751289177Speter goto print_error; 752289177Speter break; 753289177Speter 754289177Speter case svn_wc_notify_unlocked: 755289177Speter if ((err = svn_cmdline_printf(pool, _("'%s' unlocked.\n"), 756289177Speter path_local))) 757289177Speter goto print_error; 758289177Speter break; 759289177Speter 760289177Speter case svn_wc_notify_failed_lock: 761289177Speter case svn_wc_notify_failed_unlock: 762289177Speter svn_handle_warning2(stderr, n->err, "svn: "); 763289177Speter break; 764289177Speter 765289177Speter case svn_wc_notify_changelist_set: 766289177Speter if ((err = svn_cmdline_printf(pool, "A [%s] %s\n", 767289177Speter n->changelist_name, path_local))) 768289177Speter goto print_error; 769289177Speter break; 770289177Speter 771289177Speter case svn_wc_notify_changelist_clear: 772289177Speter case svn_wc_notify_changelist_moved: 773289177Speter if ((err = svn_cmdline_printf(pool, 774289177Speter "D [%s] %s\n", 775289177Speter n->changelist_name, path_local))) 776289177Speter goto print_error; 777289177Speter break; 778289177Speter 779289177Speter case svn_wc_notify_merge_begin: 780289177Speter if (n->merge_range == NULL) 781289177Speter err = svn_cmdline_printf(pool, 782289177Speter _("--- Merging differences between " 783289177Speter "repository URLs into '%s':\n"), 784289177Speter path_local); 785289177Speter else if (n->merge_range->start == n->merge_range->end - 1 786289177Speter || n->merge_range->start == n->merge_range->end) 787289177Speter err = svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"), 788289177Speter n->merge_range->end, path_local); 789289177Speter else if (n->merge_range->start - 1 == n->merge_range->end) 790289177Speter err = svn_cmdline_printf(pool, 791289177Speter _("--- Reverse-merging r%ld into '%s':\n"), 792289177Speter n->merge_range->start, path_local); 793289177Speter else if (n->merge_range->start < n->merge_range->end) 794289177Speter err = svn_cmdline_printf(pool, 795289177Speter _("--- Merging r%ld through r%ld into " 796289177Speter "'%s':\n"), 797289177Speter n->merge_range->start + 1, 798289177Speter n->merge_range->end, path_local); 799289177Speter else /* n->merge_range->start > n->merge_range->end - 1 */ 800289177Speter err = svn_cmdline_printf(pool, 801289177Speter _("--- Reverse-merging r%ld through r%ld " 802289177Speter "into '%s':\n"), 803289177Speter n->merge_range->start, 804289177Speter n->merge_range->end + 1, path_local); 805289177Speter if (err) 806289177Speter goto print_error; 807289177Speter break; 808289177Speter 809289177Speter case svn_wc_notify_merge_record_info_begin: 810289177Speter if (!n->merge_range) 811289177Speter { 812289177Speter err = svn_cmdline_printf(pool, 813289177Speter _("--- Recording mergeinfo for merge " 814289177Speter "between repository URLs into '%s':\n"), 815289177Speter path_local); 816289177Speter } 817289177Speter else 818289177Speter { 819289177Speter if (n->merge_range->start == n->merge_range->end - 1 820289177Speter || n->merge_range->start == n->merge_range->end) 821289177Speter err = svn_cmdline_printf( 822289177Speter pool, 823289177Speter _("--- Recording mergeinfo for merge of r%ld into '%s':\n"), 824289177Speter n->merge_range->end, path_local); 825289177Speter else if (n->merge_range->start - 1 == n->merge_range->end) 826289177Speter err = svn_cmdline_printf( 827289177Speter pool, 828289177Speter _("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"), 829289177Speter n->merge_range->start, path_local); 830289177Speter else if (n->merge_range->start < n->merge_range->end) 831289177Speter err = svn_cmdline_printf( 832289177Speter pool, 833289177Speter _("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"), 834289177Speter n->merge_range->start + 1, n->merge_range->end, path_local); 835289177Speter else /* n->merge_range->start > n->merge_range->end - 1 */ 836289177Speter err = svn_cmdline_printf( 837289177Speter pool, 838289177Speter _("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"), 839289177Speter n->merge_range->start, n->merge_range->end + 1, path_local); 840289177Speter } 841289177Speter 842289177Speter if (err) 843289177Speter goto print_error; 844289177Speter break; 845289177Speter 846289177Speter case svn_wc_notify_merge_elide_info: 847289177Speter if ((err = svn_cmdline_printf(pool, 848289177Speter _("--- Eliding mergeinfo from '%s':\n"), 849289177Speter path_local))) 850289177Speter goto print_error; 851289177Speter break; 852289177Speter 853289177Speter case svn_wc_notify_foreign_merge_begin: 854289177Speter if (n->merge_range == NULL) 855289177Speter err = svn_cmdline_printf(pool, 856289177Speter _("--- Merging differences between " 857289177Speter "foreign repository URLs into '%s':\n"), 858289177Speter path_local); 859289177Speter else if (n->merge_range->start == n->merge_range->end - 1 860289177Speter || n->merge_range->start == n->merge_range->end) 861289177Speter err = svn_cmdline_printf(pool, 862289177Speter _("--- Merging (from foreign repository) " 863289177Speter "r%ld into '%s':\n"), 864289177Speter n->merge_range->end, path_local); 865289177Speter else if (n->merge_range->start - 1 == n->merge_range->end) 866289177Speter err = svn_cmdline_printf(pool, 867289177Speter _("--- Reverse-merging (from foreign " 868289177Speter "repository) r%ld into '%s':\n"), 869289177Speter n->merge_range->start, path_local); 870289177Speter else if (n->merge_range->start < n->merge_range->end) 871289177Speter err = svn_cmdline_printf(pool, 872289177Speter _("--- Merging (from foreign repository) " 873289177Speter "r%ld through r%ld into '%s':\n"), 874289177Speter n->merge_range->start + 1, 875289177Speter n->merge_range->end, path_local); 876289177Speter else /* n->merge_range->start > n->merge_range->end - 1 */ 877289177Speter err = svn_cmdline_printf(pool, 878289177Speter _("--- Reverse-merging (from foreign " 879289177Speter "repository) r%ld through r%ld into " 880289177Speter "'%s':\n"), 881289177Speter n->merge_range->start, 882289177Speter n->merge_range->end + 1, path_local); 883289177Speter if (err) 884289177Speter goto print_error; 885289177Speter break; 886289177Speter 887289177Speter case svn_wc_notify_tree_conflict: 888289177Speter nb->tree_conflicts++; 889289177Speter add_conflicted_path(nb, n->path); 890289177Speter if ((err = svn_cmdline_printf(pool, " C %s\n", path_local))) 891289177Speter goto print_error; 892289177Speter break; 893289177Speter 894289177Speter case svn_wc_notify_update_shadowed_add: 895289177Speter nb->received_some_change = TRUE; 896289177Speter if ((err = svn_cmdline_printf(pool, " A %s\n", path_local))) 897289177Speter goto print_error; 898289177Speter break; 899289177Speter 900289177Speter case svn_wc_notify_update_shadowed_update: 901289177Speter nb->received_some_change = TRUE; 902289177Speter if ((err = svn_cmdline_printf(pool, " U %s\n", path_local))) 903289177Speter goto print_error; 904289177Speter break; 905289177Speter 906289177Speter case svn_wc_notify_update_shadowed_delete: 907289177Speter nb->received_some_change = TRUE; 908289177Speter if ((err = svn_cmdline_printf(pool, " D %s\n", path_local))) 909289177Speter goto print_error; 910289177Speter break; 911289177Speter 912289177Speter case svn_wc_notify_property_modified: 913289177Speter case svn_wc_notify_property_added: 914289177Speter err = svn_cmdline_printf(pool, 915289177Speter _("property '%s' set on '%s'\n"), 916289177Speter n->prop_name, path_local); 917289177Speter if (err) 918289177Speter goto print_error; 919289177Speter break; 920289177Speter 921289177Speter case svn_wc_notify_property_deleted: 922289177Speter err = svn_cmdline_printf(pool, 923289177Speter _("property '%s' deleted from '%s'.\n"), 924289177Speter n->prop_name, path_local); 925289177Speter if (err) 926289177Speter goto print_error; 927289177Speter break; 928289177Speter 929289177Speter case svn_wc_notify_property_deleted_nonexistent: 930289177Speter err = svn_cmdline_printf(pool, 931289177Speter _("Attempting to delete nonexistent " 932289177Speter "property '%s' on '%s'\n"), n->prop_name, 933289177Speter path_local); 934289177Speter if (err) 935289177Speter goto print_error; 936289177Speter break; 937289177Speter 938289177Speter case svn_wc_notify_revprop_set: 939289177Speter err = svn_cmdline_printf(pool, 940289177Speter _("property '%s' set on repository revision %ld\n"), 941289177Speter n->prop_name, n->revision); 942289177Speter if (err) 943289177Speter goto print_error; 944289177Speter break; 945289177Speter 946289177Speter case svn_wc_notify_revprop_deleted: 947289177Speter err = svn_cmdline_printf(pool, 948289177Speter _("property '%s' deleted from repository revision %ld\n"), 949289177Speter n->prop_name, n->revision); 950289177Speter if (err) 951289177Speter goto print_error; 952289177Speter break; 953289177Speter 954289177Speter case svn_wc_notify_upgraded_path: 955289177Speter err = svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local); 956289177Speter if (err) 957289177Speter goto print_error; 958289177Speter break; 959289177Speter 960289177Speter case svn_wc_notify_url_redirect: 961289177Speter err = svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"), 962289177Speter n->url); 963289177Speter if (err) 964289177Speter goto print_error; 965289177Speter break; 966289177Speter 967289177Speter case svn_wc_notify_path_nonexistent: 968289177Speter err = svn_cmdline_printf(pool, _("'%s' is not under version control"), 969289177Speter path_local); 970289177Speter if (err) 971289177Speter goto print_error; 972289177Speter break; 973289177Speter 974289177Speter case svn_wc_notify_conflict_resolver_starting: 975289177Speter /* Once all operations invoke the interactive conflict resolution after 976289177Speter * they've completed, we can run svn_cl__print_conflict_stats() here. */ 977289177Speter break; 978289177Speter 979289177Speter case svn_wc_notify_conflict_resolver_done: 980289177Speter break; 981289177Speter 982289177Speter default: 983289177Speter break; 984289177Speter } 985289177Speter 986289177Speter if ((err = svn_cmdline_fflush(stdout))) 987289177Speter goto print_error; 988289177Speter 989289177Speter return; 990289177Speter 991289177Speter print_error: 992289177Speter /* If we had no errors before, print this error to stderr. Else, don't print 993289177Speter anything. The user already knows there were some output errors, 994289177Speter so there is no point in flooding her with an error per notification. */ 995289177Speter if (!nb->had_print_error) 996289177Speter { 997289177Speter nb->had_print_error = TRUE; 998289177Speter /* Issue #3014: 999289177Speter * Don't print anything on broken pipes. The pipe was likely 1000289177Speter * closed by the process at the other end. We expect that 1001289177Speter * process to perform error reporting as necessary. 1002289177Speter * 1003289177Speter * ### This assumes that there is only one error in a chain for 1004289177Speter * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */ 1005289177Speter if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR) 1006289177Speter svn_handle_error2(err, stderr, FALSE, "svn: "); 1007289177Speter } 1008289177Speter svn_error_clear(err); 1009289177Speter} 1010289177Speter 1011289177Speter 1012289177Spetersvn_error_t * 1013289177Spetersvn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p, 1014289177Speter void **notify_baton_p, 1015289177Speter apr_pool_t *pool) 1016289177Speter{ 1017289177Speter struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb)); 1018289177Speter 1019289177Speter nb->received_some_change = FALSE; 1020289177Speter nb->sent_first_txdelta = FALSE; 1021289177Speter nb->is_checkout = FALSE; 1022289177Speter nb->is_export = FALSE; 1023289177Speter nb->is_wc_to_repos_copy = FALSE; 1024289177Speter nb->in_external = FALSE; 1025289177Speter nb->had_print_error = FALSE; 1026289177Speter nb->text_conflicts = 0; 1027289177Speter nb->prop_conflicts = 0; 1028289177Speter nb->tree_conflicts = 0; 1029289177Speter nb->skipped_paths = 0; 1030289177Speter nb->conflicted_paths = apr_hash_make(pool); 1031289177Speter SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool)); 1032289177Speter 1033289177Speter *notify_func_p = notify; 1034289177Speter *notify_baton_p = nb; 1035289177Speter return SVN_NO_ERROR; 1036289177Speter} 1037289177Speter 1038289177Spetersvn_error_t * 1039289177Spetersvn_cl__notifier_mark_export(void *baton) 1040289177Speter{ 1041289177Speter struct notify_baton *nb = baton; 1042289177Speter 1043289177Speter nb->is_export = TRUE; 1044289177Speter return SVN_NO_ERROR; 1045289177Speter} 1046