Make "svn status" able to show information about only items in conflict, using a new command-line option "--conflicts". * subversion/svn/cl.h (svn_cl__opt_state_t): Add a new flag "for_conflicts" to represent the new command-line option. (svn_cl__print_status_of_conflict): New function. * subversion/svn/main.c (svn_cl__longopt_t, svn_cl__options): Add a new option "--conflicts". (svn_cl__cmd_table): Add the new option and help text for it to the "status" command. (main): Copy the new option's value into the svn_cl__opt_state_t. * subversion/svn/status.c (conflict_action_letter, conflict_reason_letter, print_status_of_conflict, svn_cl__print_status_of_conflict): New functions. * subversion/svn/status-cmd.c (status_baton): Add a new flag "for_conflicts" to represent the new command-line option. (print_status_normal_or_xml): Change the type of the baton argument to the actual type required. (The callers know it, so it doesn't need to be "void *".) In "for_conflicts" mode, call the new printing function. (print_status): In "for_conflicts" mode, skip non-conflicted items. (svn_cl__status): Pass on the "for_conflicts" flag. Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revision 33777) +++ subversion/svn/cl.h (working copy) @@ -211,6 +211,7 @@ typedef struct svn_cl__opt_state_t svn_boolean_t reintegrate; /* use "reintegrate" merge-source heuristic */ svn_boolean_t trust_server_cert; /* trust server SSL certs that would otherwise be rejected as "untrusted" */ + svn_boolean_t for_conflicts; /* operate on items in conflict */ } svn_cl__opt_state_t; @@ -374,6 +375,14 @@ svn_cl__print_status(const char *path, apr_pool_t *pool); +/* Print STATUS for PATH to stdout for human consumption, showing details + of any conflict. */ +svn_error_t * +svn_cl__print_status_of_conflict(const char *path, + const svn_wc_status2_t *status, + apr_pool_t *pool); + + /* Print STATUS for PATH in XML to stdout. Use POOL for temporary allocations. */ svn_error_t * Index: subversion/svn/main.c =================================================================== --- subversion/svn/main.c (revision 33777) +++ subversion/svn/main.c (working copy) @@ -103,7 +103,8 @@ typedef enum { opt_accept, opt_show_revs, opt_reintegrate, - opt_trust_server_cert + opt_trust_server_cert, + opt_conflicts } svn_cl__longopt_t; /* Option codes and descriptions for the command line client. @@ -272,6 +273,8 @@ const apr_getopt_option_t svn_cl__option "('merged', 'eligible')")}, {"reintegrate", opt_reintegrate, 0, N_("lump-merge all of source URL's unmerged changes")}, + {"conflicts", opt_conflicts, 0, + N_("operate on items in conflict")}, /* Long-opt Aliases * @@ -810,6 +813,8 @@ const svn_opt_subcommand_desc2_t svn_cl_ " With -q, print only summary information about locally modified items.\n" " With -u, add working revision and server out-of-date information.\n" " With -v, print full revision information on every item.\n" + " With --conflicts, print information about items in conflict, in a\n" + " different format.\n" "\n" " The first seven columns in the output are each one character wide:\n" " First column: Says if item was added, deleted, or otherwise changed\n" @@ -880,7 +885,7 @@ const svn_opt_subcommand_desc2_t svn_cl_ " 965 687 joe wc/zig.c\n" " Status against revision: 981\n"), { 'u', 'v', 'N', opt_depth, 'q', opt_no_ignore, opt_incremental, opt_xml, - opt_ignore_externals, opt_changelist} }, + opt_ignore_externals, opt_changelist, opt_conflicts} }, { "switch", svn_cl__switch, {"sw"}, N_ ("Update the working copy to a different URL.\n" @@ -1497,6 +1502,9 @@ main(int argc, const char *argv[]) case opt_reintegrate: opt_state.reintegrate = TRUE; break; + case opt_conflicts: + opt_state.for_conflicts = TRUE; + break; default: /* Hmmm. Perhaps this would be a good place to squirrel away opts that commands like svn diff might need. Hmmm indeed. */ Index: subversion/svn/status.c =================================================================== --- subversion/svn/status.c (revision 33777) +++ subversion/svn/status.c (working copy) @@ -226,6 +226,67 @@ print_status(const char *path, return svn_cmdline_fflush(stdout); } +static char +conflict_action_letter(svn_wc_conflict_action_t action) +{ + switch (action) + { + case svn_wc_conflict_action_edit: + return 'M'; + case svn_wc_conflict_action_add: + return 'A'; + case svn_wc_conflict_action_delete: + return 'D'; + default: + return '?'; + } +} + +static char +conflict_reason_letter(svn_wc_conflict_reason_t reason) +{ + switch (reason) + { + case svn_wc_conflict_reason_edited: + return 'M'; + case svn_wc_conflict_reason_obstructed: + return 'O'; + case svn_wc_conflict_reason_deleted: + return 'D'; + case svn_wc_conflict_reason_added: + return 'A'; + case svn_wc_conflict_reason_missing: + return '!'; + case svn_wc_conflict_reason_unversioned: + return '?'; + default: + return '?'; + } +} + +static svn_error_t * +print_status_of_conflict(const char *path, + const svn_wc_status2_t *status, + apr_pool_t *pool) +{ + char tree_status_code = (status->is_tree_conflict_victim ? 'C' : ' '); + svn_wc_adm_access_t *adm_access; + svn_wc_conflict_description_t *conflict; + + /* Get adm access for path, or maybe for path's parent. */ + SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, path, FALSE, 0, NULL, NULL, pool)); + SVN_ERR(svn_wc_get_tree_conflict(&conflict, path, adm_access, pool)); + + tc_status = apr_psprintf(pool, "(%c>%c)", + conflict_action_letter(conflict->action), + conflict_reason_letter(conflict->reason)); + SVN_ERR(svn_cmdline_printf(pool, "%c%c%c %s %s\n", + generate_status_code(status->text_status), + generate_status_code(status->prop_status), + tree_status_code, tc_status, path)); + + return svn_cmdline_fflush(stdout); +} svn_error_t * svn_cl__print_status_xml(const char *path, @@ -366,3 +427,12 @@ svn_cl__print_status(const char *path, detailed, show_last_committed, repos_locks, status, pool); } + +svn_error_t * +svn_cl__print_status_of_conflict(const char *path, + const svn_wc_status2_t *status, + apr_pool_t *pool) +{ + return print_status_of_conflict(svn_path_local_style(path, pool), status, + pool); +} Index: subversion/svn/status-cmd.c =================================================================== --- subversion/svn/status-cmd.c (revision 33777) +++ subversion/svn/status-cmd.c (working copy) @@ -54,6 +54,7 @@ struct status_baton svn_boolean_t had_print_error; /* To avoid printing lots of errors if we get errors while printing to stdout */ svn_boolean_t xml_mode; + svn_boolean_t for_conflicts; }; @@ -103,16 +104,16 @@ print_finish_target_xml(svn_revnum_t rep /* Function which *actually* causes a status structure to be output to the user. Called by both print_status() and svn_cl__status(). */ -static svn_error_t * -print_status_normal_or_xml(void *baton, +static svn_error_t * +print_status_normal_or_xml(struct status_baton *sb, const char *path, const svn_wc_status2_t *status, apr_pool_t *pool) { - struct status_baton *sb = baton; - if (sb->xml_mode) return svn_cl__print_status_xml(path, status, pool); + else if (sb->for_conflicts) + return svn_cl__print_status_of_conflict(path, status, pool); else return svn_cl__print_status(path, status, sb->detailed, sb->show_last_committed, @@ -157,7 +158,16 @@ print_status(void *baton, return SVN_NO_ERROR; } - return print_status_normal_or_xml(baton, path, status, pool); + /* If we're in "for_conflicts" mode, skip items that are not in conflict. */ + if (sb->for_conflicts) + { + if (! (status->text_status == svn_wc_status_conflicted + || status->prop_status == svn_wc_status_conflicted + || status->is_tree_conflict_victim)) + return SVN_NO_ERROR; + } + + return print_status_normal_or_xml(sb, path, status, pool); } /* This implements the `svn_opt_subcommand_t' interface. */ @@ -215,6 +225,7 @@ svn_cl__status(apr_getopt_t *os, sb.skip_unrecognized = opt_state->quiet; sb.repos_locks = opt_state->update; sb.xml_mode = opt_state->xml; + sb.for_conflicts = opt_state->for_conflicts; sb.cached_changelists = master_cl_hash; sb.cl_pool = pool;