In "svn status", report tree conflict status on each victim individually. (For the time being, we still also report the parent as having tree-conflicted children.) * subversion/svn/status.c (print_status): Print "TT" in the text and property status columns if this is a tree conflict victim. (svn_cl__print_status): Don't skip an item that has no WC entry and a text status of 'none', as it can still be a tree conflict victim. * subversion/tests/cmdline/stat_tests.py (status_with_tree_conflicts): Expect tree-conflict status on the victims, not on the parent. * subversion/tests/cmdline/tree_conflict_tests.py (ensure_status_c_on_parent): Rename. (ensure_no_status_c_on_parent): Rename. (ensure_tree_conflict): Adjust accordingly. Index: subversion/svn/status.c =================================================================== --- subversion/svn/status.c (revision 33183) +++ subversion/svn/status.c (working copy) @@ -90,7 +90,8 @@ print_status(const char *path, const svn_wc_status2_t *status, apr_pool_t *pool) { - enum svn_wc_status_kind text_status = status->text_status; + char text_status_code = generate_status_code(status->text_status); + char prop_status_code = generate_status_code(status->prop_status); /* To signal that a directory contains tree conflicts, we "hijack" * the text status column if it is blank. */ @@ -98,7 +99,18 @@ print_status(const char *path, && (status->entry->kind == svn_node_dir) && (status->text_status == svn_wc_status_normal) && (status->has_tree_conflicted_children)) - text_status = svn_wc_status_conflicted; + text_status_code = generate_status_code(svn_wc_status_conflicted); + + /* To indicate this node is the victim of a tree conflict, we show + 'TT' in the text-conflict and prop-conflict columns, overriding + any other status. */ + if (status->is_tree_conflict_victim) + { + /*SVN_ERR_ASSERT(status->text_status == svn_wc_status_normal);*/ + /*SVN_ERR_ASSERT(status->prop_status == svn_wc_status_normal);*/ + text_status_code = 'T'; + prop_status_code = 'T'; + } if (detailed) { @@ -165,8 +177,8 @@ print_status(const char *path, SVN_ERR (svn_cmdline_printf(pool, "%c%c%c%c%c%c %c %6s %6s %-12s %s\n", - generate_status_code(text_status), - generate_status_code(status->prop_status), + text_status_code, + prop_status_code, status->locked ? 'L' : ' ', status->copied ? '+' : ' ', status->switched ? 'S' : ' ', @@ -180,8 +192,8 @@ print_status(const char *path, else SVN_ERR (svn_cmdline_printf(pool, "%c%c%c%c%c%c %c %6s %s\n", - generate_status_code(text_status), - generate_status_code(status->prop_status), + text_status_code, + prop_status_code, status->locked ? 'L' : ' ', status->copied ? '+' : ' ', status->switched ? 'S' : ' ', @@ -193,8 +205,8 @@ print_status(const char *path, else SVN_ERR (svn_cmdline_printf(pool, "%c%c%c%c%c%c %s\n", - generate_status_code(text_status), - generate_status_code(status->prop_status), + text_status_code, + prop_status_code, status->locked ? 'L' : ' ', status->copied ? '+' : ' ', status->switched ? 'S' : ' ', @@ -235,7 +247,7 @@ svn_cl__print_status_xml(const char *pat if (status->entry && ! status->entry->copied) apr_hash_set(att_hash, "revision", APR_HASH_KEY_STRING, apr_psprintf(pool, "%ld", status->entry->revision)); - if (status->has_tree_conflicted_children) + if (status->is_tree_conflict_victim) apr_hash_set(att_hash, "has-tree-conflicted-children", APR_HASH_KEY_STRING, "true"); svn_xml_make_open_tag_hash(&sb, pool, svn_xml_normal, "wc-status", @@ -334,9 +346,8 @@ svn_cl__print_status(const char *path, apr_pool_t *pool) { if (! status - || (skip_unrecognized && ! status->entry) - || (status->text_status == svn_wc_status_none - && status->repos_text_status == svn_wc_status_none)) + || (skip_unrecognized && ! status->entry + && ! status->is_tree_conflict_victim)) return SVN_NO_ERROR; return print_status(svn_path_local_style(path, pool), Index: subversion/tests/cmdline/stat_tests.py =================================================================== --- subversion/tests/cmdline/stat_tests.py (revision 33183) +++ subversion/tests/cmdline/stat_tests.py (working copy) @@ -1513,40 +1513,40 @@ def status_dash_u_type_change(sbox): #---------------------------------------------------------------------- def status_with_tree_conflicts(sbox): - "status with tree conflicts" - + "status with tree conflicts" + # Status messages reflecting tree conflict status. - # These tests correspond to use cases 1-3 in - # notes/tree-conflicts/use-cases.txt. + # These tests correspond to use cases 1-3 in + # notes/tree-conflicts/use-cases.txt, which are conflicts raised by + # 'svn update' on files. svntest.actions.build_greek_tree_conflicts(sbox) wc_dir = sbox.wc_dir G = os.path.join(wc_dir, 'A', 'D', 'G') + # The files in conflict are pi, rho and tau. pi = os.path.join(G, 'pi') rho = os.path.join(G, 'rho') + tau = os.path.join(G, 'tau') - # check status of G expected = svntest.verify.UnorderedOutput( ["C %s\n" % G, - "D %s\n" % pi, - "? %s\n" % rho, + "TT %s\n" % pi, + "TT %s\n" % rho, + "TT %s\n" % tau, ]) - svntest.actions.run_and_verify_svn(None, - expected, - [], + svntest.actions.run_and_verify_svn(None, expected, [], "status", G) - # check status of G, with -v + # check status with -v expected = svntest.verify.UnorderedOutput( ["C 2 2 jrandom %s\n" % G, - "D 2 2 jrandom %s\n" % pi, - "? %s\n" % rho, + "TT 2 2 jrandom %s\n" % pi, + "TT %s\n" % rho, + "TT %s\n" % tau, ]) - svntest.actions.run_and_verify_svn(None, - expected, - [], + svntest.actions.run_and_verify_svn(None, expected, [], "status", "-v", G) # check status of G, with -xml Index: subversion/tests/cmdline/tree_conflict_tests.py =================================================================== --- subversion/tests/cmdline/tree_conflict_tests.py (revision 33183) +++ subversion/tests/cmdline/tree_conflict_tests.py (working copy) @@ -343,16 +343,23 @@ def ensure_status_c_on_parent(parent): expected_stdout = svntest.verify.RegexOutput("^C.* " + re.escape(parent) + "$", match_all=False) - run_and_verify_svn(None, expected_stdout, [], - 'status', parent) + run_and_verify_svn(None, expected_stdout, [], 'status', parent) + +# Ensure "svn status" on path PARENT shows a tree conflict on a child of it. +def ensure_tree_conflict_on_child_of(parent): + expected_stdout = svntest.verify.RegexOutput("^TT.* " + + re.escape(parent + os.sep) + + ".*$", + match_all=False) + run_and_verify_svn(None, expected_stdout, [], 'status', parent) # Ensure "svn status" on path PARENT shows no Conflicts. -def ensure_no_status_c_on_parent(parent): +def ensure_no_conflict_status(parent): exitcode, stdout, stderr = run_and_verify_svn(None, None, [], 'status', parent) for line in stdout: - if line[0] == 'C': # and line.endswith(victim + '\n'): - raise svntest.Failure("unexpected status C") # on path '" + victim + "'") + if line.startswith('C') or line.startswith('TT'): + raise svntest.Failure("unexpected conflict status: " + line) #---------------------------------------------------------------------- @@ -455,6 +462,7 @@ def ensure_tree_conflict(sbox, operation verbose_print("--- Checking that 'status' reports the conflict") ensure_status_c_on_parent(target_path) + ensure_tree_conflict_on_child_of(target_path) verbose_print("--- Resolving the conflict") run_and_verify_svn(None, @@ -462,7 +470,7 @@ def ensure_tree_conflict(sbox, operation 'resolved', target_path) #verbose_print("--- Checking that 'status' does not report a conflict") - #ensure_no_status_c_on_parent(target_path) + #ensure_no_conflict_status(target_path) #verbose_print("--- Committing (should now succeed)") #run_and_verify_svn(None, None, [],