Author: brane
Date: Fri Mar 28 14:19:27 2014
New Revision: 1582756
URL: http://svn.apache.org/r1582756
Log:
On the remote-only-status branch: First approximation of a working solution.
* subversion/libsvn_wc/status.c
(struct edit_baton): Move member ignore_local_mods from here ...
(struct walk_status_baton): ... to here. Update all uses.
(assemble_status): Add argument ignore_local_mods. Update all uses.
When set, do not check for missing nodes in the working copy.
(read_base_node_info): New.
(get_dir_status): Update implementation to for ignore_local_mods.
(internal_status): Likewise.
* subversion/tests/libsvn_client/client-test.c
(test_remote_only_status): Add another validity check and set to PASS.
Modified:
subversion/branches/remote-only-status/subversion/libsvn_wc/status.c
subversion/branches/remote-only-status/subversion/tests/libsvn_client/client-test.c
Modified: subversion/branches/remote-only-status/subversion/libsvn_wc/status.c
URL:
http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_wc/status.c?rev=1582756&r1=1582755&r2=1582756&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_wc/status.c
(original)
+++ subversion/branches/remote-only-status/subversion/libsvn_wc/status.c Fri
Mar 28 14:19:27 2014
@@ -71,6 +71,10 @@ struct walk_status_baton
/* Should we ignore text modifications? */
svn_boolean_t ignore_text_mods;
+ /* Ignore all local modifications; only check for differences
+ between the BASE tree and the repository. */
+ svn_boolean_t ignore_local_mods;
+
/* Externals info harvested during the status run. */
apr_hash_t *externals;
@@ -107,10 +111,6 @@ struct edit_baton
/* Do we want all statuses (instead of just the interesting ones) ? */
svn_boolean_t get_all;
- /* Ignore all local modifications; only check for differences
- between the BASE tree and the repository. */
- svn_boolean_t ignore_local_mods;
-
/* Ignore the svn:ignores. */
svn_boolean_t no_ignore;
@@ -372,6 +372,7 @@ assemble_status(svn_wc_status3_t **statu
const svn_io_dirent2_t *dirent,
svn_boolean_t get_all,
svn_boolean_t ignore_text_mods,
+ svn_boolean_t ignore_local_mods,
const svn_lock_t *repos_lock,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -429,7 +430,7 @@ assemble_status(svn_wc_status3_t **statu
copied = TRUE; /* Working deletion */
}
}
- else
+ else if (!ignore_local_mods)
{
/* Examine whether our target is missing or obstructed. To detect
* obstructions, we have to look at the on-disk status in DIRENT. */
@@ -824,7 +825,8 @@ send_status_structure(const struct walk_
SVN_ERR(assemble_status(&statstruct, wb->db, local_abspath,
parent_repos_root_url, parent_repos_relpath,
parent_repos_uuid,
- info, dirent, get_all, wb->ignore_text_mods,
+ info, dirent, get_all,
+ wb->ignore_text_mods, wb->ignore_local_mods,
repos_lock, scratch_pool, scratch_pool));
if (statstruct && status_func)
@@ -1181,6 +1183,51 @@ one_child_status(const struct walk_statu
return SVN_NO_ERROR;
}
+/*
+ */
+static svn_error_t *
+read_base_node_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_depth_t depth;
+ const svn_checksum_t *checksum;
+ struct svn_wc__db_info_t *bi = apr_pcalloc(scratch_pool, sizeof(*bi));
+
+ SVN_ERR(svn_wc__db_base_get_info(&bi->status,
+ &bi->kind,
+ &bi->revnum,
+ &bi->repos_relpath,
+ &bi->repos_root_url,
+ &bi->repos_uuid,
+ &bi->changed_rev,
+ &bi->changed_date,
+ &bi->changed_author,
+ &depth, &checksum,
+ NULL /* target */,
+ &bi->lock,
+ &bi->had_props,
+ NULL /* props */,
+ NULL /* update_root */,
+ db, local_abspath,
+ result_pool, scratch_pool));
+ if (bi->kind != svn_node_dir)
+ bi->depth = svn_depth_unknown;
+ else
+ bi->depth = depth;
+ if (bi->kind == svn_node_file && checksum != NULL)
+ bi->has_checksum = TRUE;
+ else
+ bi->has_checksum = FALSE;
+ bi->have_base = TRUE;
+
+ *info = bi;
+ return SVN_NO_ERROR;
+}
+
+
/* Send svn_wc_status3_t * structures for the directory LOCAL_ABSPATH and
for all its child nodes (according to DEPTH) through STATUS_FUNC /
STATUS_BATON.
@@ -1238,21 +1285,32 @@ get_dir_status(const struct walk_status_
iterpool = svn_pool_create(scratch_pool);
- err = svn_io_get_dirents3(&dirents, local_abspath, FALSE, scratch_pool,
- iterpool);
- if (err
- && (APR_STATUS_IS_ENOENT(err->apr_err)
- || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
+ if (!wb->ignore_local_mods)
{
- svn_error_clear(err);
- dirents = apr_hash_make(scratch_pool);
+ err = svn_io_get_dirents3(&dirents, local_abspath, FALSE, scratch_pool,
+ iterpool);
+ if (err
+ && (APR_STATUS_IS_ENOENT(err->apr_err)
+ || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
+ {
+ svn_error_clear(err);
+ dirents = apr_hash_make(scratch_pool);
+ }
+ else
+ SVN_ERR(err);
}
else
- SVN_ERR(err);
+ dirents = apr_hash_make(scratch_pool);
if (!dir_info)
- SVN_ERR(svn_wc__db_read_single_info(&dir_info, wb->db, local_abspath,
- scratch_pool, iterpool));
+ {
+ if (!wb->ignore_local_mods)
+ SVN_ERR(svn_wc__db_read_single_info(&dir_info, wb->db, local_abspath,
+ scratch_pool, iterpool));
+ else
+ SVN_ERR(read_base_node_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,
@@ -1264,13 +1322,24 @@ get_dir_status(const struct walk_status_
/* Create a hash containing all children. The source hashes
don't all map the same types, but only the keys of the result
hash are subsequently used. */
- SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
- wb->db, local_abspath,
- scratch_pool, iterpool));
-
- all_children = apr_hash_overlay(scratch_pool, nodes, dirents);
- if (apr_hash_count(conflicts) > 0)
- all_children = apr_hash_overlay(scratch_pool, conflicts, all_children);
+ if (!wb->ignore_local_mods)
+ {
+ sorted_children = NULL;
+ SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
+ wb->db, local_abspath,
+ scratch_pool, iterpool));
+
+ all_children = apr_hash_overlay(scratch_pool, nodes, dirents);
+ if (apr_hash_count(conflicts) > 0)
+ all_children = apr_hash_overlay(scratch_pool, conflicts, all_children);
+ }
+ else
+ {
+ all_children = NULL;
+ SVN_ERR(svn_wc__db_base_get_children(
+ (const apr_array_header_t **)&sorted_children,
+ wb->db, local_abspath, scratch_pool, iterpool));
+ }
/* Handle "this-dir" first. */
if (! skip_this_dir)
@@ -1322,27 +1391,53 @@ get_dir_status(const struct walk_status_
return SVN_NO_ERROR;
/* Walk all the children of this directory. */
- sorted_children = svn_sort__hash(all_children,
- svn_sort_compare_items_lexically,
- scratch_pool);
+ if (all_children)
+ sorted_children = svn_sort__hash(all_children,
+ svn_sort_compare_items_lexically,
+ scratch_pool);
+ else
+ {
+ SVN_ERR_ASSERT(sorted_children != NULL);
+ qsort(sorted_children->elts,
+ sorted_children->nelts,
+ sorted_children->elt_size,
+ svn_sort_compare_paths);
+ }
+
for (i = 0; i < sorted_children->nelts; i++)
{
- const void *key;
- apr_ssize_t klen;
- svn_sort__item_t item;
+ svn_boolean_t unversioned_tree_conflicted;
const char *child_abspath;
svn_io_dirent2_t *child_dirent;
const struct svn_wc__db_info_t *child_info;
svn_pool_clear(iterpool);
- item = APR_ARRAY_IDX(sorted_children, i, svn_sort__item_t);
- key = item.key;
- klen = item.klen;
-
- child_abspath = svn_dirent_join(local_abspath, key, iterpool);
- child_dirent = apr_hash_get(dirents, key, klen);
- child_info = apr_hash_get(nodes, key, klen);
+ if (all_children)
+ {
+ const void *key;
+ apr_ssize_t klen;
+ svn_sort__item_t item;
+
+ item = APR_ARRAY_IDX(sorted_children, i, svn_sort__item_t);
+ key = item.key;
+ klen = item.klen;
+
+ child_abspath = svn_dirent_join(local_abspath, key, iterpool);
+ child_dirent = apr_hash_get(dirents, key, klen);
+ child_info = apr_hash_get(nodes, key, klen);
+ unversioned_tree_conflicted =
+ (apr_hash_get(conflicts, key, klen) != NULL);
+ }
+ else
+ {
+ const char *name = APR_ARRAY_IDX(sorted_children, i, const char*);
+ child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+ child_dirent = NULL;
+ SVN_ERR(read_base_node_info(&child_info, wb->db, child_abspath,
+ scratch_pool, iterpool));
+ unversioned_tree_conflicted = FALSE;
+ }
SVN_ERR(one_child_status(wb,
child_abspath,
@@ -1352,7 +1447,7 @@ get_dir_status(const struct walk_status_
dir_repos_root_url,
dir_repos_relpath,
dir_repos_uuid,
- apr_hash_get(conflicts, key, klen) != NULL,
+ unversioned_tree_conflicted,
&collected_ignore_patterns,
ignore_patterns,
depth,
@@ -2007,7 +2102,7 @@ delete_entry(const char *path,
statushash immediately. No need to wait until close_file or
close_dir, because there's no risk of having to honor the 'added'
flag. We already know this item exists in the working copy. */
- SVN_ERR(tweak_statushash(db, db, TRUE, eb->db, eb->ignore_local_mods,
+ SVN_ERR(tweak_statushash(db, db, TRUE, eb->db, eb->wb.ignore_local_mods,
local_abspath,
svn_wc_status_deleted, 0, 0, revision, NULL, pool));
@@ -2016,7 +2111,7 @@ delete_entry(const char *path,
node). */
if (db->parent_baton && (! *eb->target_basename))
SVN_ERR(tweak_statushash(db->parent_baton, db, TRUE,
- eb->db, eb->ignore_local_mods,
+ eb->db, eb->wb.ignore_local_mods,
db->local_abspath,
svn_wc_status_modified, svn_wc_status_modified,
0, SVN_INVALID_REVNUM, NULL, pool));
@@ -2141,7 +2236,7 @@ close_directory(void *dir_baton,
/* ### When we add directory locking, we need to find a
### directory lock here. */
SVN_ERR(tweak_statushash(pb, db, TRUE,
- eb->db, eb->ignore_local_mods,
+ eb->db, eb->wb.ignore_local_mods,
db->local_abspath,
repos_node_status, repos_text_status,
repos_prop_status, SVN_INVALID_REVNUM, NULL,
@@ -2394,7 +2489,7 @@ close_file(void *file_baton,
}
return tweak_statushash(fb, NULL, FALSE, fb->edit_baton->db,
- fb->edit_baton->ignore_local_mods,
+ fb->edit_baton->wb.ignore_local_mods,
fb->local_abspath, repos_node_status,
repos_text_status, repos_prop_status,
SVN_INVALID_REVNUM, repos_lock, pool);
@@ -2469,7 +2564,6 @@ svn_wc__get_status_editor(const svn_delt
eb->target_revision = edit_revision;
eb->db = wc_ctx->db;
eb->get_all = get_all;
- eb->ignore_local_mods = ignore_local_mods;
eb->no_ignore = no_ignore;
eb->status_func = status_func;
eb->status_baton = status_baton;
@@ -2485,6 +2579,7 @@ svn_wc__get_status_editor(const svn_delt
eb->wb.db = wc_ctx->db;
eb->wb.target_abspath = eb->target_abspath;
eb->wb.ignore_text_mods = ignore_local_mods;
+ eb->wb.ignore_local_mods = ignore_local_mods;
eb->wb.repos_locks = NULL;
eb->wb.repos_root = NULL;
@@ -2509,7 +2604,7 @@ svn_wc__get_status_editor(const svn_delt
/* The edit baton's status structure maps to PATH, and the editor
have to be aware of whether that is the anchor or the target. */
SVN_ERR(internal_status(&(eb->anchor_status), wc_ctx->db, anchor_abspath,
- FALSE, result_pool, scratch_pool));
+ ignore_local_mods, result_pool, scratch_pool));
/* Construct an editor. */
tree_editor->set_target_revision = set_target_revision;
@@ -2615,6 +2710,7 @@ svn_wc__internal_walk_status(svn_wc__db_
wb.db = db;
wb.target_abspath = local_abspath;
wb.ignore_text_mods = ignore_text_mods;
+ wb.ignore_local_mods = FALSE;
wb.repos_root = NULL;
wb.repos_locks = NULL;
@@ -2794,24 +2890,15 @@ internal_status(svn_wc_status3_t **statu
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- err = svn_wc__db_read_single_info(&info, db, local_abspath,
- scratch_pool, scratch_pool);
-
- if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_trace(err);
-
-
- /* FIXME: Must do something quite a bit smarter here. This is just
- a stopgap to avoid crashing when ignore_local_mods is set. */
- if (ignore_local_mods)
- {
- dirent = NULL;
- info = NULL;
- }
- else
+ if (!ignore_local_mods)
{
+ err = svn_wc__db_read_single_info(&info, db, local_abspath,
+ scratch_pool, scratch_pool);
if (err)
{
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_trace(err);
+
svn_error_clear(err);
info = NULL;
@@ -2822,6 +2909,13 @@ internal_status(svn_wc_status3_t **statu
SVN_ERR(stat_wc_dirent_case_sensitive(&dirent, db, local_abspath,
scratch_pool, scratch_pool));
}
+ else
+ {
+ SVN_ERR(read_base_node_info(&info, db, local_abspath,
+ scratch_pool, scratch_pool));
+ dirent = NULL;
+ }
+
if (!info
|| info->kind == svn_node_unknown
@@ -2846,16 +2940,25 @@ internal_status(svn_wc_status3_t **statu
{
const char *parent_abspath = svn_dirent_dirname(local_abspath,
scratch_pool);
-
- SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL,
- &parent_repos_relpath,
- &parent_repos_root_url,
- &parent_repos_uuid, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- db, parent_abspath,
- result_pool, scratch_pool));
+ if (!ignore_local_mods)
+ SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL,
+ &parent_repos_relpath,
+ &parent_repos_root_url,
+ &parent_repos_uuid, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ db, parent_abspath,
+ result_pool, scratch_pool));
+ else
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL,
+ &parent_repos_relpath,
+ &parent_repos_root_url,
+ &parent_repos_uuid,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, parent_abspath,
+ result_pool, scratch_pool));
}
else
{
@@ -2871,7 +2974,7 @@ internal_status(svn_wc_status3_t **statu
info,
dirent,
TRUE /* get_all */,
- FALSE,
+ FALSE, ignore_local_mods,
NULL /* repos_lock */,
result_pool, scratch_pool));
}
Modified:
subversion/branches/remote-only-status/subversion/tests/libsvn_client/client-test.c
URL:
http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/tests/libsvn_client/client-test.c?rev=1582756&r1=1582755&r2=1582756&view=diff
==============================================================================
---
subversion/branches/remote-only-status/subversion/tests/libsvn_client/client-test.c
(original)
+++
subversion/branches/remote-only-status/subversion/tests/libsvn_client/client-test.c
Fri Mar 28 14:19:27 2014
@@ -935,6 +935,7 @@ test_remote_only_status(const svn_test_o
remote_only_status_receiver, results, pool));
SVN_TEST_ASSERT(result_rev == 2);
+ SVN_TEST_ASSERT(results->nelts == 3);
qsort(results->elts, results->nelts, results->elt_size,
compare_status_paths);
@@ -965,7 +966,6 @@ test_remote_only_status(const svn_test_o
SVN_TEST_ASSERT(st->revision == 1);
SVN_TEST_ASSERT(st->ood_changed_rev == 2);
SVN_TEST_ASSERT(st->node_status == svn_wc_status_normal);
- /* FIXME: svn_wc_status_none? */
if (0 == strcmp(relpath, "iota"))
SVN_TEST_ASSERT(st->repos_node_status == svn_wc_status_modified);
else
@@ -997,9 +997,8 @@ static struct svn_test_descriptor_t test
SVN_TEST_OPTS_PASS(test_youngest_common_ancestor, "test
youngest_common_ancestor"),
SVN_TEST_OPTS_PASS(test_suggest_mergesources,
"test svn_client_suggest_merge_sources"),
- SVN_TEST_OPTS_WIMP(test_remote_only_status,
- "test svn_client_status6 with ignore_local_mods",
- "status editor does not ignore local mods yet"),
+ SVN_TEST_OPTS_PASS(test_remote_only_status,
+ "test svn_client_status6 with ignore_local_mods"),
SVN_TEST_NULL
};