Author: rhuijben
Date: Mon Feb 23 13:34:47 2015
New Revision: 1661664
URL: http://svn.apache.org/r1661664
Log:
Fix tree conflict detection in the update editor on unversioned nodes that
exist where there used to be a deleted node.
* subversion/include/svn_wc.h
(svn_wc_status3_t): Provide kind of what is actually in the working copy,
to allow status callbacks to see that there is really something else,
where we just deleted something.
* subversion/libsvn_wc/status.c
(assemble_status,
assemble_unversioned): Set actual_kind.
* subversion/libsvn_wc/update_editor.c
(modcheck_callback): Handle unversioned nodes as a change, even when they
are in the same place as a delete.
* subversion/tests/cmdline/special_tests.py
(update_obstructing_symlink): Update expected results: tree conflict!
Modified:
subversion/trunk/subversion/include/svn_wc.h
subversion/trunk/subversion/libsvn_wc/status.c
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/tests/cmdline/special_tests.py
Modified: subversion/trunk/subversion/include/svn_wc.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1661664&r1=1661663&r2=1661664&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Mon Feb 23 13:34:47 2015
@@ -3835,6 +3835,13 @@ typedef struct svn_wc_status3_t
* @since New in 1.8. */
svn_boolean_t file_external;
+
+ /** The actual kind of the node in the working copy. May differ from kind
+ * on obstructions, deletes, etc. svn_node_unknown if unavailable.
+ *
+ * @since New in 1.9 */
+ svn_node_kind_t actual_kind;
+
/* NOTE! Please update svn_wc_dup_status3() when adding new fields here. */
} svn_wc_status3_t;
Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1661664&r1=1661663&r2=1661664&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Mon Feb 23 13:34:47 2015
@@ -378,9 +378,6 @@ assemble_status(svn_wc_status3_t **statu
svn_boolean_t copied = FALSE;
svn_boolean_t conflicted;
const char *moved_from_abspath = NULL;
- svn_filesize_t filesize = (dirent && (dirent->kind == svn_node_file))
- ? dirent->filesize
- : SVN_INVALID_FILESIZE;
/* Defaults for two main variables. */
enum svn_wc_status_kind node_status = svn_wc_status_normal;
@@ -644,7 +641,21 @@ assemble_status(svn_wc_status3_t **statu
stat->kind = svn_node_unknown;
}
stat->depth = info->depth;
- stat->filesize = filesize;
+ if (dirent)
+ {
+ stat->filesize = (dirent->kind == svn_node_file)
+ ? dirent->filesize
+ : SVN_INVALID_FILESIZE;
+ stat->actual_kind = dirent->special ? svn_node_symlink
+ : dirent->kind;
+ }
+ else
+ {
+ stat->filesize = SVN_INVALID_FILESIZE;
+ stat->actual_kind = ignore_text_mods ? svn_node_unknown
+ : svn_node_none;
+ }
+
stat->node_status = node_status;
stat->text_status = text_status;
stat->prop_status = prop_status;
@@ -733,9 +744,20 @@ assemble_unversioned(svn_wc_status3_t **
/*stat->versioned = FALSE;*/
stat->kind = svn_node_unknown; /* not versioned */
stat->depth = svn_depth_unknown;
- stat->filesize = (dirent && dirent->kind == svn_node_file)
- ? dirent->filesize
- : SVN_INVALID_FILESIZE;
+ if (dirent)
+ {
+ stat->actual_kind = dirent->special ? svn_node_symlink
+ : dirent->kind;
+ stat->filesize = (dirent->kind == svn_node_file)
+ ? dirent->filesize
+ : SVN_INVALID_FILESIZE;
+ }
+ else
+ {
+ stat->actual_kind = svn_node_none;
+ stat->filesize = SVN_INVALID_FILESIZE;
+ }
+
stat->node_status = svn_wc_status_none;
stat->text_status = svn_wc_status_none;
stat->prop_status = svn_wc_status_none;
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1661664&r1=1661663&r2=1661664&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Mon Feb 23 13:34:47
2015
@@ -1332,14 +1332,21 @@ modcheck_callback(void *baton,
case svn_wc_status_incomplete:
case svn_wc_status_ignored:
case svn_wc_status_none:
- case svn_wc_status_unversioned:
case svn_wc_status_external:
break;
case svn_wc_status_deleted:
mb->found_mod = TRUE;
+ if (status->actual_kind != svn_node_none
+ && status->actual_kind != svn_node_unknown)
+ {
+ /* The delete is obstructed by something unversioned */
+ mb->found_not_delete = TRUE;
+ return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
+ }
break;
+ case svn_wc_status_unversioned:
case svn_wc_status_missing:
case svn_wc_status_obstructed:
mb->found_mod = TRUE;
Modified: subversion/trunk/subversion/tests/cmdline/special_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/special_tests.py?rev=1661664&r1=1661663&r2=1661664&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/special_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/special_tests.py Mon Feb 23
13:34:47 2015
@@ -617,19 +617,55 @@ def update_obstructing_symlink(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- mu_path = os.path.join(wc_dir, 'A', 'mu')
- mu_url = sbox.repo_url + '/A/mu'
- iota_path = os.path.join(wc_dir, 'iota')
-
- # delete A/mu and replace it with a symlink
- svntest.main.run_svn(None, 'rm', mu_path)
- sbox.simple_add_symlink(iota_path, 'mu')
+ mu_path = sbox.ospath('A/mu')
- svntest.main.run_svn(None, 'rm', mu_url,
- '-m', 'log msg')
+ # delete mu and replace it with an (not-added) symlink
+ sbox.simple_rm('A/mu')
+ sbox.simple_symlink(sbox.ospath('iota'), 'A/mu')
- svntest.main.run_svn(None,
- 'up', wc_dir)
+ # delete pi and replace it with an added symlink
+ sbox.simple_rm('A/D/G/pi')
+ sbox.simple_add_symlink(sbox.ospath('iota'), 'A/D/G/pi')
+
+ if not os.path.exists(mu_path):
+ raise svntest.Failure("mu should be there")
+
+ # Now remove mu and pi in the repository
+ svntest.main.run_svn(None, 'rm', '-m', 'log msg',
+ sbox.repo_url + '/A/mu',
+ sbox.repo_url + '/A/D/G/pi')
+
+ # We expect tree conflicts
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/mu': Item(status=' ', treeconflict='C'),
+ 'A/D/G/pi': Item(status=' ', treeconflict='C')
+ })
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.tweak('A/mu', status='? ', treeconflict='C',
+ wc_rev=None)
+
+ expected_status.tweak('A/D/G/pi', status='A ',treeconflict='C',
+ wc_rev='-')
+
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output, None,
+ expected_status)
+
+ expected_info = [
+ {
+ 'Path': re.escape(sbox.ospath('A/D/G/pi')),
+ 'Tree conflict': 'local file replace, incoming file delete or move.*'
+ },
+ {
+ 'Path': re.escape(sbox.ospath('A/mu')),
+ 'Tree conflict': 'local file delete, incoming file delete or move.*'
+ }
+ ]
+
+ svntest.actions.run_and_verify_info(expected_info,
+ sbox.ospath('A/D/G/pi'),
+ sbox.ospath('A/mu'))
# check that the symlink is still there
if not os.path.exists(mu_path):