You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2013/01/22 00:37:04 UTC
svn commit: r1436688 [7/12] - in /subversion/branches/ev2-export: ./
contrib/client-side/emacs/ notes/commit-access-templates/
subversion/bindings/javahl/native/ subversion/bindings/swig/perl/native/t/
subversion/bindings/swig/ruby/test/ subversion/inc...
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c Mon Jan 21 23:37:01 2013
@@ -21,7 +21,13 @@
* ====================================================================
*/
-/* This editor is used during resolution of tree conflicts.
+/* This file implements an editor and an edit driver which are used
+ * to resolve an "incoming edit, local move-away" tree conflict resulting
+ * from an update (or switch).
+ *
+ * Our goal is to be able to resolve this conflict such that the end
+ * result is just the same as if the user had run the update *before*
+ * the local move.
*
* When an update (or switch) produces incoming changes for a locally
* moved-away subtree, it updates the base nodes of the moved-away tree
@@ -40,9 +46,8 @@
* layer. The destination may have additional higher op-depths
* representing adds, deletes, moves within the move destination. [2]
*
- * After the intial move an update, or this editor for trees that have
- * been moved more than once, has modified the NODES in the move
- * source, and introduced a tree-conflict since the source and
+ * After the intial move an update has modified the NODES in the move
+ * source and may have introduced a tree-conflict since the source and
* destination trees are no longer equivalent. The source is a
* different revision and may have text, property and tree changes
* compared to the destination. The driver will compare the two NODES
@@ -71,6 +76,8 @@
#define SVN_WC__I_AM_WC_DB
+#include <assert.h>
+
#include "svn_checksum.h"
#include "svn_dirent_uri.h"
#include "svn_error.h"
@@ -78,6 +85,7 @@
#include "svn_wc.h"
#include "svn_props.h"
#include "svn_pools.h"
+#include "svn_sorts.h"
#include "private/svn_skel.h"
#include "private/svn_sqlite.h"
@@ -115,6 +123,7 @@ struct tc_editor_baton {
non-Ev2, depth-first, drive for this to make sense. */
const char *conflict_root_relpath;
+ svn_wc_operation_t operation;
svn_wc_conflict_version_t *old_version;
svn_wc_conflict_version_t *new_version;
svn_wc_notify_func2_t notify_func;
@@ -129,12 +138,15 @@ mark_tree_conflict(struct tc_editor_bato
svn_node_kind_t new_kind,
svn_wc_conflict_reason_t reason,
svn_wc_conflict_action_t action,
+ svn_skel_t *conflict,
apr_pool_t *scratch_pool)
{
const char *repos_relpath;
- svn_skel_t *conflict = svn_wc__conflict_skel_create(scratch_pool);
svn_wc_conflict_version_t *old_version, *new_version;
+ if (!conflict)
+ conflict = svn_wc__conflict_skel_create(scratch_pool);
+
b->conflict_root_relpath = apr_pstrdup(b->result_pool, local_relpath);
SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
@@ -173,10 +185,20 @@ mark_tree_conflict(struct tc_editor_bato
new_kind,
scratch_pool);
- /* What about switch? */
- SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict,
- old_version, new_version,
- scratch_pool, scratch_pool));
+ if (b->operation == svn_wc_operation_update)
+ {
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(
+ conflict, old_version, new_version,
+ scratch_pool, scratch_pool));
+ }
+ else
+ {
+ assert(b->operation == svn_wc_operation_switch);
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+ conflict, old_version, new_version,
+ scratch_pool, scratch_pool));
+ }
+
SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, local_relpath,
conflict, scratch_pool));
@@ -194,6 +216,7 @@ check_tree_conflict(svn_boolean_t *is_co
struct tc_editor_baton *b,
const char *local_relpath,
svn_node_kind_t kind,
+ svn_wc_conflict_action_t action,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
@@ -240,7 +263,8 @@ check_tree_conflict(svn_boolean_t *is_co
{
conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath,
scratch_pool);
- old_kind = svn_node_dir;
+ old_kind = kind = svn_node_dir;
+ action = svn_wc_conflict_action_edit;
}
SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, b->wcroot,
@@ -248,8 +272,22 @@ check_tree_conflict(svn_boolean_t *is_co
scratch_pool, scratch_pool));
if (conflict)
- /* ### TODO: check this is the right sort of tree-conflict? */
- return SVN_NO_ERROR;
+ {
+ svn_error_t *err
+ = svn_wc__conflict_read_tree_conflict(NULL, NULL,
+ b->db, b->wcroot->abspath,
+ conflict,
+ scratch_pool, scratch_pool);
+ if (err && err->apr_err != SVN_ERR_WC_MISSING)
+ return err;
+
+ if (!err)
+ /* Already a tree-conflict. */
+ return SVN_NO_ERROR;
+
+ /* Not a tree-conflict. */
+ svn_error_clear(err);
+ }
SVN_ERR(svn_wc__db_scan_deletion_internal(NULL, &moved_to_relpath,
NULL, NULL,
@@ -260,7 +298,7 @@ check_tree_conflict(svn_boolean_t *is_co
(moved_to_relpath
? svn_wc_conflict_reason_moved_away
: svn_wc_conflict_reason_deleted),
- svn_wc_conflict_action_edit,
+ action, conflict,
scratch_pool));
return SVN_NO_ERROR;
}
@@ -287,6 +325,7 @@ tc_editor_add_directory(void *baton,
/* Check for NODES tree-conflict. */
SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath, svn_node_dir,
+ svn_wc_conflict_action_add,
scratch_pool));
if (is_conflicted)
return SVN_NO_ERROR;
@@ -301,7 +340,7 @@ tc_editor_add_directory(void *baton,
default:
SVN_ERR(mark_tree_conflict(b, relpath, kind, svn_node_dir,
svn_wc_conflict_reason_unversioned,
- svn_wc_conflict_action_add,
+ svn_wc_conflict_action_add, NULL,
scratch_pool));
break;
@@ -342,6 +381,7 @@ tc_editor_add_file(void *baton,
/* Check for NODES tree-conflict. */
SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath, svn_node_file,
+ svn_wc_conflict_action_add,
scratch_pool));
if (is_conflicted)
return SVN_NO_ERROR;
@@ -354,7 +394,7 @@ tc_editor_add_file(void *baton,
{
SVN_ERR(mark_tree_conflict(b, relpath, kind, svn_node_file,
svn_wc_conflict_reason_unversioned,
- svn_wc_conflict_action_add,
+ svn_wc_conflict_action_add, NULL,
scratch_pool));
return SVN_NO_ERROR;
}
@@ -413,6 +453,7 @@ create_conflict_markers(svn_skel_t **wor
svn_wc__db_t *db,
const char *repos_relpath,
svn_skel_t *conflict_skel,
+ svn_wc_operation_t operation,
const working_node_version_t *old_version,
const working_node_version_t *new_version,
apr_pool_t *result_pool,
@@ -425,17 +466,27 @@ create_conflict_markers(svn_skel_t **wor
old_version->location_and_kind, scratch_pool);
original_version->path_in_repos = repos_relpath;
original_version->node_kind = svn_node_file; /* ### ? */
- SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel,
- original_version,
- NULL /* ### derive from new_version & new kind? */,
- scratch_pool,
- scratch_pool));
+ if (operation == svn_wc_operation_update)
+ {
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(
+ conflict_skel, original_version,
+ NULL /* ### derive from new_version & new kind? */,
+ scratch_pool, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+ conflict_skel, original_version,
+ NULL /* ### derive from new_version & new kind? */,
+ scratch_pool, scratch_pool));
+ }
+
/* According to this func's doc string, it is "Currently only used for
* property conflicts as text conflict markers are just in-wc files." */
SVN_ERR(svn_wc__conflict_create_markers(&work_item, db,
local_abspath,
conflict_skel,
- scratch_pool,
+ result_pool,
scratch_pool));
*work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
@@ -504,6 +555,7 @@ tc_editor_alter_directory(void *baton,
SVN_ERR_ASSERT(expected_move_dst_revision == b->old_version->peg_rev);
SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, svn_node_dir,
+ svn_wc_conflict_action_edit,
scratch_pool));
if (is_conflicted)
return SVN_NO_ERROR;
@@ -546,7 +598,7 @@ tc_editor_alter_directory(void *baton,
/* ### need to pass in the node kinds (before & after)? */
SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
b->db, move_dst_repos_relpath,
- conflict_skel,
+ conflict_skel, b->operation,
&old_version, &new_version,
b->result_pool, scratch_pool));
SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
@@ -592,6 +644,7 @@ static svn_error_t *
update_working_file(svn_skel_t **work_items,
const char *local_relpath,
const char *repos_relpath,
+ svn_wc_operation_t operation,
const working_node_version_t *old_version,
const working_node_version_t *new_version,
svn_wc__db_wcroot_t *wcroot,
@@ -611,23 +664,15 @@ update_working_file(svn_skel_t **work_it
apr_array_header_t *propchanges;
enum svn_wc_merge_outcome_t merge_outcome;
svn_wc_notify_state_t prop_state, content_state;
+ svn_skel_t *work_item;
+
+ *work_items = NULL;
SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
&actual_props, db, local_abspath,
old_version, new_version,
result_pool, scratch_pool));
- /* If there are any conflicts to be stored, convert them into work items
- * too. */
- if (conflict_skel)
- {
- /* ### need to pass in the node kinds (before & after)? */
- SVN_ERR(create_conflict_markers(work_items, local_abspath, db,
- repos_relpath, conflict_skel,
- old_version, new_version,
- result_pool, scratch_pool));
- }
-
/*
* Run a 3-way merge to update the file, using the pre-update
* pristine text as the merge base, the post-update pristine
@@ -642,7 +687,7 @@ update_working_file(svn_skel_t **work_it
db, wcroot->abspath,
new_version->checksum,
scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__internal_merge(work_items, &conflict_skel,
+ SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
&merge_outcome, db,
old_pristine_abspath,
new_pristine_abspath,
@@ -657,6 +702,8 @@ update_working_file(svn_skel_t **work_it
NULL, NULL, /* cancel_func + baton */
result_pool, scratch_pool));
+ *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
/* If there are any conflicts to be stored, convert them into work items
* too. */
if (conflict_skel)
@@ -664,7 +711,7 @@ update_working_file(svn_skel_t **work_it
/* ### need to pass in the node kinds (before & after)? */
SVN_ERR(create_conflict_markers(work_items, local_abspath, db,
repos_relpath, conflict_skel,
- old_version, new_version,
+ operation, old_version, new_version,
result_pool, scratch_pool));
SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
conflict_skel,
@@ -728,6 +775,7 @@ tc_editor_alter_file(void *baton,
svn_boolean_t is_conflicted;
SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, svn_node_file,
+ svn_wc_conflict_action_edit,
scratch_pool));
if (is_conflicted)
return SVN_NO_ERROR;
@@ -751,18 +799,17 @@ tc_editor_alter_file(void *baton,
new_version.props = new_props ? new_props : old_version.props;
/* Update file and prop contents if the update has changed them. */
- if (!svn_checksum_match(new_checksum, old_version.checksum)
- /* ### || props have changed */)
+ if (!svn_checksum_match(new_checksum, old_version.checksum) || new_props)
{
- svn_skel_t *work_item;
+ svn_skel_t *work_items;
- SVN_ERR(update_working_file(&work_item, dst_relpath,
+ SVN_ERR(update_working_file(&work_items, dst_relpath,
move_dst_repos_relpath,
- &old_version, &new_version,
+ b->operation, &old_version, &new_version,
b->wcroot, b->db,
b->notify_func, b->notify_baton,
b->result_pool, scratch_pool));
- *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
+ *b->work_items = svn_wc__wq_merge(*b->work_items, work_items,
b->result_pool);
}
@@ -789,6 +836,58 @@ tc_editor_delete(void *baton,
struct tc_editor_baton *b = baton;
svn_sqlite__stmt_t *stmt;
int op_depth = relpath_depth(b->move_root_dst_relpath);
+ svn_boolean_t is_conflicted;
+
+ /* Check before retracting delete to catch delete-delete conflicts. */
+ SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath, svn_node_unknown,
+ svn_wc_conflict_action_delete,
+ scratch_pool));
+
+ if (!is_conflicted)
+ {
+ svn_boolean_t is_modified, is_all_deletes;
+
+ SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, b->db,
+ svn_dirent_join(b->wcroot->abspath,
+ relpath,
+ scratch_pool),
+ NULL, NULL, scratch_pool));
+ if (is_modified)
+ {
+ /* No conflict means no NODES rows at the relpath op-depth
+ so it's easy to convert the modified tree into a copy. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ STMT_UPDATE_OP_DEPTH_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
+ op_depth, relpath_depth(relpath)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ SVN_ERR(mark_tree_conflict(b, relpath,
+ /* ### kinds? */
+ svn_node_dir, svn_node_dir,
+ svn_wc_conflict_reason_edited,
+ svn_wc_conflict_action_delete, NULL,
+ scratch_pool));
+ is_conflicted = TRUE;
+ }
+ else if (is_all_deletes)
+ {
+ SVN_ERR(mark_tree_conflict(b, relpath,
+ /* ### kinds? */
+ svn_node_dir, svn_node_dir,
+ svn_wc_conflict_reason_deleted,
+ svn_wc_conflict_action_delete, NULL,
+ scratch_pool));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ STMT_DELETE_WORKING_OP_DEPTH_ABOVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+ op_depth));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ is_conflicted = TRUE;
+ }
+ }
/* Deleting the ROWS is valid so long as we update the parent before
committing the transaction. */
@@ -801,7 +900,11 @@ tc_editor_delete(void *baton,
SVN_ERR(svn_wc__db_retract_parent_delete(b->wcroot, relpath, op_depth,
scratch_pool));
- /* ### TODO check for, and flag, tree conflict */
+ if (is_conflicted)
+ return SVN_NO_ERROR;
+
+ /* ### TODO delete working files/dirs */
+
return SVN_NO_ERROR;
}
@@ -962,188 +1065,254 @@ get_tc_info(svn_wc_operation_t *operatio
return SVN_NO_ERROR;
}
-/* ### Drive TC_EDITOR so as to ...
- */
-static svn_error_t *
-update_moved_away_file(svn_editor_t *tc_editor,
- svn_boolean_t add,
- const char *src_relpath,
- const char *dst_relpath,
- const char *move_root_dst_relpath,
- svn_revnum_t move_root_dst_revision,
- svn_wc__db_t *db,
- svn_wc__db_wcroot_t *wcroot,
- apr_pool_t *scratch_pool)
-{
- svn_kind_t kind;
- svn_stream_t *new_contents;
- const svn_checksum_t *new_checksum;
- apr_hash_t *new_props;
-
- /* Read post-update contents from the updated moved-away file and tell
- * the editor to merge them into the moved-here file. */
- SVN_ERR(svn_wc__db_read_pristine_info(NULL, &kind, NULL, NULL, NULL, NULL,
- &new_checksum, NULL, NULL, &new_props,
- db, svn_dirent_join(wcroot->abspath,
- src_relpath,
- scratch_pool),
- scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_pristine_read(&new_contents, NULL, db,
- wcroot->abspath, new_checksum,
- scratch_pool, scratch_pool));
-
- if (add)
- /* FIXME: editor API violation: missing svn_editor_alter_directory. */
- SVN_ERR(svn_editor_add_file(tc_editor, dst_relpath,
- new_checksum, new_contents,
- apr_hash_make(scratch_pool), /* ### TODO props */
- move_root_dst_revision));
+/* Return *PROPS, *CHECKSUM, *CHILDREN and *KIND for LOCAL_RELPATH at
+ OP_DEPTH provided the row exists. Return *KIND of svn_kind_none if
+ the row does not exist. *CHILDREN is a sorted array of basenames of
+ type 'const char *', rather than a hash, to allow the driver to
+ process children in a defined order. */
+static svn_error_t *
+get_info(apr_hash_t **props,
+ const svn_checksum_t **checksum,
+ apr_array_header_t **children,
+ svn_kind_t *kind,
+ const char *local_relpath,
+ int op_depth,
+ svn_wc__db_wcroot_t *wcroot,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_t *hash_children;
+ apr_array_header_t *sorted_children;
+ svn_error_t *err;
+ int i;
+
+ err = svn_wc__db_depth_get_info(NULL, kind, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, checksum, NULL, NULL, props,
+ wcroot, local_relpath, op_depth,
+ result_pool, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ *kind = svn_kind_none;
+ }
else
- SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
- move_root_dst_revision,
- new_props, new_checksum,
- new_contents));
+ SVN_ERR(err);
- SVN_ERR(svn_stream_close(new_contents));
+
+ SVN_ERR(svn_wc__db_get_children_op_depth(&hash_children, wcroot,
+ local_relpath, op_depth,
+ scratch_pool, scratch_pool));
+ sorted_children = svn_sort__hash(hash_children,
+ svn_sort_compare_items_as_paths,
+ scratch_pool);
+
+ *children = apr_array_make(result_pool, sorted_children->nelts,
+ sizeof(const char *));
+ for (i = 0; i < sorted_children->nelts; ++i)
+ APR_ARRAY_PUSH(*children, const char *)
+ = apr_pstrdup(result_pool, APR_ARRAY_IDX(sorted_children, i,
+ svn_sort__item_t).key);
+
return SVN_NO_ERROR;
}
-/* ### Drive TC_EDITOR so as to ...
- */
+/* Return TRUE if SRC_CHILDREN and DST_CHILDREN represent the same
+ children, FALSE otherwise. SRC_CHILDREN and DST_CHILDREN are
+ sorted arrays of basenames of type 'const char *'. */
+static svn_boolean_t
+children_match(apr_array_header_t *src_children,
+ apr_array_header_t *dst_children) { int i;
+
+ if (src_children->nelts != dst_children->nelts)
+ return FALSE;
+
+ for(i = 0; i < src_children->nelts; ++i)
+ {
+ const char *src_child =
+ APR_ARRAY_IDX(src_children, i, const char *);
+ const char *dst_child =
+ APR_ARRAY_IDX(dst_children, i, const char *);
+
+ if (strcmp(src_child, dst_child))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Return TRUE if SRC_PROPS and DST_PROPS contain the same properties,
+ FALSE otherwise. SRC_PROPS and DST_PROPS are standard property
+ hashes. */
static svn_error_t *
-update_moved_away_dir(svn_editor_t *tc_editor,
- svn_boolean_t add,
- apr_hash_t *children_hash,
- const char *src_relpath,
- const char *dst_relpath,
- const char *move_root_dst_relpath,
- svn_revnum_t move_root_dst_revision,
- svn_wc__db_t *db,
- svn_wc__db_wcroot_t *wcroot,
- apr_pool_t *scratch_pool)
+props_match(svn_boolean_t *match,
+ apr_hash_t *src_props,
+ apr_hash_t *dst_props,
+ apr_pool_t *scratch_pool)
{
- apr_array_header_t *new_children;
- apr_hash_t *new_props;
- const char *src_abspath = svn_dirent_join(wcroot->abspath,
- src_relpath,
- scratch_pool);
-
- SVN_ERR(svn_hash_keys(&new_children, children_hash, scratch_pool));
-
- SVN_ERR(svn_wc__db_read_pristine_props(&new_props, db, src_abspath,
- scratch_pool, scratch_pool));
-
- /* This is a non-Ev2, depth-first, drive that calls add/alter on all
- directories. */
- if (add)
- SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath,
- new_children, new_props,
- move_root_dst_revision));
+ if (!src_props && !dst_props)
+ *match = TRUE;
+ else if (!src_props || ! dst_props)
+ *match = FALSE;
else
- SVN_ERR(svn_editor_alter_directory(tc_editor, dst_relpath,
- move_root_dst_revision,
- new_children, new_props));
+ {
+ apr_array_header_t *propdiffs;
+ SVN_ERR(svn_prop_diffs(&propdiffs, src_props, dst_props, scratch_pool));
+ *match = propdiffs->nelts ? FALSE : TRUE;
+ }
return SVN_NO_ERROR;
}
/* ### Drive TC_EDITOR so as to ...
*/
static svn_error_t *
-update_moved_away_subtree(svn_editor_t *tc_editor,
- svn_boolean_t add,
- const char *src_relpath,
- const char *dst_relpath,
- int src_op_depth,
- const char *move_root_dst_relpath,
- svn_revnum_t move_root_dst_revision,
- svn_wc__db_t *db,
- svn_wc__db_wcroot_t *wcroot,
- apr_pool_t *scratch_pool)
+update_moved_away_node(svn_editor_t *tc_editor,
+ const char *src_relpath,
+ const char *dst_relpath,
+ int src_op_depth,
+ const char *move_root_dst_relpath,
+ svn_revnum_t move_root_dst_revision,
+ svn_wc__db_t *db,
+ svn_wc__db_wcroot_t *wcroot,
+ apr_pool_t *scratch_pool)
{
- apr_hash_t *src_children, *dst_children;
- apr_pool_t *iterpool;
- apr_hash_index_t *hi;
+ svn_kind_t src_kind, dst_kind;
+ const svn_checksum_t *src_checksum, *dst_checksum;
+ apr_hash_t *src_props, *dst_props;
+ apr_array_header_t *src_children, *dst_children;
+ int dst_op_depth = relpath_depth(move_root_dst_relpath);
+
+ SVN_ERR(get_info(&src_props, &src_checksum, &src_children, &src_kind,
+ src_relpath, src_op_depth,
+ wcroot, scratch_pool, scratch_pool));
+
+ SVN_ERR(get_info(&dst_props, &dst_checksum, &dst_children, &dst_kind,
+ dst_relpath, dst_op_depth,
+ wcroot, scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_get_children_op_depth(&src_children, wcroot,
- src_relpath, src_op_depth,
- scratch_pool, scratch_pool));
+ if (src_kind == svn_kind_none
+ || (dst_kind != svn_kind_none && src_kind != dst_kind))
+ {
+ SVN_ERR(svn_editor_delete(tc_editor, dst_relpath,
+ move_root_dst_revision));
+ }
+
+ if (src_kind != svn_kind_none && src_kind != dst_kind)
+ {
+ if (src_kind == svn_kind_file || src_kind == svn_kind_symlink)
+ {
+ svn_stream_t *contents;
- SVN_ERR(update_moved_away_dir(tc_editor, add, src_children,
- src_relpath, dst_relpath,
- move_root_dst_relpath,
- move_root_dst_revision,
- db, wcroot, scratch_pool));
-
- SVN_ERR(svn_wc__db_get_children_op_depth(&dst_children, wcroot,
- dst_relpath,
- relpath_depth(move_root_dst_relpath),
+ SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db,
+ wcroot->abspath, src_checksum,
scratch_pool, scratch_pool));
- iterpool = svn_pool_create(scratch_pool);
- for (hi = apr_hash_first(scratch_pool, src_children);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *src_name = svn__apr_hash_index_key(hi);
- svn_kind_t *src_kind = svn__apr_hash_index_val(hi);
- svn_kind_t *dst_kind = apr_hash_get(dst_children, src_name,
- APR_HASH_KEY_STRING);
- svn_boolean_t is_add = FALSE;
- const char *child_src_relpath, *child_dst_relpath;
-
- svn_pool_clear(iterpool);
-
- child_src_relpath = svn_relpath_join(src_relpath, src_name, iterpool);
- child_dst_relpath = svn_relpath_join(dst_relpath, src_name, iterpool);
-
- if (!dst_kind || (*src_kind != *dst_kind))
- {
- is_add = TRUE;
- if (dst_kind)
- /* FIXME:editor API violation:missing svn_editor_alter_directory. */
- SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath,
+ SVN_ERR(svn_editor_add_file(tc_editor, dst_relpath,
+ src_checksum, contents, src_props,
move_root_dst_revision));
}
-
- if (*src_kind == svn_kind_file || *src_kind == svn_kind_symlink)
+ else if (src_kind == svn_kind_dir)
{
- SVN_ERR(update_moved_away_file(tc_editor, is_add,
- child_src_relpath,
- child_dst_relpath,
- move_root_dst_relpath,
- move_root_dst_revision,
- db, wcroot, iterpool));
+ SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath,
+ src_children, src_props,
+ move_root_dst_revision));
}
- else if (*src_kind == svn_kind_dir)
+ }
+ else if (src_kind != svn_kind_none)
+ {
+ svn_boolean_t match;
+ apr_hash_t *props;
+
+ SVN_ERR(props_match(&match, src_props, dst_props, scratch_pool));
+ props = match ? NULL: src_props;
+
+
+ if (src_kind == svn_kind_file || src_kind == svn_kind_symlink)
{
- SVN_ERR(update_moved_away_subtree(tc_editor, is_add,
- child_src_relpath,
- child_dst_relpath,
- src_op_depth,
- move_root_dst_relpath,
- move_root_dst_revision,
- db, wcroot, iterpool));
+ svn_stream_t *contents;
+
+ if (svn_checksum_match(src_checksum, dst_checksum))
+ src_checksum = NULL;
+
+ if (src_checksum)
+ SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db,
+ wcroot->abspath, src_checksum,
+ scratch_pool, scratch_pool));
+ else
+ contents = NULL;
+
+ if (props || src_checksum)
+ SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
+ move_root_dst_revision,
+ props, src_checksum, contents));
}
- else
- ; /* ### TODO */
+ else if (src_kind == svn_kind_dir)
+ {
+ apr_array_header_t *children
+ = children_match(src_children, dst_children) ? NULL : src_children;
- apr_hash_set(dst_children, src_name, APR_HASH_KEY_STRING, NULL);
+ if (props || children)
+ SVN_ERR(svn_editor_alter_directory(tc_editor, dst_relpath,
+ move_root_dst_revision,
+ children, props));
+ }
}
- for (hi = apr_hash_first(scratch_pool, dst_children);
- hi;
- hi = apr_hash_next(hi))
+
+ if (src_kind == svn_kind_dir)
{
- const char *dst_name = svn__apr_hash_index_key(hi);
- const char *child_dst_relpath;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ int i = 0, j = 0;
- svn_pool_clear(iterpool);
- child_dst_relpath = svn_relpath_join(dst_relpath, dst_name, iterpool);
+ while (i < src_children->nelts || j < dst_children->nelts)
+ {
+ const char *child_name;
+ const char *src_child_relpath, *dst_child_relpath;
+ svn_boolean_t src_only = FALSE, dst_only = FALSE;
- SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath,
- move_root_dst_revision));
+ svn_pool_clear(iterpool);
+ if (i >= src_children->nelts)
+ {
+ dst_only = TRUE;
+ child_name = APR_ARRAY_IDX(dst_children, j, const char *);
+ }
+ else if (j >= dst_children->nelts)
+ {
+ src_only = TRUE;
+ child_name = APR_ARRAY_IDX(src_children, i, const char *);
+ }
+ else
+ {
+ const char *src_name = APR_ARRAY_IDX(src_children, i,
+ const char *);
+ const char *dst_name = APR_ARRAY_IDX(dst_children, j,
+ const char *);
+ int cmp = strcmp(src_name, dst_name);
+
+ if (cmp > 0)
+ dst_only = TRUE;
+ else if (cmp < 0)
+ src_only = TRUE;
+
+ child_name = dst_only ? dst_name : src_name;
+ }
+
+ src_child_relpath = svn_relpath_join(src_relpath, child_name,
+ iterpool);
+ dst_child_relpath = svn_relpath_join(dst_relpath, child_name,
+ iterpool);
+
+ SVN_ERR(update_moved_away_node(tc_editor, src_child_relpath,
+ dst_child_relpath, src_op_depth,
+ move_root_dst_relpath,
+ move_root_dst_revision,
+ db, wcroot, scratch_pool));
+
+ if (!dst_only)
+ ++i;
+ if (!src_only)
+ ++j;
+ }
}
- svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -1242,16 +1411,10 @@ drive_tree_conflict_editor(svn_editor_t
/* We walk the move source (i.e. the post-update tree), comparing each node
* with the equivalent node at the move destination and applying the update
* to nodes at the move destination. */
- if (old_version->node_kind == svn_node_file)
- SVN_ERR(update_moved_away_file(tc_editor, FALSE, src_relpath, dst_relpath,
- dst_relpath, old_version->peg_rev,
- db, wcroot, scratch_pool));
- else if (old_version->node_kind == svn_node_dir)
- SVN_ERR(update_moved_away_subtree(tc_editor, FALSE,
- src_relpath, dst_relpath,
- src_op_depth,
- dst_relpath, old_version->peg_rev,
- db, wcroot, scratch_pool));
+ SVN_ERR(update_moved_away_node(tc_editor, src_relpath, dst_relpath,
+ src_op_depth,
+ dst_relpath, old_version->peg_rev,
+ db, wcroot, scratch_pool));
SVN_ERR(svn_editor_complete(tc_editor));
@@ -1300,6 +1463,7 @@ update_moved_away_conflict_victim(svn_sk
svn_dirent_join(wcroot->abspath, victim_relpath,
scratch_pool),
scratch_pool));
+ tc_editor_baton->operation = operation;
tc_editor_baton->old_version= old_version;
tc_editor_baton->new_version= new_version;
tc_editor_baton->db = db;
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/workqueue.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/workqueue.c Mon Jan 21 23:37:01 2013
@@ -155,7 +155,10 @@ run_base_remove(svn_wc__db_t *db,
}
}
- SVN_ERR(svn_wc__db_base_remove(db, local_abspath, FALSE, not_present_rev,
+ SVN_ERR(svn_wc__db_base_remove(db, local_abspath,
+ FALSE /* keep_as_working */,
+ TRUE /* queue_deletes */,
+ not_present_rev,
NULL, NULL, scratch_pool));
return SVN_NO_ERROR;
@@ -1476,10 +1479,7 @@ dispatch_work_item(svn_wc__db_t *db,
Contrary to issue #1581, we cannot simply remove work items and
continue, so bail out with an error. */
return svn_error_createf(SVN_ERR_WC_BAD_ADM_LOG, NULL,
- _("Unrecognized work item in the queue "
- "associated with '%s'"),
- svn_dirent_local_style(wri_abspath,
- scratch_pool));
+ _("Unrecognized work item in the queue"));
}
return SVN_NO_ERROR;
@@ -1511,6 +1511,7 @@ svn_wc__wq_run(svn_wc__db_t *db,
{
apr_uint64_t id;
svn_skel_t *work_item;
+ svn_error_t *err;
svn_pool_clear(iterpool);
@@ -1530,8 +1531,20 @@ svn_wc__wq_run(svn_wc__db_t *db,
we're done. */
if (work_item == NULL)
break;
- SVN_ERR(dispatch_work_item(db, wri_abspath, work_item,
- cancel_func, cancel_baton, iterpool));
+
+ err = dispatch_work_item(db, wri_abspath, work_item,
+ cancel_func, cancel_baton, iterpool);
+ if (err)
+ {
+ const char *skel = svn_skel__unparse(work_item, scratch_pool)->data;
+
+ return svn_error_createf(SVN_ERR_WC_BAD_ADM_LOG, err,
+ _("Failed to run the WC DB work queue "
+ "associated with '%s', work item %d %s"),
+ svn_dirent_local_style(wri_abspath,
+ scratch_pool),
+ (int)id, skel);
+ }
/* The work item finished without error. Mark it completed
in the next loop. */
Modified: subversion/branches/ev2-export/subversion/mod_authz_svn/INSTALL
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_authz_svn/INSTALL?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/mod_authz_svn/INSTALL (original)
+++ subversion/branches/ev2-export/subversion/mod_authz_svn/INSTALL Mon Jan 21 23:37:01 2013
@@ -56,6 +56,12 @@ II. Configuration
Satisfy Any
Require valid-user
</Location>
+
+ NOTE: The access control is designed to never display entries that
+ the user does not have access to. Combining anonymous access on the
+ top levels while restricting read access lower in the directory
+ structure makes it difficult to browse because the server will not
+ request authentication.
C. Example 3: Authenticated access only
@@ -123,7 +129,7 @@ II. Configuration
restrict access to this authz file and it is in the same repository
you should include a rule for it.
- F. Example 5: Authz file stored inside the repository being accessed.
+ F. Example 6: Authz file stored inside the repository being accessed.
This configuration allows providing a relative path within the
repository being accessed.
@@ -144,6 +150,43 @@ II. Configuration
NOTE: You should include rules in your authz file to restirct access
to the authz file as desired.
+ G. Example 7: Authenticated access to "Collection of Repositories"
+
+ The "Collection of Repositories" is filtered based on read access to
+ the root of each repository, i.e. consistent with the directory lists
+ within repositories. If read access is restricted in repository roots,
+ it is typically desirable to require authentication for "Collection of
+ Repositories" in order to ensure that repositories where the user has
+ access are displayed.
+
+ This is accomplished by specifying "Satisfy All" (which is the default
+ setting):
+
+ <Location /svn>
+ DAV svn
+ SVNParentPath /path/to/reposparent
+
+ AuthType Basic
+ AuthName "Subversion repository"
+ AuthUserFile /path/to/htpasswd/file
+
+ AuthzSVNAccessFile /path/to/access/file
+ # Implicit Satisfy All
+ Require valid-user
+ </Location>
+
+ If the same server must be able to serve paths with anonymous access,
+ it can be defined using an additional location.
+
+ <LocationMatch "^/svn/.+">
+ Satisfy Any
+ Require valid-user
+ </LocationMatch>
+
+ The "Require" statement in the previous example is not strictly
+ needed, but has been included for clarity.
+
+
2. Specifying permissions
The file format of the access file looks like this: