Author: rhuijben
Date: Sun Feb 22 22:05:27 2015
New Revision: 1661570
URL: http://svn.apache.org/r1661570
Log:
Fix a nasty bug in our update editor's tree conflict detection. On an
incoming delete, it reports the local operation as delete if the only
change somewhere in the tree is a delete. This make it take the wrong
decisions on how to handle the tree conflict: it just deletes everything
while it should have made a copy in WORKING.
Only when the root is deleted (or moved), it should be reported as a
local deleted or the conflict resolver will take the wrong strategy.
This will allow implementing automatic move-update logic for quite a
few cases where that appeared impossible before.
* subversion/libsvn_wc/update_editor.c
(check_tree_conflict): Only report the tree as deleted, when it
is deleted.
* subversion/tests/cmdline/switch_tests.py
(tree_conflicts_on_switch_2_2): Update expectations.
* subversion/tests/cmdline/update_tests.py
(tree_conflicts_on_update_2_2): Update expectations.
* subversion/tests/libsvn_wc/op-depth-test.c
(move_away_delete_update,
move_update_parent_replace): Update expected results. These
cases currently expect a broken move.
Modified:
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/tests/cmdline/switch_tests.py
subversion/trunk/subversion/tests/cmdline/update_tests.py
subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1661570&r1=1661569&r2=1661570&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Sun Feb 22 22:05:27
2015
@@ -1554,7 +1554,7 @@ check_tree_conflict(svn_skel_t **pconfli
if (modified)
{
- if (all_mods_are_deletes)
+ if (working_status == svn_wc__db_status_deleted)
reason = svn_wc_conflict_reason_deleted;
else
reason = svn_wc_conflict_reason_edited;
Modified: subversion/trunk/subversion/tests/cmdline/switch_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/switch_tests.py?rev=1661570&r1=1661569&r2=1661570&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/switch_tests.py Sun Feb 22
22:05:27 2015
@@ -2391,12 +2391,12 @@ def tree_conflicts_on_switch_2_2(sbox):
expected_output = deep_trees_conflict_output
expected_disk = svntest.wc.State('', {
+ 'DDF/D1/D2' : Item(),
'F' : Item(),
'D' : Item(),
- 'DF' : Item(),
- 'DD' : Item(),
- 'DDF' : Item(),
- 'DDD' : Item(),
+ 'DF/D1' : Item(),
+ 'DD/D1' : Item(),
+ 'DDD/D1/D2' : Item(),
})
expected_status = svntest.deeptrees.deep_trees_virginal_state.copy()
@@ -2408,20 +2408,16 @@ def tree_conflicts_on_switch_2_2(sbox):
# Expect the incoming tree deletes and the local leaf deletes to mean
# that all deleted paths are *really* gone, not simply scheduled for
# deletion.
- expected_status.tweak('F/alpha',
- 'D/D1',
- 'DD/D1',
- 'DF/D1',
- 'DDD/D1',
- 'DDF/D1',
+ expected_status.tweak('DD/D1', 'DF/D1', 'DDF/D1', 'DDD/D1',
+ status='A ', copied='+', treeconflict='C',
+ wc_rev='-')
+ expected_status.tweak('DDF/D1/D2', 'DDD/D1/D2',
+ copied='+', wc_rev='-')
+ expected_status.tweak('DD/D1/D2', 'DF/D1/beta', 'DDD/D1/D2/D3',
+ 'DDF/D1/D2/gamma',
+ status='D ', copied='+', wc_rev='-')
+ expected_status.tweak('F/alpha', 'D/D1',
status='! ', treeconflict='C', wc_rev=None)
- # Remove from expected status and disk everything below the deleted paths.
- expected_status.remove('DD/D1/D2',
- 'DF/D1/beta',
- 'DDD/D1/D2',
- 'DDD/D1/D2/D3',
- 'DDF/D1/D2',
- 'DDF/D1/D2/gamma',)
expected_info = {
'F/alpha' : {
@@ -2432,13 +2428,13 @@ def tree_conflicts_on_switch_2_2(sbox):
},
'DF/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon switch'
+ '^local dir edit, incoming dir delete or move upon switch'
+ ' Source left: .dir.*/DF/D1@2'
+ ' Source right: .none.*(/DF/D1@3)?$',
},
'DDF/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon switch'
+ '^local dir edit, incoming dir delete or move upon switch'
+ ' Source left: .dir.*/DDF/D1@2'
+ ' Source right: .none.*(/DDF/D1@3)?$',
},
@@ -2450,13 +2446,13 @@ def tree_conflicts_on_switch_2_2(sbox):
},
'DD/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon switch'
+ '^local dir edit, incoming dir delete or move upon switch'
+ ' Source left: .dir.*/DD/D1@2'
+ ' Source right: .none.*(/DD/D1@3)?$',
},
'DDD/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon switch'
+ '^local dir edit, incoming dir delete or move upon switch'
+ ' Source left: .dir.*/DDD/D1@2'
+ ' Source right: .none.*(/DDD/D1@3)?$',
},
Modified: subversion/trunk/subversion/tests/cmdline/update_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/update_tests.py?rev=1661570&r1=1661569&r2=1661570&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/update_tests.py Sun Feb 22
22:05:27 2015
@@ -4386,12 +4386,12 @@ def tree_conflicts_on_update_2_2(sbox):
expected_output = deep_trees_conflict_output
expected_disk = svntest.wc.State('', {
+ 'DDF/D1/D2' : Item(),
'F' : Item(),
'D' : Item(),
- 'DF' : Item(),
- 'DD' : Item(),
- 'DDF' : Item(),
- 'DDD' : Item(),
+ 'DF/D1' : Item(),
+ 'DD/D1' : Item(),
+ 'DDD/D1/D2' : Item(),
})
expected_status = svntest.deeptrees.deep_trees_virginal_state.copy()
@@ -4410,20 +4410,16 @@ def tree_conflicts_on_update_2_2(sbox):
# Expect the incoming tree deletes and the local leaf deletes to mean
# that all deleted paths are *really* gone, not simply scheduled for
# deletion.
- expected_status.tweak('F/alpha',
- 'D/D1',
- 'DD/D1',
- 'DF/D1',
- 'DDD/D1',
- 'DDF/D1',
- status='! ', wc_rev=None)
- # Remove from expected status and disk everything below the deleted paths.
- expected_status.remove('DD/D1/D2',
- 'DF/D1/beta',
- 'DDD/D1/D2',
- 'DDD/D1/D2/D3',
- 'DDF/D1/D2',
- 'DDF/D1/D2/gamma',)
+ expected_status.tweak('DD/D1', 'DF/D1', 'DDF/D1', 'DDD/D1',
+ status='A ', copied='+', treeconflict='C',
+ wc_rev='-')
+ expected_status.tweak('DDF/D1/D2', 'DDD/D1/D2',
+ copied='+', wc_rev='-')
+ expected_status.tweak('DD/D1/D2', 'DF/D1/beta', 'DDD/D1/D2/D3',
+ 'DDF/D1/D2/gamma',
+ status='D ', copied='+', wc_rev='-')
+ expected_status.tweak('F/alpha', 'D/D1',
+ status='! ', treeconflict='C', wc_rev=None)
expected_info = {
'F/alpha' : {
@@ -4434,13 +4430,13 @@ def tree_conflicts_on_update_2_2(sbox):
},
'DF/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon update'
+ '^local dir edit, incoming dir delete or move upon update'
+ ' Source left: .dir.*/DF/D1@2'
+ ' Source right: .none.*(/DF/D1@3)?$',
},
'DDF/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon update'
+ '^local dir edit, incoming dir delete or move upon update'
+ ' Source left: .dir.*/DDF/D1@2'
+ ' Source right: .none.*(/DDF/D1@3)?$',
},
@@ -4452,13 +4448,13 @@ def tree_conflicts_on_update_2_2(sbox):
},
'DD/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon update'
+ '^local dir edit, incoming dir delete or move upon update'
+ ' Source left: .dir.*/DD/D1@2'
+ ' Source right: .none.*(/DD/D1@3)?$',
},
'DDD/D1' : {
'Tree conflict' :
- '^local dir delete, incoming dir delete or move upon update'
+ '^local dir edit, incoming dir delete or move upon update'
+ ' Source left: .dir.*/DDD/D1@2'
+ ' Source right: .none.*(/DDD/D1@3)?$',
},
Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1661570&r1=1661569&r2=1661570&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Sun Feb 22
22:05:27 2015
@@ -7240,9 +7240,21 @@ move_away_delete_update(const svn_test_o
{0, "P", "normal", 2, "P"},
{1, "C2", "normal", 1, "A/B/C"},
{1, "Q2", "normal", 1, "P/Q"},
+
+ {2, "A/B", "normal", 1, "A/B"},
+ {2, "A/B/C", "normal", 1, "A/B/C", FALSE, "C2"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ conflict_info_t conflicts[] = {
+ {"A/B", FALSE, FALSE, {svn_wc_conflict_action_delete,
+ svn_wc_conflict_reason_edited}},
+ {"P/Q", FALSE, FALSE, {svn_wc_conflict_action_delete,
+ svn_wc_conflict_reason_moved_away, "P/Q"}},
{0}
};
SVN_ERR(check_db_rows(&b, "", nodes));
+ SVN_ERR(check_db_conflicts(&b, "", conflicts));
}
return SVN_NO_ERROR;
@@ -8684,36 +8696,46 @@ move_update_parent_replace(const svn_tes
SVN_ERR(sbox_wc_update(&b, "", 2));
{
nodes_row_t nodes[] = {
- {0, "", "normal", 2, ""},
- {0, "A", "normal", 2, "A"},
- {0, "A/B", "normal", 2, "A/B"},
- {2, "A/C", "normal", 1, "A/B/C"},
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+
+ {2, "A/C", "normal", 1, "A/B/C"},
+
+ {2, "A/B", "normal", 1, "A/B"},
+ {2, "A/B/C", "normal", 1, "A/B/C", FALSE, "A/C"},
+
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM},
+
{0}
};
- actual_row_t actual[] = {
- {"A/B", NULL},
+ conflict_info_t conflicts[] = {
+ {"A/B", FALSE, FALSE, {svn_wc_conflict_action_replace,
+ svn_wc_conflict_reason_edited}},
{0}
};
SVN_ERR(check_db_rows(&b, "", nodes));
- SVN_ERR(check_db_actual(&b, actual));
+ SVN_ERR(check_db_conflicts(&b, "", conflicts));
}
SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_infinity,
- svn_wc_conflict_choose_mine_conflict));
+ svn_wc_conflict_choose_merged));
{
nodes_row_t nodes[] = {
- {0, "", "normal", 2, ""},
- {0, "A", "normal", 2, "A"},
- {0, "A/B", "normal", 2, "A/B"},
- {2, "A/C", "normal", 1, "A/B/C"},
- {0}
- };
- actual_row_t actual[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {2, "A/C", "normal", 1, "A/B/C"},
+ {2, "A/B", "normal", 1, "A/B"},
+ {2, "A/B/C", "normal", 1, "A/B/C", FALSE, "A/C"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM},
+
{0}
};
+
SVN_ERR(check_db_rows(&b, "", nodes));
- SVN_ERR(check_db_actual(&b, actual));
+ SVN_ERR(check_db_conflicts(&b, "", NULL));
}
return SVN_NO_ERROR;