You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/12/23 06:58:53 UTC
svn commit: r1425414 [4/5] - in /subversion/branches/javahl-ra: ./
notes/wc-ng/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/
subversion/bindings/javahl/tests/org/tigris/subversion/javahl/
subversion/include/ subversion/libsvn_subr/ su...
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/update_editor.c?rev=1425414&r1=1425413&r2=1425414&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/update_editor.c Sun Dec 23 05:58:52 2012
@@ -46,6 +46,7 @@
#include "wc.h"
#include "adm_files.h"
+#include "conflicts.h"
#include "entries.h"
#include "translate.h"
#include "workqueue.h"
@@ -298,6 +299,9 @@ struct dir_baton
/* The revision of the directory before updating */
svn_revnum_t old_revision;
+ /* The repos_relpath before updating/switching */
+ const char *old_repos_relpath;
+
/* The global edit baton. */
struct edit_baton *edit_baton;
@@ -325,7 +329,7 @@ struct dir_baton
const char *changed_author;
/* If not NULL, contains a mapping of const char* basenames of children that
- have been deleted to their svn_wc_conflict_description2_t* tree conflicts.
+ have been deleted to their svn_skel_t* tree conflicts.
We store this hash to allow replacements to continue under a just
installed tree conflict.
@@ -355,7 +359,7 @@ struct dir_baton
svn_boolean_t edited;
/* The tree conflict to install once the node is really edited */
- svn_wc_conflict_description2_t *edit_conflict;
+ svn_skel_t *edit_conflict;
/* The bump information for this directory. */
struct bump_dir_info *bump_info;
@@ -720,6 +724,9 @@ struct file_baton
/* The revision of the file before updating */
svn_revnum_t old_revision;
+ /* The repos_relpath before updating/switching */
+ const char *old_repos_relpath;
+
/* The global edit baton. */
struct edit_baton *edit_baton;
@@ -774,7 +781,7 @@ struct file_baton
svn_boolean_t edited;
/* The tree conflict to install once the node is really edited */
- svn_wc_conflict_description2_t *edit_conflict;
+ svn_skel_t *edit_conflict;
};
@@ -866,10 +873,10 @@ mark_directory_edited(struct dir_baton *
if (db->edit_conflict)
{
/* We have a (delayed) tree conflict to install */
- SVN_ERR(svn_wc__db_op_set_tree_conflict(db->edit_baton->db,
- db->local_abspath,
- db->edit_conflict,
- scratch_pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(db->edit_baton->db,
+ db->local_abspath,
+ db->edit_conflict, NULL,
+ scratch_pool));
do_notification(db->edit_baton, db->local_abspath, svn_node_dir,
svn_wc_notify_tree_conflict, scratch_pool);
@@ -894,10 +901,10 @@ mark_file_edited(struct file_baton *fb,
if (fb->edit_conflict)
{
/* We have a (delayed) tree conflict to install */
- SVN_ERR(svn_wc__db_op_set_tree_conflict(fb->edit_baton->db,
- fb->local_abspath,
- fb->edit_conflict,
- scratch_pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(fb->edit_baton->db,
+ fb->local_abspath,
+ fb->edit_conflict, NULL,
+ scratch_pool));
do_notification(fb->edit_baton, fb->local_abspath, svn_node_file,
svn_wc_notify_tree_conflict, scratch_pool);
@@ -1131,7 +1138,8 @@ open_root(void *edit_baton,
/* For an update with a NULL target, this is equivalent to open_dir(): */
/* Read the depth from the entry. */
- SVN_ERR(svn_wc__db_base_get_info(&status, NULL, NULL, NULL, NULL, NULL,
+ SVN_ERR(svn_wc__db_base_get_info(&status, NULL, &db->old_revision,
+ &db->old_repos_relpath, NULL, NULL,
&db->changed_rev, &db->changed_date,
&db->changed_author, &db->ambient_depth,
NULL, NULL, NULL, NULL, NULL,
@@ -1285,37 +1293,28 @@ node_has_local_mods(svn_boolean_t *modif
*
* The REASON is stored directly in the tree conflict info.
*
- * All temporary allocactions are be made in SCRATCH_POOL, while allocations
+ * All temporary allocations are be made in SCRATCH_POOL, while allocations
* needed for the returned conflict struct are made in RESULT_POOL.
*
* All other parameters are identical to and described by
* check_tree_conflict(), with the slight modification that this function
* relies on the reason passed in REASON instead of actively looking for one. */
static svn_error_t *
-create_tree_conflict(svn_wc_conflict_description2_t **pconflict,
+create_tree_conflict(svn_skel_t **pconflict,
struct edit_baton *eb,
const char *local_abspath,
svn_wc_conflict_reason_t reason,
svn_wc_conflict_action_t action,
- svn_node_kind_t their_node_kind,
- const char *their_relpath,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- const char *repos_root_url = NULL;
- const char *repos_uuid = NULL;
const char *left_repos_relpath;
svn_revnum_t left_revision;
svn_node_kind_t left_kind;
- const char *right_repos_relpath;
- const char *added_repos_relpath = NULL;
- svn_node_kind_t conflict_node_kind;
svn_wc_conflict_version_t *src_left_version;
- svn_wc_conflict_version_t *src_right_version;
*pconflict = NULL;
SVN_ERR_ASSERT(reason != SVN_WC_CONFLICT_REASON_NONE);
- SVN_ERR_ASSERT(their_relpath != NULL);
/* 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
@@ -1323,8 +1322,6 @@ create_tree_conflict(svn_wc_conflict_des
if (reason == svn_wc_conflict_reason_added ||
reason == svn_wc_conflict_reason_moved_here)
{
- svn_wc__db_status_t added_status;
-
/* ###TODO: It would be nice to tell the user at which URL and
* ### revision source-left was empty, which could be quite difficult
* ### to code, and is a slight theoretical leap of the svn mind.
@@ -1342,22 +1339,6 @@ create_tree_conflict(svn_wc_conflict_des
left_kind = svn_node_none;
left_revision = SVN_INVALID_REVNUM;
left_repos_relpath = NULL;
-
- /* Still get the repository root needed by both 'update' and 'switch',
- * and the would-be repos_relpath needed to construct the source-right
- * in case of an 'update'. Check sanity while we're at it. */
- SVN_ERR(svn_wc__db_scan_addition(&added_status, NULL,
- &added_repos_relpath,
- &repos_root_url,
- &repos_uuid,
- NULL, NULL, NULL, NULL, NULL,
- NULL, eb->db, local_abspath,
- result_pool, scratch_pool));
-
- /* This better really be an added status. */
- SVN_ERR_ASSERT(added_status == svn_wc__db_status_added
- || added_status == svn_wc__db_status_copied
- || added_status == svn_wc__db_status_moved_here);
}
else if (reason == svn_wc_conflict_reason_unversioned)
{
@@ -1366,8 +1347,6 @@ create_tree_conflict(svn_wc_conflict_des
left_kind = svn_node_none;
left_revision = SVN_INVALID_REVNUM;
left_repos_relpath = NULL;
- repos_root_url = eb->repos_root;
- repos_uuid = eb->repos_uuid;
}
else
{
@@ -1386,8 +1365,7 @@ create_tree_conflict(svn_wc_conflict_des
SVN_ERR(svn_wc__db_base_get_info(NULL, &base_kind,
&left_revision,
&left_repos_relpath,
- &repos_root_url,
- &repos_uuid,
+ NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
eb->db, local_abspath,
@@ -1402,40 +1380,6 @@ create_tree_conflict(svn_wc_conflict_des
SVN_ERR_MALFUNCTION();
}
- SVN_ERR_ASSERT(strcmp(repos_root_url, eb->repos_root) == 0);
-
- /* Find the source-right information, i.e. the state in the repository
- * to which we would like to update. */
- if (eb->switch_relpath)
- {
- /* This is a 'switch' operation. */
- right_repos_relpath = their_relpath;
- }
- else
- {
- /* 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 ||
- reason == svn_wc_conflict_reason_moved_here) ?
- added_repos_relpath : left_repos_relpath);
- if (! right_repos_relpath)
- right_repos_relpath = their_relpath;
- }
-
- SVN_ERR_ASSERT(right_repos_relpath != NULL);
-
- /* Determine PCONFLICT's overall node kind, which is not allowed to be
- * svn_node_none. We give it the source-right revision (THEIR_NODE_KIND)
- * -- unless source-right is deleted and hence == svn_node_none, in which
- * case we take it from source-left, which has to be the node kind that
- * was deleted. */
- conflict_node_kind = (action == svn_wc_conflict_action_delete ?
- left_kind : their_node_kind);
- SVN_ERR_ASSERT(conflict_node_kind == svn_node_file
- || conflict_node_kind == svn_node_dir);
-
-
/* Construct the tree conflict info structs. */
if (left_repos_relpath == NULL)
@@ -1443,27 +1387,29 @@ create_tree_conflict(svn_wc_conflict_des
* Send an 'empty' left revision. */
src_left_version = NULL;
else
- src_left_version = svn_wc_conflict_version_create2(repos_root_url,
- repos_uuid,
+ src_left_version = svn_wc_conflict_version_create2(eb->repos_root,
+ eb->repos_uuid,
left_repos_relpath,
left_revision,
left_kind,
result_pool);
- src_right_version = svn_wc_conflict_version_create2(repos_root_url,
- repos_uuid,
- right_repos_relpath,
- *eb->target_revision,
- their_node_kind,
- result_pool);
-
- *pconflict = svn_wc_conflict_description_create_tree2(
- local_abspath, conflict_node_kind,
- eb->switch_relpath ?
- svn_wc_operation_switch : svn_wc_operation_update,
- src_left_version, src_right_version, result_pool);
- (*pconflict)->action = action;
- (*pconflict)->reason = reason;
+ *pconflict = svn_wc__conflict_skel_create(result_pool);
+
+ SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(*pconflict,
+ eb->db, local_abspath,
+ reason,
+ action,
+ result_pool, scratch_pool));
+
+ if (eb->switch_relpath)
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(*pconflict,
+ src_left_version,
+ result_pool, scratch_pool));
+ else
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(*pconflict,
+ src_left_version,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1484,28 +1430,17 @@ create_tree_conflict(svn_wc_conflict_des
* tree conflict info is returned in *PCONFLICT. PCONFLICT must be non-NULL,
* while *PCONFLICT is always overwritten.
*
- * THEIR_NODE_KIND should be the node kind reflected by the incoming edit
- * function. E.g. dir_opened() should pass svn_node_dir, etc.
- * In some cases of delete, svn_node_none may be used here.
- *
- * THEIR_RELPATH should be 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).
- *
* The tree conflict is allocated in RESULT_POOL. Temporary allocations use
* SCRACTH_POOl.
*/
static svn_error_t *
-check_tree_conflict(svn_wc_conflict_description2_t **pconflict,
+check_tree_conflict(svn_skel_t **pconflict,
struct edit_baton *eb,
const char *local_abspath,
svn_wc__db_status_t working_status,
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)
@@ -1515,8 +1450,6 @@ check_tree_conflict(svn_wc_conflict_desc
svn_boolean_t modified = FALSE;
svn_boolean_t all_mods_are_deletes = FALSE;
- SVN_ERR_ASSERT(their_relpath != NULL);
-
*pconflict = NULL;
/* Find out if there are any local changes to this node that may
@@ -1679,8 +1612,7 @@ check_tree_conflict(svn_wc_conflict_desc
/* A conflict was detected. Append log commands to the log accumulator
* to record it. */
return svn_error_trace(create_tree_conflict(pconflict, eb, local_abspath,
- reason, action, their_node_kind,
- their_relpath,
+ reason, action,
result_pool, scratch_pool));
}
@@ -1781,7 +1713,7 @@ delete_entry(const char *path,
svn_boolean_t conflicted;
svn_boolean_t have_base;
svn_boolean_t have_work;
- svn_wc_conflict_description2_t *tree_conflict = NULL;
+ svn_skel_t *tree_conflict = NULL;
svn_skel_t *work_item = NULL;
svn_wc__db_status_t status;
svn_wc__db_status_t base_status;
@@ -1894,13 +1826,13 @@ 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, moved_to_abspath,
- pb->pool, scratch_pool));
+ svn_wc_conflict_action_delete,
+ moved_to_abspath, pb->pool, scratch_pool));
}
if (tree_conflict != NULL)
{
+ svn_wc_conflict_reason_t reason;
/* When we raise a tree conflict on a node, we don't want to mark the
* node as skipped, to allow a replacement to continue doing at least
* a bit of its work (possibly adding a not present node, for the
@@ -1911,15 +1843,12 @@ delete_entry(const char *path,
apr_hash_set(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
APR_HASH_KEY_STRING, tree_conflict);
- SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
- local_abspath,
- tree_conflict,
- scratch_pool));
-
- do_notification(eb, local_abspath, svn_node_unknown,
- svn_wc_notify_tree_conflict, scratch_pool);
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+ eb->db, local_abspath,
+ tree_conflict,
+ scratch_pool, scratch_pool));
- if (tree_conflict->reason == svn_wc_conflict_reason_edited)
+ if (reason == svn_wc_conflict_reason_edited)
{
/* The item exists locally and has some sort of local mod.
* It no longer exists in the repository at its target URL@REV.
@@ -1933,11 +1862,10 @@ delete_entry(const char *path,
/* Fall through to remove the BASE_NODEs properly, with potentially
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_moved_away_and_edited
- || tree_conflict->reason == svn_wc_conflict_reason_replaced)
+ else if (reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
+ || reason == svn_wc_conflict_reason_moved_away_and_edited
+ || reason == svn_wc_conflict_reason_replaced)
{
/* The item does not exist locally because it was already shadowed.
* We must complete the deletion, leaving the tree conflict info
@@ -1994,15 +1922,25 @@ delete_entry(const char *path,
eb->target_deleted = TRUE;
}
- SVN_ERR(svn_wc__db_wq_add(eb->db, pb->local_abspath, work_item,
- scratch_pool));
+ if (tree_conflict)
+ {
+ SVN_ERR(svn_wc__db_op_mark_conflict(eb->db, local_abspath,
+ tree_conflict, work_item,
+ scratch_pool));
+ }
+ else
+ SVN_ERR(svn_wc__db_wq_add(eb->db, pb->local_abspath, work_item,
+ scratch_pool));
SVN_ERR(svn_wc__wq_run(eb->db, pb->local_abspath,
eb->cancel_func, eb->cancel_baton,
scratch_pool));
- /* Notify. (If tree_conflict, we've already notified.) */
- if (tree_conflict == NULL)
+ /* Notify. */
+ if (tree_conflict)
+ do_notification(eb, local_abspath, svn_node_unknown,
+ svn_wc_notify_tree_conflict, scratch_pool);
+ else
{
svn_wc_notify_action_t action = svn_wc_notify_update_delete;
svn_node_kind_t node_kind;
@@ -2041,7 +1979,7 @@ add_directory(const char *path,
svn_kind_t wc_kind;
svn_boolean_t conflicted;
svn_boolean_t versioned_locally_and_present;
- svn_wc_conflict_description2_t *tree_conflict = NULL;
+ svn_skel_t *tree_conflict = NULL;
svn_error_t *err;
SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
@@ -2169,15 +2107,37 @@ add_directory(const char *path,
if (tree_conflict)
{
+ svn_wc_conflict_reason_t reason;
/* So this deletion wasn't just a deletion, it is actually a
- replacement. Luckily we still have the conflict so we can
- just update it. */
+ replacement. Let's install a better tree conflict. */
+
+ /* ### Should store the conflict in DB to allow reinstalling
+ ### with theoretically more data in close_directory() */
- /* ### What else should we update? */
- tree_conflict->action = svn_wc_conflict_action_replace;
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+ eb->db,
+ db->local_abspath,
+ tree_conflict,
+ db->pool, db->pool));
- SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, db->local_abspath,
- tree_conflict, pool));
+ tree_conflict = svn_wc__conflict_skel_create(db->pool);
+
+ SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+ tree_conflict,
+ eb->db, db->local_abspath,
+ reason, svn_wc_conflict_action_replace,
+ db->pool, db->pool));
+
+ /* Node does not pre-exist so no original location */
+ if (eb->switch_relpath)
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(tree_conflict, NULL,
+ db->pool, db->pool));
+ else
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(tree_conflict, NULL,
+ db->pool, db->pool));
+
+ SVN_ERR(svn_wc__db_op_mark_conflict(eb->db, db->local_abspath,
+ tree_conflict, NULL, db->pool));
/* And now stop checking for conflicts here and just perform
a shadowed update */
@@ -2273,7 +2233,6 @@ add_directory(const char *path,
db->local_abspath,
status, wc_kind, FALSE,
svn_wc_conflict_action_add,
- svn_node_dir, db->new_relpath,
NULL, pool, pool));
}
@@ -2299,8 +2258,7 @@ add_directory(const char *path,
db->local_abspath,
svn_wc_conflict_reason_unversioned,
svn_wc_conflict_action_add,
- svn_node_dir,
- db->new_relpath, pool, pool));
+ pool, pool));
SVN_ERR_ASSERT(tree_conflict != NULL);
}
}
@@ -2336,8 +2294,9 @@ add_directory(const char *path,
if (tree_conflict != NULL)
{
- SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, db->local_abspath,
- tree_conflict, pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(eb->db, db->local_abspath,
+ tree_conflict, NULL,
+ db->pool));
db->already_notified = TRUE;
@@ -2395,7 +2354,7 @@ open_directory(const char *path,
struct edit_baton *eb = pb->edit_baton;
svn_boolean_t have_work;
svn_boolean_t conflicted;
- svn_wc_conflict_description2_t *tree_conflict = NULL;
+ svn_skel_t *tree_conflict = NULL;
svn_wc__db_status_t status, base_status;
svn_kind_t wc_kind;
svn_error_t *err;
@@ -2430,8 +2389,9 @@ open_directory(const char *path,
/* We should have a write lock on every directory touched. */
SVN_ERR(svn_wc__write_check(eb->db, db->local_abspath, pool));
- SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &db->old_revision, NULL,
- NULL, NULL, &db->changed_rev, &db->changed_date,
+ SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &db->old_revision,
+ &db->old_repos_relpath, NULL, NULL,
+ &db->changed_rev, &db->changed_date,
&db->changed_author, &db->ambient_depth,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
@@ -2444,10 +2404,10 @@ open_directory(const char *path,
base_status = status;
else
SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db->old_revision,
- NULL, NULL, NULL, &db->changed_rev,
- &db->changed_date, &db->changed_author,
- &db->ambient_depth, NULL, NULL, NULL,
- NULL, NULL,
+ &db->old_repos_relpath, NULL, NULL,
+ &db->changed_rev, &db->changed_date,
+ &db->changed_author, &db->ambient_depth,
+ NULL, NULL, NULL, NULL, NULL,
eb->db, db->local_abspath,
db->pool, pool));
@@ -2498,21 +2458,24 @@ open_directory(const char *path,
if (!db->shadowed)
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->moved_to_abspath,
- db->pool, pool));
+ svn_wc_conflict_action_edit,
+ db->moved_to_abspath, db->pool, pool));
/* Remember the roots of any locally deleted trees. */
if (tree_conflict != NULL)
{
+ svn_wc_conflict_reason_t reason;
db->edit_conflict = tree_conflict;
/* 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_moved_away_and_edited ||
- tree_conflict->reason == svn_wc_conflict_reason_replaced);
+
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+ eb->db, db->local_abspath,
+ tree_conflict,
+ db->pool, db->pool));
+ SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
+ || reason == svn_wc_conflict_reason_moved_away_and_edited
+ || reason == svn_wc_conflict_reason_replaced);
/* Continue updating BASE */
db->shadowed = TRUE;
@@ -2592,6 +2555,7 @@ close_directory(void *dir_baton,
const char *new_changed_author = NULL;
apr_pool_t *scratch_pool = db->pool;
svn_skel_t *all_work_items = NULL;
+ svn_skel_t *conflict_skel = NULL;
/* Skip if we're in a conflicted tree. */
if (db->skip_this)
@@ -2602,6 +2566,9 @@ close_directory(void *dir_baton,
return SVN_NO_ERROR;
}
+ if (db->edited)
+ conflict_skel = db->edit_conflict;
+
SVN_ERR(svn_categorize_props(db->propchanges, &entry_prop_changes,
&dav_prop_changes, ®ular_prop_changes, pool));
@@ -2674,8 +2641,6 @@ close_directory(void *dir_baton,
to deal with them. */
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. */
@@ -2723,23 +2688,19 @@ close_directory(void *dir_baton,
/* Merge pending properties into temporary files (ignoring
conflicts). */
- SVN_ERR_W(svn_wc__merge_props(&work_item,
+ SVN_ERR_W(svn_wc__merge_props(&conflict_skel,
&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,
@@ -2747,8 +2708,6 @@ close_directory(void *dir_baton,
_("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,
@@ -2919,6 +2878,54 @@ close_directory(void *dir_baton,
if (props == NULL)
props = base_props;
+ if (conflict_skel)
+ {
+ svn_skel_t *work_item;
+ svn_boolean_t completed;
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&completed,
+ conflict_skel));
+
+ if (completed)
+ {
+ /* Avoid assertion */
+ }
+ else if (eb->switch_relpath)
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+ conflict_skel,
+ db->adding_dir
+ ? NULL
+ : svn_wc_conflict_version_create2(
+ eb->repos_root,
+ eb->repos_uuid,
+ db->old_repos_relpath,
+ db->old_revision,
+ svn_node_dir,
+ scratch_pool),
+ db->pool, db->pool));
+ else
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(
+ conflict_skel,
+ db->adding_dir
+ ? NULL
+ : svn_wc_conflict_version_create2(
+ eb->repos_root,
+ eb->repos_uuid,
+ db->old_repos_relpath,
+ db->old_revision,
+ svn_node_dir,
+ scratch_pool),
+ db->pool, db->pool));
+
+ SVN_ERR(svn_wc__conflict_create_markers(&work_item,
+ eb->db, db->local_abspath,
+ conflict_skel,
+ scratch_pool, scratch_pool));
+
+ all_work_items = svn_wc__wq_merge(all_work_items, work_item,
+ scratch_pool);
+ }
+
/* Update the BASE data for the directory and mark the directory
complete */
SVN_ERR(svn_wc__db_base_add_directory(
@@ -2934,7 +2941,7 @@ close_directory(void *dir_baton,
(dav_prop_changes->nelts > 0)
? svn_prop_array_to_hash(dav_prop_changes, pool)
: NULL,
- NULL /* conflict */,
+ conflict_skel,
(! db->shadowed) && new_base_props != NULL,
new_actual_props,
all_work_items,
@@ -2981,6 +2988,14 @@ close_directory(void *dir_baton,
eb->cancel_func, eb->cancel_baton,
scratch_pool));
+ if (conflict_skel && eb->conflict_func)
+ SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
+ conflict_skel,
+ NULL /* merge_options */,
+ eb->conflict_func,
+ eb->conflict_baton,
+ scratch_pool));
+
/* Notify of any prop changes on this directory -- but do nothing if
it's an added or skipped directory, because notification has already
happened in that case - unless the add was obstructed by a dir
@@ -3156,7 +3171,7 @@ add_file(const char *path,
apr_pool_t *scratch_pool;
svn_boolean_t conflicted = FALSE;
svn_boolean_t versioned_locally_and_present = FALSE;
- svn_wc_conflict_description2_t *tree_conflict = NULL;
+ svn_skel_t *tree_conflict = NULL;
svn_error_t *err = SVN_NO_ERROR;
SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
@@ -3270,15 +3285,37 @@ add_file(const char *path,
if (tree_conflict)
{
+ svn_wc_conflict_reason_t reason;
/* So this deletion wasn't just a deletion, it is actually a
- replacement. Luckily we still have the conflict so we can
- just update it. */
+ replacement. Let's install a better tree conflict. */
+
+ /* ### Should store the conflict in DB to allow reinstalling
+ ### with theoretically more data in close_directory() */
+
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+ eb->db,
+ fb->local_abspath,
+ tree_conflict,
+ fb->pool, fb->pool));
- /* ### What else should we update? */
- tree_conflict->action = svn_wc_conflict_action_replace;
+ tree_conflict = svn_wc__conflict_skel_create(fb->pool);
- SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, fb->local_abspath,
- tree_conflict, pool));
+ SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+ tree_conflict,
+ eb->db, fb->local_abspath,
+ reason, svn_wc_conflict_action_replace,
+ fb->pool, fb->pool));
+
+ /* Node does not pre-exist so no original location */
+ if (eb->switch_relpath)
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(tree_conflict, NULL,
+ fb->pool, fb->pool));
+ else
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(tree_conflict, NULL,
+ fb->pool, fb->pool));
+
+ SVN_ERR(svn_wc__db_op_mark_conflict(eb->db, fb->local_abspath,
+ tree_conflict, NULL, fb->pool));
/* And now stop checking for conflicts here and just perform
a shadowed update */
@@ -3369,8 +3406,7 @@ add_file(const char *path,
SVN_ERR(check_tree_conflict(&tree_conflict, eb,
fb->local_abspath,
status, wc_kind, FALSE,
- svn_wc_conflict_action_add,
- svn_node_file, fb->new_relpath, NULL,
+ svn_wc_conflict_action_add, NULL,
scratch_pool, scratch_pool));
}
@@ -3397,8 +3433,6 @@ add_file(const char *path,
fb->local_abspath,
svn_wc_conflict_reason_unversioned,
svn_wc_conflict_action_add,
- svn_node_file,
- fb->new_relpath,
scratch_pool, scratch_pool));
SVN_ERR_ASSERT(tree_conflict != NULL);
}
@@ -3417,10 +3451,10 @@ add_file(const char *path,
if (tree_conflict != NULL)
{
- SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
- fb->local_abspath,
- tree_conflict,
- scratch_pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
+ fb->local_abspath,
+ tree_conflict, NULL,
+ scratch_pool));
fb->already_notified = TRUE;
do_notification(eb, fb->local_abspath, svn_node_file,
@@ -3457,7 +3491,7 @@ open_file(const char *path,
svn_boolean_t have_work;
svn_wc__db_status_t status;
svn_kind_t wc_kind;
- svn_wc_conflict_description2_t *tree_conflict = NULL;
+ svn_skel_t *tree_conflict = NULL;
/* the file_pool can stick around for a *long* time, so we want to use
a subpool for any temporary allocations. */
@@ -3493,8 +3527,9 @@ open_file(const char *path,
/* Sanity check. */
/* If replacing, make sure the .svn entry already exists. */
- SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &fb->old_revision, NULL,
- NULL, NULL, &fb->changed_rev, &fb->changed_date,
+ SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &fb->old_revision,
+ &fb->old_repos_relpath, NULL, NULL,
+ &fb->changed_rev, &fb->changed_date,
&fb->changed_author, NULL,
&fb->original_checksum, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
@@ -3505,9 +3540,10 @@ open_file(const char *path,
if (have_work)
SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &fb->old_revision,
- NULL, NULL, NULL, &fb->changed_rev,
- &fb->changed_date, &fb->changed_author,
- NULL, &fb->original_checksum, NULL, NULL,
+ &fb->old_repos_relpath, NULL, NULL,
+ &fb->changed_rev, &fb->changed_date,
+ &fb->changed_author, NULL,
+ &fb->original_checksum, NULL, NULL,
NULL, NULL,
eb->db, fb->local_abspath,
fb->pool, scratch_pool));
@@ -3544,22 +3580,24 @@ open_file(const char *path,
if (!fb->shadowed)
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->moved_to_abspath,
- fb->pool, scratch_pool));
+ svn_wc_conflict_action_edit,
+ fb->moved_to_abspath, fb->pool, scratch_pool));
/* Is this path the victim of a newly-discovered tree conflict? */
if (tree_conflict != NULL)
{
+ svn_wc_conflict_reason_t reason;
fb->edit_conflict = tree_conflict;
-
/* 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_moved_away_and_edited ||
- tree_conflict->reason == svn_wc_conflict_reason_replaced);
+
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+ eb->db, fb->local_abspath,
+ tree_conflict,
+ fb->pool, fb->pool));
+ SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
+ || reason == svn_wc_conflict_reason_moved_away_and_edited
+ || reason == svn_wc_conflict_reason_replaced);
/* Continue updating BASE */
fb->shadowed = TRUE;
@@ -3746,6 +3784,7 @@ change_file_prop(void *file_baton,
*/
svn_error_t *
svn_wc__perform_file_merge(svn_skel_t **work_items,
+ svn_skel_t **conflict_skel,
enum svn_wc_merge_outcome_t *merge_outcome,
svn_wc__db_t *db,
const char *local_abspath,
@@ -3758,8 +3797,6 @@ svn_wc__perform_file_merge(svn_skel_t **
svn_revnum_t target_revision,
const apr_array_header_t *propchanges,
const char *diff3_cmd,
- svn_wc_conflict_resolver_func2_t conflict_func,
- void *conflict_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
@@ -3827,17 +3864,17 @@ svn_wc__perform_file_merge(svn_skel_t **
Remember that this function wants full paths! */
/* ### TODO: Pass version info here. */
SVN_ERR(svn_wc__internal_merge(&work_item,
+ conflict_skel,
merge_outcome,
db,
- merge_left, NULL,
- new_text_base_tmp_abspath, NULL,
+ merge_left,
+ new_text_base_tmp_abspath,
local_abspath,
wri_abspath,
oldrev_str, newrev_str, mine_str,
actual_props,
FALSE /* dry_run */,
diff3_cmd, NULL, propchanges,
- conflict_func, conflict_baton,
cancel_func, cancel_baton,
result_pool, scratch_pool));
@@ -3879,6 +3916,7 @@ svn_wc__perform_file_merge(svn_skel_t **
*/
static svn_error_t *
merge_file(svn_skel_t **work_items,
+ svn_skel_t **conflict_skel,
svn_boolean_t *install_pristine,
const char **install_from,
svn_wc_notify_state_t *content_state,
@@ -3980,6 +4018,7 @@ merge_file(svn_skel_t **work_items,
Now we need to let loose svn_wc__merge_internal() to merge
the textual changes into the working file. */
SVN_ERR(svn_wc__perform_file_merge(work_items,
+ conflict_skel,
&merge_outcome,
eb->db,
working_abspath,
@@ -3994,7 +4033,6 @@ merge_file(svn_skel_t **work_items,
*eb->target_revision,
fb->propchanges,
eb->diff3_cmd,
- eb->conflict_func, eb->conflict_baton,
eb->cancel_func, eb->cancel_baton,
result_pool, scratch_pool));
} /* end: working file exists and has mods */
@@ -4108,6 +4146,7 @@ close_file(void *file_baton,
apr_hash_t *current_actual_props = NULL;
apr_hash_t *local_actual_props = NULL;
svn_skel_t *all_work_items = NULL;
+ svn_skel_t *conflict_skel = NULL;
svn_skel_t *work_item;
apr_pool_t *scratch_pool = fb->pool; /* Destroyed at function exit */
svn_boolean_t keep_recorded_info = FALSE;
@@ -4122,6 +4161,9 @@ close_file(void *file_baton,
return SVN_NO_ERROR;
}
+ if (fb->edited)
+ conflict_skel = fb->edit_conflict;
+
if (expected_md5_digest)
SVN_ERR(svn_checksum_parse_hex(&expected_md5_checksum, svn_checksum_md5,
expected_md5_digest, scratch_pool));
@@ -4270,7 +4312,7 @@ close_file(void *file_baton,
if (local_is_link != incoming_is_link)
{
- svn_wc_conflict_description2_t *tree_conflict = NULL;
+ svn_skel_t *tree_conflict = NULL;
fb->shadowed = TRUE;
fb->obstruction_found = TRUE;
@@ -4280,12 +4322,11 @@ close_file(void *file_baton,
fb->local_abspath,
svn_wc_conflict_reason_added,
svn_wc_conflict_action_add,
- svn_node_file, fb->new_relpath,
scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
- fb->local_abspath,
- tree_conflict,
- scratch_pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
+ fb->local_abspath,
+ tree_conflict, NULL,
+ scratch_pool));
fb->already_notified = TRUE;
do_notification(eb, fb->local_abspath, svn_node_unknown,
@@ -4304,35 +4345,31 @@ close_file(void *file_baton,
/* 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(&work_item,
+ SVN_ERR(svn_wc__merge_props(&conflict_skel,
&prop_state,
&new_base_props,
&new_actual_props,
eb->db,
working_abspath,
svn_kind_file,
- NULL /* left_version */,
- NULL /* right_version */,
NULL /* server_baseprops (update, not merge) */,
current_base_props,
current_actual_props,
regular_prop_changes, /* propchanges */
TRUE /* base_merge */,
FALSE /* dry_run */,
- eb->conflict_func, eb->conflict_baton,
eb->cancel_func, eb->cancel_baton,
scratch_pool,
scratch_pool));
/* We will ALWAYS have properties to save (after a not-dry-run merge). */
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);
/* Merge the text. This will queue some additional work. */
if (!fb->obstruction_found)
{
svn_error_t *err;
- err = merge_file(&work_item, &install_pristine, &install_from,
+ err = merge_file(&work_item, &conflict_skel,
+ &install_pristine, &install_from,
&content_state, fb, current_actual_props,
fb->changed_date, scratch_pool, scratch_pool);
@@ -4443,29 +4480,23 @@ close_file(void *file_baton,
/* Store the incoming props (sent as propchanges) in new_base_props
and create a set of new actual props to use for notifications */
- SVN_ERR(svn_wc__merge_props(&work_item,
+ SVN_ERR(svn_wc__merge_props(&conflict_skel,
&prop_state,
&new_base_props,
&new_actual_props,
eb->db,
fb->local_abspath,
svn_kind_file,
- NULL /* left_version */,
- NULL /* right_version */,
NULL /* server_baseprops (not merging) */,
current_base_props /* pristine_props */,
fake_actual_props /* actual_props */,
regular_prop_changes, /* propchanges */
TRUE /* base_merge */,
FALSE /* dry_run */,
- NULL, NULL, /* No conflict handling */
eb->cancel_func, eb->cancel_baton,
scratch_pool,
scratch_pool));
- all_work_items = svn_wc__wq_merge(all_work_items, work_item,
- scratch_pool);
-
if (fb->new_text_base_sha1_checksum)
content_state = svn_wc_notify_state_changed;
else
@@ -4484,6 +4515,52 @@ close_file(void *file_baton,
if (new_checksum == NULL)
new_checksum = fb->original_checksum;
+ if (conflict_skel)
+ {
+ svn_skel_t *work_item;
+ svn_boolean_t completed;
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&completed,
+ conflict_skel));
+
+ if (completed)
+ {
+ /* Avoid assertion */
+ }
+ else if (eb->switch_relpath)
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+ conflict_skel,
+ fb->adding_file
+ ? NULL
+ : svn_wc_conflict_version_create2(eb->repos_root,
+ eb->repos_uuid,
+ fb->old_repos_relpath,
+ fb->old_revision,
+ svn_node_file,
+ fb->pool),
+ fb->pool, fb->pool));
+ else
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(
+ conflict_skel,
+ fb->adding_file
+ ? NULL
+ : svn_wc_conflict_version_create2(eb->repos_root,
+ eb->repos_uuid,
+ fb->old_repos_relpath,
+ fb->old_revision,
+ svn_node_file,
+ fb->pool),
+ fb->pool, fb->pool));
+
+ SVN_ERR(svn_wc__conflict_create_markers(&work_item,
+ eb->db, fb->local_abspath,
+ conflict_skel,
+ scratch_pool, scratch_pool));
+
+ all_work_items = svn_wc__wq_merge(all_work_items, work_item,
+ scratch_pool);
+ }
+
SVN_ERR(svn_wc__db_base_add_file(eb->db, fb->local_abspath,
eb->wcroot_abspath,
fb->new_relpath,
@@ -4499,7 +4576,7 @@ close_file(void *file_baton,
dav_prop_changes,
scratch_pool)
: NULL,
- NULL /* conflict */,
+ conflict_skel,
(! fb->shadowed) && new_base_props,
new_actual_props,
keep_recorded_info,
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc-queries.sql?rev=1425414&r1=1425413&r2=1425414&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc-queries.sql Sun Dec 23 05:58:52 2012
@@ -760,12 +760,6 @@ SELECT local_relpath, tree_conflict_data
FROM actual_node
WHERE wc_id = ?1 AND parent_relpath = ?2 AND tree_conflict_data IS NOT NULL
--- STMT_SELECT_CONFLICT_DETAILS
-SELECT prop_reject, conflict_old, conflict_new, conflict_working,
- tree_conflict_data
-FROM actual_node
-WHERE wc_id = ?1 AND local_relpath = ?2
-
-- STMT_CLEAR_TEXT_CONFLICT
UPDATE actual_node SET
conflict_old = NULL,
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc.h?rev=1425414&r1=1425413&r2=1425414&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc.h Sun Dec 23 05:58:52 2012
@@ -151,6 +151,9 @@ extern "C" {
*
* == 1.7.x shipped with format 29
*
+ * The bump to 30 switched the conflict storage to a skel inside conflict_data.
+ * Also clears some known invalid state.
+ *
* Please document any further format changes here.
*/
@@ -182,6 +185,9 @@ extern "C" {
/* A version < this has no work queue (see workqueue.h). */
#define SVN_WC__HAS_WORK_QUEUE 13
+/* The first version that uses conflict skels for all conflicts */
+#define SVN_WC__USES_CONFLICT_SKELS 30
+
/* Return true iff error E indicates an "is not a working copy" type
of error, either because something wasn't a working copy at all, or
because it's a working copy from a previous version (in need of
@@ -392,16 +398,6 @@ svn_wc__internal_file_modified_p(svn_boo
When MERGE_OPTIONS are specified, they are used by the internal
diff3 routines, or passed to the external diff3 tool.
- If CONFLICT_FUNC is non-NULL, then call it with CONFLICT_BATON if a
- conflict is encountered, giving the callback a chance to resolve
- the conflict (before marking the file 'conflicted').
-
- When LEFT_VERSION and RIGHT_VERSION are non-NULL, pass them to the
- conflict resolver as older_version and their_version.
-
- ## TODO: We should store the information in LEFT_VERSION and RIGHT_VERSION
- in the working copy for future retrieval via svn info.
-
WRI_ABSPATH describes in which working copy information should be
retrieved. (Interesting for merging file externals).
@@ -418,12 +414,11 @@ svn_wc__internal_file_modified_p(svn_boo
*/
svn_error_t *
svn_wc__internal_merge(svn_skel_t **work_items,
+ svn_skel_t **conflict_skel,
enum svn_wc_merge_outcome_t *merge_outcome,
svn_wc__db_t *db,
const char *left_abspath,
- const svn_wc_conflict_version_t *left_version,
const char *right_abspath,
- const svn_wc_conflict_version_t *right_version,
const char *target_abspath,
const char *wri_abspath,
const char *left_label,
@@ -434,8 +429,6 @@ svn_wc__internal_merge(svn_skel_t **work
const char *diff3_cmd,
const apr_array_header_t *merge_options,
const apr_array_header_t *prop_diff,
- svn_wc_conflict_resolver_func2_t conflict_func,
- void *conflict_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
@@ -709,6 +702,7 @@ svn_wc__write_check(svn_wc__db_t *db,
*/
svn_error_t *
svn_wc__perform_file_merge(svn_skel_t **work_items,
+ svn_skel_t **conflict_skel,
enum svn_wc_merge_outcome_t *merge_outcome,
svn_wc__db_t *db,
const char *local_abspath,
@@ -721,8 +715,6 @@ svn_wc__perform_file_merge(svn_skel_t **
svn_revnum_t target_revision,
const apr_array_header_t *propchanges,
const char *diff3_cmd,
- svn_wc_conflict_resolver_func2_t conflict_func,
- void *conflict_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c?rev=1425414&r1=1425413&r2=1425414&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c Sun Dec 23 05:58:52 2012
@@ -42,6 +42,7 @@
#include "wc-queries.h"
#include "entries.h"
#include "lock.h"
+#include "conflicts.h"
#include "tree_conflicts.h"
#include "wc_db_private.h"
#include "workqueue.h"
@@ -214,6 +215,9 @@ typedef struct insert_working_baton_t {
/* may have work items to queue in this transaction */
const svn_skel_t *work_items;
+ /* may have conflict to install in this transaction */
+ const svn_skel_t *conflict;
+
/* If the value is > 0 and < op_depth, also insert a not-present
at op-depth NOT_PRESENT_OP_DEPTH, based on this same information */
int not_present_op_depth;
@@ -306,6 +310,33 @@ set_actual_props(apr_int64_t wc_id,
apr_pool_t *scratch_pool);
static svn_error_t *
+temp_op_set_text_conflict_marker_files(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const char *old_abspath,
+ const char *new_abspath,
+ const char *wrk_abspath,
+ apr_pool_t *scratch_pool);
+
+static svn_error_t *
+temp_op_set_prop_conflict_marker_file(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const char *prej_abspath,
+ apr_pool_t *scratch_pool);
+
+static svn_error_t *
+temp_op_set_tree_conflict(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool);
+
+
+static svn_error_t *
+mark_conflict(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const svn_skel_t *conflict_skel,
+ apr_pool_t *scratch_pool);
+
+static svn_error_t *
insert_incomplete_children(svn_sqlite__db_t *sdb,
apr_int64_t wc_id,
const char *local_relpath,
@@ -734,9 +765,6 @@ insert_base_node(void *baton,
SVN_ERR_ASSERT(repos_id != INVALID_REPOS_ID);
SVN_ERR_ASSERT(pibb->repos_relpath != NULL);
- /* ### we can't handle this right now */
- SVN_ERR_ASSERT(pibb->conflict == NULL);
-
if (pibb->keep_recorded_info)
{
svn_boolean_t have_row;
@@ -867,6 +895,8 @@ insert_base_node(void *baton,
}
SVN_ERR(add_work_items(wcroot->sdb, pibb->work_items, scratch_pool));
+ if (pibb->conflict)
+ SVN_ERR(mark_conflict(wcroot, local_relpath, pibb->conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1054,8 +1084,6 @@ insert_working_node(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
- SVN_ERR(add_work_items(wcroot->sdb, piwb->work_items, scratch_pool));
-
if (piwb->not_present_op_depth > 0
&& piwb->not_present_op_depth < piwb->op_depth)
{
@@ -1077,6 +1105,11 @@ insert_working_node(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
+ SVN_ERR(add_work_items(wcroot->sdb, piwb->work_items, scratch_pool));
+ if (piwb->conflict)
+ SVN_ERR(mark_conflict(wcroot, local_relpath, piwb->conflict,
+ scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -2738,6 +2771,7 @@ svn_wc__db_external_add_file(svn_wc__db_
apr_hash_t *new_actual_props,
svn_boolean_t keep_recorded_info,
+ const svn_skel_t *conflict,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -2794,6 +2828,7 @@ svn_wc__db_external_add_file(svn_wc__db_
ieb.keep_recorded_info = keep_recorded_info;
+ ieb.conflict = conflict;
ieb.work_items = work_items;
return svn_error_trace(
@@ -4309,7 +4344,6 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
#if 0
SVN_ERR_ASSERT(children != NULL);
#endif
- SVN_ERR_ASSERT(conflict == NULL); /* ### can't handle yet */
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
local_abspath, scratch_pool, scratch_pool));
@@ -4345,6 +4379,7 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
iwb.depth = depth;
iwb.work_items = work_items;
+ iwb.conflict = conflict;
SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, insert_working_node, &iwb,
scratch_pool));
@@ -4384,7 +4419,6 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
|| (original_repos_relpath && original_root_url
&& original_uuid && checksum
&& original_revision != SVN_INVALID_REVNUM));
- SVN_ERR_ASSERT(conflict == NULL); /* ### can't handle yet */
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
local_abspath, scratch_pool, scratch_pool));
@@ -4419,6 +4453,7 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
iwb.checksum = checksum;
iwb.work_items = work_items;
+ iwb.conflict = conflict;
SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, insert_working_node, &iwb,
scratch_pool));
@@ -4453,7 +4488,6 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
/* ### any assertions for CHANGED_* ? */
/* ### any assertions for ORIGINAL_* ? */
SVN_ERR_ASSERT(target != NULL);
- SVN_ERR_ASSERT(conflict == NULL); /* ### can't handle yet */
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
local_abspath, scratch_pool, scratch_pool));
@@ -4488,6 +4522,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
iwb.target = target;
iwb.work_items = work_items;
+ iwb.conflict = conflict;
SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, insert_working_node, &iwb,
scratch_pool));
@@ -4714,12 +4749,6 @@ set_props_txn(void *baton,
struct set_props_baton_t *spb = baton;
apr_hash_t *pristine_props;
- /* ### we dunno what to do with CONFLICT yet. */
- SVN_ERR_ASSERT(spb->conflict == NULL);
-
- /* First order of business: insert all the work items. */
- SVN_ERR(add_work_items(wcroot->sdb, spb->work_items, scratch_pool));
-
/* Check if the props are modified. If no changes, then wipe out the
ACTUAL props. PRISTINE_PROPS==NULL means that any
ACTUAL props are okay as provided, so go ahead and set them. */
@@ -4746,6 +4775,11 @@ set_props_txn(void *baton,
SVN_ERR(db_record_fileinfo(&rb, wcroot, local_relpath, scratch_pool));
}
+ /* And finally. */
+ SVN_ERR(add_work_items(wcroot->sdb, spb->work_items, scratch_pool));
+ if (spb->conflict)
+ SVN_ERR(mark_conflict(wcroot, local_relpath, spb->conflict, scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -5169,15 +5203,220 @@ svn_wc__db_op_set_changelist(svn_wc__db_
scratch_pool));
}
+/* Implementation of svn_wc__db_op_mark_conflict() */
+static svn_error_t *
+mark_conflict(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const svn_skel_t *conflict_skel,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t is_complete;
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&is_complete, conflict_skel));
+
+ SVN_ERR_ASSERT(is_complete);
+
+#if SVN_WC__VERSION < SVN_WC__USES_CONFLICT_SKELS
+ if (conflict_skel)
+ {
+ /* Store conflict data in the old locations */
+ svn_boolean_t text_conflict;
+ svn_boolean_t prop_conflict;
+ svn_boolean_t tree_conflict;
+
+ svn_wc_conflict_reason_t local_change;
+ svn_wc_conflict_action_t incoming_change;
+ const apr_array_header_t *locations;
+ svn_wc_operation_t operation;
+
+ svn_wc__db_t *db;
+ const char *local_abspath;
+
+ /* Ugly but temporary hack: obtain a DB for transforming paths.
+ ### Can't use this for a write tranaction or we get a deadlock! */
+
+ SVN_ERR(svn_wc__db_open(&db, NULL, FALSE, FALSE,
+ scratch_pool, scratch_pool));
+
+ local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
+ scratch_pool);
+
+ SVN_ERR(svn_wc__conflict_read_info(&operation, &locations,
+ &text_conflict, &prop_conflict,
+ &tree_conflict,
+ db, local_abspath, conflict_skel,
+ scratch_pool, scratch_pool));
+
+ if (text_conflict)
+ {
+ const char *mine_abspath;
+ const char *their_old_abspath;
+ const char *their_abspath;
+
+ SVN_ERR(svn_wc__conflict_read_text_conflict(&mine_abspath,
+ &their_old_abspath,
+ &their_abspath,
+ db, local_abspath,
+ conflict_skel,
+ scratch_pool,
+ scratch_pool));
+
+ SVN_ERR(temp_op_set_text_conflict_marker_files(wcroot, local_relpath,
+ their_old_abspath,
+ their_abspath,
+ mine_abspath,
+ scratch_pool));
+ }
+
+ if (prop_conflict)
+ {
+ const char *prej_abspath;
+
+ SVN_ERR(svn_wc__conflict_read_prop_conflict(&prej_abspath, NULL,
+ NULL, NULL, NULL,
+ db, local_abspath,
+ conflict_skel,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(temp_op_set_prop_conflict_marker_file(wcroot, local_relpath,
+ prej_abspath,
+ scratch_pool));
+ }
+
+ if (tree_conflict)
+ {
+ svn_wc_conflict_description2_t *desc;
+ svn_wc_conflict_version_t *v1;
+ svn_wc_conflict_version_t *v2;
+ svn_node_kind_t tc_kind;
+
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&local_change,
+ &incoming_change,
+ db, local_abspath,
+ conflict_skel,
+ scratch_pool, scratch_pool));
+
+
+ v1 = (locations && locations->nelts > 0)
+ ? APR_ARRAY_IDX(locations, 0, svn_wc_conflict_version_t *)
+ : NULL;
+
+ v2 = (locations && locations->nelts > 1)
+ ? APR_ARRAY_IDX(locations, 1, svn_wc_conflict_version_t *)
+ : NULL;
+
+ if (incoming_change != svn_wc_conflict_action_delete
+ && (operation == svn_wc_operation_update
+ || operation == svn_wc_operation_switch))
+ {
+ svn_wc__db_status_t status;
+ svn_revnum_t revision;
+ const char *repos_relpath;
+ apr_int64_t repos_id;
+ svn_kind_t kind;
+ svn_error_t *err;
+
+ /* ### Theoretically we should just fetch the BASE information
+ here. This code might need tweaks until all tree conflicts
+ are installed in the proper state */
+
+ SVN_ERR_ASSERT(v2 == NULL); /* Not set for update and switch */
+
+ /* With an update or switch we have to fetch the second location
+ for a tree conflict from WORKING. (For text or prop from BASE)
+ */
+ err = base_get_info(&status, &kind, &revision,
+ &repos_relpath, &repos_id, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ wcroot, local_relpath,
+ scratch_pool, scratch_pool);
+
+ if (err)
+ {
+ if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ /* Ignore BASE */
+
+ tc_kind = svn_node_file; /* Avoid assertion */
+ }
+ else if (repos_relpath)
+ {
+ const char *repos_root_url;
+ const char *repos_uuid;
+
+ SVN_ERR(fetch_repos_info(&repos_root_url, &repos_uuid,
+ wcroot->sdb, repos_id,
+ scratch_pool));
+
+ v2 = svn_wc_conflict_version_create2(repos_root_url,
+ repos_uuid,
+ repos_relpath,
+ revision,
+ svn__node_kind_from_kind(kind),
+ scratch_pool);
+ tc_kind = svn__node_kind_from_kind(kind);
+ }
+ else
+ tc_kind = svn_node_file; /* Avoid assertion */
+ }
+ else
+ {
+ if (v2)
+ tc_kind = v2->node_kind;
+ else if (v1)
+ tc_kind = v1->node_kind;
+ else
+ tc_kind = svn_node_file; /* Avoid assertion */
+ }
+
+ desc = svn_wc_conflict_description_create_tree2(local_abspath,
+ tc_kind,
+ operation,
+ v1, v2,
+ scratch_pool);
+ desc->reason = local_change;
+ desc->action = incoming_change;
+
+ SVN_ERR(temp_op_set_tree_conflict(desc, wcroot, local_relpath,
+ scratch_pool));
+ }
+ SVN_ERR(svn_wc__db_close(db));
+ }
+#else
+ /* And in the new location */
+#endif
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc__db_op_mark_conflict(svn_wc__db_t *db,
const char *local_abspath,
+ const svn_skel_t *conflict_skel,
+ const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- NOT_IMPLEMENTED();
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+ local_abspath, scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_ERR(mark_conflict(wcroot, local_relpath, conflict_skel, scratch_pool));
+
+ /* ### Should be handled in the same transaction as setting the conflict */
+ if (work_items)
+ SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
+
+ SVN_ERR(flush_entries(wcroot, local_abspath, svn_depth_empty, scratch_pool));
+
+ return SVN_NO_ERROR;
+
}
/* Baton for db_op_mark_resolved */
@@ -5274,10 +5513,10 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
/* */
static svn_error_t *
-set_tc_txn(void *baton,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
+temp_op_set_tree_conflict(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
{
const svn_wc_conflict_description2_t *tree_conflict = baton;
const char *parent_relpath;
@@ -5355,7 +5594,7 @@ svn_wc__db_op_set_tree_conflict(svn_wc__
db, local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, set_tc_txn,
+ SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, temp_op_set_tree_conflict,
(void *) tree_conflict, scratch_pool));
/* There may be some entries, and the conflict info is now out of date. */
@@ -11563,7 +11802,7 @@ svn_wc__db_read_conflicts(const apr_arra
/* First look for text and property conflicts in ACTUAL */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_CONFLICT_DETAILS));
+ STMT_SELECT_ACTUAL_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
cflcts = apr_array_make(result_pool, 4,
@@ -11596,9 +11835,9 @@ svn_wc__db_read_conflicts(const apr_arra
APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t*) = desc;
}
- conflict_old = svn_sqlite__column_text(stmt, 1, NULL);
- conflict_new = svn_sqlite__column_text(stmt, 2, NULL);
- conflict_working = svn_sqlite__column_text(stmt, 3, NULL);
+ conflict_old = svn_sqlite__column_text(stmt, 2, NULL);
+ conflict_new = svn_sqlite__column_text(stmt, 3, NULL);
+ conflict_working = svn_sqlite__column_text(stmt, 4, NULL);
if (conflict_old || conflict_new || conflict_working)
{
@@ -11620,7 +11859,7 @@ svn_wc__db_read_conflicts(const apr_arra
APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t*) = desc;
}
- conflict_data = svn_sqlite__column_text(stmt, 4, scratch_pool);
+ conflict_data = svn_sqlite__column_text(stmt, 5, scratch_pool);
if (conflict_data)
{
const svn_wc_conflict_description2_t *desc;
@@ -12562,30 +12801,18 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_wc__db_temp_op_set_text_conflict_marker_files(svn_wc__db_t *db,
- const char *local_abspath,
- const char *old_abspath,
- const char *new_abspath,
- const char *wrk_abspath,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+temp_op_set_text_conflict_marker_files(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const char *old_abspath,
+ const char *new_abspath,
+ const char *wrk_abspath,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath, *old_relpath, *new_relpath, *wrk_relpath;
+ const char *old_relpath, *new_relpath, *wrk_relpath;
svn_sqlite__stmt_t *stmt;
svn_boolean_t got_row;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR_ASSERT(svn_dirent_is_absolute(old_abspath));
- SVN_ERR_ASSERT(svn_dirent_is_absolute(new_abspath));
- /* Binary files usually send NULL */
- SVN_ERR_ASSERT(!wrk_abspath || svn_dirent_is_absolute(wrk_abspath));
-
- SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
- local_abspath,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_WCROOT(wcroot);
-
/* This should be handled in a transaction, but we can assume a db lock
and this code won't survive until 1.7 */
@@ -12622,14 +12849,14 @@ svn_wc__db_temp_op_set_text_conflict_mar
return svn_error_createf(SVN_ERR_BAD_FILENAME, svn_sqlite__reset(stmt),
_("Invalid conflict file '%s' for '%s'"),
svn_dirent_local_style(old_abspath, scratch_pool),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(wcroot, local_relpath,
scratch_pool));
new_relpath = svn_dirent_skip_ancestor(wcroot->abspath, new_abspath);
if (new_relpath == new_abspath)
return svn_error_createf(SVN_ERR_BAD_FILENAME, svn_sqlite__reset(stmt),
_("Invalid conflict file '%s' for '%s'"),
svn_dirent_local_style(new_abspath, scratch_pool),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(wcroot, local_relpath,
scratch_pool));
if (wrk_abspath)
@@ -12640,7 +12867,7 @@ svn_wc__db_temp_op_set_text_conflict_mar
_("Invalid conflict file '%s' for '%s'"),
svn_dirent_local_style(wrk_abspath,
scratch_pool),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(wcroot, local_relpath,
scratch_pool));
}
else
@@ -12655,27 +12882,16 @@ svn_wc__db_temp_op_set_text_conflict_mar
return svn_error_trace(svn_sqlite__step_done(stmt));
}
-
-/* Set the conflict marker information on LOCAL_ABSPATH to the specified
- values */
-svn_error_t *
-svn_wc__db_temp_op_set_property_conflict_marker_file(svn_wc__db_t *db,
- const char *local_abspath,
- const char *prej_abspath,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+temp_op_set_prop_conflict_marker_file(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const char *prej_abspath,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath, *prej_relpath;
+ const char *prej_relpath;
svn_sqlite__stmt_t *stmt;
svn_boolean_t got_row;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
- local_abspath,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_WCROOT(wcroot);
-
/* This should be handled in a transaction, but we can assume a db locl\
and this code won't survive until 1.7 */
@@ -12709,7 +12925,7 @@ svn_wc__db_temp_op_set_property_conflict
return svn_error_createf(SVN_ERR_BAD_FILENAME, svn_sqlite__reset(stmt),
_("Invalid property reject file '%s' for '%s'"),
svn_dirent_local_style(prej_abspath, scratch_pool),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(wcroot, local_relpath,
scratch_pool));
SVN_ERR(svn_sqlite__bindf(stmt, "iss", wcroot->wc_id,
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h?rev=1425414&r1=1425413&r2=1425414&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h Sun Dec 23 05:58:52 2012
@@ -1017,6 +1017,7 @@ svn_wc__db_external_add_file(svn_wc__db_
apr_hash_t *new_actual_props,
svn_boolean_t keep_recorded_info,
+ const svn_skel_t *conflict,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
@@ -1499,12 +1500,21 @@ svn_wc__db_op_set_changelist(svn_wc__db_
void *cancel_baton,
apr_pool_t *scratch_pool);
+/* Record CONFLICT on LOCAL_ABSPATH, potentially replacing other conflicts
+ recorded on LOCAL_ABSPATH.
-/* ### caller maintains ACTUAL. we're just recording state. */
-/* ### we probably need to record details of the conflict. how? */
+ Users should in most cases pass CONFLICT to another WC_DB call instead of
+ calling svn_wc__db_op_mark_conflict() directly outside a transaction, to
+ allow recording atomically with the operation involved.
+
+ Any work items that are necessary as part of marking this node conflicted
+ can be passed in WORK_ITEMS.
+ */
svn_error_t *
svn_wc__db_op_mark_conflict(svn_wc__db_t *db,
const char *local_abspath,
+ const svn_skel_t *conflict,
+ const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
@@ -2943,25 +2953,6 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
const char *local_abspath,
apr_pool_t *scratch_pool);
-
-/* Set the conflict marker information on LOCAL_ABSPATH to the specified
- values */
-svn_error_t *
-svn_wc__db_temp_op_set_text_conflict_marker_files(svn_wc__db_t *db,
- const char *local_abspath,
- const char *old_abspath,
- const char *new_abspath,
- const char *wrk_abspath,
- apr_pool_t *scratch_pool);
-
-/* Set the conflict marker information on LOCAL_ABSPATH to the specified
- values */
-svn_error_t *
-svn_wc__db_temp_op_set_property_conflict_marker_file(svn_wc__db_t *db,
- const char *local_abspath,
- const char *prej_abspath,
- apr_pool_t *scratch_pool);
-
/* Add a new directory in BASE, whether WORKING nodes exist or not. Mark it
as incomplete and with revision REVISION. If REPOS_RELPATH is not NULL,
apply REPOS_RELPATH, REPOS_ROOT_URL and REPOS_UUID.