#define APR_WANT_STDIO
#define APR_WANT_STRFUNC
#include <apr_want.h>
#include "svn_cmdline.h"
#include "svn_pools.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_sorts.h"
#include "svn_hash.h"
#include "cl.h"
#include "private/svn_subr_private.h"
#include "private/svn_dep_compat.h"
#include "svn_private_config.h"
struct notify_baton
{
svn_boolean_t received_some_change;
svn_boolean_t is_checkout;
svn_boolean_t is_export;
svn_boolean_t is_wc_to_repos_copy;
svn_boolean_t sent_first_txdelta;
int in_external;
svn_boolean_t had_print_error;
svn_cl__conflict_stats_t *conflict_stats;
const char *path_prefix;
};
struct svn_cl__conflict_stats_t
{
apr_pool_t *stats_pool;
apr_hash_t *text_conflicts, *prop_conflicts, *tree_conflicts;
int text_conflicts_resolved, prop_conflicts_resolved, tree_conflicts_resolved;
int skipped_paths;
};
svn_cl__conflict_stats_t *
svn_cl__conflict_stats_create(apr_pool_t *pool)
{
svn_cl__conflict_stats_t *conflict_stats
= apr_palloc(pool, sizeof(*conflict_stats));
conflict_stats->stats_pool = pool;
conflict_stats->text_conflicts = apr_hash_make(pool);
conflict_stats->prop_conflicts = apr_hash_make(pool);
conflict_stats->tree_conflicts = apr_hash_make(pool);
conflict_stats->text_conflicts_resolved = 0;
conflict_stats->prop_conflicts_resolved = 0;
conflict_stats->tree_conflicts_resolved = 0;
conflict_stats->skipped_paths = 0;
return conflict_stats;
}
static void
store_path(struct notify_baton *nb, apr_hash_t *hash, const char *path)
{
svn_hash_sets(hash, apr_pstrdup(nb->conflict_stats->stats_pool, path), "");
}
void
svn_cl__conflict_stats_resolved(svn_cl__conflict_stats_t *conflict_stats,
const char *path_local,
svn_wc_conflict_kind_t conflict_kind)
{
switch (conflict_kind)
{
case svn_wc_conflict_kind_text:
if (svn_hash_gets(conflict_stats->text_conflicts, path_local))
{
svn_hash_sets(conflict_stats->text_conflicts, path_local, NULL);
conflict_stats->text_conflicts_resolved++;
}
break;
case svn_wc_conflict_kind_property:
if (svn_hash_gets(conflict_stats->prop_conflicts, path_local))
{
svn_hash_sets(conflict_stats->prop_conflicts, path_local, NULL);
conflict_stats->prop_conflicts_resolved++;
}
break;
case svn_wc_conflict_kind_tree:
if (svn_hash_gets(conflict_stats->tree_conflicts, path_local))
{
svn_hash_sets(conflict_stats->tree_conflicts, path_local, NULL);
conflict_stats->tree_conflicts_resolved++;
}
break;
}
}
static const char *
remaining_str(apr_pool_t *pool, int n_remaining)
{
return apr_psprintf(pool, Q_("%d remaining",
"%d remaining",
n_remaining),
n_remaining);
}
static const char *
resolved_str(apr_pool_t *pool, int n_resolved)
{
return apr_psprintf(pool, Q_("and %d already resolved",
"and %d already resolved",
n_resolved),
n_resolved);
}
svn_error_t *
svn_cl__print_conflict_stats(svn_cl__conflict_stats_t *conflict_stats,
apr_pool_t *scratch_pool)
{
int n_text = apr_hash_count(conflict_stats->text_conflicts);
int n_prop = apr_hash_count(conflict_stats->prop_conflicts);
int n_tree = apr_hash_count(conflict_stats->tree_conflicts);
int n_text_r = conflict_stats->text_conflicts_resolved;
int n_prop_r = conflict_stats->prop_conflicts_resolved;
int n_tree_r = conflict_stats->tree_conflicts_resolved;
if (n_text > 0 || n_text_r > 0
|| n_prop > 0 || n_prop_r > 0
|| n_tree > 0 || n_tree_r > 0
|| conflict_stats->skipped_paths > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_("Summary of conflicts:\n")));
if (n_text_r == 0 && n_prop_r == 0 && n_tree_r == 0)
{
if (n_text > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Text conflicts: %d\n"),
n_text));
if (n_prop > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Property conflicts: %d\n"),
n_prop));
if (n_tree > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Tree conflicts: %d\n"),
n_tree));
}
else
{
if (n_text > 0 || n_text_r > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Text conflicts: %s (%s)\n"),
remaining_str(scratch_pool, n_text),
resolved_str(scratch_pool, n_text_r)));
if (n_prop > 0 || n_prop_r > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Property conflicts: %s (%s)\n"),
remaining_str(scratch_pool, n_prop),
resolved_str(scratch_pool, n_prop_r)));
if (n_tree > 0 || n_tree_r > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Tree conflicts: %s (%s)\n"),
remaining_str(scratch_pool, n_tree),
resolved_str(scratch_pool, n_tree_r)));
}
if (conflict_stats->skipped_paths > 0)
SVN_ERR(svn_cmdline_printf(scratch_pool,
_(" Skipped paths: %d\n"),
conflict_stats->skipped_paths));
return SVN_NO_ERROR;
}
svn_error_t *
svn_cl__notifier_print_conflict_stats(void *baton, apr_pool_t *scratch_pool)
{
struct notify_baton *nb = baton;
SVN_ERR(svn_cl__print_conflict_stats(nb->conflict_stats, scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
notify_body(struct notify_baton *nb,
const svn_wc_notify_t *n,
apr_pool_t *pool)
{
char statchar_buf[5] = " ";
const char *path_local;
if (n->url)
path_local = n->url;
else
{
if (n->path_prefix)
path_local = svn_cl__local_style_skip_ancestor(n->path_prefix, n->path,
pool);
else
path_local = svn_cl__local_style_skip_ancestor(nb->path_prefix, n->path,
pool);
}
switch (n->action)
{
case svn_wc_notify_skip:
nb->conflict_stats->skipped_paths++;
if (n->content_state == svn_wc_notify_state_missing)
{
SVN_ERR(svn_cmdline_printf(pool,
_("Skipped missing target: '%s'\n"),
path_local));
}
else if (n->content_state == svn_wc_notify_state_source_missing)
{
SVN_ERR(svn_cmdline_printf(
pool,
_("Skipped target: '%s' -- copy-source is missing\n"),
path_local));
}
else
{
SVN_ERR(svn_cmdline_printf(pool, _("Skipped '%s'\n"), path_local));
}
break;
case svn_wc_notify_update_skip_obstruction:
nb->conflict_stats->skipped_paths++;
SVN_ERR(svn_cmdline_printf(
pool,
_("Skipped '%s' -- An obstructing working copy was found\n"),
path_local));
break;
case svn_wc_notify_update_skip_working_only:
nb->conflict_stats->skipped_paths++;
SVN_ERR(svn_cmdline_printf(
pool, _("Skipped '%s' -- Has no versioned parent\n"),
path_local));
break;
case svn_wc_notify_update_skip_access_denied:
nb->conflict_stats->skipped_paths++;
SVN_ERR(svn_cmdline_printf(
pool, _("Skipped '%s' -- Access denied\n"),
path_local));
break;
case svn_wc_notify_skip_conflicted:
nb->conflict_stats->skipped_paths++;
SVN_ERR(svn_cmdline_printf(
pool, _("Skipped '%s' -- Node remains in conflict\n"),
path_local));
break;
case svn_wc_notify_update_delete:
case svn_wc_notify_exclude:
nb->received_some_change = TRUE;
SVN_ERR(svn_cmdline_printf(pool, "D %s\n", path_local));
break;
case svn_wc_notify_update_broken_lock:
SVN_ERR(svn_cmdline_printf(pool, "B %s\n", path_local));
break;
case svn_wc_notify_update_external_removed:
nb->received_some_change = TRUE;
if (n->err && n->err->message)
{
SVN_ERR(svn_cmdline_printf(pool, _("Removed external '%s': %s\n"),
path_local, n->err->message));
}
else
{
SVN_ERR(svn_cmdline_printf(pool, _("Removed external '%s'\n"),
path_local));
}
break;
case svn_wc_notify_left_local_modifications:
SVN_ERR(svn_cmdline_printf(pool, _("Left local modifications as '%s'\n"),
path_local));
break;
case svn_wc_notify_update_replace:
nb->received_some_change = TRUE;
SVN_ERR(svn_cmdline_printf(pool, "R %s\n", path_local));
break;
case svn_wc_notify_update_add:
nb->received_some_change = TRUE;
if (n->content_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->text_conflicts, path_local);
SVN_ERR(svn_cmdline_printf(pool, "C %s\n", path_local));
}
else
{
SVN_ERR(svn_cmdline_printf(pool, "A %s\n", path_local));
}
break;
case svn_wc_notify_exists:
nb->received_some_change = TRUE;
if (n->content_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->text_conflicts, path_local);
statchar_buf[0] = 'C';
}
else
statchar_buf[0] = 'E';
if (n->prop_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
statchar_buf[1] = 'C';
}
else if (n->prop_state == svn_wc_notify_state_merged)
statchar_buf[1] = 'G';
SVN_ERR(svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local));
break;
case svn_wc_notify_restore:
SVN_ERR(svn_cmdline_printf(pool, _("Restored '%s'\n"),
path_local));
break;
case svn_wc_notify_revert:
SVN_ERR(svn_cmdline_printf(pool, _("Reverted '%s'\n"),
path_local));
break;
case svn_wc_notify_failed_revert:
SVN_ERR(svn_cmdline_printf(pool, _("Failed to revert '%s' -- "
"try updating instead.\n"),
path_local));
break;
case svn_wc_notify_resolved:
SVN_ERR(svn_cmdline_printf(pool,
_("Resolved conflicted state of '%s'\n"),
path_local));
break;
case svn_wc_notify_add:
if (n->mime_type && (svn_mime_type_is_binary(n->mime_type)))
{
SVN_ERR(svn_cmdline_printf(pool, "A (bin) %s\n",
path_local));
}
else
{
SVN_ERR(svn_cmdline_printf(pool, "A %s\n",
path_local));
}
break;
case svn_wc_notify_delete:
nb->received_some_change = TRUE;
SVN_ERR(svn_cmdline_printf(pool, "D %s\n",
path_local));
break;
case svn_wc_notify_patch:
{
nb->received_some_change = TRUE;
if (n->content_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->text_conflicts, path_local);
statchar_buf[0] = 'C';
}
else if (n->kind == svn_node_file)
{
if (n->content_state == svn_wc_notify_state_merged)
statchar_buf[0] = 'G';
else if (n->content_state == svn_wc_notify_state_changed)
statchar_buf[0] = 'U';
}
if (n->prop_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
statchar_buf[1] = 'C';
}
else if (n->prop_state == svn_wc_notify_state_changed)
statchar_buf[1] = 'U';
if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
{
SVN_ERR(svn_cmdline_printf(pool, "%s %s\n",
statchar_buf, path_local));
}
}
break;
case svn_wc_notify_patch_applied_hunk:
nb->received_some_change = TRUE;
if (n->hunk_original_start != n->hunk_matched_line)
{
apr_uint64_t off;
const char *s;
const char *minus;
if (n->hunk_matched_line > n->hunk_original_start)
{
if (n->hunk_original_start == 0 && n->hunk_matched_line == 1)
off = 0;
else
off = n->hunk_matched_line - n->hunk_original_start;
minus = "";
}
else
{
off = n->hunk_original_start - n->hunk_matched_line;
minus = "-";
}
if (n->hunk_fuzz)
{
if (n->prop_name)
{
s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## "
"with offset %s");
SVN_ERR(svn_cmdline_printf(pool,
apr_pstrcat(pool, s,
"%"APR_UINT64_T_FMT
" and fuzz %lu (%s)\n",
SVN_VA_NULL),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
minus, off, n->hunk_fuzz,
n->prop_name));
}
else
{
s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ "
"with offset %s");
SVN_ERR(svn_cmdline_printf(pool,
apr_pstrcat(pool, s,
"%"APR_UINT64_T_FMT
" and fuzz %lu\n",
SVN_VA_NULL),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
minus, off, n->hunk_fuzz));
}
}
else
{
if (n->prop_name)
{
s = _("> applied hunk ## -%lu,%lu +%lu,%lu ## "
"with offset %s");
SVN_ERR(svn_cmdline_printf(pool,
apr_pstrcat(pool, s,
"%"APR_UINT64_T_FMT" (%s)\n",
SVN_VA_NULL),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
minus, off, n->prop_name));
}
else
{
s = _("> applied hunk @@ -%lu,%lu +%lu,%lu @@ "
"with offset %s");
SVN_ERR(svn_cmdline_printf(pool,
apr_pstrcat(pool, s,
"%"APR_UINT64_T_FMT"\n",
SVN_VA_NULL),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
minus, off));
}
}
}
else if (n->hunk_fuzz)
{
if (n->prop_name)
SVN_ERR(svn_cmdline_printf(pool,
_("> applied hunk ## -%lu,%lu +%lu,%lu ## "
"with fuzz %lu (%s)\n"),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
n->hunk_fuzz,
n->prop_name));
else
SVN_ERR(svn_cmdline_printf(pool,
_("> applied hunk @@ -%lu,%lu +%lu,%lu @@ "
"with fuzz %lu\n"),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
n->hunk_fuzz));
}
break;
case svn_wc_notify_patch_rejected_hunk:
nb->received_some_change = TRUE;
if (n->prop_name)
SVN_ERR(svn_cmdline_printf(pool,
_("> rejected hunk "
"## -%lu,%lu +%lu,%lu ## (%s)\n"),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
n->prop_name));
else
SVN_ERR(svn_cmdline_printf(pool,
_("> rejected hunk "
"@@ -%lu,%lu +%lu,%lu @@\n"),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length));
break;
case svn_wc_notify_patch_hunk_already_applied:
nb->received_some_change = TRUE;
if (n->prop_name)
SVN_ERR(svn_cmdline_printf(pool,
_("> hunk "
"## -%lu,%lu +%lu,%lu ## "
"already applied (%s)\n"),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length,
n->prop_name));
else
SVN_ERR(svn_cmdline_printf(pool,
_("> hunk "
"@@ -%lu,%lu +%lu,%lu @@ "
"already applied\n"),
n->hunk_original_start,
n->hunk_original_length,
n->hunk_modified_start,
n->hunk_modified_length));
break;
case svn_wc_notify_update_update:
case svn_wc_notify_merge_record_info:
{
if (n->content_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->text_conflicts, path_local);
statchar_buf[0] = 'C';
}
else if (n->kind == svn_node_file)
{
if (n->content_state == svn_wc_notify_state_merged)
statchar_buf[0] = 'G';
else if (n->content_state == svn_wc_notify_state_changed)
statchar_buf[0] = 'U';
}
if (n->prop_state == svn_wc_notify_state_conflicted)
{
store_path(nb, nb->conflict_stats->prop_conflicts, path_local);
statchar_buf[1] = 'C';
}
else if (n->prop_state == svn_wc_notify_state_merged)
statchar_buf[1] = 'G';
else if (n->prop_state == svn_wc_notify_state_changed)
statchar_buf[1] = 'U';
if (n->lock_state == svn_wc_notify_lock_state_unlocked)
statchar_buf[2] = 'B';
if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
nb->received_some_change = TRUE;
if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
|| statchar_buf[2] != ' ')
{
SVN_ERR(svn_cmdline_printf(pool, "%s %s\n",
statchar_buf, path_local));
}
}
break;
case svn_wc_notify_update_external:
++nb->in_external;
SVN_ERR(svn_cmdline_printf(pool,
_("\nFetching external item into '%s':\n"),
path_local));
break;
case svn_wc_notify_failed_external:
if (nb->in_external)
{
svn_handle_warning2(stderr, n->err, "svn: ");
--nb->in_external;
SVN_ERR(svn_cmdline_printf(pool, "\n"));
}
else
{
svn_error_t *warn_err =
svn_error_createf(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL,
_("Error handling externals definition for '%s':"),
path_local);
svn_handle_warning2(stderr, warn_err, "svn: ");
svn_error_clear(warn_err);
svn_handle_warning2(stderr, n->err, "svn: ");
}
break;
case svn_wc_notify_update_started:
if (! (nb->in_external ||
nb->is_checkout ||
nb->is_export))
{
SVN_ERR(svn_cmdline_printf(pool, _("Updating '%s':\n"),
path_local));
}
break;
case svn_wc_notify_update_completed:
{
if (SVN_IS_VALID_REVNUM(n->revision))
{
if (nb->is_export)
{
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("Exported external at revision %ld.\n")
: _("Exported revision %ld.\n"),
n->revision));
}
else if (nb->is_checkout)
{
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("Checked out external at revision %ld.\n")
: _("Checked out revision %ld.\n"),
n->revision));
}
else
{
if (nb->received_some_change)
{
nb->received_some_change = FALSE;
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("Updated external to revision %ld.\n")
: _("Updated to revision %ld.\n"),
n->revision));
}
else
{
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("External at revision %ld.\n")
: _("At revision %ld.\n"),
n->revision));
}
}
}
else
{
if (nb->is_export)
{
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("External export complete.\n")
: _("Export complete.\n")));
}
else if (nb->is_checkout)
{
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("External checkout complete.\n")
: _("Checkout complete.\n")));
}
else
{
SVN_ERR(svn_cmdline_printf(
pool, nb->in_external
? _("External update complete.\n")
: _("Update complete.\n")));
}
}
}
if (nb->in_external)
{
--nb->in_external;
SVN_ERR(svn_cmdline_printf(pool, "\n"));
}
break;
case svn_wc_notify_status_external:
SVN_ERR(svn_cmdline_printf(
pool, _("\nPerforming status on external item at '%s':\n"),
path_local));
break;
case svn_wc_notify_info_external:
SVN_ERR(svn_cmdline_printf(
pool, _("\nPerforming info on external item at '%s':\n"),
path_local));
break;
case svn_wc_notify_status_completed:
if (SVN_IS_VALID_REVNUM(n->revision))
SVN_ERR(svn_cmdline_printf(pool,
_("Status against revision: %6ld\n"),
n->revision));
break;
case svn_wc_notify_commit_modified:
SVN_ERR(svn_cmdline_printf(pool,
nb->is_wc_to_repos_copy
? _("Sending copy of %s\n")
: _("Sending %s\n"),
path_local));
break;
case svn_wc_notify_commit_added:
case svn_wc_notify_commit_copied:
if (n->mime_type && svn_mime_type_is_binary(n->mime_type))
{
SVN_ERR(svn_cmdline_printf(pool,
nb->is_wc_to_repos_copy
? _("Adding copy of (bin) %s\n")
: _("Adding (bin) %s\n"),
path_local));
}
else
{
SVN_ERR(svn_cmdline_printf(pool,
nb->is_wc_to_repos_copy
? _("Adding copy of %s\n")
: _("Adding %s\n"),
path_local));
}
break;
case svn_wc_notify_commit_deleted:
SVN_ERR(svn_cmdline_printf(pool,
nb->is_wc_to_repos_copy
? _("Deleting copy of %s\n")
: _("Deleting %s\n"),
path_local));
break;
case svn_wc_notify_commit_replaced:
case svn_wc_notify_commit_copied_replaced:
SVN_ERR(svn_cmdline_printf(pool,
nb->is_wc_to_repos_copy
? _("Replacing copy of %s\n")
: _("Replacing %s\n"),
path_local));
break;
case svn_wc_notify_commit_postfix_txdelta:
if (! nb->sent_first_txdelta)
{
nb->sent_first_txdelta = TRUE;
SVN_ERR(svn_cmdline_printf(pool,
_("Transmitting file data ")));
}
SVN_ERR(svn_cmdline_printf(pool, "."));
break;
case svn_wc_notify_locked:
SVN_ERR(svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"),
path_local, n->lock->owner));
break;
case svn_wc_notify_unlocked:
SVN_ERR(svn_cmdline_printf(pool, _("'%s' unlocked.\n"),
path_local));
break;
case svn_wc_notify_failed_lock:
case svn_wc_notify_failed_unlock:
svn_handle_warning2(stderr, n->err, "svn: ");
break;
case svn_wc_notify_changelist_set:
SVN_ERR(svn_cmdline_printf(pool, "A [%s] %s\n",
n->changelist_name, path_local));
break;
case svn_wc_notify_changelist_clear:
case svn_wc_notify_changelist_moved:
SVN_ERR(svn_cmdline_printf(pool,
"D [%s] %s\n",
n->changelist_name, path_local));
break;
case svn_wc_notify_merge_begin:
if (n->merge_range == NULL)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Merging differences between "
"repository URLs into '%s':\n"),
path_local));
else if (n->merge_range->start == n->merge_range->end - 1
|| n->merge_range->start == n->merge_range->end)
SVN_ERR(svn_cmdline_printf(pool, _("--- Merging r%ld into '%s':\n"),
n->merge_range->end, path_local));
else if (n->merge_range->start - 1 == n->merge_range->end)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Reverse-merging r%ld into '%s':\n"),
n->merge_range->start, path_local));
else if (n->merge_range->start < n->merge_range->end)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Merging r%ld through r%ld into "
"'%s':\n"),
n->merge_range->start + 1,
n->merge_range->end, path_local));
else
SVN_ERR(svn_cmdline_printf(pool,
_("--- Reverse-merging r%ld through r%ld "
"into '%s':\n"),
n->merge_range->start,
n->merge_range->end + 1, path_local));
break;
case svn_wc_notify_merge_record_info_begin:
if (!n->merge_range)
{
SVN_ERR(svn_cmdline_printf(pool,
_("--- Recording mergeinfo for merge "
"between repository URLs into '%s':\n"),
path_local));
}
else
{
if (n->merge_range->start == n->merge_range->end - 1
|| n->merge_range->start == n->merge_range->end)
SVN_ERR(svn_cmdline_printf(
pool,
_("--- Recording mergeinfo for merge of r%ld into '%s':\n"),
n->merge_range->end, path_local));
else if (n->merge_range->start - 1 == n->merge_range->end)
SVN_ERR(svn_cmdline_printf(
pool,
_("--- Recording mergeinfo for reverse merge of r%ld into '%s':\n"),
n->merge_range->start, path_local));
else if (n->merge_range->start < n->merge_range->end)
SVN_ERR(svn_cmdline_printf(
pool,
_("--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n"),
n->merge_range->start + 1, n->merge_range->end, path_local));
else
SVN_ERR(svn_cmdline_printf(
pool,
_("--- Recording mergeinfo for reverse merge of r%ld through r%ld into '%s':\n"),
n->merge_range->start, n->merge_range->end + 1, path_local));
}
break;
case svn_wc_notify_merge_elide_info:
SVN_ERR(svn_cmdline_printf(pool,
_("--- Eliding mergeinfo from '%s':\n"),
path_local));
break;
case svn_wc_notify_foreign_merge_begin:
if (n->merge_range == NULL)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Merging differences between "
"foreign repository URLs into '%s':\n"),
path_local));
else if (n->merge_range->start == n->merge_range->end - 1
|| n->merge_range->start == n->merge_range->end)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Merging (from foreign repository) "
"r%ld into '%s':\n"),
n->merge_range->end, path_local));
else if (n->merge_range->start - 1 == n->merge_range->end)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Reverse-merging (from foreign "
"repository) r%ld into '%s':\n"),
n->merge_range->start, path_local));
else if (n->merge_range->start < n->merge_range->end)
SVN_ERR(svn_cmdline_printf(pool,
_("--- Merging (from foreign repository) "
"r%ld through r%ld into '%s':\n"),
n->merge_range->start + 1,
n->merge_range->end, path_local));
else
SVN_ERR(svn_cmdline_printf(pool,
_("--- Reverse-merging (from foreign "
"repository) r%ld through r%ld into "
"'%s':\n"),
n->merge_range->start,
n->merge_range->end + 1, path_local));
break;
case svn_wc_notify_tree_conflict:
store_path(nb, nb->conflict_stats->tree_conflicts, path_local);
SVN_ERR(svn_cmdline_printf(pool, " C %s\n", path_local));
break;
case svn_wc_notify_update_shadowed_add:
nb->received_some_change = TRUE;
SVN_ERR(svn_cmdline_printf(pool, " A %s\n", path_local));
break;
case svn_wc_notify_update_shadowed_update:
nb->received_some_change = TRUE;
SVN_ERR(svn_cmdline_printf(pool, " U %s\n", path_local));
break;
case svn_wc_notify_update_shadowed_delete:
nb->received_some_change = TRUE;
SVN_ERR(svn_cmdline_printf(pool, " D %s\n", path_local));
break;
case svn_wc_notify_property_modified:
case svn_wc_notify_property_added:
SVN_ERR(svn_cmdline_printf(pool,
_("property '%s' set on '%s'\n"),
n->prop_name, path_local));
break;
case svn_wc_notify_property_deleted:
SVN_ERR(svn_cmdline_printf(pool,
_("property '%s' deleted from '%s'.\n"),
n->prop_name, path_local));
break;
case svn_wc_notify_property_deleted_nonexistent:
SVN_ERR(svn_cmdline_printf(pool,
_("Attempting to delete nonexistent "
"property '%s' on '%s'\n"), n->prop_name,
path_local));
break;
case svn_wc_notify_revprop_set:
SVN_ERR(svn_cmdline_printf(pool,
_("property '%s' set on repository revision %ld\n"),
n->prop_name, n->revision));
break;
case svn_wc_notify_revprop_deleted:
SVN_ERR(svn_cmdline_printf(pool,
_("property '%s' deleted from repository revision %ld\n"),
n->prop_name, n->revision));
break;
case svn_wc_notify_upgraded_path:
SVN_ERR(svn_cmdline_printf(pool, _("Upgraded '%s'\n"), path_local));
break;
case svn_wc_notify_url_redirect:
SVN_ERR(svn_cmdline_printf(pool, _("Redirecting to URL '%s':\n"),
n->url));
break;
case svn_wc_notify_path_nonexistent:
SVN_ERR(svn_cmdline_printf(pool, "%s\n",
apr_psprintf(pool, _("'%s' is not under version control"),
path_local)));
break;
case svn_wc_notify_conflict_resolver_starting:
break;
case svn_wc_notify_conflict_resolver_done:
break;
case svn_wc_notify_foreign_copy_begin:
if (n->merge_range == NULL)
{
SVN_ERR(svn_cmdline_printf(
pool,
_("--- Copying from foreign repository URL '%s':\n"),
n->url));
}
break;
case svn_wc_notify_move_broken:
SVN_ERR(svn_cmdline_printf(pool,
_("Breaking move with source path '%s'\n"),
path_local));
break;
case svn_wc_notify_cleanup_external:
SVN_ERR(svn_cmdline_printf
(pool, _("Performing cleanup on external item at '%s'.\n"),
path_local));
break;
case svn_wc_notify_commit_finalizing:
if (nb->sent_first_txdelta)
{
SVN_ERR(svn_cmdline_printf(pool, _("done\n")));
}
SVN_ERR(svn_cmdline_printf(pool, _("Committing transaction...\n")));
break;
default:
break;
}
SVN_ERR(svn_cmdline_fflush(stdout));
return SVN_NO_ERROR;
}
static void
notify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool)
{
struct notify_baton *nb = baton;
svn_error_t *err;
err = notify_body(nb, n, pool);
if (err && !nb->had_print_error)
{
nb->had_print_error = TRUE;
if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
svn_handle_error2(err, stderr, FALSE, "svn: ");
}
svn_error_clear(err);
}
svn_error_t *
svn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p,
void **notify_baton_p,
svn_cl__conflict_stats_t *conflict_stats,
apr_pool_t *pool)
{
struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb));
nb->received_some_change = FALSE;
nb->sent_first_txdelta = FALSE;
nb->is_checkout = FALSE;
nb->is_export = FALSE;
nb->is_wc_to_repos_copy = FALSE;
nb->in_external = 0;
nb->had_print_error = FALSE;
nb->conflict_stats = conflict_stats;
SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool));
*notify_func_p = notify;
*notify_baton_p = nb;
return SVN_NO_ERROR;
}
svn_error_t *
svn_cl__notifier_mark_checkout(void *baton)
{
struct notify_baton *nb = baton;
nb->is_checkout = TRUE;
return SVN_NO_ERROR;
}
svn_error_t *
svn_cl__notifier_mark_export(void *baton)
{
struct notify_baton *nb = baton;
nb->is_export = TRUE;
return SVN_NO_ERROR;
}
svn_error_t *
svn_cl__notifier_mark_wc_to_repos_copy(void *baton)
{
struct notify_baton *nb = baton;
nb->is_wc_to_repos_copy = TRUE;
return SVN_NO_ERROR;
}
void
svn_cl__check_externals_failed_notify_wrapper(void *baton,
const svn_wc_notify_t *n,
apr_pool_t *pool)
{
struct svn_cl__check_externals_failed_notify_baton *nwb = baton;
if (n->action == svn_wc_notify_failed_external)
nwb->had_externals_error = TRUE;
if (nwb->wrapped_func)
nwb->wrapped_func(nwb->wrapped_baton, n, pool);
}