You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/03/30 22:58:01 UTC
svn commit: r929279 [14/20] - in
/subversion/branches/svn-patch-improvements: ./ build/ac-macros/
build/generator/ build/generator/templates/ contrib/client-side/emacs/
notes/feedback/ notes/meetings/ notes/wc-ng/ subversion/
subversion/bindings/javahl...
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/update_editor.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/update_editor.c Tue Mar 30 20:57:53 2010
@@ -170,7 +170,7 @@ struct edit_baton
/* Array of file extension patterns to preserve as extensions in
generated conflict files. */
- apr_array_header_t *ext_patterns;
+ const apr_array_header_t *ext_patterns;
/* The revision we're targeting...or something like that. This
starts off as a pointer to the revision to which we are updating,
@@ -203,15 +203,15 @@ struct edit_baton
that the edit was completed successfully. */
svn_boolean_t close_edit_complete;
- /* If this is a 'switch' operation, the target URL (### corresponding to
- the ANCHOR plus TARGET path?), else NULL. */
- const char *switch_url;
+ /* If this is a 'switch' operation, the new relpath of target_abspath,
+ else NULL. */
+ const char *switch_relpath;
- /* The URL to the root of the repository, or NULL. */
- const char *repos;
+ /* The URL to the root of the repository. */
+ const char *repos_root;
/* The UUID of the repos, or NULL. */
- const char *uuid;
+ const char *repos_uuid;
/* External diff3 to use for merges (can be null, in which case
internal merge code is used). */
@@ -278,8 +278,8 @@ struct dir_baton
/* Absolute path of this directory */
const char *local_abspath;
- /* The repository URL this directory will correspond to. */
- const char *new_URL;
+ /* The repository relative path this directory will correspond to. */
+ const char *new_relpath;
/* The revision of the directory before updating */
svn_revnum_t old_revision;
@@ -336,7 +336,11 @@ struct dir_baton
svn_depth_t ambient_depth;
/* Was the directory marked as incomplete before the update?
- (In other words, are we resuming an interrupted update?) */
+ (In other words, are we resuming an interrupted update?)
+
+ If WAS_INCOMPLETE is set to TRUE we expect to receive all child nodes
+ and properties for/of the directory. If WAS_INCOMPLETE is FALSE then
+ we only receive the changes in/for children and properties.*/
svn_boolean_t was_incomplete;
/* The pool in which this baton itself is allocated. */
@@ -417,7 +421,17 @@ struct handler_baton
/* Get an empty file in the temporary area for WRI_ABSPATH. The file will
not be set for automatic deletion, and the name will be returned in
- TMP_FILENAME. */
+ TMP_FILENAME.
+
+ This implementation creates a new empty file with a unique name.
+
+ ### This is inefficient for callers that just want an empty file to read
+ ### from. There could be (and there used to be) a permanent, shared
+ ### empty file for this purpose.
+
+ ### This is inefficient for callers that just want to reserve a unique
+ ### file name to create later. A better way may not be readily available.
+ */
static svn_error_t *
get_empty_tmp_file(const char **tmp_filename,
svn_wc__db_t *db,
@@ -440,30 +454,54 @@ get_empty_tmp_file(const char **tmp_file
}
-/* Return the url for LOCAL_ABSPATH allocated in RESULT_POOL, or NULL if
- * unable to obtain a url.
+/* Return the repository relative path for LOCAL_ABSPATH allocated in
+ * RESULT_POOL, or NULL if unable to obtain.
*
- * Use WC_CTX to retrieve information on LOCAL_ABSPATH, and do
- * all temporary allocation in SCRATCH_POOL.
+ * Use DB to retrieve information on LOCAL_ABSPATH, and do all temporary
+ * allocation in SCRATCH_POOL.
*/
static const char *
-node_get_url_ignore_errors(svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+node_get_relpath_ignore_errors(svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
+ svn_wc__db_status_t status;
svn_error_t *err;
- const char *url;
+ const char *relpath = NULL;
+
+ err = svn_wc__db_read_info(&status, NULL, NULL, &relpath, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL,
+ db, local_abspath, result_pool, scratch_pool);
- err = svn_wc__node_get_url(&url, wc_ctx, local_abspath, result_pool,
- scratch_pool);
if (err)
{
svn_error_clear(err);
- url = NULL;
+ return NULL;
}
- return url;
+ if (relpath)
+ return relpath;
+
+ if (status == svn_wc__db_status_added ||
+ status == svn_wc__db_status_obstructed_add)
+ {
+ svn_error_clear(svn_wc__db_scan_addition(NULL, NULL, &relpath, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath,
+ result_pool, scratch_pool));
+ }
+ else if (status != svn_wc__db_status_deleted &&
+ status != svn_wc__db_status_obstructed_delete)
+ {
+ svn_error_clear(svn_wc__db_scan_base_repos(&relpath, NULL, NULL,
+ db, local_abspath,
+ result_pool, scratch_pool));
+ }
+
+ return relpath;
}
/* Flush accumulated log entries to a log file on disk for DIR_BATON and
@@ -472,12 +510,8 @@ node_get_url_ignore_errors(svn_wc_contex
static svn_error_t *
flush_log(struct dir_baton *db, apr_pool_t *pool)
{
- if (! svn_stringbuf_isempty(db->log_accum))
- {
- SVN_ERR(svn_wc__wq_add_loggy(db->edit_baton->db, db->local_abspath,
- db->log_accum, pool));
- svn_stringbuf_setempty(db->log_accum);
- }
+ SVN_WC__FLUSH_LOG_ACCUM(db->edit_baton->db, db->local_abspath,
+ db->log_accum, pool);
return SVN_NO_ERROR;
}
@@ -494,7 +528,9 @@ cleanup_dir_baton(void *dir_baton)
err = flush_log(db, pool);
if (!err)
- err = svn_wc__run_log2(eb->db, db->local_abspath, pool);
+ err = svn_wc__wq_run(eb->db, db->local_abspath,
+ eb->cancel_func, eb->cancel_baton,
+ pool);
/* If the editor aborts for some sort of error, the command line
client relies on pool cleanup to run outstanding work queues and
@@ -505,11 +541,7 @@ cleanup_dir_baton(void *dir_baton)
associated with a pool distinct from the edit pool and so were
removed separately. */
if (!err && !eb->close_edit_complete)
- {
- svn_wc_context_t fake_ctx;
- fake_ctx.db = eb->db;
- err = svn_wc__release_write_lock(&fake_ctx, db->local_abspath, pool);
- }
+ err = svn_wc__release_write_lock(eb->wc_ctx, db->local_abspath, pool);
if (err)
{
@@ -573,8 +605,8 @@ make_dir_baton(struct dir_baton **d_p,
d->local_abspath = eb->anchor_abspath;
}
- /* Figure out the new_URL for this directory. */
- if (eb->switch_url)
+ /* Figure out the new_relpath for this directory. */
+ if (eb->switch_relpath)
{
/* Switches are, shall we say, complex. If this directory is
the root directory (it has no parent), then it either gets
@@ -584,9 +616,9 @@ make_dir_baton(struct dir_baton **d_p,
if (! pb)
{
if (! *eb->target_basename) /* anchor is also target */
- d->new_URL = apr_pstrdup(dir_pool, eb->switch_url);
+ d->new_relpath = apr_pstrdup(dir_pool, eb->switch_relpath);
else
- d->new_URL = svn_uri_dirname(eb->switch_url, dir_pool);
+ d->new_relpath = svn_relpath_dirname(eb->switch_relpath, dir_pool);
}
/* Else this directory is *not* the root (has a parent). If it
is the target (there is a target, and this directory has no
@@ -595,10 +627,10 @@ make_dir_baton(struct dir_baton **d_p,
else
{
if (*eb->target_basename && (! pb->parent_baton))
- d->new_URL = apr_pstrdup(dir_pool, eb->switch_url);
+ d->new_relpath = apr_pstrdup(dir_pool, eb->switch_relpath);
else
- d->new_URL = svn_path_url_add_component2(pb->new_URL,
- d->name, dir_pool);
+ d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
+ dir_pool);
}
}
else /* must be an update */
@@ -606,11 +638,10 @@ make_dir_baton(struct dir_baton **d_p,
/* updates are the odds ones. if we're updating a path already
present on disk, we use its original URL. otherwise, we'll
telescope based on its parent's URL. */
- d->new_URL = node_get_url_ignore_errors(eb->wc_ctx, d->local_abspath,
- dir_pool, scratch_pool);
- if ((! d->new_URL) && pb)
- d->new_URL = svn_path_url_add_component2(pb->new_URL, d->name,
- dir_pool);
+ d->new_relpath = node_get_relpath_ignore_errors(eb->db, d->local_abspath,
+ dir_pool, scratch_pool);
+ if ((! d->new_relpath) && pb)
+ d->new_relpath = svn_relpath_join(pb->new_relpath, d->name, dir_pool);
}
/* the bump information lives in the edit pool */
@@ -663,6 +694,25 @@ already_in_a_tree_conflict(svn_boolean_t
apr_pool_t *scratch_pool);
+static void
+do_notification(const struct edit_baton *eb,
+ const char *local_abspath,
+ svn_node_kind_t kind,
+ svn_wc_notify_action_t action,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc_notify_t *notify;
+
+ if (eb->notify_func == NULL)
+ return;
+
+ notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
+ notify->kind = kind;
+
+ (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+}
+
+
/* Helper for maybe_bump_dir_info():
In a single atomic action, (1) remove any 'deleted' entries from a
@@ -687,14 +737,14 @@ complete_directory(struct edit_baton *eb
/* Before we can finish, we may need to clear the exclude flag for
target. Also give a chance to the target that is explicitly pulled
in. */
- svn_depth_t depth;
svn_wc__db_kind_t kind;
+ svn_wc__db_status_t status;
svn_error_t *err;
SVN_ERR_ASSERT(strcmp(local_abspath, eb->anchor_abspath) == 0);
- err = svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, &depth, NULL, NULL, NULL,
+ err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL,
eb->db, eb->target_abspath, pool, pool);
@@ -706,11 +756,10 @@ complete_directory(struct edit_baton *eb
else if (err)
return svn_error_return(err);
- if (depth == svn_depth_exclude)
+ if (status == svn_wc__db_status_excluded)
{
/* There is a small chance that the target is gone in the
- repository. If so, we should get rid of the entry
- (and thus get rid of the exclude flag) now. */
+ repository. If so, we should get rid of the entry now. */
if (kind == svn_wc__db_kind_dir &&
svn_wc__adm_missing(eb->db, eb->target_abspath, pool))
@@ -722,11 +771,6 @@ complete_directory(struct edit_baton *eb
SVN_ERR(do_entry_deletion(eb, eb->target_abspath,
NULL, FALSE, pool));
}
- else
- {
- SVN_ERR(svn_wc__set_depth(eb->db, eb->target_abspath,
- eb->requested_depth, pool));
- }
}
return SVN_NO_ERROR;
@@ -736,26 +780,13 @@ complete_directory(struct edit_baton *eb
SVN_ERR(svn_wc__db_temp_op_set_base_incomplete(eb->db, local_abspath, FALSE,
pool));
- /* ### If we are updating below a delete-* treeconflict, all the
- entries are moved to the copied state. This duplicates the incomplete
- state to WORKING_NODE, so also clear it there. */
- {
- svn_wc__db_status_t status;
- SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
- eb->db, local_abspath, pool, pool));
-
- if (status == svn_wc__db_status_incomplete)
- SVN_ERR(svn_wc__db_temp_op_set_working_incomplete(eb->db, local_abspath,
- FALSE, pool));
- }
-
if (eb->depth_is_sticky)
{
svn_depth_t depth;
+ /* ### We should specifically check BASE_NODE here and then only remove
+ the BASE_NODE if there is a WORKING_NODE. */
+
SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, &depth, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -841,16 +872,11 @@ complete_directory(struct edit_baton *eb
{
SVN_ERR(svn_wc__entry_remove(eb->db, node_abspath, iterpool));
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(node_abspath,
- svn_wc_notify_update_delete,
- iterpool);
- notify->kind = (kind == svn_wc__db_kind_dir) ? svn_node_dir
- : svn_node_file;
- (* eb->notify_func)(eb->notify_baton, notify, iterpool);
- }
+ do_notification(eb, node_abspath, svn_wc_notify_update_delete,
+ (kind == svn_wc__db_kind_dir)
+ ? svn_node_dir
+ : svn_node_file,
+ iterpool);
}
}
@@ -902,8 +928,8 @@ struct file_baton
/* Absolute path to this file */
const char *local_abspath;
- /* The repository URL this file will correspond to. */
- const char *new_URL;
+ /* The repository relative path this file will correspond to. */
+ const char *new_relpath;
/* The revision of the file before updating */
svn_revnum_t old_revision;
@@ -997,9 +1023,6 @@ struct file_baton
/* Bump information for the directory this file lives in */
struct bump_dir_info *bump_info;
-
- /* log accumulator; will be flushed and run in close_file(). */
- svn_stringbuf_t *log_accum;
};
@@ -1025,19 +1048,12 @@ make_file_baton(struct file_baton **f_p,
f->local_abspath = svn_dirent_join(pb->local_abspath, f->name, file_pool);
/* Figure out the new_URL for this file. */
- if (pb->edit_baton->switch_url)
- {
- f->new_URL = svn_path_url_add_component2(pb->new_URL, f->name,
- file_pool);
- }
+ if (pb->edit_baton->switch_relpath)
+ f->new_relpath = svn_relpath_join(pb->new_relpath, f->name, file_pool);
else
- {
- f->new_URL = node_get_url_ignore_errors(pb->edit_baton->wc_ctx,
- svn_dirent_join(pb->local_abspath,
- f->name,
- scratch_pool),
- file_pool, scratch_pool);
- }
+ f->new_relpath = node_get_relpath_ignore_errors(pb->edit_baton->db,
+ f->local_abspath,
+ file_pool, scratch_pool);
f->pool = file_pool;
f->edit_baton = pb->edit_baton;
@@ -1049,8 +1065,6 @@ make_file_baton(struct file_baton **f_p,
f->deleted = FALSE;
f->dir_baton = pb;
- f->log_accum = svn_stringbuf_create("", file_pool);
-
/* No need to initialize f->digest, since we used pcalloc(). */
/* the directory's bump info has one more referer now */
@@ -1060,24 +1074,8 @@ make_file_baton(struct file_baton **f_p,
return SVN_NO_ERROR;
}
-static svn_error_t *
-flush_file_log(struct file_baton *fb, apr_pool_t *pool)
-{
- if (! svn_stringbuf_isempty(fb->log_accum))
- {
- SVN_ERR(svn_wc__wq_add_loggy(fb->edit_baton->db,
- fb->dir_baton->local_abspath,
- fb->log_accum, pool));
- svn_stringbuf_setempty(fb->log_accum);
- }
-
- return SVN_NO_ERROR;
-}
-
-
-
-/*** Helpers for the editor callbacks. ***/
+/* */
static svn_error_t *
window_handler(svn_txdelta_window_t *window, void *baton)
{
@@ -1156,7 +1154,7 @@ prep_directory(struct dir_baton *db,
svn_revnum_t ancestor_revision,
apr_pool_t *pool)
{
- const char *repos;
+ const char *repos_root;
const char *dir_abspath;
svn_boolean_t locked_here;
@@ -1167,17 +1165,17 @@ prep_directory(struct dir_baton *db,
/* Use the repository root of the anchor, but only if it actually is an
ancestor of the URL of this directory. */
- if (db->edit_baton->repos
- && svn_uri_is_ancestor(db->edit_baton->repos, ancestor_url))
- repos = db->edit_baton->repos;
+ if (svn_uri_is_ancestor(db->edit_baton->repos_root, ancestor_url))
+ repos_root = db->edit_baton->repos_root;
else
- repos = NULL;
+ repos_root = NULL;
/* Make sure it's the right working copy, either by creating it so,
or by checking that it is so already. */
SVN_ERR(svn_wc__internal_ensure_adm(db->edit_baton->db, dir_abspath,
- ancestor_url, repos,
- db->edit_baton->uuid, ancestor_revision,
+ ancestor_url, repos_root,
+ db->edit_baton->repos_uuid,
+ ancestor_revision,
db->ambient_depth, pool));
SVN_ERR(svn_wc_locked2(&locked_here, NULL, db->edit_baton->wc_ctx,
@@ -1204,18 +1202,27 @@ struct last_change_info
const char *cmt_author;
};
-/* Accumulate last change info in LAST_CHANGE to set on LOCAL_ABSPATH.
- ENTRY_PROPS is an array of svn_prop_t* entry props.
- If ENTRY_PROPS contains the removal of a lock token, the lock info is
- directly removed from LOCAL_ABSPATH in DB and LOCK_STATE, if non-NULL, will
- be set to svn_wc_notify_lock_state_unlocked. Else, LOCK_STATE, if non-NULL
- will be set to svn_wc_lock_state_unchanged. */
+/* Update the fields of *LAST_CHANGE to represent the last-change info found
+ in ENTRY_PROPS, an array of svn_prop_t* entry props. Update each field
+ separately, ignoring any unexpected properties and any properties with
+ null values (except the lock token as described below).
+
+ If ENTRY_PROPS contains a lock token property with a null value, remove
+ the lock info directly from LOCAL_ABSPATH in DB and set *LOCK_STATE (if
+ LOCK_STATE is non-NULL) to svn_wc_notify_lock_state_unlocked, else set
+ *LOCK_STATE (if LOCK_STATE is non-NULL) to svn_wc_lock_state_unchanged.
+ ENTRY_PROPS must not contain a lock token with a non-null value.
+
+ If *LAST_CHANGE was NULL, first set it to a new structure allocated from
+ RESULT_POOL and initialize each field to its appropriate null or invalid
+ value.
+ */
static svn_error_t *
accumulate_last_change(struct last_change_info **last_change,
svn_wc_notify_lock_state_t *lock_state,
svn_wc__db_t *db,
const char *local_abspath,
- apr_array_header_t *entry_props,
+ const apr_array_header_t *entry_props,
apr_pool_t *scratch_pool,
apr_pool_t *result_pool)
{
@@ -1233,6 +1240,7 @@ accumulate_last_change(struct last_chang
defunct, so remove it directly. */
if (! strcmp(prop->name, SVN_PROP_ENTRY_LOCK_TOKEN))
{
+ SVN_ERR_ASSERT(prop->value == NULL);
SVN_ERR(svn_wc__db_lock_remove(db, local_abspath, scratch_pool));
if (lock_state)
@@ -1319,7 +1327,6 @@ set_target_revision(void *edit_baton,
return SVN_NO_ERROR;
}
-
/* An svn_delta_editor_t function. */
static svn_error_t *
open_root(void *edit_baton,
@@ -1367,12 +1374,8 @@ open_root(void *edit_baton,
/* Notify that we skipped the target, while we actually skipped
the anchor */
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(eb->target_abspath,
- svn_wc_notify_skip,
- pool),
- pool);
+ do_notification(eb, eb->target_abspath, svn_node_unknown,
+ svn_wc_notify_skip, pool);
return SVN_NO_ERROR;
}
@@ -1380,33 +1383,23 @@ open_root(void *edit_baton,
if (! *eb->target_basename)
{
/* For an update with a NULL target, this is equivalent to open_dir(): */
- svn_wc_entry_t tmp_entry;
svn_depth_t depth;
svn_wc__db_status_t status;
- apr_uint64_t flags = SVN_WC__ENTRY_MODIFY_REVISION |
- SVN_WC__ENTRY_MODIFY_URL;
/* Read the depth from the entry. */
- SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
+ SVN_ERR(svn_wc__db_base_get_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, &depth, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
- eb->db, db->local_abspath, pool, pool));
+ NULL, eb->db, db->local_abspath, pool, pool));
db->ambient_depth = depth;
db->was_incomplete = (status == svn_wc__db_status_incomplete);
/* ### TODO: Skip if inside a conflicted tree. */
- /* Mark directory as being at target_revision, but incomplete. */
- tmp_entry.revision = *(eb->target_revision);
- tmp_entry.url = db->new_URL;
- SVN_ERR(svn_wc__entry_modify2(eb->db, db->local_abspath, svn_node_dir,
- FALSE,
- &tmp_entry, flags,
- pool));
-
- SVN_ERR(svn_wc__db_temp_op_set_base_incomplete(eb->db, db->local_abspath,
- TRUE, pool));
+ SVN_ERR(svn_wc__db_temp_op_start_directory_update(eb->db,
+ db->local_abspath,
+ db->new_relpath,
+ *eb->target_revision,
+ pool));
}
return SVN_NO_ERROR;
@@ -1488,6 +1481,7 @@ typedef struct modcheck_baton_t {
then this field has no meaning. */
} modcheck_baton_t;
+/* */
static svn_error_t *
modcheck_found_node(const char *local_abspath,
void *walk_baton,
@@ -1573,10 +1567,11 @@ tree_has_local_mods(svn_boolean_t *modif
* function. E.g. dir_opened() should pass svn_node_dir, etc.
* In some cases of delete, svn_node_none may be used here.
*
- * THEIR_URL is the involved node's URL on the source-right side, the
- * side that the target should become after the update. Simply put,
- * that's the URL obtained from the node's dir_baton->new_URL or
- * file_baton->new_URL (but it's more complex for a delete).
+ * THEIR_RELPATH is the involved node's repository relative path on the
+ * source-right side, the side that the target should become after the
+ * update. Simply put, that's the URL obtained from the node's
+ * dir_baton->new_relpath or file_baton->new_relpath (but it's more
+ * complex for a delete).
*
* ACCEPT_DELETED is true if one of the ancestors got tree conflicted, but
* the operation continued updating a deleted base tree.
@@ -1590,7 +1585,7 @@ check_tree_conflict(svn_wc_conflict_desc
const char *local_abspath,
svn_wc_conflict_action_t action,
svn_node_kind_t their_node_kind,
- const char *their_url,
+ const char *their_relpath,
apr_pool_t *pool)
{
svn_wc__db_status_t status;
@@ -1756,8 +1751,7 @@ 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)
/* 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);
@@ -1775,8 +1769,8 @@ check_tree_conflict(svn_wc_conflict_desc
svn_node_kind_t conflict_node_kind;
svn_wc_conflict_version_t *src_left_version;
svn_wc_conflict_version_t *src_right_version;
-
- /* Get the source-left information, i.e. the local state of the node
+
+ /* 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)
@@ -1842,8 +1836,7 @@ check_tree_conflict(svn_wc_conflict_desc
if (base_kind == svn_wc__db_kind_file
|| base_kind == svn_wc__db_kind_symlink)
left_kind = svn_node_file;
- else
- if (base_kind == svn_wc__db_kind_dir)
+ else if (base_kind == svn_wc__db_kind_dir)
left_kind = svn_node_dir;
else
SVN_ERR_MALFUNCTION();
@@ -1852,13 +1845,12 @@ check_tree_conflict(svn_wc_conflict_desc
/* Find the source-right information, i.e. the state in the repository
* to which we would like to update. */
- if (eb->switch_url != NULL)
+ if (eb->switch_relpath)
{
/* If this is a 'switch' operation, try to construct the switch
* target's REPOS_RELPATH. */
- if (their_url != NULL)
- right_repos_relpath = svn_uri_is_child(repos_root_url, their_url,
- pool);
+ if (their_relpath != NULL)
+ right_repos_relpath = their_relpath;
else
{
/* The complete source-right URL is not available, but it
@@ -1867,8 +1859,7 @@ check_tree_conflict(svn_wc_conflict_desc
* ### TODO: Construct a proper THEIR_URL in some of the
* delete cases that still pass NULL for THEIR_URL when
* calling this function. Do that on the caller's side. */
- right_repos_relpath = svn_uri_is_child(repos_root_url,
- eb->switch_url, pool);
+ right_repos_relpath = eb->switch_relpath;
right_repos_relpath = apr_pstrcat(pool, right_repos_relpath,
"_THIS_IS_INCOMPLETE", NULL);
}
@@ -1905,7 +1896,7 @@ check_tree_conflict(svn_wc_conflict_desc
left_revision,
left_kind,
pool);
-
+
src_right_version = svn_wc_conflict_version_create(repos_root_url,
right_repos_relpath,
*eb->target_revision,
@@ -1914,7 +1905,7 @@ check_tree_conflict(svn_wc_conflict_desc
*pconflict = svn_wc_conflict_description_create_tree2(
local_abspath, conflict_node_kind,
- eb->switch_url ?
+ eb->switch_relpath ?
svn_wc_operation_switch : svn_wc_operation_update,
src_left_version, src_right_version, pool);
(*pconflict)->action = action;
@@ -2049,236 +2040,31 @@ node_already_conflicted(svn_boolean_t *c
return SVN_NO_ERROR;
}
-
-/* A walk baton for schedule_existing_item_for_re_add()'s call
- to svn_wc_walk_entries3(). */
-struct set_copied_baton_t
-{
- struct edit_baton *eb;
-
- /* The PATH arg to schedule_existing_item_for_re_add(). */
- const char *added_subtree_root_path;
-};
-
-/* An svn_wc__node_found_func_t callback function.
- * Set the 'copied' flag on the given ENTRY for every PATH
- * under ((set_copied_baton_t *)WALK_BATON)->ADDED_SUBTREE_ROOT_PATH
- * which has a normal schedule. */
-static svn_error_t *
-set_copied_callback(const char *local_abspath,
- void *walk_baton,
- apr_pool_t *scratch_pool)
-{
- struct set_copied_baton_t *b = walk_baton;
- svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
-
- if (strcmp(local_abspath, b->added_subtree_root_path) == 0)
- return SVN_NO_ERROR; /* Don't touch the root */
-
- SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- b->eb->db, local_abspath,
- scratch_pool, scratch_pool));
-
- if (kind == svn_wc__db_kind_dir)
- {
- /* We don't want to mark a deleted PATH as copied. If PATH
- is added without history we don't want to make it look like
- it has history. If PATH is replaced we don't want to make
- it look like it has history if it doesn't. Only if PATH is
- schedule normal do we need to mark it as copied. */
- if (status == svn_wc__db_status_normal)
- {
- svn_wc_entry_t tmp_entry;
-
- /* Set the 'copied' flag and write the entry out to disk. */
- tmp_entry.copied = TRUE;
- SVN_ERR(svn_wc__entry_modify2(b->eb->db,
- local_abspath,
- svn_node_dir,
- TRUE,
- &tmp_entry,
- SVN_WC__ENTRY_MODIFY_COPIED,
- scratch_pool));
- }
- }
-
- /* We don't want to mark a deleted PATH as copied. If PATH
- is added without history we don't want to make it look like
- it has history. If PATH is replaced we don't want to make
- it look like it has history if it doesn't. Only if PATH is
- schedule normal do we need to mark it as copied. */
- if (status == svn_wc__db_status_normal)
- {
- svn_wc_entry_t tmp_entry;
- apr_hash_t *props;
-
- /* We switch the node from BASE to WORKING.. We have to move the
- properties with it */
- SVN_ERR(svn_wc__db_read_pristine_props(&props, b->eb->db, local_abspath,
- scratch_pool, scratch_pool));
-
- /* Set the 'copied' flag and write the entry out to disk. */
- tmp_entry.copied = TRUE;
- SVN_ERR(svn_wc__entry_modify2(b->eb->db,
- local_abspath,
- kind == svn_wc__db_kind_dir
- ? svn_node_dir
- : svn_node_file,
- FALSE,
- &tmp_entry,
- SVN_WC__ENTRY_MODIFY_COPIED,
- scratch_pool));
-
- SVN_ERR(svn_wc__db_temp_op_set_pristine_props(b->eb->db, local_abspath, props,
- TRUE, scratch_pool));
- }
- return SVN_NO_ERROR;
-}
-
-/* Schedule the WC item LOCAL_ABSPATH, whose entry is ENTRY, for re-addition.
- * If MODIFY_COPYFROM is TRUE, re-add the item as a copy with history
- * of (ENTRY->url)@(ENTRY->rev).
- * Assume that the item exists locally and is scheduled as still existing with
- * some local modifications relative to its (old) base, but does not exist in
- * the repository at the target revision.
- *
- * Use the local content of the item, even if it
- * If the item is a directory, recursively schedule its contents to be the
- * contents of the re-added tree, even if they are locally modified relative
- * to it.
- *
- * THEIR_URL is the deleted node's URL on the source-right side, the
- * side that the target should become after the update. In other words,
- * that's the new URL the node would have if it were not deleted.
- *
- * Make changes to entries immediately, not loggily, because that is easier
- * to keep track of when multiple directories are involved.
- * */
-static svn_error_t *
-schedule_existing_item_for_re_add(const svn_wc_entry_t *entry,
- struct edit_baton *eb,
- const char *local_abspath,
- const char *their_url,
- svn_boolean_t modify_copyfrom,
- apr_pool_t *pool)
-{
- svn_wc_entry_t tmp_entry;
- apr_uint64_t flags = 0;
- apr_hash_t *props;
-
- SVN_ERR(svn_wc__db_read_pristine_props(&props, eb->db, local_abspath,
- pool, pool));
-
- /* Update the details of the base rev/url to reflect the incoming
- * delete, while leaving the working version as it is, scheduling it
- * for re-addition unless it was already non-existent. */
- tmp_entry.url = their_url;
- flags |= SVN_WC__ENTRY_MODIFY_URL;
-
- /* Schedule the working version to be re-added. */
- tmp_entry.schedule = svn_wc_schedule_add;
- flags |= SVN_WC__ENTRY_MODIFY_SCHEDULE;
- flags |= SVN_WC__ENTRY_MODIFY_FORCE;
-
- if (modify_copyfrom)
- {
- tmp_entry.copyfrom_url = entry->url;
- flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_URL;
- tmp_entry.copyfrom_rev = entry->revision;
- flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_REV;
- tmp_entry.copied = TRUE;
- flags |= SVN_WC__ENTRY_MODIFY_COPIED;
- }
-
- /* ### Need to change the "base" into a "revert-base" ? */
-
- /* Determine which adm dir holds this node's entry */
- SVN_ERR(svn_wc__entry_modify2(eb->db,
- local_abspath,
- entry->kind,
- FALSE,
- &tmp_entry,
- flags, pool));
-
- SVN_ERR(svn_wc__db_temp_op_set_pristine_props(eb->db, local_abspath, props,
- TRUE, pool));
-
- /* If it's a directory, set the 'copied' flag recursively. The rest of the
- * directory tree's state can stay exactly as it was before being
- * scheduled for re-add. */
- /* ### BH: I don't think this code handles switched subpaths, excluded
- and absent items in any usefull way. Needs carefull redesign */
- if (entry->kind == svn_node_dir)
- {
- struct set_copied_baton_t set_copied_baton;
-
- /* Set the 'copied' flag recursively, to support the
- * cases where this is a directory. */
- set_copied_baton.eb = eb;
- set_copied_baton.added_subtree_root_path = local_abspath;
- SVN_ERR(svn_wc__internal_walk_children(eb->db, local_abspath, FALSE,
- set_copied_callback,
- &set_copied_baton,
- svn_depth_infinity,
- NULL, NULL, pool));
-
- /* If PATH is a directory then we must also record in PARENT_PATH's
- entry that we are re-adding PATH. */
- flags &= ~SVN_WC__ENTRY_MODIFY_URL;
- SVN_ERR(svn_wc__entry_modify2(eb->db, local_abspath, svn_node_dir, TRUE,
- &tmp_entry, flags, pool));
-
- /* ### Need to do something more, such as change 'base' into
- ### 'revert-base'? */
- }
-
- return SVN_NO_ERROR;
-}
-
/* Delete PATH from its immediate parent PARENT_PATH, in the edit
* represented by EB. PATH is relative to EB->anchor.
* PARENT_PATH is relative to the current working directory.
*
- * THEIR_URL is the deleted node's URL on the source-right side, the
- * side that the target should become after the update. In other words,
- * that's the new URL the node would have if it were not deleted.
+ * THEIR_RELPATH is the deleted node's repository relative path on the
+ * source-right side, the side that the target should become after the
+ * update. In other words, that's the new URL the node would have if it
+ * were not deleted.
*
* Perform all allocations in POOL.
*/
static svn_error_t *
do_entry_deletion(struct edit_baton *eb,
const char *local_abspath,
- const char *their_url,
+ const char *their_relpath,
svn_boolean_t in_deleted_and_tree_conflicted_subtree,
apr_pool_t *pool)
{
- svn_error_t *err;
- const svn_wc_entry_t *entry;
+ svn_wc__db_kind_t kind;
svn_boolean_t already_conflicted;
- svn_stringbuf_t *log_item = svn_stringbuf_create("", pool);
svn_wc_conflict_description2_t *tree_conflict = NULL;
const char *dir_abspath = svn_dirent_dirname(local_abspath, pool);
svn_boolean_t hidden;
- /* ### hmm. in case we need to re-add the node, we use some fields from
- ### this entry. I believe the required fields are filled in, but getting
- ### just the stub might be a problem. */
- err = svn_wc__get_entry(&entry, eb->db, local_abspath,
- FALSE /* allow_unversioned */, svn_node_unknown,
- TRUE /* need_parent_stub */, pool, pool);
- if (err)
- {
- if (err->apr_err != SVN_ERR_NODE_UNEXPECTED_KIND)
- return svn_error_return(err);
-
- /* The node was a file, and we got the "real" entry, not the stub.
- That is just what we'd like. */
- svn_error_clear(err);
- }
+ SVN_ERR(svn_wc__db_read_kind(&kind, eb->db, local_abspath, FALSE, pool));
/* Is this path a conflict victim? */
SVN_ERR(node_already_conflicted(&already_conflicted, eb->db,
@@ -2288,12 +2074,8 @@ do_entry_deletion(struct edit_baton *eb,
SVN_ERR(remember_skipped_tree(eb, local_abspath));
/* ### TODO: Also print victim_path in the skip msg. */
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_skip,
- pool),
- pool);
+ do_notification(eb, local_abspath, svn_node_unknown, svn_wc_notify_skip,
+ pool);
return SVN_NO_ERROR;
}
@@ -2321,23 +2103,25 @@ do_entry_deletion(struct edit_baton *eb,
if (!in_deleted_and_tree_conflicted_subtree)
SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
svn_wc_conflict_action_delete, svn_node_none,
- their_url, pool));
+ their_relpath, pool));
if (tree_conflict != NULL)
{
/* When we raise a tree conflict on a directory, we want to avoid
* making any changes inside it. (Will an update ever try to make
* further changes to or inside a directory it's just deleted?) */
- SVN_ERR(svn_wc__loggy_add_tree_conflict(&log_item, tree_conflict, pool));
+ {
+ svn_stringbuf_t *log_accum = NULL;
+
+ SVN_ERR(svn_wc__loggy_add_tree_conflict(&log_accum, tree_conflict,
+ pool));
+ SVN_ERR(svn_wc__wq_add_loggy(eb->db, dir_abspath, log_accum, pool));
+ }
SVN_ERR(remember_skipped_tree(eb, local_abspath));
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_tree_conflict,
- pool),
- pool);
+ do_notification(eb, local_abspath, svn_node_unknown,
+ svn_wc_notify_tree_conflict, pool);
if (tree_conflict->reason == svn_wc_conflict_reason_edited)
{
@@ -2352,12 +2136,13 @@ do_entry_deletion(struct edit_baton *eb,
/* Run the log in the parent dir, to record the tree conflict.
* Do this before schedule_existing_item_for_re_add(), in case
* that needs to modify the same entries. */
- SVN_ERR(svn_wc__wq_add_loggy(eb->db, dir_abspath, log_item, pool));
- SVN_ERR(svn_wc__run_log2(eb->db, dir_abspath, pool));
+ SVN_ERR(svn_wc__wq_run(eb->db, dir_abspath,
+ eb->cancel_func, eb->cancel_baton,
+ pool));
+
+ SVN_ERR(svn_wc__db_temp_op_make_copy(eb->db, local_abspath, TRUE,
+ pool));
- SVN_ERR(schedule_existing_item_for_re_add(entry, eb,
- local_abspath, their_url,
- TRUE, pool));
return SVN_NO_ERROR;
}
else if (tree_conflict->reason == svn_wc_conflict_reason_deleted)
@@ -2381,12 +2166,13 @@ do_entry_deletion(struct edit_baton *eb,
/* Run the log in the parent dir, to record the tree conflict.
* Do this before schedule_existing_item_for_re_add(), in case
* that needs to modify the same entries. */
- SVN_ERR(svn_wc__wq_add_loggy(eb->db, dir_abspath, log_item, pool));
- SVN_ERR(svn_wc__run_log2(eb->db, dir_abspath, pool));
+ SVN_ERR(svn_wc__wq_run(eb->db, dir_abspath,
+ eb->cancel_func, eb->cancel_baton,
+ pool));
+
+ SVN_ERR(svn_wc__db_temp_op_make_copy(eb->db, local_abspath, TRUE,
+ pool));
- SVN_ERR(schedule_existing_item_for_re_add(entry, eb,
- local_abspath, their_url,
- FALSE, pool));
return SVN_NO_ERROR;
}
else
@@ -2396,7 +2182,6 @@ do_entry_deletion(struct edit_baton *eb,
/* Issue a loggy command to delete the entry from version control and to
* delete it from disk if unmodified, but leave any modified files on disk
* unversioned. */
- SVN_WC__FLUSH_LOG_ACCUM(eb->db, dir_abspath, log_item, pool);
SVN_ERR(svn_wc__loggy_delete_entry(eb->db, dir_abspath, local_abspath,
pool));
@@ -2406,27 +2191,31 @@ do_entry_deletion(struct edit_baton *eb,
if (strcmp(local_abspath, eb->target_abspath) == 0)
{
svn_wc_entry_t tmp_entry;
+ svn_stringbuf_t *log_accum = NULL;
tmp_entry.revision = *(eb->target_revision);
/* ### Why not URL as well? This might be a switch. ... */
/* tmp_entry.url = *(eb->target_url) or db->new_URL ? */
- tmp_entry.kind = entry->kind;
+ if (kind == svn_wc__db_kind_dir)
+ tmp_entry.kind = svn_node_dir;
+ else /* kind == svn_wc__db_kind_file || kind == svn_wc__db_kind_symlink*/
+ tmp_entry.kind = svn_node_file;
+
tmp_entry.deleted = TRUE;
- SVN_ERR(svn_wc__loggy_entry_modify(&log_item,
+ SVN_ERR(svn_wc__loggy_entry_modify(&log_accum,
dir_abspath, local_abspath,
&tmp_entry,
SVN_WC__ENTRY_MODIFY_REVISION
| SVN_WC__ENTRY_MODIFY_KIND
| SVN_WC__ENTRY_MODIFY_DELETED,
pool, pool));
+ SVN_ERR(svn_wc__wq_add_loggy(eb->db, dir_abspath, log_accum, pool));
eb->target_deleted = TRUE;
}
- SVN_ERR(svn_wc__wq_add_loggy(eb->db, dir_abspath, log_item, pool));
-
- if (eb->switch_url)
+ if (eb->switch_relpath)
{
/* The SVN_WC__LOG_DELETE_ENTRY log item will cause
* svn_wc_remove_from_revision_control() to be run. But that
@@ -2443,7 +2232,7 @@ do_entry_deletion(struct edit_baton *eb,
* the log item is to remove the entry in the parent directory.
*/
- if (entry->kind == svn_node_dir)
+ if (kind == svn_wc__db_kind_dir)
{
SVN_ERR(leftmod_error_chain(
svn_wc__internal_remove_from_revision_control(
@@ -2459,18 +2248,14 @@ do_entry_deletion(struct edit_baton *eb,
/* Note: these two lines are duplicated in the tree-conflicts bail out
* above. */
- SVN_ERR(svn_wc__run_log2(eb->db, dir_abspath, pool));
+ SVN_ERR(svn_wc__wq_run(eb->db, dir_abspath,
+ eb->cancel_func, eb->cancel_baton,
+ pool));
/* Notify. (If tree_conflict, we've already notified.) */
- if (eb->notify_func
- && tree_conflict == NULL)
- {
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_update_delete,
- pool),
- pool);
- }
+ if (tree_conflict == NULL)
+ do_notification(eb, local_abspath, svn_node_unknown,
+ svn_wc_notify_update_delete, pool);
return SVN_NO_ERROR;
}
@@ -2486,7 +2271,7 @@ delete_entry(const char *path,
struct dir_baton *pb = parent_baton;
const char *base = svn_relpath_basename(path, pool);
const char *local_abspath;
- const char *their_url;
+ const char *their_relpath;
local_abspath = svn_dirent_join(pb->local_abspath, base, pool);
@@ -2500,13 +2285,13 @@ delete_entry(const char *path,
SVN_ERR(check_path_under_root(pb->local_abspath, base, pool));
- their_url = svn_path_url_add_component2(pb->new_URL, base, pool);
+ their_relpath = svn_relpath_join(pb->new_relpath, base, pool);
/* Flush parent log before potentially adding tree conflicts */
- flush_log(pb, pool);
+ SVN_ERR(flush_log(pb, pool));
return do_entry_deletion(pb->edit_baton, local_abspath,
- their_url,
+ their_relpath,
pb->in_deleted_and_tree_conflicted_subtree,
pool);
}
@@ -2588,12 +2373,8 @@ add_directory(const char *path,
db->already_notified = TRUE;
/* ### TODO: Also print victim_path in the skip msg. */
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(db->local_abspath,
- svn_wc_notify_skip,
- pool),
- pool);
+ do_notification(eb, db->local_abspath, svn_node_unknown,
+ svn_wc_notify_skip, pool);
return SVN_NO_ERROR;
}
@@ -2613,7 +2394,6 @@ add_directory(const char *path,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL,
eb->db, db->local_abspath, db->pool, db->pool);
-
if (err)
{
if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
@@ -2630,16 +2410,8 @@ add_directory(const char *path,
wc_kind != svn_wc__db_kind_dir && IS_NODE_PRESENT(status)))
{
db->already_notified = TRUE;
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(db->local_abspath,
- svn_wc_notify_update_obstruction,
- pool);
-
- notify->kind = svn_node_dir;
- eb->notify_func(eb->notify_baton, notify, pool);
- }
+ do_notification(eb, db->local_abspath, svn_node_dir,
+ svn_wc_notify_update_obstruction, pool);
return svn_error_createf(
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
@@ -2657,16 +2429,8 @@ add_directory(const char *path,
if (!eb->allow_unver_obstructions)
{
db->already_notified = TRUE;
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(db->local_abspath,
- svn_wc_notify_update_obstruction,
- pool);
-
- notify->kind = svn_node_dir;
- eb->notify_func(eb->notify_baton, notify, pool);
- }
+ do_notification(eb, db->local_abspath, svn_node_dir,
+ svn_wc_notify_update_obstruction, pool);
return svn_error_createf(
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
@@ -2700,32 +2464,25 @@ add_directory(const char *path,
svn_dirent_local_style(db->local_abspath, pool));
}
- if (switched && !eb->switch_url)
+ if (!err && switched && !eb->switch_relpath)
{
err = svn_error_createf(
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
_("Switched directory '%s' does not match "
"expected URL '%s'"),
svn_dirent_local_style(db->local_abspath, pool),
- db->new_URL);
+ svn_path_url_add_component2(eb->repos_root,
+ db->new_relpath, pool));
}
- }
- if (err != NULL)
- {
- db->already_notified = TRUE;
- if (eb->notify_func)
+ if (err != NULL)
{
- svn_wc_notify_t *notify =
- svn_wc_create_notify(db->local_abspath,
- svn_wc_notify_update_obstruction,
- pool);
+ db->already_notified = TRUE;
+ do_notification(eb, db->local_abspath, svn_node_dir,
+ svn_wc_notify_update_obstruction, pool);
- notify->kind = svn_node_dir;
- eb->notify_func(eb->notify_baton, notify, pool);
+ return svn_error_return(err);
}
-
- return svn_error_return(err);
}
/* What to do with a versioned or schedule-add dir:
@@ -2781,7 +2538,7 @@ add_directory(const char *path,
SVN_ERR(check_tree_conflict(&tree_conflict, eb,
db->local_abspath,
svn_wc_conflict_action_add,
- svn_node_dir, db->new_URL, pool));
+ svn_node_dir, db->new_relpath, pool));
if (tree_conflict != NULL)
{
@@ -2797,13 +2554,8 @@ add_directory(const char *path,
db->skip_descendants = TRUE;
db->already_notified = TRUE;
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(
- db->local_abspath,
- svn_wc_notify_tree_conflict,
- pool),
- pool);
+ do_notification(eb, db->local_abspath, svn_node_unknown,
+ svn_wc_notify_tree_conflict, pool);
return SVN_NO_ERROR;
}
@@ -2887,10 +2639,11 @@ add_directory(const char *path,
tmp_entry.revision = *(eb->target_revision);
- if (eb->switch_url)
+ if (eb->switch_relpath)
{
- tmp_entry.url = svn_path_url_add_component2(eb->switch_url,
- db->name, pool);
+ tmp_entry.url = svn_path_url_add_component2(eb->repos_root,
+ db->new_relpath,
+ pool);
modify_flags |= SVN_WC__ENTRY_MODIFY_URL;
}
@@ -2901,7 +2654,8 @@ add_directory(const char *path,
}
SVN_ERR(prep_directory(db,
- db->new_URL,
+ svn_path_url_add_component2(eb->repos_root,
+ db->new_relpath, pool),
*(eb->target_revision),
db->pool));
@@ -2912,25 +2666,7 @@ add_directory(const char *path,
entries. */
if (pb->in_deleted_and_tree_conflicted_subtree)
{
- svn_wc_entry_t tmp_entry;
- apr_uint64_t modify_flags = SVN_WC__ENTRY_MODIFY_SCHEDULE;
-
- tmp_entry.schedule = svn_wc_schedule_delete;
-
- /* Mark PATH as scheduled for deletion in its parent. */
- SVN_ERR(svn_wc__entry_modify2(eb->db, db->local_abspath,
- svn_node_dir, TRUE,
- &tmp_entry, modify_flags, pool));
-
- /* ### HACK: Remove the incomplete status or the next entry_modify2
- will move the incomplete status to WORKING_NODE */
- SVN_ERR(svn_wc__db_temp_op_set_base_incomplete(eb->db, db->local_abspath,
- FALSE, pool));
-
- /* Mark PATH's 'this dir' entry as scheduled for deletion. */
- SVN_ERR(svn_wc__entry_modify2(eb->db, db->local_abspath,
- svn_node_dir, FALSE,
- &tmp_entry, modify_flags, pool));
+ SVN_ERR(svn_wc__db_temp_op_delete(eb->db, db->local_abspath, pool));
}
/* If this add was obstructed by dir scheduled for addition without
@@ -2940,7 +2676,6 @@ add_directory(const char *path,
issued. */
if (eb->notify_func && !db->already_notified && !db->add_existed)
{
- svn_wc_notify_t *notify;
svn_wc_notify_action_t action;
if (db->in_deleted_and_tree_conflicted_subtree)
@@ -2950,10 +2685,9 @@ add_directory(const char *path,
else
action = svn_wc_notify_update_add;
- notify = svn_wc_create_notify(db->local_abspath, action, pool);
- notify->kind = svn_node_dir;
- eb->notify_func(eb->notify_baton, notify, pool);
db->already_notified = TRUE;
+
+ do_notification(eb, db->local_abspath, svn_node_dir, action, pool);
}
return SVN_NO_ERROR;
@@ -2969,17 +2703,17 @@ open_directory(const char *path,
{
struct dir_baton *db, *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- svn_wc_entry_t tmp_entry;
- apr_uint64_t flags = SVN_WC__ENTRY_MODIFY_REVISION |
- SVN_WC__ENTRY_MODIFY_URL;
-
+ svn_boolean_t base_shadowed;
svn_boolean_t already_conflicted;
svn_wc_conflict_description2_t *tree_conflict = NULL;
- svn_wc__db_status_t status;
+ svn_wc__db_status_t status, base_status;
SVN_ERR(make_dir_baton(&db, path, eb, pb, FALSE, pool));
*child_baton = db;
+ /* We should have a write lock on every directory touched. */
+ SVN_ERR(svn_wc__write_check(eb->db, db->local_abspath, pool));
+
if (pb->skip_descendants)
{
if (!pb->skip_this)
@@ -3002,11 +2736,20 @@ open_directory(const char *path,
SVN_ERR(svn_wc__db_read_info(&status, NULL, &db->old_revision, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
&db->ambient_depth, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ &base_shadowed, NULL, NULL,
eb->db, db->local_abspath, pool, pool));
- db->was_incomplete = (status == svn_wc__db_status_incomplete);
+ if (!base_shadowed)
+ base_status = status;
+ else
+ SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db->old_revision,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &db->ambient_depth, NULL, NULL, NULL,
+ NULL,
+ eb->db, db->local_abspath, pool, pool));
+
+ db->was_incomplete = (base_status == svn_wc__db_status_incomplete);
/* Is this path a conflict victim? */
SVN_ERR(node_already_conflicted(&already_conflicted, eb->db,
@@ -3019,12 +2762,8 @@ open_directory(const char *path,
db->skip_descendants = TRUE;
db->already_notified = TRUE;
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(db->local_abspath,
- svn_wc_notify_skip,
- pool),
- pool);
+ do_notification(eb, db->local_abspath, svn_node_unknown,
+ svn_wc_notify_skip, pool);
return SVN_NO_ERROR;
}
@@ -3037,7 +2776,7 @@ open_directory(const char *path,
if (!db->in_deleted_and_tree_conflicted_subtree)
SVN_ERR(check_tree_conflict(&tree_conflict, eb, db->local_abspath,
svn_wc_conflict_action_edit, svn_node_dir,
- db->new_URL, pool));
+ db->new_relpath, pool));
/* Remember the roots of any locally deleted trees. */
if (tree_conflict != NULL)
@@ -3045,17 +2784,9 @@ open_directory(const char *path,
SVN_ERR(svn_wc__loggy_add_tree_conflict(&pb->log_accum, tree_conflict,
pool));
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(db->local_abspath,
- svn_wc_notify_tree_conflict,
- pool);
- notify->kind = svn_node_dir;
-
- eb->notify_func(eb->notify_baton, notify, pool);
- db->already_notified = TRUE;
- }
+ do_notification(eb, db->local_abspath, svn_node_dir,
+ svn_wc_notify_tree_conflict, pool);
+ db->already_notified = TRUE;
/* Even if PATH is locally deleted we still need mark it as being
at TARGET_REVISION, so fall through to the code below to do just
@@ -3074,16 +2805,10 @@ open_directory(const char *path,
}
/* Mark directory as being at target_revision and URL, but incomplete. */
- tmp_entry.revision = *(eb->target_revision);
- tmp_entry.url = db->new_URL;
-
- SVN_ERR(svn_wc__entry_modify2(eb->db, db->local_abspath,
- svn_node_dir, FALSE,
- &tmp_entry, flags,
- pool));
-
- SVN_ERR(svn_wc__db_temp_op_set_base_incomplete(eb->db, db->local_abspath,
- TRUE, pool));
+ SVN_ERR(svn_wc__db_temp_op_start_directory_update(eb->db, db->local_abspath,
+ db->new_relpath,
+ *eb->target_revision,
+ pool));
return SVN_NO_ERROR;
}
@@ -3114,7 +2839,7 @@ change_dir_prop(void *dir_baton,
null. If PROPCHANGES contains more than one such change, return
the first. */
static const svn_prop_t *
-externals_prop_changed(apr_array_header_t *propchanges)
+externals_prop_changed(const apr_array_header_t *propchanges)
{
int i;
@@ -3189,10 +2914,12 @@ close_directory(void *dir_baton,
{
db->bump_info->skipped = TRUE;
- SVN_ERR(flush_log(db, pool));
+ /* The log accumulator better be empty because we aren't going to
+ be running any logs in this directory. */
+ SVN_ERR_ASSERT(svn_stringbuf_isempty(db->log_accum));
/* Allow the parent to complete its update. */
- SVN_ERR(maybe_bump_dir_info(db->edit_baton, db->bump_info, db->pool));
+ SVN_ERR(maybe_bump_dir_info(eb, db->bump_info, db->pool));
return SVN_NO_ERROR;
}
@@ -3210,7 +2937,7 @@ close_directory(void *dir_baton,
apr_hash_t *props_to_delete;
svn_wc__db_kind_t kind;
- SVN_ERR(svn_wc__db_read_kind(&kind, db->edit_baton->db,
+ SVN_ERR(svn_wc__db_read_kind(&kind, eb->db,
db->local_abspath, TRUE, pool));
if (kind == svn_wc__db_kind_unknown)
{
@@ -3220,7 +2947,7 @@ close_directory(void *dir_baton,
else
{
SVN_ERR(svn_wc__load_props(&base_props, &working_props,
- db->edit_baton->db, db->local_abspath,
+ eb->db, db->local_abspath,
pool, pool));
}
@@ -3244,15 +2971,12 @@ close_directory(void *dir_baton,
to deal with them. */
if (regular_props->nelts || entry_props->nelts || wc_props->nelts)
{
- /* Make a temporary log accumulator for dirprop changes.*/
- svn_stringbuf_t *dirprop_log = svn_stringbuf_create("", pool);
-
if (regular_props->nelts)
{
/* 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 (db->edit_baton->external_func)
+ if (eb->external_func)
{
const svn_prop_t *change = externals_prop_changed(regular_props);
@@ -3262,7 +2986,7 @@ close_directory(void *dir_baton,
const svn_string_t *old_val_s;
SVN_ERR(svn_wc__internal_propget(
- &old_val_s, db->edit_baton->db, db->local_abspath,
+ &old_val_s, eb->db, db->local_abspath,
SVN_PROP_EXTERNALS, db->pool, db->pool));
if ((new_val_s == NULL) && (old_val_s == NULL))
@@ -3273,8 +2997,8 @@ close_directory(void *dir_baton,
else if (old_val_s || new_val_s)
/* something changed, record the change */
{
- SVN_ERR((db->edit_baton->external_func)(
- db->edit_baton->external_baton,
+ SVN_ERR((eb->external_func)(
+ eb->external_baton,
db->local_abspath,
old_val_s,
new_val_s,
@@ -3286,8 +3010,7 @@ close_directory(void *dir_baton,
/* Merge pending properties into temporary files (ignoring
conflicts). */
- SVN_ERR_W(svn_wc__merge_props(&dirprop_log,
- &prop_state,
+ SVN_ERR_W(svn_wc__merge_props(&prop_state,
&new_base_props,
&new_actual_props,
eb->db,
@@ -3299,10 +3022,10 @@ close_directory(void *dir_baton,
regular_props,
TRUE /* base_merge */,
FALSE /* dry_run */,
- db->edit_baton->conflict_func,
- db->edit_baton->conflict_baton,
- db->edit_baton->cancel_func,
- db->edit_baton->cancel_baton,
+ eb->conflict_func,
+ eb->conflict_baton,
+ eb->cancel_func,
+ eb->cancel_baton,
db->pool,
pool),
_("Couldn't do property merge"));
@@ -3320,18 +3043,15 @@ close_directory(void *dir_baton,
pool),
pool));
}
-
- /* Add the dirprop loggy entries to the baton's log
- accumulator. */
- svn_stringbuf_appendstr(db->log_accum, dirprop_log);
}
+ /* Queue some items to install the properties. */
if (new_base_props || new_actual_props)
SVN_ERR(svn_wc__install_props(eb->db, db->local_abspath,
new_base_props, new_actual_props,
TRUE /* write_base_props */, TRUE, pool));
- /* Flush and run the log. */
+ /* Flush the log. */
SVN_ERR(flush_log(db, pool));
if (last_change)
@@ -3341,12 +3061,15 @@ close_directory(void *dir_baton,
last_change->cmt_author,
pool));
- SVN_ERR(svn_wc__run_log2(eb->db, db->local_abspath, pool));
+ /* Process all of the queued work items for this directory. */
+ SVN_ERR(svn_wc__wq_run(eb->db, db->local_abspath,
+ eb->cancel_func, eb->cancel_baton,
+ pool));
/* We're done with this directory, so remove one reference from the
bump information. This may trigger a number of actions. See
maybe_bump_dir_info() for more information. */
- SVN_ERR(maybe_bump_dir_info(db->edit_baton, db->bump_info, db->pool));
+ SVN_ERR(maybe_bump_dir_info(eb, db->bump_info, db->pool));
/* Notify of any prop changes on this directory -- but do nothing if
it's an added or skipped directory, because notification has already
@@ -3368,10 +3091,10 @@ close_directory(void *dir_baton,
notify = svn_wc_create_notify(db->local_abspath, action, pool);
notify->kind = svn_node_dir;
notify->prop_state = prop_state;
- notify->revision = *db->edit_baton->target_revision;
+ notify->revision = *eb->target_revision;
notify->old_revision = db->old_revision;
- eb->notify_func(db->edit_baton->notify_baton, notify, pool);
+ eb->notify_func(eb->notify_baton, notify, pool);
}
bdi = db->bump_info;
@@ -3693,8 +3416,8 @@ copy_regular_props(apr_hash_t *props_in,
for (hi = apr_hash_first(pool, props_in); hi; hi = apr_hash_next(hi))
{
- const char *propname = svn_apr_hash_index_key(hi);
- svn_string_t *propval = svn_apr_hash_index_val(hi);
+ const char *propname = svn__apr_hash_index_key(hi);
+ svn_string_t *propval = svn__apr_hash_index_val(hi);
if (svn_property_kind(NULL, propname) == svn_prop_regular_kind)
apr_hash_set(props_out, propname, APR_HASH_KEY_STRING, propval);
@@ -3726,7 +3449,6 @@ add_file_with_history(const char *path,
apr_hash_t *base_props, *working_props;
svn_error_t *err;
svn_stream_t *copied_stream;
- const char *temp_dir_abspath;
const char *src_local_abspath;
svn_wc__db_t *db = eb->db;
const char *dir_repos_relpath, *dir_repos_root, *dir_repos_uuid;
@@ -3752,13 +3474,10 @@ add_file_with_history(const char *path,
else
SVN_ERR(err);
- SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath, db, pb->local_abspath,
- subpool, subpool));
- SVN_ERR(svn_stream_open_unique(&copied_stream,
- &tfb->copied_text_base,
- temp_dir_abspath,
- svn_io_file_del_none,
- pool, pool));
+ /* Open the text base for writing (this will get us a temporary file). */
+ SVN_ERR(svn_wc__open_writable_base(&copied_stream, &tfb->copied_text_base,
+ db, pb->local_abspath,
+ pool, pool));
#ifdef SVN_EXPERIMENTAL
/* Copy the 'copied_stream' into a WC-NG pristine temp file as well. */
SVN_ERR(get_pristine_tee_stream(&copied_stream, &tfb->temp_pristine_abspath,
@@ -3805,6 +3524,11 @@ add_file_with_history(const char *path,
SVN_ERR(svn_wc__get_pristine_contents(&source_text_base, db,
src_local_abspath,
subpool, subpool));
+
+ /* If this has no base, should we use an empty stream?
+ * This assert wants to verify that there are no such callers. */
+ SVN_ERR_ASSERT(source_text_base != NULL);
+
SVN_ERR(svn_wc__load_props(&base_props, &working_props, db,
src_local_abspath, pool, subpool));
}
@@ -3924,12 +3648,8 @@ add_file(const char *path,
fb->skip_this = TRUE;
fb->already_notified = TRUE;
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(fb->local_abspath,
- svn_wc_notify_skip,
- subpool),
- subpool);
+ do_notification(eb, fb->local_abspath, svn_node_unknown,
+ svn_wc_notify_skip, subpool);
svn_pool_destroy(subpool);
@@ -3969,16 +3689,8 @@ add_file(const char *path,
wc_kind != svn_wc__db_kind_symlink && IS_NODE_PRESENT(status)))
{
fb->already_notified = TRUE;
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(fb->local_abspath,
- svn_wc_notify_update_obstruction,
- pool);
-
- notify->kind = svn_node_file;
- eb->notify_func(eb->notify_baton, notify, pool);
- }
+ do_notification(eb, fb->local_abspath, svn_node_file,
+ svn_wc_notify_update_obstruction, pool);
return svn_error_createf(
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
@@ -3995,16 +3707,8 @@ add_file(const char *path,
if (!eb->allow_unver_obstructions)
{
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(fb->local_abspath,
- svn_wc_notify_update_obstruction,
- pool);
-
- notify->kind = svn_node_file;
- eb->notify_func(eb->notify_baton, notify, pool);
- }
+ do_notification(eb, fb->local_abspath, svn_node_file,
+ svn_wc_notify_update_obstruction, pool);
return svn_error_createf(
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
@@ -4036,29 +3740,22 @@ add_file(const char *path,
svn_dirent_local_style(fb->local_abspath, pool));
}
- if (switched && !eb->switch_url)
+ if (switched && !eb->switch_relpath)
{
err = svn_error_createf(
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
_("Switched file '%s' does not match "
"expected URL '%s'"),
svn_dirent_local_style(fb->local_abspath, pool),
- fb->new_URL);
+ svn_path_url_add_component2(eb->repos_root,
+ fb->new_relpath, pool));
}
if (err != NULL)
{
fb->already_notified = TRUE;
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(fb->local_abspath,
- svn_wc_notify_update_obstruction,
- pool);
-
- notify->kind = svn_node_file;
- eb->notify_func(eb->notify_baton, notify, pool);
- }
+ do_notification(eb, fb->local_abspath, svn_node_file,
+ svn_wc_notify_update_obstruction, pool);
return svn_error_return(err);
}
@@ -4119,27 +3816,27 @@ add_file(const char *path,
SVN_ERR(check_tree_conflict(&tree_conflict, eb,
fb->local_abspath,
svn_wc_conflict_action_add,
- svn_node_file, fb->new_URL,
+ svn_node_file, fb->new_relpath,
subpool));
if (tree_conflict != NULL)
{
+ svn_stringbuf_t *log_accum = NULL;
+
/* Record the conflict so that the file is skipped silently
by the other callbacks. */
- SVN_ERR(svn_wc__loggy_add_tree_conflict(&fb->log_accum,
+ SVN_ERR(svn_wc__loggy_add_tree_conflict(&log_accum,
tree_conflict,
subpool));
+ SVN_ERR(svn_wc__wq_add_loggy(eb->db, pb->local_abspath,
+ log_accum, subpool));
+
SVN_ERR(remember_skipped_tree(eb, fb->local_abspath));
fb->skip_this = TRUE;
fb->already_notified = TRUE;
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(
- fb->local_abspath,
- svn_wc_notify_tree_conflict,
- subpool),
- subpool);
+ do_notification(eb, fb->local_abspath, svn_node_unknown,
+ svn_wc_notify_tree_conflict, subpool);
return SVN_NO_ERROR;
}
@@ -4217,12 +3914,8 @@ open_file(const char *path,
fb->skip_this = TRUE;
fb->already_notified = TRUE;
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(fb->local_abspath,
- svn_wc_notify_skip,
- subpool),
- subpool);
+ do_notification(eb, fb->local_abspath, svn_node_unknown,
+ svn_wc_notify_skip, subpool);
svn_pool_destroy(subpool);
@@ -4236,13 +3929,17 @@ open_file(const char *path,
if (!pb->in_deleted_and_tree_conflicted_subtree)
SVN_ERR(check_tree_conflict(&tree_conflict, eb, fb->local_abspath,
svn_wc_conflict_action_edit, svn_node_file,
- fb->new_URL, pool));
+ fb->new_relpath, pool));
/* Is this path the victim of a newly-discovered tree conflict? */
if (tree_conflict)
{
- SVN_ERR(svn_wc__loggy_add_tree_conflict(&fb->log_accum, tree_conflict,
+ svn_stringbuf_t *log_accum = NULL;
+
+ SVN_ERR(svn_wc__loggy_add_tree_conflict(&log_accum, tree_conflict,
pool));
+ SVN_ERR(svn_wc__wq_add_loggy(eb->db, pb->local_abspath, log_accum,
+ pool));
if (tree_conflict->reason == svn_wc_conflict_reason_deleted ||
tree_conflict->reason == svn_wc_conflict_reason_replaced)
@@ -4256,12 +3953,8 @@ open_file(const char *path,
fb->skip_this = TRUE;
fb->already_notified = TRUE;
- if (eb->notify_func)
- eb->notify_func(eb->notify_baton,
- svn_wc_create_notify(fb->local_abspath,
- svn_wc_notify_tree_conflict,
- pool),
- pool);
+ do_notification(eb, fb->local_abspath, svn_node_unknown,
+ svn_wc_notify_tree_conflict, pool);
}
svn_pool_destroy(subpool);
@@ -4269,8 +3962,8 @@ open_file(const char *path,
return SVN_NO_ERROR;
}
-/* For the given PATH, fill out OLD_TEXT_BASE with the permanent text-base
- path, or (if the entry is replaced with history) to the permanent
+/* For the given LOCAL_ABSPATH, set *OLD_TEXT_BASE_ABSPATH to the permanent
+ text-base path, or (if the entry is replaced with history) to the permanent
revert-base path.
If REPLACED_P is non-NULL, set *REPLACED_P to whether or not the
@@ -4278,13 +3971,10 @@ open_file(const char *path,
use the revert base). If CHECKSUM_P is non-NULL and the path
already has an entry, set *CHECKSUM_P to the entry's checksum.
- ROOT_ACCESS is an access baton which can be used to find associated
- batons for the directory that PATH resides within.
-
Use SCRATCH_POOL for temporary allocation and for *CHECKSUM_P (if
- applicable), but allocate OLD_TEXT_BASE in RESULT_POOL. */
+ applicable), but allocate OLD_TEXT_BASE_ABSPATH in RESULT_POOL. */
static svn_error_t *
-choose_base_paths(const char **old_text_base,
+choose_base_paths(const char **old_text_base_abspath,
const char **checksum_p,
svn_boolean_t *replaced_p,
svn_wc__db_t *db,
@@ -4301,10 +3991,10 @@ choose_base_paths(const char **old_text_
replaced = entry && entry->schedule == svn_wc_schedule_replace;
/* ### Should use pristine api here */
if (replaced)
- SVN_ERR(svn_wc__text_revert_path(old_text_base,
+ SVN_ERR(svn_wc__text_revert_path(old_text_base_abspath,
db, local_abspath, result_pool));
else
- SVN_ERR(svn_wc__text_base_path(old_text_base,
+ SVN_ERR(svn_wc__text_base_path(old_text_base_abspath,
db, local_abspath, FALSE, result_pool));
if (checksum_p)
@@ -4391,9 +4081,13 @@ apply_textdelta(void *file_baton,
fb->local_abspath,
handler_pool, handler_pool));
else
- SVN_ERR(svn_wc__get_pristine_contents(&source, fb->edit_baton->db,
- fb->local_abspath,
- handler_pool, handler_pool));
+ {
+ SVN_ERR(svn_wc__get_pristine_contents(&source, fb->edit_baton->db,
+ fb->local_abspath,
+ handler_pool, handler_pool));
+ if (source == NULL)
+ source = svn_stream_empty(handler_pool);
+ }
}
else
{
@@ -4426,8 +4120,7 @@ apply_textdelta(void *file_baton,
/* Open the text base for writing (this will get us a temporary file). */
err = svn_wc__open_writable_base(&target, &hb->work_abspath,
- fb->local_abspath,
- replaced /* need_revert_base */,
+ fb->edit_baton->db, fb->local_abspath,
handler_pool, pool);
if (err)
{
@@ -4492,106 +4185,20 @@ change_file_prop(void *file_baton,
}
-/* TODO ### Update to mention DB, FILE_ABSPATH, DIR_ABSPATH; not ADM_ACCESS.
-
- Write log commands to merge PROP_CHANGES into the existing
- properties of FILE_PATH. PROP_CHANGES can contain regular
- properties as well as entryprops and wcprops. Update *PROP_STATE
- to reflect the result of the regular prop merge. Make *LOCK_STATE
- reflect the possible removal of a lock token from FILE_PATH's
- entryprops. BASE_PROPS and WORKING_PROPS are hashes of the base and
- working props of the file; if NULL they are read from the wc.
-
- CONFICT_FUNC/BATON is a callback which allows the client to
- possibly resolve a property conflict interactively.
-
- ADM_ACCESS is the access baton for FILE_PATH. Append log commands to
- LOG_ACCUM. Use POOL for temporary allocations. */
-static svn_error_t *
-merge_props(svn_stringbuf_t *log_accum,
- svn_wc_notify_state_t *prop_state,
- svn_wc_notify_lock_state_t *lock_state,
- apr_hash_t **new_base_props,
- apr_hash_t **new_actual_props,
- struct last_change_info **last_change,
- svn_wc__db_t *db,
- const char *file_abspath,
- const char *dir_abspath,
- const svn_wc_conflict_version_t *left_version,
- const svn_wc_conflict_version_t *right_version,
- const apr_array_header_t *prop_changes,
- apr_hash_t *base_props,
- apr_hash_t *working_props,
- svn_wc_conflict_resolver_func_t conflict_func,
- void *conflict_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-{
- apr_array_header_t *regular_props = NULL, *wc_props = NULL,
- *entry_props = NULL;
-
- /* Sort the property list into three arrays, based on kind. */
- SVN_ERR(svn_categorize_props(prop_changes, &entry_props, &wc_props,
- ®ular_props, pool));
-
- /* Always initialize to unknown state. */
- *prop_state = svn_wc_notify_state_unknown;
-
- /* Merge the 'regular' props into the existing working proplist. */
- if (regular_props)
- {
- /* This will merge the old and new props into a new prop db, and
- write <cp> commands to the logfile to install the merged
- props. */
- SVN_ERR(svn_wc__merge_props(&log_accum,
- prop_state,
- new_base_props,
- new_actual_props,
- db,
- file_abspath,
- left_version,
- right_version,
- NULL /* update, not merge */,
- base_props,
- working_props,
- regular_props, TRUE, FALSE,
- conflict_func, conflict_baton,
- cancel_func, cancel_baton,
- pool,
- pool));
- }
-
- /* If there are any ENTRY PROPS, make sure those get appended to the
- growing log as fields for the file's entry.
-
- Note that no merging needs to happen; these kinds of props aren't
- versioned, so if the property is present, we overwrite the value. */
- if (entry_props)
- SVN_ERR(accumulate_last_change(last_change, lock_state,
- db, file_abspath, entry_props,
- pool, pool));
- else
- *lock_state = svn_wc_notify_lock_state_unchanged;
-
- /* This writes a whole bunch of log commands to install wcprops. */
- if (wc_props)
- SVN_ERR(svn_wc__db_base_set_dav_cache(db, file_abspath,
- prop_hash_from_array(wc_props, pool),
- pool));
-
- return SVN_NO_ERROR;
-}
/* Append to LOG_ACCUM, log commands to update the entry for LOCAL_ABSPATH
- with a NEW_REVISION and a NEW_URL (if non-NULL), making sure
+ with a NEW_REVISION and a NEW_RELPATH(if non-NULL), making sure
the entry refers to a file and has no absent or deleted state.
- Use POOL for temporary allocations. */
+ Use POOL for temporary allocations.
+
+ ### REPOS_ROOT must be the current repository root while still using
+ entries here */
static svn_error_t *
-loggy_tweak_base_node(svn_stringbuf_t *log_accum,
+loggy_tweak_base_node(svn_stringbuf_t **log_accum,
const char *local_abspath,
svn_revnum_t new_revision,
- const char *new_URL,
+ const char *repos_root,
+ const char *new_relpath,
apr_pool_t *pool)
{
/* Write log entry which will bump the revision number. Also, just
@@ -4621,14 +4228,15 @@ loggy_tweak_base_node(svn_stringbuf_t *l
tmp_entry.text_time = 0;
/* Possibly install a *non*-inherited URL in the entry. */
- if (new_URL)
+ if (new_relpath)
{
- tmp_entry.url = new_URL;
+ tmp_entry.url = svn_path_url_add_component2(repos_root, new_relpath,
+ pool);
modify_flags |= SVN_WC__ENTRY_MODIFY_URL;
}
return svn_error_return(
- svn_wc__loggy_entry_modify(&log_accum,
+ svn_wc__loggy_entry_modify(log_accum,
svn_dirent_dirname(local_abspath, pool),
local_abspath, &tmp_entry, modify_flags,
pool, pool));
@@ -4695,25 +4303,21 @@ install_text_base(svn_stringbuf_t **log_
* POOL is used for all bookkeeping work during the installation.
*/
static svn_error_t *
-merge_file(svn_wc_notify_state_t *content_state,
- svn_wc_notify_state_t *prop_state,
- svn_wc_notify_lock_state_t *lock_state,
- apr_hash_t **new_base_props,
- apr_hash_t **new_actual_props,
- struct last_change_info **last_change,
+merge_file(svn_stringbuf_t **log_accum,
+ svn_wc_notify_state_t *content_state,
+ const svn_wc_entry_t *entry,
struct file_baton *fb,
const char *new_text_base_abspath,
const svn_checksum_t *actual_checksum,
+ svn_boolean_t lock_removed,
apr_pool_t *pool)
{
struct edit_baton *eb = fb->edit_baton;
struct dir_baton *pb = fb->dir_baton;
- svn_stringbuf_t *log_accum = svn_stringbuf_create("", pool);
svn_boolean_t is_locally_modified;
svn_boolean_t is_replaced = FALSE;
svn_boolean_t magic_props_changed;
enum svn_wc_merge_outcome_t merge_outcome = svn_wc_merge_unchanged;
- const svn_wc_entry_t *entry;
svn_wc_conflict_version_t *left_version = NULL; /* ### Fill */
svn_wc_conflict_version_t *right_version = NULL; /* ### Fill */
@@ -4733,44 +4337,23 @@ merge_file(svn_wc_notify_state_t *conten
- fb->old_text_base_path is the old pristine F.
(This is only set if there's a new text base).
- The goal is to update the local working copy of F to reflect
- the changes received from the repository, preserving any local
- modifications.
+ The goal is to update the local working copy of F to reflect
+ the changes received from the repository, preserving any local
+ modifications.
*/
+#if 0
+ /* ### this will break update_tests 43. see comment in close_file() */
+ SVN_WC__FLUSH_LOG_ACCUM(eb->db, pb->local_abspath, *log_accum, pool);
+#endif
+
/* Start by splitting the file path, getting an access baton for the parent,
and an entry for the file if any. */
- SVN_ERR(svn_wc__get_entry(&entry, eb->db, fb->local_abspath, TRUE,
- svn_node_file, FALSE, pool, pool));
- if (! entry && ! fb->added)
- return svn_error_createf(
- SVN_ERR_UNVERSIONED_RESOURCE, NULL,
- _("'%s' is not under version control"),
- svn_dirent_local_style(fb->local_abspath, pool));
-
/* Determine if any of the propchanges are the "magic" ones that
might require changing the working file. */
magic_props_changed = svn_wc__has_magic_property(fb->propchanges);
- /* Set the new revision and URL in the entry and clean up some other
- fields. This clears DELETED from any prior versioned file with the
- same name (needed before attempting to install props). */
- SVN_ERR(loggy_tweak_base_node(log_accum, fb->local_abspath,
- *eb->target_revision, fb->new_URL, pool));
-
- /* Install all kinds of properties. It is important to do this before
[... 1102 lines stripped ...]