Hi!
[[[
As part of WC-NG, replace entry calls for revisions from
svn_wc_status2_t related code.
The entries code set the revision of newly added nodes to 0 but the db
sets them to -1. Since too many tests needs to be changed and 'svn info'
also uses 0, I'll change those values in a follow-up patch instead.
* subversion/tests/cmdline/copy_tests.py
(repos_to_wc): Change revision to 0 since the node is added. Don't
check against entries since the behavior differs.
* subversion/tests/cmdline/stat_tests.py
(status_with_tree_conflicts): An copied node should not have a
changed_rev or author.
* subversion/tests/cmdline/svntest/actions.py
(run_and_verify_status): Add new parameter check_entries. We only
check the entries if check_entries is set to True.
* subversion/tests/cmdline/merge_tests.py
(merge_into_missing): Add revision to status output for missing dir.
Previously, missing dirs did not have a revision, only files had.
Don't check entries since the behavior differs.
* subversion/svn/status.c
(print_status): Replace checks for revisions using entries with the
direct fields in svn_wc_status3_t. Set the revision for added and
replaced nodes to 0. WC-NG sets those revisions to -1, but changing
all the involved tests is for a follow-up.
* subversion/include/svn_wc.h
(svn_wc_status2_t): Add fields revision, changed_rev and
changed_author.
* subversion/libsvn_wc/status.c
(assemble_status): Fill in the new fields with data from the wc db.
(svn_wc_dup_status3): Copy the changed_author field.
]]]
Quirks
========
Checking entries
-------------------
I need to tweak the status output when doing a compare against the
entries in run_and_verify_status(). The code changes the behaviour for
revisions in three ways:
i) Missing dirs, now have a revision
ii) Copies from foreign repos to wc has the rev set to -1
iii) A copied node should not have a changed_author or changed_rev set.
I could change tweak_for_entries_compare() to fix i) but for the
other two I would have to write a func for tweaking the status returned
by 'entries-dump'. Can't I just use the check_entries parameter I've
added to run_and_verify_status() instead? I would only disable the
entries check for three tests.
Getting revisions of deleted nodes
-----------------------------------
I'm using base_get_info() for both nodes having the op_root from a plain
delete and those from a delete within an add. In the later case, the
revision, changed_rev and changed_author will be set to the default nil
values which match what I would get from read_info().
Cheers,
Daniel
Index: subversion/tests/cmdline/copy_tests.py
===================================================================
--- subversion/tests/cmdline/copy_tests.py (revision 936812)
+++ subversion/tests/cmdline/copy_tests.py (working copy)
@@ -980,9 +980,10 @@ def repos_to_wc(sbox):
expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
expected_output.add({
- 'pi' : Item(status='A ', wc_rev='1'),
+ 'pi' : Item(status='A ', wc_rev='0'),
})
- svntest.actions.run_and_verify_status(wc_dir, expected_output)
+ svntest.actions.run_and_verify_status(wc_dir, expected_output,
+ check_entries=False)
# Revert everything and verify.
svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
Index: subversion/tests/cmdline/stat_tests.py
===================================================================
--- subversion/tests/cmdline/stat_tests.py (revision 936812)
+++ subversion/tests/cmdline/stat_tests.py (working copy)
@@ -1593,7 +1593,7 @@ def status_with_tree_conflicts(sbox):
[" 2 2 jrandom %s\n" % G,
"D C 2 2 jrandom %s\n" % pi,
" > local delete, incoming edit upon update\n",
- "A + C - 1 jrandom %s\n" % rho,
+ "A + C - ? ? %s\n" % rho,
" > local edit, incoming delete upon update\n",
"! C %s\n" % tau,
" > local delete, incoming delete upon update\n",
Index: subversion/tests/cmdline/svntest/actions.py
===================================================================
--- subversion/tests/cmdline/svntest/actions.py (revision 936812)
+++ subversion/tests/cmdline/svntest/actions.py (working copy)
@@ -1280,6 +1280,7 @@ def run_and_verify_commit(wc_dir_name, output_tree
# This function always passes '-q' to the status command, which
# suppresses the printing of any unversioned or nonexistent items.
def run_and_verify_status(wc_dir_name, output_tree,
+ check_entries = True,
singleton_handler_a = None,
a_baton = None,
singleton_handler_b = None,
@@ -1314,7 +1315,7 @@ def run_and_verify_status(wc_dir_name, output_tree
# if we have an output State, and we can/are-allowed to create an
# entries-based State, then compare the two.
- if output_state:
+ if output_state and check_entries:
entries_state = wc.State.from_entries(wc_dir_name)
if entries_state:
tweaked = output_state.copy()
Index: subversion/tests/cmdline/merge_tests.py
===================================================================
--- subversion/tests/cmdline/merge_tests.py (revision 936812)
+++ subversion/tests/cmdline/merge_tests.py (working copy)
@@ -2161,7 +2161,7 @@ def merge_into_missing(sbox):
expected_status = wc.State(F_path, {
'' : Item(status=' ', wc_rev=1),
'foo' : Item(status='! ', wc_rev=2),
- 'Q' : Item(status='! ', wc_rev='?'),
+ 'Q' : Item(status='! ', wc_rev='2'),
})
expected_skip = wc.State(F_path, {
'Q' : Item(),
@@ -2183,7 +2183,7 @@ def merge_into_missing(sbox):
expected_status = wc.State(F_path, {
'' : Item(status=' M', wc_rev=1),
'foo' : Item(status='!M', wc_rev=2),
- 'Q' : Item(status='! ', wc_rev='?'),
+ 'Q' : Item(status='! ', wc_rev='2'),
})
expected_mergeinfo_output = wc.State(F_path, {
'' : Item(status=' U'),
@@ -2214,9 +2214,10 @@ def merge_into_missing(sbox):
expected_status.add({
'A/B/F' : Item(status=' M', wc_rev=1),
'A/B/F/foo' : Item(status='!M', wc_rev=2),
- 'A/B/F/Q' : Item(status='! ', wc_rev='?'),
+ 'A/B/F/Q' : Item(status='! ', wc_rev='2'),
})
- svntest.actions.run_and_verify_status(wc_dir, expected_status)
+ svntest.actions.run_and_verify_status(wc_dir, expected_status,
+ check_entries=False)
#----------------------------------------------------------------------
# A test for issue 1738
Index: subversion/svn/status.c
===================================================================
--- subversion/svn/status.c (revision 936812)
+++ subversion/svn/status.c (working copy)
@@ -142,12 +142,20 @@ print_status(const char *path,
if (! status->entry)
working_rev = "";
- else if (! SVN_IS_VALID_REVNUM(status->entry->revision))
- working_rev = " ? ";
+ else if (! SVN_IS_VALID_REVNUM(status->revision))
+ {
+ if (status->copied)
+ working_rev = "-";
+ else if (text_status == svn_wc_status_added
+ || text_status == svn_wc_status_replaced)
+ working_rev = "0";
+ else
+ working_rev = " ? ";
+ }
else if (status->copied)
working_rev = "-";
else
- working_rev = apr_psprintf(pool, "%ld", status->entry->revision);
+ working_rev = apr_psprintf(pool, "%ld", status->revision);
if (status->repos_text_status != svn_wc_status_none
|| status->repos_prop_status != svn_wc_status_none)
@@ -183,15 +191,15 @@ print_status(const char *path,
const char *commit_rev;
const char *commit_author;
- if (status->entry && SVN_IS_VALID_REVNUM(status->entry->cmt_rev))
- commit_rev = apr_psprintf(pool, "%ld", status->entry->cmt_rev);
+ if (SVN_IS_VALID_REVNUM(status->changed_rev))
+ commit_rev = apr_psprintf(pool, "%ld", status->changed_rev);
else if (status->entry)
commit_rev = " ? ";
else
commit_rev = "";
- if (status->entry && status->entry->cmt_author)
- commit_author = status->entry->cmt_author;
+ if (status->changed_author)
+ commit_author = status->changed_author;
else if (status->entry)
commit_author = " ? ";
else
@@ -277,17 +285,17 @@ svn_cl__print_status_xml(const char *path,
apr_hash_set(att_hash, "file-external", APR_HASH_KEY_STRING, "true");
if (status->entry && ! status->entry->copied)
apr_hash_set(att_hash, "revision", APR_HASH_KEY_STRING,
- apr_psprintf(pool, "%ld", status->entry->revision));
+ apr_psprintf(pool, "%ld", status->revision));
if (status->tree_conflict)
apr_hash_set(att_hash, "tree-conflicted", APR_HASH_KEY_STRING,
"true");
svn_xml_make_open_tag_hash(&sb, pool, svn_xml_normal, "wc-status",
att_hash);
- if (status->entry && SVN_IS_VALID_REVNUM(status->entry->cmt_rev))
+ if (SVN_IS_VALID_REVNUM(status->changed_rev))
{
- svn_cl__print_xml_commit(&sb, status->entry->cmt_rev,
- status->entry->cmt_author,
+ svn_cl__print_xml_commit(&sb, status->changed_rev,
+ status->changed_author,
svn_time_to_cstring(status->entry->cmt_date,
pool),
pool);
Index: subversion/include/svn_wc.h
===================================================================
--- subversion/include/svn_wc.h (revision 936812)
+++ subversion/include/svn_wc.h (working copy)
@@ -3617,6 +3617,21 @@ typedef struct svn_wc_status3_t
*/
enum svn_wc_status_kind pristine_prop_status;
+ /** Base revision.
+ * @since New in 1.7
+ */
+ svn_revnum_t revision;
+
+ /** Last revision this was changed
+ * @since New in 1.7
+ */
+ svn_revnum_t changed_rev;
+
+ /** Last commit author of this item
+ * @since New in 1.7
+ */
+ const char *changed_author;
+
/* NOTE! Please update svn_wc_dup_status3() when adding new fields here. */
} svn_wc_status3_t;
Index: subversion/libsvn_wc/status.c
===================================================================
--- subversion/libsvn_wc/status.c (revision 936812)
+++ subversion/libsvn_wc/status.c (working copy)
@@ -297,6 +297,11 @@ assemble_status(svn_wc_status3_t **status,
svn_boolean_t switched_p = FALSE;
const svn_wc_conflict_description2_t *tree_conflict;
svn_boolean_t file_external_p = FALSE;
+ svn_wc__db_status_t db_status;
+ svn_revnum_t revision;
+ svn_revnum_t changed_rev;
+ const char *changed_author;
+ svn_boolean_t base_shadowed;
#ifdef HAVE_SYMLINK
svn_boolean_t wc_special;
#endif /* HAVE_SYMLINK */
@@ -376,6 +381,9 @@ assemble_status(svn_wc_status3_t **status,
stat->repos_lock = repos_lock;
stat->url = NULL;
+ stat->revision = SVN_INVALID_REVNUM;
+ stat->changed_rev = SVN_INVALID_REVNUM;
+ stat->changed_author = NULL;
stat->ood_last_cmt_rev = SVN_INVALID_REVNUM;
stat->ood_last_cmt_date = 0;
stat->ood_kind = svn_node_none;
@@ -385,6 +393,51 @@ assemble_status(svn_wc_status3_t **status,
return SVN_NO_ERROR;
}
+ SVN_ERR(svn_wc__db_read_info(&db_status, NULL, &revision, NULL, NULL, NULL,
+ &changed_rev, NULL, &changed_author,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, &base_shadowed, NULL,
+ NULL, db, local_abspath, result_pool,
+ scratch_pool));
+
+ if (db_status == svn_wc__db_status_deleted)
+ {
+ const char *work_del_abspath = NULL;
+ const char *base_del_abspath = NULL;
+ const char *op_root_abspath;
+ svn_boolean_t base_replaced;
+
+ SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, &base_replaced,
+ NULL, &work_del_abspath, db,
+ local_abspath, scratch_pool,
+ result_pool));
+ if (work_del_abspath)
+ op_root_abspath = work_del_abspath;
+ else
+ op_root_abspath = base_del_abspath;
+
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &revision, NULL,
+ NULL, NULL, &changed_rev,
+ NULL, &changed_author, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, op_root_abspath,
+ result_pool, scratch_pool));
+ }
+ else if (base_shadowed)
+ {
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &revision, NULL, NULL, NULL,
+ &changed_rev, NULL, &changed_author,
+ NULL, NULL, NULL, NULL, NULL, NULL, db,
+ local_abspath, result_pool,
+ scratch_pool));
+ }
+ else if (db_status == svn_wc__db_status_added)
+ {
+ revision = SVN_INVALID_REVNUM;
+ changed_rev = SVN_INVALID_REVNUM;
+ changed_author = NULL;
+ }
+
/* Someone either deleted the administrative directory in the versioned
subdir, or deleted the directory altogether and created a new one.
In any case, what is currently there is in the way.
@@ -606,6 +659,9 @@ assemble_status(svn_wc_status3_t **status,
stat->copied = entry->copied;
stat->repos_lock = repos_lock;
stat->url = (entry->url ? entry->url : NULL);
+ stat->revision = revision;
+ stat->changed_rev = changed_rev;
+ stat->changed_author = changed_author;
stat->ood_last_cmt_rev = SVN_INVALID_REVNUM;
stat->ood_last_cmt_date = 0;
stat->ood_kind = svn_node_none;
@@ -2457,6 +2513,9 @@ svn_wc_dup_status3(const svn_wc_status3_t *orig_st
if (orig_stat->url)
new_stat->url = apr_pstrdup(pool, orig_stat->url);
+ if (orig_stat->changed_author)
+ new_stat->changed_author = apr_pstrdup(pool, orig_stat->changed_author);
+
if (orig_stat->ood_last_cmt_author)
new_stat->ood_last_cmt_author
= apr_pstrdup(pool, orig_stat->ood_last_cmt_author);