You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2015/02/25 09:15:42 UTC
svn commit: r1662177 [11/18] - in /subversion/branches/reuse-ra-session: ./
build/ build/generator/ contrib/client-side/svncopy/
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/...
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c?rev=1662177&r1=1662176&r2=1662177&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c Wed Feb 25 08:15:39 2015
@@ -278,10 +278,9 @@ add_work_items(svn_sqlite__db_t *sdb,
apr_pool_t *scratch_pool);
static svn_error_t *
-set_actual_props(apr_int64_t wc_id,
+set_actual_props(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_hash_t *props,
- svn_sqlite__db_t *db,
apr_pool_t *scratch_pool);
static svn_error_t *
@@ -487,35 +486,6 @@ repos_location_from_columns(apr_int64_t
}
}
-
-/* Get the statement given by STMT_IDX, and bind the appropriate wc_id and
- local_relpath based upon LOCAL_ABSPATH. Store it in *STMT, and use
- SCRATCH_POOL for temporary allocations.
-
- Note: WC_ID and LOCAL_RELPATH must be arguments 1 and 2 in the statement. */
-static svn_error_t *
-get_statement_for_path(svn_sqlite__stmt_t **stmt,
- svn_wc__db_t *db,
- const char *local_abspath,
- int stmt_idx,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath;
-
- 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);
-
- SVN_ERR(svn_sqlite__get_statement(stmt, wcroot->sdb, stmt_idx));
- SVN_ERR(svn_sqlite__bindf(*stmt, "is", wcroot->wc_id, local_relpath));
-
- return SVN_NO_ERROR;
-}
-
-
/* For a given REPOS_ROOT_URL/REPOS_UUID pair, return the existing REPOS_ID
value. If one does not exist, then create a new one. */
static svn_error_t *
@@ -611,8 +581,7 @@ blank_ibb(insert_base_baton_t *pibb)
was recorded, otherwise to FALSE.
*/
static svn_error_t *
-db_extend_parent_delete(svn_boolean_t *added_delete,
- svn_wc__db_wcroot_t *wcroot,
+db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_node_kind_t kind,
int op_depth,
@@ -625,9 +594,6 @@ db_extend_parent_delete(svn_boolean_t *a
SVN_ERR_ASSERT(local_relpath[0]);
- if (added_delete)
- *added_delete = FALSE;
-
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_LOWEST_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, parent_relpath,
@@ -654,9 +620,6 @@ db_extend_parent_delete(svn_boolean_t *a
local_relpath, parent_op_depth,
parent_relpath, kind_map, kind));
SVN_ERR(svn_sqlite__update(NULL, stmt));
-
- if (added_delete)
- *added_delete = TRUE;
}
}
@@ -750,6 +713,7 @@ insert_base_node(const insert_base_baton
svn_sqlite__stmt_t *stmt;
svn_filesize_t recorded_size = SVN_INVALID_FILESIZE;
apr_int64_t recorded_time;
+ svn_boolean_t present;
/* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
bind the appropriate parent_relpath. */
@@ -780,6 +744,9 @@ insert_base_node(const insert_base_baton
SVN_ERR(svn_sqlite__reset(stmt));
}
+ present = (pibb->status == svn_wc__db_status_normal
+ || pibb->status == svn_wc__db_status_incomplete);
+
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isdsisr"
"tstr" /* 8 - 11 */
@@ -792,15 +759,16 @@ insert_base_node(const insert_base_baton
pibb->repos_relpath,
pibb->revision,
presence_map, pibb->status, /* 8 */
- (pibb->kind == svn_node_dir) ? /* 9 */
- svn_token__to_word(depth_map, pibb->depth) : NULL,
+ (pibb->kind == svn_node_dir && present) /* 9 */
+ ? svn_token__to_word(depth_map, pibb->depth)
+ : NULL,
kind_map, pibb->kind, /* 10 */
pibb->changed_rev, /* 11 */
pibb->changed_date, /* 12 */
pibb->changed_author, /* 13 */
- (pibb->kind == svn_node_symlink) ?
+ (pibb->kind == svn_node_symlink && present) ?
pibb->target : NULL)); /* 19 */
- if (pibb->kind == svn_node_file)
+ if (pibb->kind == svn_node_file && present)
{
if (!pibb->checksum
&& pibb->status != svn_wc__db_status_not_present
@@ -825,11 +793,14 @@ insert_base_node(const insert_base_baton
assert(pibb->status == svn_wc__db_status_normal
|| pibb->status == svn_wc__db_status_incomplete
|| pibb->props == NULL);
- SVN_ERR(svn_sqlite__bind_properties(stmt, 15, pibb->props,
- scratch_pool));
+ if (present)
+ {
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 15, pibb->props,
+ scratch_pool));
- SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, pibb->iprops,
+ SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, pibb->iprops,
scratch_pool));
+ }
if (pibb->dav_cache)
SVN_ERR(svn_sqlite__bind_properties(stmt, 18, pibb->dav_cache,
@@ -859,8 +830,8 @@ insert_base_node(const insert_base_baton
new_actual_props = NULL;
}
- SVN_ERR(set_actual_props(wcroot->wc_id, local_relpath, new_actual_props,
- wcroot->sdb, scratch_pool));
+ SVN_ERR(set_actual_props(wcroot, local_relpath, new_actual_props,
+ scratch_pool));
}
if (pibb->kind == svn_node_dir && pibb->children)
@@ -881,8 +852,7 @@ insert_base_node(const insert_base_baton
|| (pibb->status == svn_wc__db_status_incomplete))
&& ! pibb->file_external)
{
- SVN_ERR(db_extend_parent_delete(NULL,
- wcroot, local_relpath,
+ SVN_ERR(db_extend_parent_delete(wcroot, local_relpath,
pibb->kind, 0,
scratch_pool));
}
@@ -1035,6 +1005,7 @@ insert_working_node(const insert_working
const char *moved_to_relpath = NULL;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ svn_boolean_t present;
SVN_ERR_ASSERT(piwb->op_depth > 0);
@@ -1053,6 +1024,9 @@ insert_working_node(const insert_working
moved_to_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
SVN_ERR(svn_sqlite__reset(stmt));
+ present = (piwb->presence == svn_wc__db_status_normal
+ || piwb->presence == svn_wc__db_status_incomplete);
+
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnntstrisn"
"nnnn" /* properties translated_size last_mod_time dav_cache */
@@ -1061,14 +1035,14 @@ insert_working_node(const insert_working
piwb->op_depth,
parent_relpath,
presence_map, piwb->presence,
- (piwb->kind == svn_node_dir)
+ (piwb->kind == svn_node_dir && present)
? svn_token__to_word(depth_map, piwb->depth) : NULL,
kind_map, piwb->kind,
piwb->changed_rev,
piwb->changed_date,
piwb->changed_author,
/* Note: incomplete nodes may have a NULL target. */
- (piwb->kind == svn_node_symlink)
+ (piwb->kind == svn_node_symlink && present)
? piwb->target : NULL,
moved_to_relpath));
@@ -1077,7 +1051,7 @@ insert_working_node(const insert_working
SVN_ERR(svn_sqlite__bind_int(stmt, 8, TRUE));
}
- if (piwb->kind == svn_node_file)
+ if (piwb->kind == svn_node_file && present)
{
SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, piwb->checksum,
scratch_pool));
@@ -1094,7 +1068,8 @@ insert_working_node(const insert_working
assert(piwb->presence == svn_wc__db_status_normal
|| piwb->presence == svn_wc__db_status_incomplete
|| piwb->props == NULL);
- SVN_ERR(svn_sqlite__bind_properties(stmt, 15, piwb->props, scratch_pool));
+ if (present && piwb->original_repos_relpath)
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 15, piwb->props, scratch_pool));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -1131,8 +1106,8 @@ insert_working_node(const insert_working
new_actual_props = NULL;
}
- SVN_ERR(set_actual_props(wcroot->wc_id, local_relpath, new_actual_props,
- wcroot->sdb, scratch_pool));
+ SVN_ERR(set_actual_props(wcroot, local_relpath, new_actual_props,
+ scratch_pool));
}
if (piwb->kind == svn_node_dir)
@@ -1178,119 +1153,40 @@ insert_working_node(const insert_working
}
-/* Each name is allocated in RESULT_POOL and stored into CHILDREN as a key
- pointed to the same name. */
-static svn_error_t *
-add_children_to_hash(apr_hash_t *children,
- int stmt_idx,
- svn_sqlite__db_t *sdb,
- apr_int64_t wc_id,
- const char *parent_relpath,
- apr_pool_t *result_pool)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, stmt_idx));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- while (have_row)
- {
- const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
- const char *name = svn_relpath_basename(child_relpath, result_pool);
-
- svn_hash_sets(children, name, name);
-
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- }
-
- return svn_sqlite__reset(stmt);
-}
-
-
-/* Set *CHILDREN to a new array of the (const char *) basenames of the
- immediate children, whatever their status, of the working node at
- LOCAL_RELPATH. */
-static svn_error_t *
-gather_children2(const apr_array_header_t **children,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- apr_hash_t *names_hash = apr_hash_make(scratch_pool);
- apr_array_header_t *names_array;
-
- /* All of the names get allocated in RESULT_POOL. It
- appears to be faster to use the hash to remove duplicates than to
- use DISTINCT in the SQL query. */
- SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_WORKING_CHILDREN,
- wcroot->sdb, wcroot->wc_id,
- local_relpath, result_pool));
-
- SVN_ERR(svn_hash_keys(&names_array, names_hash, result_pool));
- *children = names_array;
- return SVN_NO_ERROR;
-}
-
/* Return in *CHILDREN all of the children of the directory LOCAL_RELPATH,
of any status, in all op-depths in the NODES table. */
static svn_error_t *
gather_children(const apr_array_header_t **children,
svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
+ const char *parent_relpath,
+ int stmt_idx,
+ int op_depth,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- apr_hash_t *names_hash = apr_hash_make(scratch_pool);
- apr_array_header_t *names_array;
-
- /* All of the names get allocated in RESULT_POOL. It
- appears to be faster to use the hash to remove duplicates than to
- use DISTINCT in the SQL query. */
- SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_NODE_CHILDREN,
- wcroot->sdb, wcroot->wc_id,
- local_relpath, result_pool));
-
- SVN_ERR(svn_hash_keys(&names_array, names_hash, result_pool));
- *children = names_array;
- return SVN_NO_ERROR;
-}
-
-
-/* Set *CHILDREN to a new array of (const char *) names of the children of
- the repository directory corresponding to WCROOT:LOCAL_RELPATH:OP_DEPTH -
- that is, only the children that are at the same op-depth as their parent. */
-static svn_error_t *
-gather_repo_children(const apr_array_header_t **children,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- int op_depth,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *result
- = apr_array_make(result_pool, 0, sizeof(const char *));
+ apr_array_header_t *result;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_OP_DEPTH_CHILDREN));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
- op_depth));
+ result = apr_array_make(result_pool, 16, sizeof(const char*));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, stmt_idx));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, parent_relpath));
+ if (op_depth >= 0)
+ SVN_ERR(svn_sqlite__bind_int(stmt, 3, op_depth));
+
SVN_ERR(svn_sqlite__step(&have_row, stmt));
while (have_row)
{
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ const char *name = svn_relpath_basename(child_relpath, result_pool);
- /* Allocate the name in RESULT_POOL so we won't have to copy it. */
- APR_ARRAY_PUSH(result, const char *)
- = svn_relpath_basename(child_relpath, result_pool);
+ APR_ARRAY_PUSH(result, const char *) = name;
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
- SVN_ERR(svn_sqlite__reset(stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
*children = result;
return SVN_NO_ERROR;
}
@@ -1585,7 +1481,7 @@ svn_wc__db_init(svn_wc__db_t *db,
/* ### REPOS_ROOT_URL and REPOS_UUID may be NULL. ... more doc: tbd */
- SVN_ERR(svn_config_get_bool((svn_config_t *)db->config, &sqlite_exclusive,
+ SVN_ERR(svn_config_get_bool(db->config, &sqlite_exclusive,
SVN_CONFIG_SECTION_WORKING_COPY,
SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE,
FALSE));
@@ -2177,7 +2073,7 @@ clear_moved_here(svn_wc__db_wcroot_t *wc
svn_error_t *
svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot,
const char *src_relpath,
- int src_op_depth,
+ int delete_op_depth,
const char *dst_relpath,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -2188,7 +2084,7 @@ svn_wc__db_op_break_move_internal(svn_wc
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_CLEAR_MOVED_TO_RELPATH));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, src_relpath,
- src_op_depth));
+ delete_op_depth));
SVN_ERR(svn_sqlite__update(&affected, stmt));
if (affected != 1)
@@ -2211,9 +2107,9 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
const char *local_relpath,
svn_wc__db_t *db, /* For checking conflicts */
svn_boolean_t keep_as_working,
- svn_boolean_t queue_deletes,
- svn_boolean_t remove_locks,
- svn_revnum_t not_present_revision,
+ svn_boolean_t mark_not_present,
+ svn_boolean_t mark_excluded,
+ svn_revnum_t marker_revision,
svn_skel_t *conflict,
svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -2221,66 +2117,80 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
svn_wc__db_status_t status;
+ svn_revnum_t revision;
apr_int64_t repos_id;
const char *repos_relpath;
svn_node_kind_t kind;
svn_boolean_t keep_working;
+ int op_depth;
+ svn_node_kind_t wrk_kind;
+ svn_boolean_t no_delete_wc = FALSE;
- SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, NULL,
+ SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, &revision,
&repos_relpath, &repos_id,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
wcroot, local_relpath,
scratch_pool, scratch_pool));
- if (remove_locks)
- {
- svn_sqlite__stmt_t *lock_stmt;
+ /* Check if there is already a working node */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_NODE_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
- SVN_ERR(svn_sqlite__get_statement(&lock_stmt, wcroot->sdb,
- STMT_DELETE_LOCK_RECURSIVELY));
- SVN_ERR(svn_sqlite__bindf(lock_stmt, "is", repos_id, repos_relpath));
- SVN_ERR(svn_sqlite__step_done(lock_stmt));
- }
+ if (!have_row)
+ return svn_error_trace(svn_sqlite__reset(stmt)); /* No BASE */
+
+ op_depth = svn_sqlite__column_int(stmt, 0);
+ wrk_kind = svn_sqlite__column_token(stmt, 4, kind_map);
- if (status == svn_wc__db_status_normal
- && keep_as_working)
+ if (op_depth > 0
+ && op_depth == relpath_depth(local_relpath))
{
- SVN_ERR(svn_wc__db_op_make_copy(db,
- svn_dirent_join(wcroot->abspath,
- local_relpath,
- scratch_pool),
- NULL, NULL,
- scratch_pool));
- keep_working = TRUE;
+ svn_wc__db_status_t presence;
+ presence = svn_sqlite__column_token(stmt, 3, presence_map);
+
+ if (presence == svn_wc__db_status_base_deleted)
+ {
+ keep_working = FALSE;
+ no_delete_wc = TRUE;
+ }
+ else
+ {
+ keep_working = TRUE;
+ }
}
else
+ keep_working = FALSE;
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ if (keep_as_working && op_depth == 0)
{
- /* Check if there is already a working node */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step(&keep_working, stmt));
- SVN_ERR(svn_sqlite__reset(stmt));
+ if (status == svn_wc__db_status_normal
+ || status == svn_wc__db_status_incomplete)
+ {
+ SVN_ERR(svn_wc__db_op_make_copy_internal(wcroot, local_relpath, TRUE,
+ NULL, NULL,
+ scratch_pool));
+ }
+ keep_working = TRUE;
}
/* Step 1: Create workqueue operations to remove files and dirs in the
local-wc */
- if (!keep_working
- && queue_deletes
- && (status == svn_wc__db_status_normal
- || status == svn_wc__db_status_incomplete))
+ if (!keep_working && !no_delete_wc)
{
svn_skel_t *work_item;
const char *local_abspath;
local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
scratch_pool);
- if (kind == svn_node_dir)
+ if (wrk_kind == svn_node_dir)
{
apr_pool_t *iterpool;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_BASE_PRESENT));
+ STMT_SELECT_WORKING_PRESENT));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
iterpool = svn_pool_create(scratch_pool);
@@ -2359,27 +2269,12 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
ACTUAL_NODE records */
/* Step 3: Delete WORKING nodes */
- if (conflict)
+ if (!keep_working)
{
apr_pool_t *iterpool;
- /*
- * When deleting a conflicted node, moves of any moved-outside children
- * of the node must be broken. Else, the destination will still be marked
- * moved-here after the move source disappears from the working copy.
- *
- * ### FIXME: It would be nicer to have the conflict resolver
- * break the move instead. It might also be a good idea to
- * flag a tree conflict on each moved-away child. But doing so
- * might introduce actual-only nodes without direct parents,
- * and we're not yet sure if other existing code is prepared
- * to handle such nodes. To be revisited post-1.8.
- *
- * ### In case of a conflict we are most likely creating WORKING nodes
- * describing a copy of what was in BASE. The move information
- * should be updated to describe a move from the WORKING layer.
- * When stored that way the resolver of the tree conflict still has
- * the knowledge of what was moved.
+ /* When deleting everything in working we should break moves from
+ here and to here.
*/
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_MOVED_OUTSIDE));
@@ -2403,10 +2298,51 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
svn_pool_destroy(iterpool);
SVN_ERR(svn_sqlite__reset(stmt));
}
- if (keep_working)
+ else
{
+ /* We are keeping things that are in WORKING, but we should still
+ break moves of things in BASE. (Mixed revisions make it
+ impossible to guarantee that we can keep everything moved) */
+
+ apr_pool_t *iterpool;
+
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_DELETE_WORKING_BASE_DELETE));
+ STMT_SELECT_MOVED_DESCENDANTS_SRC));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ local_relpath, 0));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ iterpool = svn_pool_create(scratch_pool);
+ while (have_row)
+ {
+ int delete_op_depth = svn_sqlite__column_int(stmt, 0);
+ const char *src_relpath;
+ const char *dst_relpath;
+ svn_error_t *err;
+
+ svn_pool_clear(iterpool);
+
+ src_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
+ dst_relpath = svn_sqlite__column_text(stmt, 4, iterpool);
+
+ err = svn_wc__db_op_break_move_internal(wcroot, src_relpath,
+ delete_op_depth,
+ dst_relpath,
+ NULL,
+ iterpool);
+
+ if (err)
+ return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ svn_pool_destroy(iterpool);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
+ if (keep_working)
+ {
+ SVN_ERR(svn_sqlite__get_statement(
+ &stmt, wcroot->sdb,
+ STMT_DELETE_WORKING_BASE_DELETE_RECURSIVE));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, 0));
SVN_ERR(svn_sqlite__step_done(stmt));
}
@@ -2432,25 +2368,19 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
SVN_ERR(db_retract_parent_delete(wcroot, local_relpath, 0, scratch_pool));
- /* Step 6: Delete actual node if we don't keep working */
- if (! keep_working)
- {
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_DELETE_ACTUAL_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
-
- if (SVN_IS_VALID_REVNUM(not_present_revision))
+ if (mark_not_present || mark_excluded)
{
struct insert_base_baton_t ibb;
blank_ibb(&ibb);
ibb.repos_id = repos_id;
- ibb.status = svn_wc__db_status_not_present;
+ ibb.status = mark_excluded ? svn_wc__db_status_excluded
+ : svn_wc__db_status_not_present;
ibb.kind = kind;
ibb.repos_relpath = repos_relpath;
- ibb.revision = not_present_revision;
+ ibb.revision = SVN_IS_VALID_REVNUM(marker_revision)
+ ? marker_revision
+ : revision;
/* Depending upon KIND, any of these might get used. */
ibb.children = NULL;
@@ -2474,9 +2404,9 @@ svn_error_t *
svn_wc__db_base_remove(svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t keep_as_working,
- svn_boolean_t queue_deletes,
- svn_boolean_t remove_locks,
- svn_revnum_t not_present_revision,
+ svn_boolean_t mark_not_present,
+ svn_boolean_t mark_excluded,
+ svn_revnum_t marker_revision,
svn_skel_t *conflict,
svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -2491,8 +2421,9 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
VERIFY_USABLE_WCROOT(wcroot);
SVN_WC__DB_WITH_TXN(db_base_remove(wcroot, local_relpath,
- db, keep_as_working, queue_deletes,
- remove_locks, not_present_revision,
+ db, keep_as_working,
+ mark_not_present, mark_excluded,
+ marker_revision,
conflict, work_items, scratch_pool),
wcroot);
@@ -2843,8 +2774,10 @@ svn_wc__db_base_get_children(const apr_a
scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- return gather_repo_children(children, wcroot, local_relpath, 0,
- result_pool, scratch_pool);
+ return svn_error_trace(
+ gather_children(children, wcroot, local_relpath,
+ STMT_SELECT_OP_DEPTH_CHILDREN, 0,
+ result_pool, scratch_pool));
}
@@ -2854,12 +2787,20 @@ svn_wc__db_base_set_dav_cache(svn_wc__db
const apr_hash_t *props,
apr_pool_t *scratch_pool)
{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
svn_sqlite__stmt_t *stmt;
int affected_rows;
- SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
- STMT_UPDATE_BASE_NODE_DAV_CACHE,
- scratch_pool));
+ 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);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_UPDATE_BASE_NODE_DAV_CACHE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
@@ -2881,11 +2822,20 @@ svn_wc__db_base_get_dav_cache(apr_hash_t
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
- STMT_SELECT_BASE_DAV_CACHE, scratch_pool));
+ 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);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_BASE_DAV_CACHE));
+
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (!have_row)
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
@@ -4038,9 +3988,7 @@ scan_deletion_txn(const char **base_del_
scan = (moved_to_op_root_relpath || moved_to_relpath);
SVN_ERR(svn_sqlite__get_statement(
- &stmt, wcroot->sdb,
- scan ? STMT_SELECT_DELETION_INFO_SCAN
- : STMT_SELECT_DELETION_INFO));
+ &stmt, wcroot->sdb, STMT_SELECT_DELETION_INFO));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -4614,8 +4562,9 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro
int src_op_depth;
SVN_ERR(op_depth_of(&src_op_depth, src_wcroot, src_relpath));
- SVN_ERR(gather_repo_children(&children, src_wcroot, src_relpath,
- src_op_depth, scratch_pool, scratch_pool));
+ SVN_ERR(gather_children(&children, src_wcroot, src_relpath,
+ STMT_SELECT_OP_DEPTH_CHILDREN, src_op_depth,
+ scratch_pool, scratch_pool));
}
else
children = NULL;
@@ -4839,6 +4788,72 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
return SVN_NO_ERROR;
}
+/* Remove unneeded actual nodes for svn_wc__db_op_copy_layer_internal */
+static svn_error_t *
+clear_or_remove_actual(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ int op_depth,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row, shadowed;
+ svn_boolean_t keep_conflict = FALSE;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_NODE_INFO));
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (have_row)
+ {
+ svn_wc__db_status_t presence;
+
+ shadowed = (svn_sqlite__column_int(stmt, 0) > op_depth);
+ presence = svn_sqlite__column_token(stmt, 3, presence_map);
+
+ if (shadowed && presence == svn_wc__db_status_base_deleted)
+ {
+ keep_conflict = TRUE;
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (have_row)
+ shadowed = (svn_sqlite__column_int(stmt, 0) > op_depth);
+ else
+ shadowed = FALSE;
+ }
+ }
+ else
+ shadowed = FALSE;
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (shadowed)
+ return SVN_NO_ERROR;
+
+ if (keep_conflict)
+ {
+ /* We don't want to accidentally remove delete-delete conflicts */
+ SVN_ERR(svn_sqlite__get_statement(
+ &stmt, wcroot->sdb,
+ STMT_CLEAR_ACTUAL_NODE_LEAVING_CONFLICT));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_DELETE_ACTUAL_EMPTY));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+ else
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_DELETE_ACTUAL_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__db_op_copy_layer_internal(svn_wc__db_wcroot_t *wcroot,
const char *src_op_relpath,
@@ -4878,15 +4893,12 @@ svn_wc__db_op_copy_layer_internal(svn_wc
{
const char *src_relpath;
const char *dst_relpath;
- svn_boolean_t exists;
svn_pool_clear(iterpool);
src_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
dst_relpath = svn_sqlite__column_text(stmt, 2, iterpool);
- exists = !svn_sqlite__column_is_null(stmt, 3);
-
err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id,
src_relpath, src_op_depth,
dst_relpath, dst_op_depth,
@@ -4899,21 +4911,11 @@ svn_wc__db_op_copy_layer_internal(svn_wc
if (err)
break;
- if (strlen(dst_relpath) > strlen(dst_op_relpath))
+ /* The node can't be deleted where it is added, so extension of
+ an existing shadowing is only interesting 2 levels deep. */
+ if (relpath_depth(dst_relpath) > (dst_op_depth+1))
{
- svn_boolean_t added_delete = FALSE;
- svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map);
-
- /* The op root can't be shadowed, so extension of a parent delete
- is only needed when the parent can be deleted */
- if (relpath_depth(dst_relpath) > (dst_op_depth+1))
- {
- err = db_extend_parent_delete(&added_delete, wcroot, dst_relpath,
- kind, dst_op_depth, iterpool);
-
- if (err)
- break;
- }
+ svn_boolean_t exists = !svn_sqlite__column_is_null(stmt, 3);
if (exists)
{
@@ -4921,28 +4923,19 @@ svn_wc__db_op_copy_layer_internal(svn_wc
presence = svn_sqlite__column_token(stmt, 3, presence_map);
- if (presence == svn_wc__db_status_not_present)
+ if (presence != svn_wc__db_status_normal)
exists = FALSE;
}
- /* ### Fails in a few tests... Needs further research */
- /*SVN_ERR_ASSERT(!(exists && added_delete));*/
-
if (!exists)
{
- svn_boolean_t shadowed;
+ svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map);
- shadowed = svn_sqlite__column_int(stmt, 4);
+ err = db_extend_parent_delete(wcroot, dst_relpath,
+ kind, dst_op_depth, iterpool);
- /*if (!shadowed && !added_delete)
- {
- err = svn_error_createf(
- SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
- _("Node '%s' was unexpectedly added unshadowed"),
- path_for_error_message(wcroot, dst_relpath,
- iterpool));
- break;
- }*/
+ if (err)
+ break;
}
}
@@ -4992,6 +4985,12 @@ svn_wc__db_op_copy_layer_internal(svn_wc
err = svn_sqlite__step_done(stmt2);
/* stmt2 is reset (never modified or by step_done) */
+ if (err)
+ break;
+
+ /* Delete ACTUAL information about this node that we just deleted */
+ err = clear_or_remove_actual(wcroot, dst_relpath, dst_op_depth,
+ scratch_pool);
if (err)
break;
@@ -5009,8 +5008,6 @@ svn_wc__db_op_copy_layer_internal(svn_wc
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
- /* ### TODO: Did we handle ACTUAL as intended? */
-
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
if (conflict)
@@ -5427,8 +5424,9 @@ db_op_copy_shadowed_layer(svn_wc__db_wcr
return SVN_NO_ERROR;
}
- SVN_ERR(gather_repo_children(&children, src_wcroot, src_relpath,
- src_op_depth, scratch_pool, iterpool));
+ SVN_ERR(gather_children(&children, src_wcroot, src_relpath,
+ STMT_SELECT_OP_DEPTH_CHILDREN, src_op_depth,
+ scratch_pool, iterpool));
for (i = 0; i < children->nelts; i++)
{
@@ -5615,8 +5613,8 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
const char *original_uuid,
svn_revnum_t original_revision,
const apr_array_header_t *children,
- svn_boolean_t is_move,
svn_depth_t depth,
+ svn_boolean_t is_move,
const svn_skel_t *conflict,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -5643,11 +5641,6 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_node_dir;
- iwb.props = props;
- iwb.changed_rev = changed_rev;
- iwb.changed_date = changed_date;
- iwb.changed_author = changed_author;
-
if (original_root_url != NULL)
{
SVN_ERR(create_repos_id(&iwb.original_repos_id,
@@ -5655,6 +5648,11 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
wcroot->sdb, scratch_pool));
iwb.original_repos_relpath = original_repos_relpath;
iwb.original_revnum = original_revision;
+
+ iwb.props = props;
+ iwb.changed_rev = changed_rev;
+ iwb.changed_date = changed_date;
+ iwb.changed_author = changed_author;
}
/* ### Should we do this inside the transaction? */
@@ -5723,11 +5721,6 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_node_file;
- iwb.props = props;
- iwb.changed_rev = changed_rev;
- iwb.changed_date = changed_date;
- iwb.changed_author = changed_author;
-
if (original_root_url != NULL)
{
SVN_ERR(create_repos_id(&iwb.original_repos_id,
@@ -5735,6 +5728,11 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
wcroot->sdb, scratch_pool));
iwb.original_repos_relpath = original_repos_relpath;
iwb.original_revnum = original_revision;
+
+ iwb.props = props;
+ iwb.changed_rev = changed_rev;
+ iwb.changed_date = changed_date;
+ iwb.changed_author = changed_author;
}
/* ### Should we do this inside the transaction? */
@@ -5777,6 +5775,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
const char *original_uuid,
svn_revnum_t original_revision,
const char *target,
+ svn_boolean_t is_move,
const svn_skel_t *conflict,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -5801,11 +5800,6 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_node_symlink;
- iwb.props = props;
- iwb.changed_rev = changed_rev;
- iwb.changed_date = changed_date;
- iwb.changed_author = changed_author;
- iwb.moved_here = FALSE;
if (original_root_url != NULL)
{
@@ -5814,6 +5808,11 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
wcroot->sdb, scratch_pool));
iwb.original_repos_relpath = original_repos_relpath;
iwb.original_revnum = original_revision;
+
+ iwb.props = props;
+ iwb.changed_rev = changed_rev;
+ iwb.changed_date = changed_date;
+ iwb.changed_author = changed_author;
}
/* ### Should we do this inside the transaction? */
@@ -5823,6 +5822,8 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
wcroot, local_relpath, scratch_pool));
iwb.target = target;
+ iwb.moved_here = is_move && (parent_op_depth == 0 ||
+ iwb.op_depth == parent_op_depth);
iwb.work_items = work_items;
iwb.conflict = conflict;
@@ -6032,27 +6033,39 @@ svn_wc__db_global_record_fileinfo(svn_wc
* props; to indicate no properties when the pristine has some props,
* PROPS must be an empty hash. */
static svn_error_t *
-set_actual_props(apr_int64_t wc_id,
+set_actual_props(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_hash_t *props,
- svn_sqlite__db_t *db,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
int affected_rows;
- SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_UPDATE_ACTUAL_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_UPDATE_ACTUAL_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
if (affected_rows == 1 || !props)
- return SVN_NO_ERROR; /* We are done */
+ {
+ /* Perhaps the entire ACTUAL record is unneeded now? */
+ if (!props && affected_rows)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_DELETE_ACTUAL_EMPTY));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+
+ return SVN_NO_ERROR; /* We are done */
+ }
/* We have to insert a row in ACTUAL */
- SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_ACTUAL_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_INSERT_ACTUAL_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
if (*local_relpath != '\0')
SVN_ERR(svn_sqlite__bind_text(stmt, 3,
svn_relpath_dirname(local_relpath,
@@ -6068,8 +6081,7 @@ svn_wc__db_op_set_props_internal(svn_wc_
svn_boolean_t clear_recorded_info,
apr_pool_t *scratch_pool)
{
- SVN_ERR(set_actual_props(wcroot->wc_id, local_relpath,
- props, wcroot->sdb, scratch_pool));
+ SVN_ERR(set_actual_props(wcroot, local_relpath, props, scratch_pool));
if (clear_recorded_info)
{
@@ -6348,7 +6360,7 @@ set_changelist_txn(void *baton,
if (scb->new_changelist)
{
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_INSERT_ACTUAL_EMPTIES));
+ STMT_INSERT_ACTUAL_EMPTIES_FILES));
SVN_ERR(svn_sqlite__step_done(stmt));
}
@@ -6565,15 +6577,15 @@ svn_wc__db_op_mark_conflict(svn_wc__db_t
/* The body of svn_wc__db_op_mark_resolved().
*/
-static svn_error_t *
-db_op_mark_resolved(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- svn_wc__db_t *db,
- svn_boolean_t resolved_text,
- svn_boolean_t resolved_props,
- svn_boolean_t resolved_tree,
- const svn_skel_t *work_items,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__db_op_mark_resolved_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ svn_wc__db_t *db,
+ svn_boolean_t resolved_text,
+ svn_boolean_t resolved_props,
+ svn_boolean_t resolved_tree,
+ const svn_skel_t *work_items,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -6671,7 +6683,8 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
VERIFY_USABLE_WCROOT(wcroot);
SVN_WC__DB_WITH_TXN(
- db_op_mark_resolved(wcroot, local_relpath, db,
+ svn_wc__db_op_mark_resolved_internal(
+ wcroot, local_relpath, db,
resolved_text, resolved_props, resolved_tree,
work_items, scratch_pool),
wcroot);
@@ -6739,6 +6752,7 @@ op_revert_txn(void *baton,
int affected_rows;
const char *moved_to;
int op_depth_increased = 0;
+ int op_depth_below;
svn_skel_t *conflict;
/* ### Similar structure to op_revert_recursive_txn, should they be
@@ -6786,6 +6800,13 @@ op_revert_txn(void *baton,
op_depth = svn_sqlite__column_int(stmt, 0);
moved_here = svn_sqlite__column_boolean(stmt, 15);
moved_to = svn_sqlite__column_text(stmt, 17, scratch_pool);
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ op_depth_below = svn_sqlite__column_int(stmt, 0);
+ else
+ op_depth_below = -1;
+
SVN_ERR(svn_sqlite__reset(stmt));
if (moved_to)
@@ -6796,7 +6817,7 @@ op_revert_txn(void *baton,
}
else
{
- SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot,
+ SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, NULL, wcroot,
local_relpath,
scratch_pool, scratch_pool));
}
@@ -6873,7 +6894,7 @@ op_revert_txn(void *baton,
|| reason == svn_wc_conflict_reason_replaced)
{
SVN_ERR(svn_wc__db_op_raise_moved_away_internal(
- wcroot, local_relpath, op_depth+1, db,
+ wcroot, local_relpath, op_depth_below, db,
operation, action,
(locations && locations->nelts > 0)
? APR_ARRAY_IDX(locations, 0,
@@ -7024,7 +7045,7 @@ op_revert_recursive_txn(void *baton,
STMT_DELETE_ACTUAL_NODE_LEAVING_CHANGELIST_RECURSIVE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
-
+
SVN_ERR(svn_sqlite__get_statement(
&stmt, wcroot->sdb,
STMT_CLEAR_ACTUAL_NODE_LEAVING_CHANGELIST_RECURSIVE));
@@ -7397,9 +7418,6 @@ remove_node_txn(svn_boolean_t *left_chan
svn_wc__db_t *db,
svn_boolean_t destroy_wc,
svn_boolean_t destroy_changes,
- svn_revnum_t not_present_rev,
- svn_wc__db_status_t not_present_status,
- svn_node_kind_t not_present_kind,
const svn_skel_t *conflict,
const svn_skel_t *work_items,
svn_cancel_func_t cancel_func,
@@ -7408,9 +7426,6 @@ remove_node_txn(svn_boolean_t *left_chan
{
svn_sqlite__stmt_t *stmt;
- apr_int64_t repos_id;
- const char *repos_relpath;
-
/* Note that unlike many similar functions it is a valid scenario for this
function to be called on a wcroot! */
@@ -7420,15 +7435,6 @@ remove_node_txn(svn_boolean_t *left_chan
if (left_changes)
*left_changes = FALSE;
- /* Need info for not_present node? */
- if (SVN_IS_VALID_REVNUM(not_present_rev))
- SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
- &repos_relpath, &repos_id,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- wcroot, local_relpath,
- scratch_pool, scratch_pool));
-
if (destroy_wc
&& (!destroy_changes || *local_relpath == '\0'))
{
@@ -7625,26 +7631,6 @@ remove_node_txn(svn_boolean_t *left_chan
local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
- /* Should we leave a not-present node? */
- if (SVN_IS_VALID_REVNUM(not_present_rev))
- {
- insert_base_baton_t ibb;
- blank_ibb(&ibb);
-
- ibb.repos_id = repos_id;
-
- SVN_ERR_ASSERT(not_present_status == svn_wc__db_status_not_present
- || not_present_status == svn_wc__db_status_excluded);
-
- ibb.status = not_present_status;
- ibb.kind = not_present_kind;
-
- ibb.repos_relpath = repos_relpath;
- ibb.revision = not_present_rev;
-
- SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
- }
-
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
if (conflict)
SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
@@ -7659,9 +7645,6 @@ svn_wc__db_op_remove_node(svn_boolean_t
const char *local_abspath,
svn_boolean_t destroy_wc,
svn_boolean_t destroy_changes,
- svn_revnum_t not_present_revision,
- svn_wc__db_status_t not_present_status,
- svn_node_kind_t not_present_kind,
const svn_skel_t *conflict,
const svn_skel_t *work_items,
svn_cancel_func_t cancel_func,
@@ -7680,8 +7663,7 @@ svn_wc__db_op_remove_node(svn_boolean_t
SVN_WC__DB_WITH_TXN(remove_node_txn(left_changes,
wcroot, local_relpath, db,
destroy_wc, destroy_changes,
- not_present_revision, not_present_status,
- not_present_kind, conflict, work_items,
+ conflict, work_items,
cancel_func, cancel_baton, scratch_pool),
wcroot);
@@ -9812,7 +9794,7 @@ svn_wc__db_read_pristine_info(svn_wc__db
}
svn_error_t *
-svn_wc__db_read_children_walker_info(apr_hash_t **nodes,
+svn_wc__db_read_children_walker_info(const apr_array_header_t **items,
svn_wc__db_t *db,
const char *dir_abspath,
apr_pool_t *result_pool,
@@ -9822,6 +9804,7 @@ svn_wc__db_read_children_walker_info(apr
const char *dir_relpath;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ apr_array_header_t *nodes;
SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
@@ -9835,16 +9818,18 @@ svn_wc__db_read_children_walker_info(apr
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, dir_relpath));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
- *nodes = apr_hash_make(result_pool);
+ nodes = apr_array_make(result_pool, 16,
+ sizeof(struct svn_wc__db_walker_info_t *));
while (have_row)
{
struct svn_wc__db_walker_info_t *child;
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
- const char *name = svn_relpath_basename(child_relpath, NULL);
+ const char *name = svn_relpath_basename(child_relpath, result_pool);
int op_depth = svn_sqlite__column_int(stmt, 1);
svn_error_t *err;
child = apr_palloc(result_pool, sizeof(*child));
+ child->name = name;
child->status = svn_sqlite__column_token(stmt, 2, presence_map);
if (op_depth > 0)
{
@@ -9853,13 +9838,16 @@ svn_wc__db_read_children_walker_info(apr
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
}
child->kind = svn_sqlite__column_token(stmt, 3, kind_map);
- svn_hash_sets(*nodes, apr_pstrdup(result_pool, name), child);
+
+ APR_ARRAY_PUSH(nodes, struct svn_wc__db_walker_info_t *) = child;
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
SVN_ERR(svn_sqlite__reset(stmt));
+ *items = nodes;
+
return SVN_NO_ERROR;
}
@@ -9943,35 +9931,34 @@ svn_wc__db_read_node_install_info(const
-/* The body of svn_wc__db_read_url().
+/* The body of svn_wc__db_read_repos_info().
*/
static svn_error_t *
-read_url_txn(const char **url,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+db_read_repos_info(svn_revnum_t *revision,
+ const char **repos_relpath,
+ apr_int64_t *repos_id,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_wc__db_status_t status;
- const char *repos_relpath;
- const char *repos_root_url;
- apr_int64_t repos_id;
- svn_boolean_t have_base;
- SVN_ERR(read_info(&status, NULL, NULL, &repos_relpath, &repos_id, NULL,
+ SVN_ERR(read_info(&status, NULL, revision, repos_relpath, repos_id, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- &have_base, NULL, NULL,
- wcroot, local_relpath, scratch_pool, scratch_pool));
+ NULL, NULL, NULL,
+ wcroot, local_relpath, result_pool, scratch_pool));
- if (repos_relpath == NULL)
+ if ((repos_relpath && !*repos_relpath)
+ || (repos_id && *repos_id == INVALID_REPOS_ID))
{
if (status == svn_wc__db_status_added)
{
- SVN_ERR(scan_addition(NULL, NULL, &repos_relpath, &repos_id, NULL,
+ SVN_ERR(scan_addition(NULL, NULL, repos_relpath, repos_id, NULL,
NULL, NULL, NULL, NULL, NULL,
wcroot, local_relpath,
- scratch_pool, scratch_pool));
+ result_pool, scratch_pool));
}
else if (status == svn_wc__db_status_deleted)
{
@@ -9985,26 +9972,7 @@ read_url_txn(const char **url,
scratch_pool,
scratch_pool));
- if (base_del_relpath)
- {
- SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
- &repos_relpath,
- &repos_id,
- NULL, NULL, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- wcroot,
- base_del_relpath,
- scratch_pool,
- scratch_pool));
-
- repos_relpath = svn_relpath_join(
- repos_relpath,
- svn_dirent_skip_ancestor(base_del_relpath,
- local_relpath),
- scratch_pool);
- }
- else
+ if (work_del_relpath)
{
/* The parent of the WORKING delete, must be an addition */
const char *work_relpath = NULL;
@@ -10017,34 +9985,57 @@ read_url_txn(const char **url,
work_relpath = svn_relpath_dirname(work_del_relpath,
scratch_pool);
- SVN_ERR(scan_addition(NULL, NULL, &repos_relpath, &repos_id,
+ SVN_ERR(scan_addition(NULL, NULL, repos_relpath, repos_id,
NULL, NULL, NULL, NULL, NULL, NULL,
wcroot, work_relpath,
scratch_pool, scratch_pool));
- repos_relpath = svn_relpath_join(
- repos_relpath,
+ if (repos_relpath)
+ *repos_relpath = svn_relpath_join(
+ *repos_relpath,
svn_dirent_skip_ancestor(work_relpath,
local_relpath),
- scratch_pool);
+ result_pool);
+ }
+ else
+ {
+ SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, revision,
+ repos_relpath,
+ repos_id,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ wcroot,
+ base_del_relpath,
+ scratch_pool,
+ scratch_pool));
+
+ if (repos_relpath)
+ *repos_relpath = svn_relpath_join(
+ *repos_relpath,
+ svn_dirent_skip_ancestor(base_del_relpath,
+ local_relpath),
+ result_pool);
}
}
else if (status == svn_wc__db_status_excluded)
{
const char *parent_relpath;
const char *name;
- const char *url2;
- /* Set 'url' to the *full URL* of the parent WC dir,
- * and 'name' to the *single path component* that is the
- * basename of this WC directory, so that joining them will result
- * in the correct full URL. */
+ /* A BASE excluded would have had repository information, so
+ we have a working exclude, which must be below an addition */
+
svn_relpath_split(&parent_relpath, &name, local_relpath,
scratch_pool);
- SVN_ERR(read_url_txn(&url2, wcroot, parent_relpath,
- scratch_pool, scratch_pool));
+ SVN_ERR(scan_addition(NULL, NULL, repos_relpath, repos_id, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ wcroot, parent_relpath,
+ scratch_pool, scratch_pool));
- *url = svn_path_url_add_component2(url2, name, result_pool);
+ if (repos_relpath)
+ *repos_relpath = svn_relpath_join(*repos_relpath, name,
+ result_pool);
return SVN_NO_ERROR;
}
@@ -10056,26 +10047,23 @@ read_url_txn(const char **url,
}
}
- SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot,
- repos_id, scratch_pool));
-
- SVN_ERR_ASSERT(repos_root_url != NULL && repos_relpath != NULL);
- *url = svn_path_url_add_component2(repos_root_url, repos_relpath,
- result_pool);
-
return SVN_NO_ERROR;
}
svn_error_t *
-svn_wc__db_read_url(const char **url,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_wc__db_read_repos_info(svn_revnum_t *revision,
+ const char **repos_relpath,
+ const char **repos_root_url,
+ const char **repos_uuid,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
+ apr_int64_t repos_id = INVALID_REPOS_ID;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -10084,9 +10072,17 @@ svn_wc__db_read_url(const char **url,
scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- SVN_WC__DB_WITH_TXN(read_url_txn(url, wcroot, local_relpath,
- result_pool, scratch_pool),
- wcroot);
+ SVN_WC__DB_WITH_TXN4(db_read_repos_info(revision, repos_relpath,
+ (repos_root_url || repos_uuid)
+ ? &repos_id : NULL,
+ wcroot, local_relpath,
+ result_pool, scratch_pool),
+ svn_wc__db_fetch_repos_info(repos_root_url,
+ repos_uuid,
+ wcroot, repos_id,
+ result_pool),
+ SVN_NO_ERROR, SVN_NO_ERROR,
+ wcroot);
return SVN_NO_ERROR;
}
@@ -10928,8 +10924,34 @@ svn_wc__db_read_children_of_working_node
scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- return gather_children2(children, wcroot, local_relpath,
- result_pool, scratch_pool);
+ return svn_error_trace(
+ gather_children(children, wcroot, local_relpath,
+ STMT_SELECT_WORKING_CHILDREN, -1,
+ result_pool, scratch_pool));
+}
+
+svn_error_t *
+svn_wc__db_base_read_not_present_children(
+ const apr_array_header_t **children,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+
+ 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);
+
+ return svn_error_trace(
+ gather_children(children, wcroot, local_relpath,
+ STMT_SELECT_BASE_NOT_PRESENT_CHILDREN, -1,
+ result_pool, scratch_pool));
}
/* Helper for svn_wc__db_node_check_replace().
@@ -11116,6 +11138,7 @@ svn_wc__db_read_children(const apr_array
VERIFY_USABLE_WCROOT(wcroot);
return gather_children(children, wcroot, local_relpath,
+ STMT_SELECT_NODE_CHILDREN, -1,
result_pool, scratch_pool);
}
@@ -11321,35 +11344,18 @@ determine_repos_info(apr_int64_t *repos_
return SVN_NO_ERROR;
}
-/* Helper for svn_wc__db_global_commit()
-
- Makes local_relpath and all its descendants at the same op-depth represent
- the copy origin repos_id:repos_relpath@revision.
-
- This code is only valid to fix-up a move from an old location, to a new
- location during a commit.
-
- Assumptions:
- * local_relpath is not the working copy root (can't be moved)
- * repos_relpath is not the repository root (can't be moved)
- */
static svn_error_t *
-moved_descendant_commit(svn_wc__db_wcroot_t *wcroot,
+moved_descendant_collect(apr_hash_t **map,
+ svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
int op_depth,
- apr_int64_t repos_id,
- const char *repos_relpath,
- svn_revnum_t revision,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- apr_hash_t *children;
- apr_pool_t *iterpool;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- apr_hash_index_t *hi;
- SVN_ERR_ASSERT(*local_relpath != '\0'
- && *repos_relpath != '\0');
+ *map = NULL;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_MOVED_DESCENDANTS_SRC));
@@ -11361,21 +11367,56 @@ moved_descendant_commit(svn_wc__db_wcroo
if (! have_row)
return svn_error_trace(svn_sqlite__reset(stmt));
- children = apr_hash_make(scratch_pool);
-
- /* First, obtain all moved descendants */
- /* To keep error handling simple, first cache them in a hashtable */
+ /* Find all moved descendants. Key them on target, because that is
+ always unique */
while (have_row)
{
- const char *src_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
- const char *to_relpath = svn_sqlite__column_text(stmt, 4, scratch_pool);
+ const char *src_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+ const char *to_relpath = svn_sqlite__column_text(stmt, 4, result_pool);
+
+ if (!*map)
+ *map = apr_hash_make(result_pool);
- svn_hash_sets(children, src_relpath, to_relpath);
+ svn_hash_sets(*map, to_relpath, src_relpath);
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
SVN_ERR(svn_sqlite__reset(stmt));
+ return SVN_NO_ERROR;
+}
+
+/* Helper for svn_wc__db_global_commit()
+
+ Makes local_relpath and all its descendants at the same op-depth represent
+ the copy origin repos_id:repos_relpath@revision.
+
+ This code is only valid to fix-up a move from an old location, to a new
+ location during a commit.
+
+ Assumptions:
+ * local_relpath is not the working copy root (can't be moved)
+ * repos_relpath is not the repository root (can't be moved)
+ */
+static svn_error_t *
+moved_descendant_commit(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_int64_t repos_id,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ apr_hash_t *children,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *iterpool;
+ svn_sqlite__stmt_t *stmt;
+ apr_hash_index_t *hi;
+
+ SVN_ERR_ASSERT(*local_relpath != '\0'
+ && *repos_relpath != '\0');
+
+ if (!children)
+ return SVN_NO_ERROR;
+
/* Then update them */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_COMMIT_UPDATE_ORIGIN));
@@ -11383,11 +11424,12 @@ moved_descendant_commit(svn_wc__db_wcroo
iterpool = svn_pool_create(scratch_pool);
for (hi = apr_hash_first(scratch_pool, children); hi; hi = apr_hash_next(hi))
{
- const char *src_relpath = apr_hash_this_key(hi);
- const char *to_relpath = apr_hash_this_val(hi);
+ const char *src_relpath = apr_hash_this_val(hi);
+ const char *to_relpath = apr_hash_this_key(hi);
const char *new_repos_relpath;
int to_op_depth = relpath_depth(to_relpath);
int affected;
+ apr_hash_t *map;
svn_pool_clear(iterpool);
@@ -11414,9 +11456,11 @@ moved_descendant_commit(svn_wc__db_wcroo
SVN_ERR_ASSERT(affected >= 1); /* If this fails there is no move dest */
#endif
- SVN_ERR(moved_descendant_commit(wcroot, to_relpath, to_op_depth,
+ SVN_ERR(moved_descendant_collect(&map, wcroot, to_relpath, to_op_depth,
+ iterpool, iterpool));
+ SVN_ERR(moved_descendant_commit(wcroot, to_relpath,
repos_id, new_repos_relpath, revision,
- iterpool));
+ map, iterpool));
}
svn_pool_destroy(iterpool);
@@ -11475,7 +11519,6 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
apr_time_t changed_date,
const char *changed_author,
const svn_checksum_t *new_checksum,
- const apr_array_header_t *new_children,
apr_hash_t *new_dav_cache,
svn_boolean_t keep_changelist,
svn_boolean_t no_unlock,
@@ -11497,6 +11540,7 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
const char *repos_relpath;
int op_depth;
svn_wc__db_status_t old_presence;
+ svn_boolean_t moved_here;
/* If we are adding a file or directory, then we need to get
repository information from the parent node since "this node" does
@@ -11526,6 +11570,7 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
/* Figure out the new node's kind. It will be whatever is in WORKING_NODE,
or there will be a BASE_NODE that has it. */
+ old_presence = svn_sqlite__column_token(stmt_info, 3, presence_map);
new_kind = svn_sqlite__column_token(stmt_info, 4, kind_map);
/* What will the new depth be? */
@@ -11544,26 +11589,35 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
svn_sqlite__column_text(stmt_info, 2, NULL)) == 0);
}
- /* Find the appropriate new properties -- ACTUAL overrides any properties
- in WORKING that arrived as part of a copy/move.
+ if (old_presence != svn_wc__db_status_base_deleted)
+ {
+ /* Find the appropriate new properties -- ACTUAL overrides any properties
+ in WORKING that arrived as part of a copy/move.
- Note: we'll keep them as a big blob of data, rather than
- deserialize/serialize them. */
- if (have_act)
- prop_blob.data = svn_sqlite__column_blob(stmt_act, 1, &prop_blob.len,
- scratch_pool);
- if (prop_blob.data == NULL)
- prop_blob.data = svn_sqlite__column_blob(stmt_info, 14, &prop_blob.len,
- scratch_pool);
-
- inherited_prop_blob.data = svn_sqlite__column_blob(stmt_info, 16,
- &inherited_prop_blob.len,
- scratch_pool);
+ Note: we'll keep them as a big blob of data, rather than
+ deserialize/serialize them. */
+ if (have_act)
+ prop_blob.data = svn_sqlite__column_blob(stmt_act, 1, &prop_blob.len,
+ scratch_pool);
+ if (prop_blob.data == NULL)
+ prop_blob.data = svn_sqlite__column_blob(stmt_info, 14, &prop_blob.len,
+ scratch_pool);
- if (keep_changelist && have_act)
- changelist = svn_sqlite__column_text(stmt_act, 0, scratch_pool);
+ inherited_prop_blob.data = svn_sqlite__column_blob(
+ stmt_info, 16,
+ &inherited_prop_blob.len,
+ scratch_pool);
- old_presence = svn_sqlite__column_token(stmt_info, 3, presence_map);
+ if (keep_changelist && have_act)
+ changelist = svn_sqlite__column_text(stmt_act, 0, scratch_pool);
+
+ moved_here = svn_sqlite__column_int(stmt_info, 15);
+ }
+ else
+ {
+ moved_here = FALSE;
+ changelist = NULL;
+ }
/* ### other stuff? */
@@ -11574,6 +11628,24 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
{
int affected_rows;
+ SVN_ERR_ASSERT(op_depth == relpath_depth(local_relpath));
+
+ /* First clear the moves that we are going to delete in a bit */
+ {
+ apr_hash_t *old_moves;
+ apr_hash_index_t *hi;
+ SVN_ERR(moved_descendant_collect(&old_moves, wcroot, local_relpath, 0,
+ scratch_pool, scratch_pool));
+
+ if (old_moves)
+ for (hi = apr_hash_first(scratch_pool, old_moves);
+ hi; hi = apr_hash_next(hi))
+ {
+ SVN_ERR(clear_moved_here(wcroot, apr_hash_this_key(hi),
+ scratch_pool));
+ }
+ }
+
/* This removes all layers of this node and at the same time determines
if we need to remove shadowed layers below our descendants. */
@@ -11606,26 +11678,40 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
be integrated, they really affect a different op-depth and
completely different nodes (via a different recursion pattern). */
- /* Collapse descendants of the current op_depth in layer 0 */
- SVN_ERR(descendant_commit(wcroot, local_relpath, op_depth,
- repos_id, repos_relpath, new_revision,
- scratch_pool));
+ if (old_presence != svn_wc__db_status_base_deleted)
+ {
+ /* Collapse descendants of the current op_depth to layer 0,
+ this includes moved-from/to clearing */
+ SVN_ERR(descendant_commit(wcroot, local_relpath, op_depth,
+ repos_id, repos_relpath, new_revision,
+ scratch_pool));
+ }
+
+ if (old_presence != svn_wc__db_status_base_deleted)
+ {
+ apr_hash_t *moves = NULL;
+
+ SVN_ERR(moved_descendant_collect(&moves, wcroot, local_relpath, 0,
+ scratch_pool, scratch_pool));
- /* And make the recorded local moves represent moves of the node we just
- committed. */
- SVN_ERR(moved_descendant_commit(wcroot, local_relpath, 0,
+ /* And make the recorded local moves represent moves of the node we
+ just committed. */
+ SVN_ERR(moved_descendant_commit(wcroot, local_relpath,
repos_id, repos_relpath, new_revision,
- scratch_pool));
+ moves, scratch_pool));
+ }
- /* This node is no longer modified, so no node was moved here */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_CLEAR_MOVED_TO_FROM_DEST));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
- local_relpath));
+ if (moved_here)
+ {
+ /* This node is no longer modified, so no node was moved here */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_CLEAR_MOVED_TO_FROM_DEST));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
+ local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
}
-
/* Update or add the BASE_NODE row with all the new information. */
if (*local_relpath == '\0')
@@ -11634,38 +11720,56 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
/* Preserve any incomplete status */
- new_presence = (old_presence == svn_wc__db_status_incomplete
- ? svn_wc__db_status_incomplete
- : svn_wc__db_status_normal);
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_APPLY_CHANGES_TO_BASE_NODE));
- /* symlink_target not yet used */
- SVN_ERR(svn_sqlite__bindf(stmt, "issisrtstrisnbn",
- wcroot->wc_id, local_relpath,
- parent_relpath,
- repos_id,
- repos_relpath,
- new_revision,
- presence_map, new_presence,
- new_depth_str,
- kind_map, new_kind,
- changed_rev,
- changed_date,
- changed_author,
- prop_blob.data, prop_blob.len));
-
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 13, new_checksum,
- scratch_pool));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 15, new_dav_cache,
- scratch_pool));
- if (inherited_prop_blob.data != NULL)
+ if (old_presence != svn_wc__db_status_base_deleted)
{
- SVN_ERR(svn_sqlite__bind_blob(stmt, 17, inherited_prop_blob.data,
- inherited_prop_blob.len));
- }
+ new_presence = (old_presence == svn_wc__db_status_incomplete
+ ? svn_wc__db_status_incomplete
+ : svn_wc__db_status_normal);
- SVN_ERR(svn_sqlite__step_done(stmt));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_APPLY_CHANGES_TO_BASE_NODE));
+ /* symlink_target not yet used */
+ SVN_ERR(svn_sqlite__bindf(stmt, "issisrtstrisnbn",
+ wcroot->wc_id, local_relpath,
+ parent_relpath,
+ repos_id,
+ repos_relpath,
+ new_revision,
+ presence_map, new_presence,
+ new_depth_str,
+ kind_map, new_kind,
+ changed_rev,
+ changed_date,
+ changed_author,
+ prop_blob.data, prop_blob.len));
+
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 13, new_checksum,
+ scratch_pool));
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 15, new_dav_cache,
+ scratch_pool));
+ if (inherited_prop_blob.data != NULL)
+ {
+ SVN_ERR(svn_sqlite__bind_blob(stmt, 17, inherited_prop_blob.data,
+ inherited_prop_blob.len));
+ }
+
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+ else
+ {
+ struct insert_base_baton_t ibb;
+ blank_ibb(&ibb);
+
+ ibb.repos_id = repos_id;
+ ibb.status = svn_wc__db_status_not_present;
+ ibb.kind = new_kind;
+ ibb.repos_relpath = repos_relpath;
+ ibb.revision = new_revision;
+
+ SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+
+ keep_changelist = FALSE; /* Nothing there */
+ }
if (have_act)
{
@@ -11693,23 +11797,21 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
}
}
- if (new_kind == svn_node_dir)
- {
- /* When committing a directory, we should have its new children. */
- /* ### one day. just not today. */
-#if 0
- SVN_ERR_ASSERT(new_children != NULL);
-#endif
-
- /* ### process the children */
- }
-
if (!no_unlock)
{
svn_sqlite__stmt_t *lock_stmt;
+ svn_boolean_t op_root = (op_depth > 0
+ && (relpath_depth(local_relpath) == op_depth));
+ /* If we are committing an add of a delete, we can assume we own
+ all locks at or below REPOS_RELPATH (or the server would have
+ denied the commit). As we must have passed these to the server
+ we can now safely remove them.
+ */
SVN_ERR(svn_sqlite__get_statement(&lock_stmt, wcroot->sdb,
- STMT_DELETE_LOCK_RECURSIVELY));
+ op_root
+ ? STMT_DELETE_LOCK_RECURSIVELY
+ : STMT_DELETE_LOCK));
SVN_ERR(svn_sqlite__bindf(lock_stmt, "is", repos_id, repos_relpath));
SVN_ERR(svn_sqlite__step_done(lock_stmt));
}
@@ -11729,7 +11831,6 @@ svn_wc__db_global_commit(svn_wc__db_t *d
apr_time_t changed_date,
const char *changed_author,
const svn_checksum_t *new_checksum,
- const apr_array_header_t *new_children,
apr_hash_t *new_dav_cache,
svn_boolean_t keep_changelist,
svn_boolean_t no_unlock,
@@ -11741,7 +11842,6 @@ svn_wc__db_global_commit(svn_wc__db_t *d
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(new_revision));
- SVN_ERR_ASSERT(new_checksum == NULL || new_children == NULL);
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
local_abspath, scratch_pool, scratch_pool));
@@ -11750,7 +11850,7 @@ svn_wc__db_global_commit(svn_wc__db_t *d
SVN_WC__DB_WITH_TXN(
commit_node(wcroot, local_relpath,
new_revision, changed_revision, changed_date, changed_author,
- new_checksum, new_children, new_dav_cache, keep_changelist,
+ new_checksum, new_dav_cache, keep_changelist,
no_unlock, work_items, scratch_pool),
wcroot);
@@ -11997,11 +12097,11 @@ bump_node_revision(svn_wc__db_wcroot_t *
|| (child_info->status == svn_wc__db_status_server_excluded &&
child_info->revnum != new_rev))
{
- SVN_ERR(db_base_remove(wcroot,
- child_local_relpath,
- db, FALSE, FALSE, FALSE,
- SVN_INVALID_REVNUM,
- NULL, NULL, scratch_pool));
+ svn_sqlite__stmt_t *stmt;
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_DELETE_BASE_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, child_local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
continue;
}
@@ -13085,191 +13185,6 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_
return SVN_NO_ERROR;
}
-
-svn_error_t *
-svn_wc__db_upgrade_apply_dav_cache(svn_sqlite__db_t *sdb,
- const char *dir_relpath,
- apr_hash_t *cache_values,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- apr_int64_t wc_id;
- apr_hash_index_t *hi;
- svn_sqlite__stmt_t *stmt;
-
- SVN_ERR(svn_wc__db_util_fetch_wc_id(&wc_id, sdb, iterpool));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_BASE_NODE_DAV_CACHE));
-
- /* Iterate over all the wcprops, writing each one to the wc_db. */
- for (hi = apr_hash_first(scratch_pool, cache_values);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *name = apr_hash_this_key(hi);
- apr_hash_t *props = apr_hash_this_val(hi);
- const char *local_relpath;
-
- svn_pool_clear(iterpool);
-
- local_relpath = svn_relpath_join(dir_relpath, name, iterpool);
-
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, iterpool));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_upgrade_apply_props(svn_sqlite__db_t *sdb,
- const char *dir_abspath,
- const char *local_relpath,
- apr_hash_t *base_props,
- apr_hash_t *revert_props,
- apr_hash_t *working_props,
- int original_format,
- apr_int64_t wc_id,
- apr_pool_t *scratch_pool)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
- int top_op_depth = -1;
- int below_op_depth = -1;
- svn_wc__db_status_t top_presence;
- svn_wc__db_status_t below_presence;
- int affected_rows;
-
- /* ### working_props: use set_props_txn.
- ### if working_props == NULL, then skip. what if they equal the
- ### pristine props? we should probably do the compare here.
- ###
- ### base props go into WORKING_NODE if avail, otherwise BASE.
- ###
- ### revert only goes into BASE. (and WORKING better be there!)
-
- Prior to 1.4.0 (ORIGINAL_FORMAT < 8), REVERT_PROPS did not exist. If a
- file was deleted, then a copy (potentially with props) was disallowed
- and could not replace the deletion. An addition *could* be performed,
- but that would never bring its own props.
-
- 1.4.0 through 1.4.5 created the concept of REVERT_PROPS, but had a
- bug in svn_wc_add_repos_file2() whereby a copy-with-props did NOT
- construct a REVERT_PROPS if the target had no props. Thus, reverting
- the delete/copy would see no REVERT_PROPS to restore, leaving the
- props from the copy source intact, and appearing as if they are (now)
- the base props for the previously-deleted file. (wc corruption)
-
- 1.4.6 ensured that an empty REVERT_PROPS would be established at all
- times. See issue 2530, and r861670 as starting points.
-
- We will use ORIGINAL_FORMAT and SVN_WC__NO_REVERT_FILES to determine
- the handling of our inputs, relative to the state of this node.
- */
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_NODE_INFO));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (have_row)
- {
- top_op_depth = svn_sqlite__column_int(stmt, 0);
- top_presence = svn_sqlite__column_token(stmt, 3, presence_map);
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (have_row)
- {
- below_op_depth = svn_sqlite__column_int(stmt, 0);
- below_presence = svn_sqlite__column_token(stmt, 3, presence_map);
- }
- }
- SVN_ERR(svn_sqlite__reset(stmt));
-
- /* Detect the buggy scenario described above. We cannot upgrade this
- working copy if we have no idea where BASE_PROPS should go. */
- if (original_format > SVN_WC__NO_REVERT_FILES
- && revert_props == NULL
- && top_op_depth != -1
- && top_presence == svn_wc__db_status_normal
- && below_op_depth != -1
- && below_presence != svn_wc__db_status_not_present)
- {
- /* There should be REVERT_PROPS, so it appears that we just ran into
- the described bug. Sigh. */
- return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
- _("The properties of '%s' are in an "
- "indeterminate state and cannot be "
- "upgraded. See issue #2530."),
- svn_dirent_local_style(
- svn_dirent_join(dir_abspath, local_relpath,
- scratch_pool), scratch_pool));
- }
-
- /* Need at least one row, or two rows if there are revert props */
- if (top_op_depth == -1
- || (below_op_depth == -1 && revert_props))
- return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
- _("Insufficient NODES rows for '%s'"),
- svn_dirent_local_style(
- svn_dirent_join(dir_abspath, local_relpath,
- scratch_pool), scratch_pool));
-
- /* one row, base props only: upper row gets base props
- two rows, base props only: lower row gets base props
- two rows, revert props only: lower row gets revert props
- two rows, base and revert props: upper row gets base, lower gets revert */
-
-
- if (revert_props || below_op_depth == -1)
- {
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_NODE_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd",
- wc_id, local_relpath, top_op_depth));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 4, base_props, scratch_pool));
- SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
-
- SVN_ERR_ASSERT(affected_rows == 1);
- }
-
- if (below_op_depth != -1)
- {
- apr_hash_t *props = revert_props ? revert_props : base_props;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_NODE_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd",
- wc_id, local_relpath, below_op_depth));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool));
- SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
-
- SVN_ERR_ASSERT(affected_rows == 1);
- }
-
- /* If there are WORKING_PROPS, then they always go into ACTUAL_NODE. */
- if (working_props != NULL
- && base_props != NULL)
- {
- apr_array_header_t *diffs;
-
- SVN_ERR(svn_prop_diffs(&diffs, working_props, base_props, scratch_pool));
-
- if (diffs->nelts == 0)
- working_props = NULL; /* No differences */
- }
-
[... 917 lines stripped ...]