You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/10/11 21:52:46 UTC
svn commit: r1182053 [19/30] - in /subversion/branches/svn_mutex: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ contrib/client-side/
contrib/hook-scripts/enforcer/ contrib/server-side/ notes/ notes/merge-t...
Modified: subversion/branches/svn_mutex/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_wc/update_editor.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_wc/update_editor.c Tue Oct 11 19:52:34 2011
@@ -699,6 +699,10 @@ struct file_baton
/* Absolute path to this file */
const char *local_abspath;
+ /* Absolute path to the new location of the file if it was moved away.
+ * If the file was not moved away, this is NULL. */
+ const char *moved_to_abspath;
+
/* The repository relative path this file will correspond to. */
const char *new_relpath;
@@ -773,8 +777,8 @@ make_file_baton(struct file_baton **f_p,
svn_boolean_t adding,
apr_pool_t *scratch_pool)
{
+ struct edit_baton *eb = pb->edit_baton;
apr_pool_t *file_pool = svn_pool_create(pb->pool);
-
struct file_baton *f = apr_pcalloc(file_pool, sizeof(*f));
SVN_ERR_ASSERT(path);
@@ -785,17 +789,35 @@ make_file_baton(struct file_baton **f_p,
SVN_ERR(path_join_under_root(&f->local_abspath,
pb->local_abspath, f->name, file_pool));
- /* Figure out the new_URL for this file. */
- if (adding || pb->edit_baton->switch_relpath)
- f->new_relpath = svn_relpath_join(pb->new_relpath, f->name, file_pool);
- else
+ /* Figure out the new URL for this file. */
+ if (eb->switch_relpath)
{
- SVN_ERR(svn_wc__db_scan_base_repos(&f->new_relpath, NULL, NULL,
- pb->edit_baton->db,
- f->local_abspath,
- file_pool, scratch_pool));
+ /* Handle switches... */
- SVN_ERR_ASSERT(f->new_relpath);
+ /* This file has a parent directory. If there is
+ no grandparent, then we may have anchored at the parent,
+ and self is the target. If we match the target, then set
+ NEW_RELPATH to the SWITCH_RELPATH.
+
+ Otherwise, we simply extend NEW_RELPATH from the parent. */
+ if (pb->parent_baton == NULL
+ && strcmp(eb->target_basename, f->name) == 0)
+ f->new_relpath = eb->switch_relpath;
+ else
+ f->new_relpath = svn_relpath_join(pb->new_relpath, f->name,
+ file_pool);
+ }
+ else /* must be an update */
+ {
+ if (adding)
+ f->new_relpath = svn_relpath_join(pb->new_relpath, f->name, file_pool);
+ else
+ {
+ SVN_ERR(svn_wc__db_scan_base_repos(&f->new_relpath, NULL, NULL,
+ eb->db, f->local_abspath,
+ file_pool, scratch_pool));
+ SVN_ERR_ASSERT(f->new_relpath);
+ }
}
f->pool = file_pool;
@@ -1046,7 +1068,6 @@ set_target_revision(void *edit_baton,
{
struct edit_baton *eb = edit_baton;
- /* Stashing a target_revision in the baton */
*(eb->target_revision) = target_revision;
return SVN_NO_ERROR;
}
@@ -1089,7 +1110,7 @@ open_root(void *edit_baton,
/* Notify that we skipped the target, while we actually skipped
the anchor */
do_notification(eb, eb->target_abspath, svn_node_unknown,
- svn_wc_notify_skip, pool);
+ svn_wc_notify_skip_conflicted, pool);
return SVN_NO_ERROR;
}
@@ -1254,7 +1275,8 @@ create_tree_conflict(svn_wc_conflict_des
/* Get the source-left information, i.e. the local state of the node
* before any changes were made to the working copy, i.e. the state the
* node would have if it was reverted. */
- if (reason == svn_wc_conflict_reason_added)
+ if (reason == svn_wc_conflict_reason_added ||
+ reason == svn_wc_conflict_reason_moved_here)
{
svn_wc__db_status_t added_status;
@@ -1282,8 +1304,8 @@ create_tree_conflict(svn_wc_conflict_des
SVN_ERR(svn_wc__db_scan_addition(&added_status, NULL,
&added_repos_relpath,
&repos_root_url,
- NULL, NULL, NULL, NULL, NULL,
- eb->db, local_abspath,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, eb->db, local_abspath,
result_pool, scratch_pool));
/* This better really be an added status. */
@@ -1303,12 +1325,13 @@ create_tree_conflict(svn_wc_conflict_des
else
{
/* A BASE node should exist. */
- svn_wc__db_kind_t base_kind;
+ svn_kind_t base_kind;
/* If anything else shows up, then this assertion is probably naive
* and that other case should also be handled. */
SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_edited
|| reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
|| reason == svn_wc_conflict_reason_replaced
|| reason == svn_wc_conflict_reason_obstructed);
@@ -1323,10 +1346,10 @@ create_tree_conflict(svn_wc_conflict_des
result_pool,
scratch_pool));
/* Translate the node kind. */
- if (base_kind == svn_wc__db_kind_file
- || base_kind == svn_wc__db_kind_symlink)
+ if (base_kind == svn_kind_file
+ || base_kind == svn_kind_symlink)
left_kind = svn_node_file;
- else if (base_kind == svn_wc__db_kind_dir)
+ else if (base_kind == svn_kind_dir)
left_kind = svn_node_dir;
else
SVN_ERR_MALFUNCTION();
@@ -1346,7 +1369,8 @@ create_tree_conflict(svn_wc_conflict_des
/* This is an 'update', so REPOS_RELPATH would be the same as for
* source-left. However, we don't have a source-left for locally
* added files. */
- right_repos_relpath = (reason == svn_wc_conflict_reason_added ?
+ right_repos_relpath = ((reason == svn_wc_conflict_reason_added ||
+ reason == svn_wc_conflict_reason_moved_here) ?
added_repos_relpath : left_repos_relpath);
if (! right_repos_relpath)
right_repos_relpath = their_relpath;
@@ -1428,11 +1452,12 @@ check_tree_conflict(svn_wc_conflict_desc
struct edit_baton *eb,
const char *local_abspath,
svn_wc__db_status_t working_status,
- svn_wc__db_kind_t working_kind,
+ svn_kind_t working_kind,
svn_boolean_t exists_in_repos,
svn_wc_conflict_action_t action,
svn_node_kind_t their_node_kind,
const char *their_relpath,
+ const char *moved_to_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1478,7 +1503,18 @@ check_tree_conflict(svn_wc_conflict_desc
* would not have been called in the first place. */
SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
- reason = svn_wc_conflict_reason_added;
+ /* Scan the addition in case our caller didn't. */
+ if (working_status == svn_wc__db_status_added)
+ SVN_ERR(svn_wc__db_scan_addition(&working_status, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ eb->db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (working_status == svn_wc__db_status_moved_here)
+ reason = svn_wc_conflict_reason_moved_here;
+ else
+ reason = svn_wc_conflict_reason_added;
}
else
{
@@ -1489,8 +1525,8 @@ check_tree_conflict(svn_wc_conflict_desc
case svn_wc__db_status_deleted:
- /* The node is locally deleted. */
- reason = svn_wc_conflict_reason_deleted;
+ if (!moved_to_abspath)
+ reason = svn_wc_conflict_reason_deleted;
break;
case svn_wc__db_status_incomplete:
@@ -1555,6 +1591,7 @@ check_tree_conflict(svn_wc_conflict_desc
* would not have been called in the first place.*/
if (reason == svn_wc_conflict_reason_edited
|| reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
|| reason == svn_wc_conflict_reason_replaced)
/* When the node existed before (it was locally deleted, replaced or
* edited), then 'update' cannot add it "again". So it can only send
@@ -1562,7 +1599,8 @@ check_tree_conflict(svn_wc_conflict_desc
SVN_ERR_ASSERT(action == svn_wc_conflict_action_edit
|| action == svn_wc_conflict_action_delete
|| action == svn_wc_conflict_action_replace);
- else if (reason == svn_wc_conflict_reason_added)
+ else if (reason == svn_wc_conflict_reason_added ||
+ reason == svn_wc_conflict_reason_moved_here)
/* When the node did not exist before (it was locally added), then 'update'
* cannot want to modify it in any way. It can only send _action_add. */
SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
@@ -1668,7 +1706,7 @@ delete_entry(const char *path,
const char *base = svn_relpath_basename(path, NULL);
const char *local_abspath;
const char *repos_relpath;
- svn_wc__db_kind_t kind, base_kind;
+ svn_kind_t kind, base_kind;
svn_boolean_t conflicted;
svn_boolean_t have_base;
svn_boolean_t have_work;
@@ -1740,7 +1778,8 @@ delete_entry(const char *path,
{
SVN_ERR(remember_skipped_tree(eb, local_abspath, scratch_pool));
- do_notification(eb, local_abspath, svn_node_unknown, svn_wc_notify_skip,
+ do_notification(eb, local_abspath, svn_node_unknown,
+ svn_wc_notify_skip_conflicted,
scratch_pool);
svn_pool_destroy(scratch_pool);
@@ -1778,7 +1817,7 @@ delete_entry(const char *path,
SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
status, kind, TRUE,
svn_wc_conflict_action_delete, svn_node_none,
- repos_relpath, pb->pool, scratch_pool));
+ repos_relpath, NULL, pb->pool, scratch_pool));
}
if (tree_conflict != NULL)
@@ -1816,6 +1855,7 @@ delete_entry(const char *path,
keeping a not-present marker */
}
else if (tree_conflict->reason == svn_wc_conflict_reason_deleted
+ || tree_conflict->reason == svn_wc_conflict_reason_moved_away
|| tree_conflict->reason == svn_wc_conflict_reason_replaced)
{
/* The item does not exist locally because it was already shadowed.
@@ -1842,7 +1882,7 @@ delete_entry(const char *path,
SVN_ERR(svn_wc__wq_build_base_remove(&work_item,
eb->db, local_abspath,
SVN_INVALID_REVNUM,
- svn_wc__db_kind_unknown,
+ svn_kind_unknown,
scratch_pool, scratch_pool));
}
else
@@ -1872,7 +1912,7 @@ delete_entry(const char *path,
if (pb->shadowed)
action = svn_wc_notify_update_shadowed_delete;
- if (kind == svn_wc__db_kind_dir)
+ if (kind == svn_kind_dir)
node_kind = svn_node_dir;
else
node_kind = svn_node_file;
@@ -1899,7 +1939,7 @@ add_directory(const char *path,
struct dir_baton *db;
svn_node_kind_t kind;
svn_wc__db_status_t status;
- svn_wc__db_kind_t wc_kind;
+ svn_kind_t wc_kind;
svn_boolean_t conflicted;
svn_boolean_t versioned_locally_and_present;
svn_wc_conflict_description2_t *tree_conflict = NULL;
@@ -1955,13 +1995,13 @@ add_directory(const char *path,
return svn_error_trace(err);
svn_error_clear(err);
- wc_kind = svn_wc__db_kind_unknown;
+ wc_kind = svn_kind_unknown;
status = svn_wc__db_status_normal;
conflicted = FALSE;
versioned_locally_and_present = FALSE;
}
- else if (wc_kind == svn_wc__db_kind_dir
+ else if (wc_kind == svn_kind_dir
&& status == svn_wc__db_status_normal)
{
/* !! We found the root of a separate working copy obstructing the wc !!
@@ -1979,7 +2019,7 @@ add_directory(const char *path,
eb->repos_root,
eb->repos_uuid,
*eb->target_revision,
- svn_wc__db_kind_file,
+ svn_kind_file,
NULL, NULL,
pool));
@@ -1993,8 +2033,8 @@ add_directory(const char *path,
return SVN_NO_ERROR;
}
else if (status == svn_wc__db_status_normal
- && (wc_kind == svn_wc__db_kind_file
- || wc_kind == svn_wc__db_kind_symlink))
+ && (wc_kind == svn_kind_file
+ || wc_kind == svn_kind_symlink))
{
/* We found a file external occupating the place we need in BASE.
@@ -2016,7 +2056,7 @@ add_directory(const char *path,
return SVN_NO_ERROR;
}
- else if (wc_kind == svn_wc__db_kind_unknown)
+ else if (wc_kind == svn_kind_unknown)
versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
else
versioned_locally_and_present = IS_NODE_PRESENT(status);
@@ -2076,13 +2116,13 @@ add_directory(const char *path,
eb->repos_root,
eb->repos_uuid,
*eb->target_revision,
- svn_wc__db_kind_dir,
+ svn_kind_dir,
NULL, NULL,
pool));
/* ### TODO: Also print victim_path in the skip msg. */
do_notification(eb, db->local_abspath, svn_node_dir,
- svn_wc_notify_skip, pool);
+ svn_wc_notify_skip_conflicted, pool);
return SVN_NO_ERROR;
}
@@ -2109,13 +2149,13 @@ add_directory(const char *path,
/* Is the local add a copy? */
if (status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&add_status, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
eb->db, db->local_abspath,
pool, pool));
/* Is there *something* that is not a dir? */
- local_is_non_dir = (wc_kind != svn_wc__db_kind_dir
+ local_is_non_dir = (wc_kind != svn_kind_dir
&& status != svn_wc__db_status_deleted);
/* Do tree conflict checking if
@@ -2135,7 +2175,7 @@ add_directory(const char *path,
status, wc_kind, FALSE,
svn_wc_conflict_action_add,
svn_node_dir, db->new_relpath,
- pool, pool));
+ NULL, pool, pool));
}
if (tree_conflict == NULL)
@@ -2189,7 +2229,7 @@ add_directory(const char *path,
### to theirs with 'svn revert'. */
if (db->shadowed && db->obstruction_found)
{
- SVN_ERR(svn_wc__db_op_delete(eb->db, db->local_abspath,
+ SVN_ERR(svn_wc__db_op_delete(eb->db, db->local_abspath, NULL,
NULL, NULL /* notification */,
eb->cancel_func, eb->cancel_baton,
pool));
@@ -2246,7 +2286,7 @@ open_directory(const char *path,
svn_boolean_t conflicted;
svn_wc_conflict_description2_t *tree_conflict = NULL;
svn_wc__db_status_t status, base_status;
- svn_wc__db_kind_t wc_kind;
+ svn_kind_t wc_kind;
SVN_ERR(make_dir_baton(&db, path, eb, pb, FALSE, pool));
*child_baton = db;
@@ -2313,7 +2353,7 @@ open_directory(const char *path,
db->already_notified = TRUE;
do_notification(eb, db->local_abspath, svn_node_unknown,
- svn_wc_notify_skip, pool);
+ svn_wc_notify_skip_conflicted, pool);
return SVN_NO_ERROR;
}
@@ -2327,7 +2367,7 @@ open_directory(const char *path,
SVN_ERR(check_tree_conflict(&tree_conflict, eb, db->local_abspath,
status, wc_kind, TRUE,
svn_wc_conflict_action_edit, svn_node_dir,
- db->new_relpath, db->pool, pool));
+ db->new_relpath, NULL, db->pool, pool));
/* Remember the roots of any locally deleted trees. */
if (tree_conflict != NULL)
@@ -2336,6 +2376,7 @@ open_directory(const char *path,
/* Other modifications wouldn't be a tree conflict */
SVN_ERR_ASSERT(
tree_conflict->reason == svn_wc_conflict_reason_deleted ||
+ tree_conflict->reason == svn_wc_conflict_reason_moved_away ||
tree_conflict->reason == svn_wc_conflict_reason_replaced);
/* Continue updating BASE */
@@ -2496,85 +2537,89 @@ close_directory(void *dir_baton,
/* If this directory has property changes stored up, now is the time
to deal with them. */
- if (regular_prop_changes->nelts || entry_prop_changes->nelts
- || dav_prop_changes->nelts)
+ if (regular_prop_changes->nelts)
{
- if (regular_prop_changes->nelts)
+ svn_skel_t *work_item;
+
+ /* If recording traversal info, then see if the
+ SVN_PROP_EXTERNALS property on this directory changed,
+ and record before and after for the change. */
+ if (eb->external_func)
{
- svn_skel_t *work_item;
+ const svn_prop_t *change
+ = externals_prop_changed(regular_prop_changes);
- /* If recording traversal info, then see if the
- SVN_PROP_EXTERNALS property on this directory changed,
- and record before and after for the change. */
- if (eb->external_func)
+ if (change)
{
- const svn_prop_t *change
- = externals_prop_changed(regular_prop_changes);
+ const svn_string_t *new_val_s = change->value;
+ const svn_string_t *old_val_s;
- if (change)
- {
- const svn_string_t *new_val_s = change->value;
- const svn_string_t *old_val_s;
-
- old_val_s = apr_hash_get(base_props, SVN_PROP_EXTERNALS,
- APR_HASH_KEY_STRING);
+ old_val_s = apr_hash_get(base_props, SVN_PROP_EXTERNALS,
+ APR_HASH_KEY_STRING);
- if ((new_val_s == NULL) && (old_val_s == NULL))
- ; /* No value before, no value after... so do nothing. */
- else if (new_val_s && old_val_s
- && (svn_string_compare(old_val_s, new_val_s)))
- ; /* Value did not change... so do nothing. */
- else if (old_val_s || new_val_s)
- /* something changed, record the change */
- {
- SVN_ERR((eb->external_func)(
- eb->external_baton,
- db->local_abspath,
- old_val_s,
- new_val_s,
- db->ambient_depth,
- db->pool));
- }
+ if ((new_val_s == NULL) && (old_val_s == NULL))
+ ; /* No value before, no value after... so do nothing. */
+ else if (new_val_s && old_val_s
+ && (svn_string_compare(old_val_s, new_val_s)))
+ ; /* Value did not change... so do nothing. */
+ else if (old_val_s || new_val_s)
+ /* something changed, record the change */
+ {
+ SVN_ERR((eb->external_func)(
+ eb->external_baton,
+ db->local_abspath,
+ old_val_s,
+ new_val_s,
+ db->ambient_depth,
+ db->pool));
}
}
+ }
- /* Merge pending properties into temporary files (ignoring
- conflicts). */
- SVN_ERR_W(svn_wc__merge_props(&work_item,
- &prop_state,
- &new_base_props,
- &new_actual_props,
- eb->db,
- db->local_abspath,
- svn_wc__db_kind_dir,
- NULL, /* left_version */
- NULL, /* right_version */
- NULL /* use baseprops */,
- base_props,
- actual_props,
- regular_prop_changes,
- TRUE /* base_merge */,
- FALSE /* dry_run */,
- eb->conflict_func,
- eb->conflict_baton,
- eb->cancel_func,
- eb->cancel_baton,
- db->pool,
- scratch_pool),
- _("Couldn't do property merge"));
- /* After a (not-dry-run) merge, we ALWAYS have props to save. */
- SVN_ERR_ASSERT(new_base_props != NULL && new_actual_props != NULL);
- all_work_items = svn_wc__wq_merge(all_work_items, work_item,
- scratch_pool);
+ if (db->shadowed)
+ {
+ /* We don't have a relevant actual row, but we need actual properties
+ to allow property merging without conflicts. */
+ if (db->adding_dir)
+ actual_props = apr_hash_make(scratch_pool);
+ else
+ actual_props = base_props;
}
- SVN_ERR(accumulate_last_change(&new_changed_rev,
- &new_changed_date,
- &new_changed_author,
- entry_prop_changes,
- scratch_pool, scratch_pool));
+ /* Merge pending properties into temporary files (ignoring
+ conflicts). */
+ SVN_ERR_W(svn_wc__merge_props(&work_item,
+ &prop_state,
+ &new_base_props,
+ &new_actual_props,
+ eb->db,
+ db->local_abspath,
+ svn_kind_dir,
+ NULL, /* left_version */
+ NULL, /* right_version */
+ NULL /* use baseprops */,
+ base_props,
+ actual_props,
+ regular_prop_changes,
+ TRUE /* base_merge */,
+ FALSE /* dry_run */,
+ eb->conflict_func,
+ eb->conflict_baton,
+ eb->cancel_func,
+ eb->cancel_baton,
+ db->pool,
+ scratch_pool),
+ _("Couldn't do property merge"));
+ /* After a (not-dry-run) merge, we ALWAYS have props to save. */
+ SVN_ERR_ASSERT(new_base_props != NULL && new_actual_props != NULL);
+ all_work_items = svn_wc__wq_merge(all_work_items, work_item,
+ scratch_pool);
}
+ SVN_ERR(accumulate_last_change(&new_changed_rev, &new_changed_date,
+ &new_changed_author, entry_prop_changes,
+ scratch_pool, scratch_pool));
+
/* Check if we should add some not-present markers before marking the
directory complete (Issue #3569) */
{
@@ -2595,7 +2640,7 @@ close_directory(void *dir_baton,
const char *child_relpath;
const svn_dirent_t *dirent;
svn_wc__db_status_t status;
- svn_wc__db_kind_t child_kind;
+ svn_kind_t child_kind;
svn_error_t *err;
svn_pool_clear(iterpool);
@@ -2606,11 +2651,11 @@ close_directory(void *dir_baton,
dirent = svn__apr_hash_index_val(hi);
child_kind = (dirent->kind == svn_node_dir)
- ? svn_wc__db_kind_dir
- : svn_wc__db_kind_file;
+ ? svn_kind_dir
+ : svn_kind_file;
if (db->ambient_depth < svn_depth_immediates
- && child_kind == svn_wc__db_kind_dir)
+ && child_kind == svn_kind_dir)
continue; /* We don't need the subdirs */
/* ### We just check if there is some node in BASE at this path */
@@ -2681,7 +2726,7 @@ close_directory(void *dir_baton,
eb->repos_root,
eb->repos_uuid,
*eb->target_revision,
- svn_wc__db_kind_file,
+ svn_kind_file,
NULL, NULL,
iterpool));
}
@@ -2803,7 +2848,7 @@ close_directory(void *dir_baton,
/* Common code for 'absent_file' and 'absent_directory'. */
static svn_error_t *
absent_node(const char *path,
- svn_wc__db_kind_t absent_kind,
+ svn_kind_t absent_kind,
void *parent_baton,
apr_pool_t *pool)
{
@@ -2814,7 +2859,7 @@ absent_node(const char *path,
const char *local_abspath;
svn_error_t *err;
svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
+ svn_kind_t kind;
if (pb->skip_this)
return SVN_NO_ERROR;
@@ -2839,11 +2884,11 @@ absent_node(const char *path,
svn_error_clear(err);
status = svn_wc__db_status_not_present;
- kind = svn_wc__db_kind_unknown;
+ kind = svn_kind_unknown;
}
if (status == svn_wc__db_status_normal
- && kind == svn_wc__db_kind_dir)
+ && kind == svn_kind_dir)
{
/* We found an obstructing working copy!
@@ -2885,16 +2930,16 @@ absent_node(const char *path,
const char *repos_relpath;
repos_relpath = svn_relpath_join(pb->new_relpath, name, scratch_pool);
- /* Insert an absent node below the parent node to note that this child
+ /* Insert an excluded node below the parent node to note that this child
is absent. (This puts it in the parent db if the child is obstructed) */
- SVN_ERR(svn_wc__db_base_add_absent_node(eb->db, local_abspath,
- repos_relpath, eb->repos_root,
- eb->repos_uuid,
- *(eb->target_revision),
- absent_kind,
- svn_wc__db_status_server_excluded,
- NULL, NULL,
- scratch_pool));
+ SVN_ERR(svn_wc__db_base_add_excluded_node(eb->db, local_abspath,
+ repos_relpath, eb->repos_root,
+ eb->repos_uuid,
+ *(eb->target_revision),
+ absent_kind,
+ svn_wc__db_status_server_excluded,
+ NULL, NULL,
+ scratch_pool));
}
svn_pool_destroy(scratch_pool);
@@ -2909,7 +2954,7 @@ absent_file(const char *path,
void *parent_baton,
apr_pool_t *pool)
{
- return absent_node(path, svn_wc__db_kind_file, parent_baton, pool);
+ return absent_node(path, svn_kind_file, parent_baton, pool);
}
@@ -2919,7 +2964,7 @@ absent_directory(const char *path,
void *parent_baton,
apr_pool_t *pool)
{
- return absent_node(path, svn_wc__db_kind_dir, parent_baton, pool);
+ return absent_node(path, svn_kind_dir, parent_baton, pool);
}
@@ -2936,7 +2981,7 @@ add_file(const char *path,
struct edit_baton *eb = pb->edit_baton;
struct file_baton *fb;
svn_node_kind_t kind = svn_node_none;
- svn_wc__db_kind_t wc_kind = svn_wc__db_kind_unknown;
+ svn_kind_t wc_kind = svn_kind_unknown;
svn_wc__db_status_t status = svn_wc__db_status_normal;
apr_pool_t *scratch_pool;
svn_boolean_t conflicted = FALSE;
@@ -2985,12 +3030,12 @@ add_file(const char *path,
return svn_error_trace(err);
svn_error_clear(err);
- wc_kind = svn_wc__db_kind_unknown;
+ wc_kind = svn_kind_unknown;
conflicted = FALSE;
versioned_locally_and_present = FALSE;
}
- else if (wc_kind == svn_wc__db_kind_dir
+ else if (wc_kind == svn_kind_dir
&& status == svn_wc__db_status_normal)
{
/* !! We found the root of a separate working copy obstructing the wc !!
@@ -3016,8 +3061,8 @@ add_file(const char *path,
return SVN_NO_ERROR;
}
else if (status == svn_wc__db_status_normal
- && (wc_kind == svn_wc__db_kind_file
- || wc_kind == svn_wc__db_kind_symlink))
+ && (wc_kind == svn_kind_file
+ || wc_kind == svn_kind_symlink))
{
/* We found a file external occupating the place we need in BASE.
@@ -3040,7 +3085,7 @@ add_file(const char *path,
return SVN_NO_ERROR;
}
- else if (wc_kind == svn_wc__db_kind_unknown)
+ else if (wc_kind == svn_kind_unknown)
versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
else
versioned_locally_and_present = IS_NODE_PRESENT(status);
@@ -3048,7 +3093,6 @@ add_file(const char *path,
/* Is this path a conflict victim? */
if (conflicted)
- if (conflicted)
{
if (pb->deletion_conflicts)
tree_conflict = apr_hash_get(pb->deletion_conflicts, fb->name,
@@ -3100,7 +3144,7 @@ add_file(const char *path,
APR_HASH_KEY_STRING, (void*)1);
do_notification(eb, fb->local_abspath, svn_node_unknown,
- svn_wc_notify_skip, scratch_pool);
+ svn_wc_notify_skip_conflicted, scratch_pool);
svn_pool_destroy(scratch_pool);
@@ -3132,13 +3176,13 @@ add_file(const char *path,
/* Is the local node a copy or move */
if (status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
eb->db, fb->local_abspath,
scratch_pool, scratch_pool));
/* Is there something that is a file? */
- local_is_file = (wc_kind == svn_wc__db_kind_file
- || wc_kind == svn_wc__db_kind_symlink);
+ local_is_file = (wc_kind == svn_kind_file
+ || wc_kind == svn_kind_symlink);
/* Do tree conflict checking if
* - if there is a local copy.
@@ -3156,7 +3200,7 @@ add_file(const char *path,
fb->local_abspath,
status, wc_kind, FALSE,
svn_wc_conflict_action_add,
- svn_node_file, fb->new_relpath,
+ svn_node_file, fb->new_relpath, NULL,
scratch_pool, scratch_pool));
}
@@ -3233,7 +3277,7 @@ open_file(const char *path,
svn_boolean_t conflicted;
svn_boolean_t have_work;
svn_wc__db_status_t status;
- svn_wc__db_kind_t wc_kind;
+ svn_kind_t wc_kind;
svn_wc_conflict_description2_t *tree_conflict = NULL;
/* the file_pool can stick around for a *long* time, so we want to use
@@ -3289,6 +3333,12 @@ open_file(const char *path,
eb->db, fb->local_abspath,
fb->pool, scratch_pool));
+ /* If the file has moved locally look up its new location. */
+ if (status == svn_wc__db_status_deleted)
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &fb->moved_to_abspath, NULL, NULL,
+ eb->db, fb->local_abspath,
+ fb->pool, scratch_pool));
+
/* Is this path a conflict victim? */
if (conflicted)
SVN_ERR(node_already_conflicted(&conflicted, eb->db,
@@ -3301,7 +3351,7 @@ open_file(const char *path,
fb->already_notified = TRUE;
do_notification(eb, fb->local_abspath, svn_node_unknown,
- svn_wc_notify_skip, scratch_pool);
+ svn_wc_notify_skip_conflicted, scratch_pool);
svn_pool_destroy(scratch_pool);
@@ -3316,7 +3366,8 @@ open_file(const char *path,
SVN_ERR(check_tree_conflict(&tree_conflict, eb, fb->local_abspath,
status, wc_kind, TRUE,
svn_wc_conflict_action_edit, svn_node_file,
- fb->new_relpath, fb->pool, scratch_pool));
+ fb->new_relpath, fb->moved_to_abspath,
+ fb->pool, scratch_pool));
/* Is this path the victim of a newly-discovered tree conflict? */
if (tree_conflict != NULL)
@@ -3326,6 +3377,7 @@ open_file(const char *path,
/* Other modifications wouldn't be a tree conflict */
SVN_ERR_ASSERT(
tree_conflict->reason == svn_wc_conflict_reason_deleted ||
+ tree_conflict->reason == svn_wc_conflict_reason_moved_away||
tree_conflict->reason == svn_wc_conflict_reason_replaced);
/* Continue updating BASE */
@@ -3660,6 +3712,8 @@ merge_file(svn_skel_t **work_items,
svn_boolean_t is_locally_modified;
enum svn_wc_merge_outcome_t merge_outcome = svn_wc_merge_unchanged;
svn_skel_t *work_item;
+ const char *working_abspath = fb->moved_to_abspath ? fb->moved_to_abspath
+ : fb->local_abspath;
SVN_ERR_ASSERT(! fb->shadowed && !fb->obstruction_found);
@@ -3704,7 +3758,7 @@ merge_file(svn_skel_t **work_items,
files that do not exist and for directories. */
SVN_ERR(svn_wc__internal_file_modified_p(&is_locally_modified,
- eb->db, fb->local_abspath,
+ eb->db, working_abspath,
FALSE /* exact_comparison */,
scratch_pool));
}
@@ -3748,7 +3802,7 @@ merge_file(svn_skel_t **work_items,
SVN_ERR(svn_wc__perform_file_merge(work_items,
&merge_outcome,
eb->db,
- fb->local_abspath,
+ working_abspath,
pb->local_abspath,
fb->new_text_base_sha1_checksum,
fb->add_existed
@@ -3780,7 +3834,7 @@ merge_file(svn_skel_t **work_items,
SVN_ERR(svn_wc__get_translate_info(NULL, NULL,
&keywords,
NULL,
- eb->db, fb->local_abspath,
+ eb->db, working_abspath,
actual_props, TRUE,
scratch_pool, scratch_pool));
if (magic_props_changed || keywords)
@@ -3800,7 +3854,7 @@ merge_file(svn_skel_t **work_items,
/* Copy and DEtranslate the working file to a temp text-base.
Note that detranslation is done according to the old props. */
SVN_ERR(svn_wc__internal_translated_file(
- &tmptext, fb->local_abspath, eb->db, fb->local_abspath,
+ &tmptext, working_abspath, eb->db, working_abspath,
SVN_WC_TRANSLATE_TO_NF
| SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP,
eb->cancel_func, eb->cancel_baton,
@@ -3842,7 +3896,7 @@ merge_file(svn_skel_t **work_items,
}
SVN_ERR(svn_wc__wq_build_record_fileinfo(&work_item,
- eb->db, fb->local_abspath,
+ eb->db, working_abspath,
set_date,
result_pool, scratch_pool));
*work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
@@ -3897,6 +3951,9 @@ close_file(void *file_baton,
svn_skel_t *work_item;
apr_pool_t *scratch_pool = fb->pool; /* Destroyed at function exit */
svn_boolean_t keep_recorded_info = FALSE;
+ const svn_checksum_t *new_checksum;
+ const char *working_abspath = fb->moved_to_abspath ? fb->moved_to_abspath
+ : fb->local_abspath;
if (fb->skip_this)
{
@@ -3912,10 +3969,13 @@ close_file(void *file_baton,
if (fb->new_text_base_md5_checksum && expected_md5_checksum
&& !svn_checksum_match(expected_md5_checksum,
fb->new_text_base_md5_checksum))
- return svn_checksum_mismatch_err(expected_md5_checksum,
- fb->new_text_base_md5_checksum, scratch_pool,
- _("Checksum mismatch for '%s'"),
- svn_dirent_local_style(fb->local_abspath, pool));
+ return svn_error_trace(
+ svn_checksum_mismatch_err(expected_md5_checksum,
+ fb->new_text_base_md5_checksum,
+ scratch_pool,
+ _("Checksum mismatch for '%s'"),
+ svn_dirent_local_style(
+ fb->local_abspath, pool)));
/* Gather the changes for each kind of property. */
SVN_ERR(svn_categorize_props(fb->propchanges, &entry_prop_changes,
@@ -3984,7 +4044,7 @@ close_file(void *file_baton,
if ((!fb->adding_file || fb->add_existed)
&& !fb->shadowed)
SVN_ERR(svn_wc__get_actual_props(&local_actual_props,
- eb->db, fb->local_abspath,
+ eb->db, working_abspath,
scratch_pool, scratch_pool));
if (local_actual_props == NULL)
local_actual_props = apr_hash_make(scratch_pool);
@@ -4060,9 +4120,9 @@ close_file(void *file_baton,
### verifying again */
SVN_ERR(check_tree_conflict(&tree_conflict, eb, fb->local_abspath,
svn_wc__db_status_added,
- svn_wc__db_kind_file, TRUE,
+ svn_kind_file, TRUE,
svn_wc_conflict_action_add,
- svn_node_file, fb->new_relpath,
+ svn_node_file, fb->new_relpath, NULL,
scratch_pool, scratch_pool));
SVN_ERR_ASSERT(tree_conflict != NULL);
SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
@@ -4092,8 +4152,8 @@ close_file(void *file_baton,
&new_base_props,
&new_actual_props,
eb->db,
- fb->local_abspath,
- svn_wc__db_kind_file,
+ working_abspath,
+ svn_kind_file,
NULL /* left_version */,
NULL /* right_version */,
NULL /* server_baseprops (update, not merge) */,
@@ -4114,9 +4174,37 @@ close_file(void *file_baton,
/* Merge the text. This will queue some additional work. */
if (!fb->obstruction_found)
{
- SVN_ERR(merge_file(&work_item, &install_pristine, &install_from,
- &content_state, fb, current_actual_props,
- fb->changed_date, scratch_pool, scratch_pool));
+ svn_error_t *err;
+ err = merge_file(&work_item, &install_pristine, &install_from,
+ &content_state, fb, current_actual_props,
+ fb->changed_date, scratch_pool, scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_ACCESS_DENIED)
+ {
+ if (eb->notify_func)
+ {
+ svn_wc_notify_t *notify =svn_wc_create_notify(
+ working_abspath,
+ svn_wc_notify_update_skip_access_denied,
+ scratch_pool);
+
+ notify->kind = svn_node_file;
+ notify->err = err;
+
+ eb->notify_func(eb->notify_baton, notify, scratch_pool);
+ }
+ svn_error_clear(err);
+
+ SVN_ERR(remember_skipped_tree(eb, fb->local_abspath,
+ scratch_pool));
+ fb->skip_this = TRUE;
+
+ SVN_ERR(maybe_release_dir_info(fb->bump_info));
+ svn_pool_destroy(fb->pool);
+ return SVN_NO_ERROR;
+ }
+ else
+ SVN_ERR(err);
all_work_items = svn_wc__wq_merge(all_work_items, work_item,
scratch_pool);
@@ -4143,7 +4231,7 @@ close_file(void *file_baton,
SVN_ERR(svn_wc__wq_build_file_install(&work_item,
eb->db,
- fb->local_abspath,
+ working_abspath,
install_from,
eb->use_commit_times,
record_fileinfo,
@@ -4159,7 +4247,7 @@ close_file(void *file_baton,
Note: this will also update the executable flag, but ... meh. */
SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, eb->db,
- fb->local_abspath,
+ working_abspath,
scratch_pool, scratch_pool));
all_work_items = svn_wc__wq_merge(all_work_items, work_item,
scratch_pool);
@@ -4177,7 +4265,7 @@ close_file(void *file_baton,
/* Remove the INSTALL_FROM file, as long as it doesn't refer to the
working file. */
if (install_from != NULL
- && strcmp(install_from, fb->local_abspath) != 0)
+ && strcmp(install_from, working_abspath) != 0)
{
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, eb->db,
install_from,
@@ -4204,7 +4292,7 @@ close_file(void *file_baton,
&new_actual_props,
eb->db,
fb->local_abspath,
- svn_wc__db_kind_file,
+ svn_kind_file,
NULL /* left_version */,
NULL /* right_version */,
NULL /* server_baseprops (not merging) */,
@@ -4228,43 +4316,62 @@ close_file(void *file_baton,
}
/* Insert/replace the BASE node with all of the new metadata. */
- {
- /* Set the 'checksum' column of the file's BASE_NODE row to
- * NEW_TEXT_BASE_SHA1_CHECKSUM. The pristine text identified by that
- * checksum is already in the pristine store. */
- const svn_checksum_t *new_checksum = fb->new_text_base_sha1_checksum;
-
- /* If we don't have a NEW checksum, then the base must not have changed.
- Just carry over the old checksum. */
- if (new_checksum == NULL)
- new_checksum = fb->original_checksum;
-
- SVN_ERR(svn_wc__db_base_add_file(eb->db, fb->local_abspath,
- eb->wcroot_abspath,
- fb->new_relpath,
- eb->repos_root, eb->repos_uuid,
- *eb->target_revision,
- new_base_props,
- fb->changed_rev,
- fb->changed_date,
- fb->changed_author,
- new_checksum,
- (dav_prop_changes->nelts > 0)
- ? svn_prop_array_to_hash(
- dav_prop_changes,
- scratch_pool)
- : NULL,
- NULL /* conflict */,
- (! fb->shadowed) && new_base_props,
- new_actual_props,
- keep_recorded_info,
- (fb->shadowed && fb->obstruction_found),
- all_work_items,
- scratch_pool));
- }
+
+ /* Set the 'checksum' column of the file's BASE_NODE row to
+ * NEW_TEXT_BASE_SHA1_CHECKSUM. The pristine text identified by that
+ * checksum is already in the pristine store. */
+ new_checksum = fb->new_text_base_sha1_checksum;
+
+ /* If we don't have a NEW checksum, then the base must not have changed.
+ Just carry over the old checksum. */
+ if (new_checksum == NULL)
+ new_checksum = fb->original_checksum;
+
+ SVN_ERR(svn_wc__db_base_add_file(eb->db, fb->local_abspath,
+ eb->wcroot_abspath,
+ fb->new_relpath,
+ eb->repos_root, eb->repos_uuid,
+ *eb->target_revision,
+ new_base_props,
+ fb->changed_rev,
+ fb->changed_date,
+ fb->changed_author,
+ new_checksum,
+ (dav_prop_changes->nelts > 0)
+ ? svn_prop_array_to_hash(
+ dav_prop_changes,
+ scratch_pool)
+ : NULL,
+ NULL /* conflict */,
+ (! fb->shadowed) && new_base_props,
+ new_actual_props,
+ keep_recorded_info,
+ (fb->shadowed && fb->obstruction_found),
+ all_work_items,
+ scratch_pool));
/* Deal with the WORKING tree, based on updates to the BASE tree. */
+ if (fb->moved_to_abspath)
+ {
+ /* Perform another in-DB move of the file to sync meta-data
+ * of the moved-away node with the new BASE node. */
+ SVN_ERR(svn_wc__db_op_copy_file(eb->db, fb->moved_to_abspath,
+ new_actual_props,
+ fb->changed_rev,
+ fb->changed_date,
+ fb->changed_author,
+ fb->new_relpath,
+ eb->repos_root,
+ eb->repos_uuid,
+ *eb->target_revision,
+ new_checksum,
+ TRUE /* is_move */,
+ NULL /* conflict */,
+ NULL, /* no work, just modify DB */
+ scratch_pool));
+ }
+
/* If this file was locally-added and is now being added by the update, we
can toss the local-add, turning this into a local-edit.
If the local file is replaced, we don't want to touch ACTUAL. */
@@ -4281,7 +4388,6 @@ close_file(void *file_baton,
about files which were already notified for another reason.) */
if (eb->notify_func && !fb->already_notified && fb->edited)
{
- const svn_string_t *mime_type;
svn_wc_notify_t *notify;
svn_wc_notify_action_t action = svn_wc_notify_update_update;
@@ -4299,7 +4405,10 @@ close_file(void *file_baton,
action = svn_wc_notify_update_add;
}
- notify = svn_wc_create_notify(fb->local_abspath, action, scratch_pool);
+ /* If the file was moved-away, notify for the moved-away node.
+ * The original location only had its BASE info changed and
+ * we don't usually notify about such changes. */
+ notify = svn_wc_create_notify(working_abspath, action, scratch_pool);
notify->kind = svn_node_file;
notify->content_state = content_state;
notify->prop_state = prop_state;
@@ -4308,12 +4417,8 @@ close_file(void *file_baton,
notify->old_revision = fb->old_revision;
/* Fetch the mimetype from the actual properties */
- mime_type = (new_actual_props != NULL)
- ? apr_hash_get(new_actual_props, SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING)
- : NULL;
-
- notify->mime_type = mime_type == NULL ? NULL : mime_type->data;
+ notify->mime_type = svn_prop_get_value(new_actual_props,
+ SVN_PROP_MIME_TYPE);
eb->notify_func(eb->notify_baton, notify, scratch_pool);
}
@@ -4440,6 +4545,63 @@ close_edit(void *edit_baton,
/*** Returning editors. ***/
+struct fetch_baton
+{
+ svn_wc__db_t *db;
+ const char *target_abspath;
+};
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+ void *baton,
+ const char *path,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct fetch_baton *fpb = baton;
+ const char *local_abspath = svn_dirent_join(fpb->target_abspath, path,
+ scratch_pool);
+ svn_error_t *err;
+
+ err = svn_wc__db_read_props(props, fpb->db, local_abspath,
+ result_pool, scratch_pool);
+
+ /* If the path doesn't exist, just return an empty set of props. */
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ *props = apr_hash_make(result_pool);
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_node_kind_t *kind,
+ void *baton,
+ const char *path,
+ apr_pool_t *scratch_pool)
+{
+ struct fetch_baton *fpb = baton;
+ const char *local_abspath = svn_dirent_join(fpb->target_abspath, path,
+ scratch_pool);
+ svn_kind_t db_kind;
+
+ SVN_ERR(svn_wc__db_read_kind(&db_kind, fpb->db, local_abspath, FALSE,
+ scratch_pool));
+
+ if (db_kind == svn_kind_dir)
+ *kind = svn_node_dir;
+ else if (db_kind == svn_kind_file)
+ *kind = svn_node_file;
+ else
+ *kind = svn_node_none;
+
+ return SVN_NO_ERROR;
+}
+
/* Helper for the three public editor-supplying functions. */
static svn_error_t *
make_editor(svn_revnum_t *target_revision,
@@ -4477,6 +4639,7 @@ make_editor(svn_revnum_t *target_revisio
svn_delta_editor_t *tree_editor = svn_delta_default_editor(edit_pool);
const svn_delta_editor_t *inner_editor;
const char *repos_root, *repos_uuid;
+ struct fetch_baton *fpb;
/* An unknown depth can't be sticky. */
if (depth == svn_depth_unknown)
@@ -4575,7 +4738,7 @@ make_editor(svn_revnum_t *target_revisio
depth. In this case the update won't describe additions that would
have been reported if we updated at the ambient depth. */
svn_error_t *err;
- svn_wc__db_kind_t dir_kind;
+ svn_kind_t dir_kind;
svn_wc__db_status_t dir_status;
const char *dir_repos_relpath;
svn_depth_t dir_depth;
@@ -4589,7 +4752,7 @@ make_editor(svn_revnum_t *target_revisio
scratch_pool, scratch_pool);
if (!err
- && dir_kind == svn_wc__db_kind_dir
+ && dir_kind == svn_kind_dir
&& dir_status == svn_wc__db_status_normal)
{
if (dir_depth > depth)
@@ -4645,7 +4808,7 @@ make_editor(svn_revnum_t *target_revisio
db, child_abspath,
iterpool, iterpool));
- if (dir_kind == svn_wc__db_kind_dir
+ if (dir_kind == svn_kind_dir
&& dir_status == svn_wc__db_status_normal
&& dir_depth > svn_depth_empty)
{
@@ -4696,13 +4859,22 @@ make_editor(svn_revnum_t *target_revisio
inner_baton,
result_pool));
- return svn_delta_get_cancellation_editor(cancel_func,
- cancel_baton,
- inner_editor,
- inner_baton,
- editor,
- edit_baton,
- result_pool);
+ SVN_ERR(svn_delta_get_cancellation_editor(cancel_func,
+ cancel_baton,
+ inner_editor,
+ inner_baton,
+ editor,
+ edit_baton,
+ result_pool));
+
+ fpb = apr_palloc(result_pool, sizeof(*fpb));
+ fpb->db = db;
+ fpb->target_abspath = eb->target_abspath;
+ SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
+ fetch_props_func, fpb, fetch_kind_func, fpb,
+ result_pool, scratch_pool));
+
+ return SVN_NO_ERROR;
}
@@ -4902,7 +5074,7 @@ svn_wc_get_switch_editor4(const svn_delt
svn_error_t *
svn_wc__check_wc_root(svn_boolean_t *wc_root,
- svn_wc__db_kind_t *kind,
+ svn_kind_t *kind,
svn_boolean_t *switched,
svn_wc__db_t *db,
const char *local_abspath,
@@ -4911,7 +5083,7 @@ svn_wc__check_wc_root(svn_boolean_t *wc_
const char *parent_abspath, *name;
const char *repos_relpath, *repos_root, *repos_uuid;
svn_wc__db_status_t status;
- svn_wc__db_kind_t my_kind;
+ svn_kind_t my_kind;
if (!kind)
kind = &my_kind;
@@ -4935,7 +5107,7 @@ svn_wc__check_wc_root(svn_boolean_t *wc_
*wc_root = FALSE;
return SVN_NO_ERROR;
}
- if (*kind != svn_wc__db_kind_dir)
+ if (*kind != svn_kind_dir)
{
/* File/symlinks cannot be a root. */
*wc_root = FALSE;
@@ -5019,7 +5191,7 @@ svn_wc_is_wc_root2(svn_boolean_t *wc_roo
{
svn_boolean_t is_root;
svn_boolean_t is_switched;
- svn_wc__db_kind_t kind;
+ svn_kind_t kind;
svn_error_t *err;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -5035,7 +5207,7 @@ svn_wc_is_wc_root2(svn_boolean_t *wc_roo
return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, err, err->message);
}
- *wc_root = is_root || (kind == svn_wc__db_kind_dir && is_switched);
+ *wc_root = is_root || (kind == svn_kind_dir && is_switched);
return SVN_NO_ERROR;
}
@@ -5075,7 +5247,7 @@ svn_wc_get_actual_target2(const char **a
apr_pool_t *scratch_pool)
{
svn_boolean_t is_wc_root, is_switched;
- svn_wc__db_kind_t kind;
+ svn_kind_t kind;
const char *local_abspath;
svn_error_t *err;
@@ -5097,7 +5269,7 @@ svn_wc_get_actual_target2(const char **a
}
/* If PATH is not a WC root, or if it is a file, lop off a basename. */
- if (!(is_wc_root || is_switched) || (kind != svn_wc__db_kind_dir))
+ if (!(is_wc_root || is_switched) || (kind != svn_kind_dir))
{
svn_dirent_split(anchor, target, path, result_pool);
}
@@ -5135,7 +5307,7 @@ svn_wc_add_repos_file4(svn_wc_context_t
svn_wc__db_t *db = wc_ctx->db;
const char *dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
+ svn_kind_t kind;
const char *tmp_text_base_abspath;
svn_checksum_t *new_text_base_md5_checksum;
svn_checksum_t *new_text_base_sha1_checksum;
@@ -5206,7 +5378,7 @@ svn_wc_add_repos_file4(svn_wc_context_t
svn_dirent_local_style(local_abspath,
scratch_pool));
}
- if (kind != svn_wc__db_kind_dir)
+ if (kind != svn_kind_dir)
return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
_("Can't schedule an addition of '%s'"
" below a not-directory node"),
@@ -5379,6 +5551,7 @@ svn_wc_add_repos_file4(svn_wc_context_t
original_uuid,
copyfrom_rev,
new_text_base_sha1_checksum,
+ FALSE /* is_move */,
NULL /* conflict */,
NULL /* work_items */,
pool));
Modified: subversion/branches/svn_mutex/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_wc/upgrade.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_wc/upgrade.c Tue Oct 11 19:52:34 2011
@@ -1106,6 +1106,18 @@ migrate_text_bases(apr_hash_t **text_bas
is_revert_base = FALSE;
}
+ if (! versioned_file_name)
+ {
+ /* Some file that doesn't end with .svn-base or .svn-revert.
+ No idea why that would be in our administrative area, but
+ we shouldn't segfault on this case.
+
+ Note that we already copied this file in the pristine store,
+ but the next cleanup will take care of that.
+ */
+ continue;
+ }
+
/* Create a new info struct for this versioned file, or fill in the
* existing one if this is the second text-base we've found for it. */
info = apr_hash_get(*text_bases_info, versioned_file_name,
@@ -1273,16 +1285,14 @@ upgrade_externals(struct bump_baton *bb,
while (have_row)
{
apr_hash_t *props;
- const svn_string_t *externals = NULL;
+ const char *externals;
svn_pool_clear(iterpool);
SVN_ERR(svn_sqlite__column_properties(&props, stmt, 0,
iterpool, iterpool));
- if (props)
- externals = apr_hash_get(props, SVN_PROP_EXTERNALS,
- APR_HASH_KEY_STRING);
+ externals = svn_prop_get_value(props, SVN_PROP_EXTERNALS);
if (externals)
{
@@ -1296,7 +1306,7 @@ upgrade_externals(struct bump_baton *bb,
iterpool);
SVN_ERR(svn_wc_parse_externals_description3(&ext, local_abspath,
- externals->data, FALSE,
+ externals, FALSE,
iterpool));
for (i = 0; i < ext->nelts; i++)
@@ -1756,6 +1766,8 @@ is_old_wcroot(const char *local_abspath,
_("Can't upgrade '%s' as it is not a pre-1.7 working copy directory"),
svn_dirent_local_style(local_abspath, scratch_pool));
}
+ else if (svn_dirent_is_root(local_abspath, strlen(local_abspath)))
+ return SVN_NO_ERROR;
svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool);
@@ -1770,14 +1782,15 @@ is_old_wcroot(const char *local_abspath,
entry = apr_hash_get(entries, name, APR_HASH_KEY_STRING);
if (!entry
|| entry->absent
- || (entry->deleted && entry->schedule != svn_wc_schedule_add))
+ || (entry->deleted && entry->schedule != svn_wc_schedule_add)
+ || entry->depth == svn_depth_exclude)
{
return SVN_NO_ERROR;
}
- svn_dirent_split(&parent_abspath, &name, parent_abspath, scratch_pool);
while (!svn_dirent_is_root(parent_abspath, strlen(parent_abspath)))
{
+ svn_dirent_split(&parent_abspath, &name, parent_abspath, scratch_pool);
err = svn_wc__read_entries_old(&entries, parent_abspath,
scratch_pool, scratch_pool);
if (err)
@@ -1789,12 +1802,12 @@ is_old_wcroot(const char *local_abspath,
entry = apr_hash_get(entries, name, APR_HASH_KEY_STRING);
if (!entry
|| entry->absent
- || (entry->deleted && entry->schedule != svn_wc_schedule_add))
+ || (entry->deleted && entry->schedule != svn_wc_schedule_add)
+ || entry->depth == svn_depth_exclude)
{
parent_abspath = svn_dirent_join(parent_abspath, name, scratch_pool);
break;
}
- svn_dirent_split(&parent_abspath, &name, parent_abspath, scratch_pool);
}
return svn_error_createf(
@@ -1901,12 +1914,12 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
scratch_pool));
SVN_ERR(svn_wc__ensure_directory(root_adm_abspath, scratch_pool));
- /* Create an empty sqlite database for this directory. */
+ /* Create an empty sqlite database for this directory and store it in DB. */
SVN_ERR(svn_wc__db_upgrade_begin(&data.sdb,
&data.repos_id, &data.wc_id,
- data.root_abspath,
+ db, data.root_abspath,
this_dir->repos, this_dir->uuid,
- scratch_pool, scratch_pool));
+ scratch_pool));
/* Migrate the entries over to the new database.
### We need to think about atomicity here.
@@ -1951,7 +1964,6 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
SVN_ERR(svn_wc__db_wq_add(db, data.root_abspath, work_items, scratch_pool));
SVN_ERR(svn_wc__db_wclock_release(db, data.root_abspath, scratch_pool));
- SVN_ERR(svn_sqlite__close(data.sdb));
SVN_ERR(svn_wc__db_close(db));
/* Renaming the db file is what makes the pre-wcng into a wcng */
@@ -1973,3 +1985,44 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__upgrade_add_external_info(svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ svn_node_kind_t kind,
+ const char *def_local_abspath,
+ const char *repos_relpath,
+ const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t def_peg_revision,
+ svn_revnum_t def_revision,
+ apr_pool_t *scratch_pool)
+{
+ svn_kind_t db_kind;
+ switch (kind)
+ {
+ case svn_node_dir:
+ db_kind = svn_kind_dir;
+ break;
+
+ case svn_node_file:
+ db_kind = svn_kind_file;
+ break;
+
+ case svn_node_unknown:
+ db_kind = svn_kind_unknown;
+ break;
+
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+
+ SVN_ERR(svn_wc__db_upgrade_insert_external(wc_ctx->db, local_abspath,
+ db_kind,
+ svn_dirent_dirname(local_abspath,
+ scratch_pool),
+ def_local_abspath, repos_relpath,
+ repos_root_url, repos_uuid,
+ def_peg_revision, def_revision,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/svn_mutex/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_wc/wc-metadata.sql?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_wc/wc-metadata.sql Tue Oct 11 19:52:34 2011
@@ -23,12 +23,11 @@
/*
* the KIND column in these tables has one of the following values
- * (documented in the corresponding C type #svn_wc__db_kind_t):
+ * (documented in the corresponding C type #svn_kind_t):
* "file"
* "dir"
* "symlink"
* "unknown"
- * "subdir"
*
* the PRESENCE column in these tables has one of the following values
* (see also the C type #svn_wc__db_status_t):
@@ -316,8 +315,8 @@ CREATE TABLE NODES (
BASE node, the location of the initial checkout.
When op_depth != 0, they indicate where this node was copied/moved from.
- In this case, the fields are set only on the root of the operation,
- and are NULL for all children. */
+ In this case, the fields are set for the root of the operation and for all
+ children. */
repos_id INTEGER REFERENCES REPOSITORY (id),
repos_path TEXT,
revision INTEGER,
@@ -384,7 +383,8 @@ CREATE TABLE NODES (
perhaps add a column called "moved_from". */
/* Boolean value, specifying if this node was moved here (rather than just
- copied). The source of the move is specified in copyfrom_*. */
+ copied). The source of the move is implied by a different node with
+ a moved_to column pointing at this node. */
moved_here INTEGER,
/* If the underlying node was moved away (rather than just deleted), this
@@ -392,8 +392,8 @@ CREATE TABLE NODES (
This is set only on the root of a move, and is NULL for all children.
Note that moved_to never refers to *this* node. It always refers
- to the "underlying" node, whether that is BASE or a child node
- implied from a parent's move/copy. */
+ to the "underlying" node in the BASE tree. A non-NULL moved_to column
+ is only valid in rows where op_depth == 0. */
moved_to TEXT,
@@ -539,7 +539,7 @@ CREATE TABLE EXTERNALS (
local_relpath TEXT NOT NULL,
/* The working copy root can't be recorded as an external in itself
- so this will never be NULL. */
+ so this will never be NULL. ### ATM only inserted, never queried */
parent_relpath TEXT NOT NULL,
/* Repository location fields */
@@ -763,6 +763,16 @@ PRAGMA user_version = 29;
number will be, however, so we're just marking it as 99 for now. */
-- format: 99
+/* TODO: Rename the "absent" presence value to "server-excluded" before
+ the 1.7 release. wc_db.c and this file have references to "absent" which
+ still need to be changed to "server-excluded". */
+/* TODO: Un-confuse *_revision column names in the EXTERNALS table to
+ "-r<operative> foo@<peg>", as suggested by the patch attached to
+ http://svn.haxx.se/dev/archive-2011-09/0478.shtml */
+/* TODO: Remove column parent_relpath from EXTERNALS. We're not using it and
+ never will. It's not interesting like in the NODES table: the external's
+ parent path may be *anything*: unversioned, "behind" a another WC... */
+
/* Now "drop" the tree_conflict_data column from actual_node. */
CREATE TABLE ACTUAL_NODE_BACKUP (
wc_id INTEGER NOT NULL,