summaryrefslogtreecommitdiff
path: root/subversion/libsvn_wc/diff_editor.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
committerPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
commit3faf8d6bffc5d0fb2525ba37bb504c53366caf9d (patch)
tree7e47911263e75034b767fe34b2f8d3d17e91f66d /subversion/libsvn_wc/diff_editor.c
parenta55fb3c0d5eca7d887798125d5b95942b1f01d4b (diff)
Notes
Diffstat (limited to 'subversion/libsvn_wc/diff_editor.c')
-rw-r--r--subversion/libsvn_wc/diff_editor.c182
1 files changed, 152 insertions, 30 deletions
diff --git a/subversion/libsvn_wc/diff_editor.c b/subversion/libsvn_wc/diff_editor.c
index fc059a5d4dea..9b1b0d50baa0 100644
--- a/subversion/libsvn_wc/diff_editor.c
+++ b/subversion/libsvn_wc/diff_editor.c
@@ -145,6 +145,9 @@ struct dir_baton_t
/* TRUE if the node is to be compared with an unrelated node*/
svn_boolean_t ignoring_ancestry;
+ /* TRUE if the directory was reported incomplete to the repository */
+ svn_boolean_t is_incomplete;
+
/* Processor state */
void *pdb;
svn_boolean_t skip;
@@ -741,9 +744,29 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
if (eb->local_before_remote && local_only)
{
+ const char *moved_from_relpath;
+
+ if (info->moved_here)
+ {
+ const char *moved_from_abspath;
+
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+ NULL, NULL, NULL,
+ db, child_abspath,
+ iterpool, iterpool));
+ SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+ moved_from_relpath = svn_dirent_skip_ancestor(
+ eb->anchor_abspath,
+ moved_from_abspath);
+ }
+ else
+ moved_from_relpath = NULL;
+
if (info->kind == svn_node_file && diff_files)
SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
child_relpath,
+ moved_from_relpath,
eb->processor, dir_baton,
eb->diff_pristine,
eb->cancel_func,
@@ -753,6 +776,7 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
child_relpath,
depth_below_here,
+ moved_from_relpath,
eb->processor, dir_baton,
eb->diff_pristine,
eb->cancel_func,
@@ -807,9 +831,29 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
if (!eb->local_before_remote && local_only)
{
+ const char *moved_from_relpath;
+
+ if (info->moved_here)
+ {
+ const char *moved_from_abspath;
+
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+ NULL, NULL, NULL,
+ db, child_abspath,
+ iterpool, iterpool));
+ SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+ moved_from_relpath = svn_dirent_skip_ancestor(
+ eb->anchor_abspath,
+ moved_from_abspath);
+ }
+ else
+ moved_from_relpath = NULL;
+
if (info->kind == svn_node_file && diff_files)
SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
child_relpath,
+ moved_from_relpath,
eb->processor, dir_baton,
eb->diff_pristine,
eb->cancel_func,
@@ -817,12 +861,13 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
iterpool));
else if (info->kind == svn_node_dir && diff_dirs)
SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
- child_relpath, depth_below_here,
- eb->processor, dir_baton,
- eb->diff_pristine,
- eb->cancel_func,
- eb->cancel_baton,
- iterpool));
+ child_relpath, depth_below_here,
+ moved_from_relpath,
+ eb->processor, dir_baton,
+ eb->diff_pristine,
+ eb->cancel_func,
+ eb->cancel_baton,
+ iterpool));
}
}
}
@@ -873,6 +918,7 @@ svn_error_t *
svn_wc__diff_local_only_file(svn_wc__db_t *db,
const char *local_abspath,
const char *relpath,
+ const char *moved_from_relpath,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
svn_boolean_t diff_pristine,
@@ -935,6 +981,7 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
{
copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
copyfrom_src->repos_relpath = original_repos_relpath;
+ copyfrom_src->moved_from_relpath = moved_from_relpath;
}
if (props_mod || !SVN_IS_VALID_REVNUM(revision))
@@ -1013,6 +1060,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
const char *local_abspath,
const char *relpath,
svn_depth_t depth,
+ const char *moved_from_relpath,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
svn_boolean_t diff_pristine,
@@ -1049,6 +1097,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
{
copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
copyfrom_src->repos_relpath = original_repos_relpath;
+ copyfrom_src->moved_from_relpath = moved_from_relpath;
}
/* svn_wc__db_status_incomplete should never happen, as the result won't be
@@ -1136,12 +1185,40 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
child_relpath = svn_relpath_join(relpath, name, iterpool);
+ if (info->moved_here)
+ {
+ const char *moved_from_abspath;
+ const char *a_abspath;
+ const char *a_relpath;
+
+ a_relpath = relpath;
+ a_abspath = local_abspath;
+ while (*a_relpath)
+ {
+ a_relpath = svn_relpath_dirname(a_relpath, iterpool);
+ a_abspath = svn_dirent_dirname(a_abspath, iterpool);
+ }
+
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+ NULL, NULL, NULL,
+ db, child_abspath,
+ iterpool, iterpool));
+ SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+ moved_from_relpath = svn_dirent_skip_ancestor(
+ a_abspath,
+ moved_from_abspath);
+ }
+ else
+ moved_from_relpath = NULL;
+
switch (info->kind)
{
case svn_node_file:
case svn_node_symlink:
SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
child_relpath,
+ moved_from_relpath,
processor, pdb,
diff_pristine,
cancel_func, cancel_baton,
@@ -1154,6 +1231,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
child_relpath,
depth_below_here,
+ moved_from_relpath,
processor, pdb,
diff_pristine,
cancel_func,
@@ -1202,6 +1280,8 @@ handle_local_only(struct dir_baton_t *pb,
{
struct edit_baton_t *eb = pb->eb;
const struct svn_wc__db_info_t *info;
+ const char *child_abspath;
+ const char *moved_from_relpath;
svn_boolean_t repos_delete = (pb->deletes
&& svn_hash_gets(pb->deletes, name));
@@ -1220,10 +1300,8 @@ handle_local_only(struct dir_baton_t *pb,
switch (info->status)
{
- case svn_wc__db_status_incomplete:
- return SVN_NO_ERROR; /* Not local only */
-
case svn_wc__db_status_normal:
+ case svn_wc__db_status_incomplete:
if (!repos_delete)
return SVN_NO_ERROR; /* Local and remote */
svn_hash_sets(pb->deletes, name, NULL);
@@ -1239,6 +1317,25 @@ handle_local_only(struct dir_baton_t *pb,
break;
}
+ child_abspath = svn_dirent_join(pb->local_abspath, name, scratch_pool);
+
+ if (info->moved_here)
+ {
+ const char *moved_from_abspath;
+
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+ NULL, NULL, NULL,
+ eb->db, child_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+ moved_from_relpath = svn_dirent_skip_ancestor(
+ eb->anchor_abspath,
+ moved_from_abspath);
+ }
+ else
+ moved_from_relpath = NULL;
+
if (info->kind == svn_node_dir)
{
svn_depth_t depth ;
@@ -1250,9 +1347,10 @@ handle_local_only(struct dir_baton_t *pb,
SVN_ERR(svn_wc__diff_local_only_dir(
eb->db,
- svn_dirent_join(pb->local_abspath, name, scratch_pool),
+ child_abspath,
svn_relpath_join(pb->relpath, name, scratch_pool),
repos_delete ? svn_depth_infinity : depth,
+ moved_from_relpath,
eb->processor, pb->pdb,
eb->diff_pristine,
eb->cancel_func, eb->cancel_baton,
@@ -1261,8 +1359,9 @@ handle_local_only(struct dir_baton_t *pb,
else
SVN_ERR(svn_wc__diff_local_only_file(
eb->db,
- svn_dirent_join(pb->local_abspath, name, scratch_pool),
+ child_abspath,
svn_relpath_join(pb->relpath, name, scratch_pool),
+ moved_from_relpath,
eb->processor, pb->pdb,
eb->diff_pristine,
eb->cancel_func, eb->cancel_baton,
@@ -1608,25 +1707,47 @@ open_directory(const char *path,
db->repos_only = TRUE;
if (!db->repos_only)
- switch (info->status)
- {
- case svn_wc__db_status_normal:
- break;
- case svn_wc__db_status_deleted:
- db->repos_only = TRUE;
-
- if (!info->have_more_work)
- svn_hash_sets(pb->compared,
- apr_pstrdup(pb->pool, db->name), "");
- break;
- case svn_wc__db_status_added:
- if (eb->ignore_ancestry)
- db->ignoring_ancestry = TRUE;
- else
+ {
+ switch (info->status)
+ {
+ case svn_wc__db_status_normal:
+ case svn_wc__db_status_incomplete:
+ db->is_incomplete = (info->status ==
+ svn_wc__db_status_incomplete);
+ break;
+ case svn_wc__db_status_deleted:
db->repos_only = TRUE;
- break;
- default:
- SVN_ERR_MALFUNCTION();
+
+ if (!info->have_more_work)
+ svn_hash_sets(pb->compared,
+ apr_pstrdup(pb->pool, db->name), "");
+ break;
+ case svn_wc__db_status_added:
+ if (eb->ignore_ancestry)
+ db->ignoring_ancestry = TRUE;
+ else
+ db->repos_only = TRUE;
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+
+ if (info->status == svn_wc__db_status_added
+ || info->status == svn_wc__db_status_deleted)
+ {
+ svn_wc__db_status_t base_status;
+
+ /* Node is shadowed; check BASE */
+ SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ eb->db, db->local_abspath,
+ dir_pool, dir_pool));
+
+ if (base_status == svn_wc__db_status_incomplete)
+ db->is_incomplete = TRUE;
+ }
}
if (!db->repos_only)
@@ -1714,7 +1835,7 @@ close_directory(void *dir_baton,
{
apr_hash_t *repos_props;
- if (db->added)
+ if (db->added || db->is_incomplete)
{
repos_props = apr_hash_make(scratch_pool);
}
@@ -1891,6 +2012,7 @@ open_file(const char *path,
switch (info->status)
{
case svn_wc__db_status_normal:
+ case svn_wc__db_status_incomplete:
break;
case svn_wc__db_status_deleted:
fb->repos_only = TRUE;