Merge r1544597, r1544600, r1544688, r1544690, r1545111, r1545122 from
^/subversion/trunk
* .
* subversion/libsvn_wc/status.c
* subversion/libsvn_wc/wc-queries.sql
* subversion/libsvn_wc/wc_db.c
* subversion/libsvn_wc/wc_db.h
* subversion/tests/cmdline/stat_tests.py
Merge changes from these revisions.
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/1.8.x-r1544597@1564550 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subversion/libsvn_wc/status.c b/subversion/libsvn_wc/status.c
index 1440b2e..26692c2 100644
--- a/subversion/libsvn_wc/status.c
+++ b/subversion/libsvn_wc/status.c
@@ -242,144 +242,7 @@
/** Code **/
-/* Fill in *INFO with the information it would contain if it were
- obtained from svn_wc__db_read_children_info. */
-static svn_error_t *
-read_info(const struct svn_wc__db_info_t **info,
- const char *local_abspath,
- svn_wc__db_t *db,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- struct svn_wc__db_info_t *mtb = apr_pcalloc(result_pool, sizeof(*mtb));
- const svn_checksum_t *checksum;
- const char *original_repos_relpath;
- SVN_ERR(svn_wc__db_read_info(&mtb->status, &mtb->kind,
- &mtb->revnum, &mtb->repos_relpath,
- &mtb->repos_root_url, &mtb->repos_uuid,
- &mtb->changed_rev, &mtb->changed_date,
- &mtb->changed_author, &mtb->depth,
- &checksum, NULL, &original_repos_relpath, NULL,
- NULL, NULL, &mtb->lock, &mtb->recorded_size,
- &mtb->recorded_time, &mtb->changelist,
- &mtb->conflicted, &mtb->op_root,
- &mtb->had_props, &mtb->props_mod,
- &mtb->have_base, &mtb->have_more_work, NULL,
- db, local_abspath,
- result_pool, scratch_pool));
-
- SVN_ERR(svn_wc__db_wclocked(&mtb->locked, db, local_abspath, scratch_pool));
-
- /* Maybe we have to get some shadowed lock from BASE to make our test suite
- happy... (It might be completely unrelated, but...) */
- if (mtb->have_base
- && (mtb->status == svn_wc__db_status_added
- || mtb->status == svn_wc__db_status_deleted
- || mtb->kind == svn_node_file))
- {
- svn_boolean_t update_root;
- svn_wc__db_lock_t **lock_arg = NULL;
-
- if (mtb->status == svn_wc__db_status_added
- || mtb->status == svn_wc__db_status_deleted)
- lock_arg = &mtb->lock;
-
- SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- lock_arg, NULL, NULL, &update_root,
- db, local_abspath,
- result_pool, scratch_pool));
-
- mtb->file_external = (update_root && mtb->kind == svn_node_file);
-
- if (mtb->status == svn_wc__db_status_deleted)
- {
- const char *moved_to_abspath;
- const char *moved_to_op_root_abspath;
-
- /* NOTE: we can't use op-root-ness as a condition here since a base
- * node can be the root of a move and still not be an explicit
- * op-root (having a working node with op_depth == pathelements).
- *
- * Both these (almost identical) situations showcase this:
- * svn mv a/b bb
- * svn del a
- * and
- * svn mv a aa
- * svn mv aa/b bb
- * In both, 'bb' is moved from 'a/b', but 'a/b' has no op_depth>0
- * node at all, as its parent 'a' is locally deleted. */
-
- SVN_ERR(svn_wc__db_scan_deletion(NULL,
- &moved_to_abspath,
- NULL,
- &moved_to_op_root_abspath,
- db, local_abspath,
- scratch_pool, scratch_pool));
- if (moved_to_abspath != NULL
- && moved_to_op_root_abspath != NULL
- && strcmp(moved_to_abspath, moved_to_op_root_abspath) == 0)
- {
- mtb->moved_to_abspath = apr_pstrdup(result_pool,
- moved_to_abspath);
- }
- /* ### ^^^ THIS SUCKS. For at least two reasons:
- * 1) We scan the node deletion and that's technically not necessary.
- * We'd be fine to know if this is an actual root of a move.
- * 2) From the elaborately calculated results, we backwards-guess
- * whether this is a root.
- * It works ok, and this code only gets called when a node is an
- * explicit target of a 'status'. But it would be better to do this
- * differently.
- * We could return moved-to via svn_wc__db_base_get_info() (called
- * just above), but as moved-to is only intended to be returned for
- * roots of a move, that doesn't fit too well. */
- }
- }
-
- /* ### svn_wc__db_read_info() could easily return the moved-here flag. But
- * for now... (The per-dir query for recursive status is far more optimal.)
- * Note that this actually scans around to get the full path, for a bool.
- * This bool then gets returned, later is evaluated, and if true leads to
- * the same paths being scanned again. We'd want to obtain this bool here as
- * cheaply as svn_wc__db_read_children_info() does. */
- if (mtb->status == svn_wc__db_status_added)
- {
- svn_wc__db_status_t status;
-
- SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- db, local_abspath,
- result_pool, scratch_pool));
-
- mtb->moved_here = (status == svn_wc__db_status_moved_here);
- mtb->incomplete = (status == svn_wc__db_status_incomplete);
- }
-
- mtb->has_checksum = (checksum != NULL);
- mtb->copied = (original_repos_relpath != NULL);
-
-#ifdef HAVE_SYMLINK
- if (mtb->kind == svn_node_file
- && (mtb->had_props || mtb->props_mod))
- {
- apr_hash_t *properties;
-
- if (mtb->props_mod)
- SVN_ERR(svn_wc__db_read_props(&properties, db, local_abspath,
- scratch_pool, scratch_pool));
- else
- SVN_ERR(svn_wc__db_read_pristine_props(&properties, db, local_abspath,
- scratch_pool, scratch_pool));
-
- mtb->special = (NULL != svn_hash_gets(properties, SVN_PROP_SPECIAL));
- }
-#endif
- *info = mtb;
-
- return SVN_NO_ERROR;
-}
/* Return *REPOS_RELPATH and *REPOS_ROOT_URL for LOCAL_ABSPATH using
information in INFO if available, falling back on
@@ -493,7 +356,8 @@
if (!info)
- SVN_ERR(read_info(&info, local_abspath, db, result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_read_single_info(&info, db, local_abspath,
+ result_pool, scratch_pool));
if (!info->repos_relpath || !parent_repos_relpath)
switched_p = FALSE;
@@ -799,8 +663,11 @@
stat->changelist = apr_pstrdup(result_pool, info->changelist);
stat->moved_from_abspath = moved_from_abspath;
- if (info->moved_to_abspath)
- stat->moved_to_abspath = apr_pstrdup(result_pool, info->moved_to_abspath);
+
+ /* ### TODO: Handle multiple moved_to values properly */
+ if (info->moved_to)
+ stat->moved_to_abspath = apr_pstrdup(result_pool,
+ info->moved_to->moved_to_abspath);
stat->file_external = info->file_external;
@@ -1345,8 +1212,8 @@
SVN_ERR(err);
if (!dir_info)
- SVN_ERR(read_info(&dir_info, local_abspath, wb->db,
- scratch_pool, iterpool));
+ SVN_ERR(svn_wc__db_read_single_info(&dir_info, wb->db, local_abspath,
+ scratch_pool, iterpool));
SVN_ERR(get_repos_root_url_relpath(&dir_repos_relpath, &dir_repos_root_url,
&dir_repos_uuid, dir_info,
@@ -1506,8 +1373,9 @@
if (dirent->kind == svn_node_none)
dirent = NULL;
- SVN_ERR(read_info(&dir_info, parent_abspath, wb->db,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_read_single_info(&dir_info,
+ wb->db, parent_abspath,
+ scratch_pool, scratch_pool));
SVN_ERR(get_repos_root_url_relpath(&dir_repos_relpath, &dir_repos_root_url,
&dir_repos_uuid, dir_info,
@@ -2710,7 +2578,8 @@
ignore_patterns = ignores;
}
- err = read_info(&info, local_abspath, db, scratch_pool, scratch_pool);
+ err = svn_wc__db_read_single_info(&info, db, local_abspath,
+ scratch_pool, scratch_pool);
if (err)
{
diff --git a/subversion/libsvn_wc/wc-queries.sql b/subversion/libsvn_wc/wc-queries.sql
index d275a7b..19c4516 100644
--- a/subversion/libsvn_wc/wc-queries.sql
+++ b/subversion/libsvn_wc/wc-queries.sql
@@ -417,6 +417,12 @@
WHERE work.wc_id = ?1 AND work.local_relpath = ?2 AND work.op_depth > 0
LIMIT 1
+-- STMT_SELECT_MOVED_TO_NODE
+SELECT op_depth, moved_to
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2 AND moved_to IS NOT NULL
+ORDER BY op_depth DESC
+
-- STMT_SELECT_OP_DEPTH_MOVED_TO
SELECT op_depth, moved_to, repos_path, revision
FROM nodes
diff --git a/subversion/libsvn_wc/wc_db.c b/subversion/libsvn_wc/wc_db.c
index 7d038cf..855b9cc 100644
--- a/subversion/libsvn_wc/wc_db.c
+++ b/subversion/libsvn_wc/wc_db.c
@@ -8680,7 +8680,11 @@
else
child->op_root = (op_depth == relpath_depth(child_relpath));
- svn_hash_sets(nodes, apr_pstrdup(result_pool, name), child);
+ if (op_depth && child->op_root)
+ child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20);
+
+ if (new_child)
+ svn_hash_sets(nodes, apr_pstrdup(result_pool, name), child);
}
if (op_depth == 0)
@@ -8702,18 +8706,48 @@
child_item->nr_layers++;
child_item->info.have_more_work = (child_item->nr_layers > 1);
- /* Moved-to can only exist at op_depth > 0. */
- /* ### Should we really do this for every layer where op_depth > 0
- in undefined order? */
+
+ /* A local_relpath can be moved multiple times at different op
+ depths and it really depends on the caller what is interesting.
+ We provide a simple linked list with the moved_from information */
+
moved_to_relpath = svn_sqlite__column_text(stmt, 21, NULL);
if (moved_to_relpath)
- child_item->info.moved_to_abspath =
- svn_dirent_join(wcroot->abspath, moved_to_relpath, result_pool);
+ {
+ struct svn_wc__db_moved_to_info_t *moved_to;
+ struct svn_wc__db_moved_to_info_t **next;
+ const char *shadow_op_relpath;
+ int cur_op_depth;
- /* Moved-here can only exist at op_depth > 0. */
- /* ### Should we really do this for every layer where op_depth > 0
- in undefined order? */
- child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20);
+ moved_to = apr_pcalloc(result_pool, sizeof(*moved_to));
+ moved_to->moved_to_abspath = svn_dirent_join(wcroot->abspath,
+ moved_to_relpath,
+ result_pool);
+
+ cur_op_depth = relpath_depth(child_relpath);
+ shadow_op_relpath = child_relpath;
+
+ while (cur_op_depth > op_depth)
+ {
+ shadow_op_relpath = svn_relpath_dirname(shadow_op_relpath,
+ scratch_pool);
+ cur_op_depth--;
+ }
+
+ moved_to->shadow_op_root_abspath =
+ svn_dirent_join(wcroot->abspath, shadow_op_relpath,
+ result_pool);
+
+ next = &child_item->info.moved_to;
+
+ while (*next &&
+ 0 < strcmp((*next)->shadow_op_root_abspath,
+ moved_to->shadow_op_root_abspath))
+ next = &((*next)->next);
+
+ moved_to->next = *next;
+ *next = moved_to;
+ }
}
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -8801,6 +8835,171 @@
return SVN_NO_ERROR;
}
+static svn_error_t *
+read_single_info(const struct svn_wc__db_info_t **info,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct svn_wc__db_info_t *mtb;
+ apr_int64_t repos_id;
+ const svn_checksum_t *checksum;
+ const char *original_repos_relpath;
+ svn_boolean_t have_work;
+
+ mtb = apr_pcalloc(result_pool, sizeof(*mtb));
+
+ SVN_ERR(read_info(&mtb->status, &mtb->kind, &mtb->revnum,
+ &mtb->repos_relpath, &repos_id, &mtb->changed_rev,
+ &mtb->changed_date, &mtb->changed_author, &mtb->depth,
+ &checksum, NULL, &original_repos_relpath, NULL, NULL,
+ &mtb->lock, &mtb->recorded_size, &mtb->recorded_time,
+ &mtb->changelist, &mtb->conflicted, &mtb->op_root,
+ &mtb->had_props, &mtb->props_mod, &mtb->have_base,
+ &mtb->have_more_work, &have_work,
+ wcroot, local_relpath,
+ result_pool, scratch_pool));
+
+ /* Query the same rows in the database again for move information */
+ if (have_work && (mtb->have_base || mtb->have_more_work))
+ {
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ const char *cur_relpath = NULL;
+ int cur_op_depth;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_MOVED_TO_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ while (have_row)
+ {
+ struct svn_wc__db_moved_to_info_t *move;
+ int op_depth = svn_sqlite__column_int(stmt, 0);
+ const char *moved_to_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+
+ move = apr_pcalloc(result_pool, sizeof(*move));
+ move->moved_to_abspath = svn_dirent_join(wcroot->abspath,
+ moved_to_relpath,
+ result_pool);
+
+ if (!cur_relpath)
+ {
+ cur_relpath = local_relpath;
+ cur_op_depth = relpath_depth(cur_relpath);
+ }
+ while (cur_op_depth > op_depth)
+ {
+ cur_relpath = svn_relpath_dirname(cur_relpath, scratch_pool);
+ cur_op_depth--;
+ }
+ move->shadow_op_root_abspath = svn_dirent_join(wcroot->abspath,
+ cur_relpath,
+ result_pool);
+
+ move->next = mtb->moved_to;
+ mtb->moved_to = move;
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
+
+ /* Maybe we have to get some shadowed lock from BASE to make our test suite
+ happy... (It might be completely unrelated, but...)
+ This queries the same BASE row again, joined to the lock table */
+ if (mtb->have_base && (have_work || mtb->kind == svn_node_file))
+ {
+ svn_boolean_t update_root;
+ svn_wc__db_lock_t **lock_arg = NULL;
+
+ if (have_work)
+ lock_arg = &mtb->lock;
+
+ SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, lock_arg, NULL, NULL,
+ &update_root,
+ wcroot, local_relpath,
+ result_pool, scratch_pool));
+
+ mtb->file_external = (update_root && mtb->kind == svn_node_file);
+ }
+
+ if (mtb->status == svn_wc__db_status_added)
+ {
+ svn_wc__db_status_t status;
+
+ SVN_ERR(scan_addition(&status, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL,
+ wcroot, local_relpath,
+ result_pool, scratch_pool));
+
+ mtb->moved_here = (status == svn_wc__db_status_moved_here);
+ mtb->incomplete = (status == svn_wc__db_status_incomplete);
+ }
+
+#ifdef HAVE_SYMLINK
+ if (mtb->kind == svn_node_file
+ && (mtb->had_props || mtb->props_mod))
+ {
+ apr_hash_t *properties;
+
+ if (mtb->props_mod)
+ SVN_ERR(svn_wc__db_read_props_internal(&properties,
+ wcroot, local_relpath,
+ scratch_pool, scratch_pool));
+ else
+ SVN_ERR(db_read_pristine_props(&properties, wcroot, local_relpath,
+ TRUE /* deleted_ok */,
+ scratch_pool, scratch_pool));
+
+ mtb->special = (NULL != svn_hash_gets(properties, SVN_PROP_SPECIAL));
+ }
+#endif
+
+ mtb->has_checksum = (checksum != NULL);
+ mtb->copied = (original_repos_relpath != NULL);
+
+ SVN_ERR(svn_wc__db_fetch_repos_info(&mtb->repos_root_url, &mtb->repos_uuid,
+ wcroot->sdb, repos_id, result_pool));
+
+ if (mtb->kind == svn_node_dir)
+ SVN_ERR(is_wclocked(&mtb->locked, wcroot, local_relpath, scratch_pool));
+
+ *info = mtb;
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_read_single_info(const struct svn_wc__db_info_t **info,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+ local_abspath,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_WC__DB_WITH_TXN(read_single_info(info, wcroot, local_relpath,
+ result_pool, scratch_pool),
+ wcroot);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__db_read_pristine_info(svn_wc__db_status_t *status,
svn_node_kind_t *kind,
diff --git a/subversion/libsvn_wc/wc_db.h b/subversion/libsvn_wc/wc_db.h
index a4ed3f9..b091494 100644
--- a/subversion/libsvn_wc/wc_db.h
+++ b/subversion/libsvn_wc/wc_db.h
@@ -1909,6 +1909,16 @@
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Structure used as linked list in svn_wc__db_info_t to describe all nodes
+ in this location that were moved to another location */
+struct svn_wc__db_moved_to_info_t
+{
+ const char *moved_to_abspath;
+ const char *shadow_op_root_abspath;
+
+ struct svn_wc__db_moved_to_info_t *next;
+};
+
/* Structure returned by svn_wc__db_read_children_info. Only has the
fields needed by status. */
struct svn_wc__db_info_t {
@@ -1945,7 +1955,10 @@
svn_wc__db_lock_t *lock; /* Repository file lock */
svn_boolean_t incomplete; /* TRUE if a working node is incomplete */
- const char *moved_to_abspath; /* Only on op-roots. See svn_wc_status3_t. */
+ struct svn_wc__db_moved_to_info_t *moved_to; /* A linked list of locations
+ where nodes at this path
+ are moved to. Highest layers
+ first */
svn_boolean_t moved_here; /* Only on op-roots. */
svn_boolean_t file_external;
@@ -1967,6 +1980,14 @@
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Like svn_wc__db_read_children_info, but only gets an info node for the root
+ element. */
+svn_error_t *
+svn_wc__db_read_single_info(const struct svn_wc__db_info_t **info,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Structure returned by svn_wc__db_read_walker_info. Only has the
fields needed by svn_wc__internal_walk_children(). */
diff --git a/subversion/tests/cmdline/stat_tests.py b/subversion/tests/cmdline/stat_tests.py
index fdaab40..6e706ef 100755
--- a/subversion/tests/cmdline/stat_tests.py
+++ b/subversion/tests/cmdline/stat_tests.py
@@ -2119,6 +2119,95 @@
expected_status = svntest.actions.get_virginal_state(rel_wc_dir, 1)
svntest.actions.run_and_verify_status(rel_wc_dir, expected_status)
+def status_move_missing_direct(sbox):
+ "move information when status is called directly"
+
+ sbox.build()
+ sbox.simple_copy('A', 'Z')
+ sbox.simple_commit('')
+ sbox.simple_update('')
+
+ sbox.simple_move('Z', 'ZZ')
+ sbox.simple_move('A', 'Z')
+ sbox.simple_move('Z/B', 'ZB')
+ sbox.simple_mkdir('Z/B')
+ sbox.simple_move('ZB/E', 'Z/B/E')
+
+ # Somehow 'svn status' now shows different output for 'ZB/E'
+ # when called directly and via an ancestor, as this handles
+ # multi-layer in a different way
+
+ # Note that the status output may change over different Subversion revisions,
+ # but the status on a node should be identical anyway 'svn status' is called
+ # on it.
+
+ expected_output = [
+ 'A + %s\n' % sbox.ospath('ZB'),
+ ' > moved from %s\n' % os.path.join('..', 'Z', 'B'),
+ 'D + %s\n' % sbox.ospath('ZB/E'),
+ ' > moved to %s\n' % os.path.join('..', 'Z', 'B', 'E'),
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'status',
+ sbox.ospath('ZB'), '--depth', 'immediates')
+
+ # And calling svn status on just 'ZB/E' should have the same result for this node
+ # except that we calculate the relative path from a different base
+ expected_output = [
+ 'D + %s\n' % sbox.ospath('ZB/E'),
+ ' > moved to %s\n' % os.path.join('..', '..', 'Z', 'B', 'E'),
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'status',
+ sbox.ospath('ZB/E'), '--depth', 'empty')
+
+def status_move_missing_direct_base(sbox):
+ "move when status is called directly with base"
+
+ sbox.build()
+ sbox.simple_copy('A', 'Z')
+ sbox.simple_mkdir('Q')
+ sbox.simple_mkdir('Q/ZB')
+ sbox.simple_mkdir('Q/ZB/E')
+ sbox.simple_commit('')
+ sbox.simple_update('')
+
+ sbox.simple_rm('Q')
+ sbox.simple_mkdir('Q')
+
+ sbox.simple_move('Z', 'ZZ')
+ sbox.simple_move('A', 'Z')
+ sbox.simple_move('Z/B', 'Q/ZB')
+ sbox.simple_mkdir('Z/B')
+ sbox.simple_move('Q/ZB/E', 'Z/B/E')
+
+ # Somehow 'svn status' now shows different output for 'Q/ZB/E'
+ # when called directly and via an ancestor, as this handles
+ # multi-layer in a different way
+
+ # Note that the status output may change over different Subversion revisions,
+ # but the status on a node should be identical anyway 'svn status' is called
+ # on it.
+
+ # This test had a different result as status_move_missing_direct at the time of
+ # writing this test.
+
+ expected_output = [
+ 'A + %s\n' % sbox.ospath('Q/ZB'),
+ ' > moved from %s\n' % os.path.join('..', '..', 'Z', 'B'),
+ 'D + %s\n' % sbox.ospath('Q/ZB/E'),
+ ' > moved to %s\n' % os.path.join('..', '..', 'Z', 'B', 'E'),
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'status',
+ sbox.ospath('Q/ZB'), '--depth', 'immediates')
+
+ # And calling svn status on just 'ZB/E' should have the same result for this node,
+ # except that the moved_to information is calculated from the node itself
+ expected_output = [
+ 'D + %s\n' % sbox.ospath('Q/ZB/E'),
+ ' > moved to %s\n' % os.path.join('..', '..', '..', 'Z', 'B', 'E'),
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'status',
+ sbox.ospath('Q/ZB/E'), '--depth', 'empty')
+
########################################################################
# Run the tests
@@ -2167,6 +2256,8 @@
status_case_changed,
move_update_timestamps,
status_path_handling,
+ status_move_missing_direct,
+ status_move_missing_direct_base,
]
if __name__ == '__main__':