You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2013/01/06 03:33:39 UTC
svn commit: r1429457 [11/21] - in /subversion/branches/tree-read-api: ./
build/ build/ac-macros/ build/generator/templates/ build/win32/
contrib/server-side/svncutter/ doc/ subversion/bindings/cxxhl/include/
subversion/bindings/cxxhl/include/svncxxhl/ ...
Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db.c Sun Jan 6 02:33:34 2013
@@ -46,6 +46,7 @@
#include "conflicts.h"
#include "wc_db_private.h"
#include "workqueue.h"
+#include "token-map.h"
#include "svn_private_config.h"
#include "private/svn_sqlite.h"
@@ -104,9 +105,9 @@
#define UNKNOWN_WC_ID ((apr_int64_t) -1)
#define FORMAT_FROM_SDB (-1)
-/* Check if the column contains actual properties. The empty set of properties
- is stored as "()", so we have properties if the size of the column is
- larger than 2. */
+/* Check if column number I, a property-skel column, contains a non-empty
+ set of properties. The empty set of properties is stored as "()", so we
+ have properties if the size of the column is larger than 2. */
#define SQLITE_PROPERTIES_AVAILABLE(stmt, i) \
(svn_sqlite__column_bytes(stmt, i) > 2)
@@ -117,6 +118,7 @@ svn_wc__db_op_depth_for_upgrade(const ch
}
+/* Representation of a new base row for the NODES table */
typedef struct insert_base_baton_t {
/* common to all insertions into BASE */
svn_wc__db_status_t status;
@@ -175,6 +177,7 @@ typedef struct insert_base_baton_t {
} insert_base_baton_t;
+/* Representation of a new working row for the NODES table */
typedef struct insert_working_baton_t {
/* common to all insertions into WORKING (including NODE_DATA) */
svn_wc__db_status_t presence;
@@ -216,6 +219,7 @@ typedef struct insert_working_baton_t {
} insert_working_baton_t;
+/* Representation of a new row for the EXTERNALS table */
typedef struct insert_external_baton_t {
/* common to all insertions into EXTERNALS */
svn_kind_t kind;
@@ -266,27 +270,6 @@ typedef struct insert_external_baton_t {
} insert_external_baton_t;
-static const svn_token_map_t kind_map[] = {
- { "file", svn_kind_file },
- { "dir", svn_kind_dir },
- { "symlink", svn_kind_symlink },
- { "unknown", svn_kind_unknown },
- { NULL }
-};
-
-/* Note: we only decode presence values from the database. These are a subset
- of all the status values. */
-static const svn_token_map_t presence_map[] = {
- { "normal", svn_wc__db_status_normal },
- { "server-excluded", svn_wc__db_status_server_excluded },
- { "excluded", svn_wc__db_status_excluded },
- { "not-present", svn_wc__db_status_not_present },
- { "incomplete", svn_wc__db_status_incomplete },
- { "base-deleted", svn_wc__db_status_base_deleted },
- { NULL }
-};
-
-
/* Forward declarations */
static svn_error_t *
add_work_items(svn_sqlite__db_t *sdb,
@@ -301,12 +284,6 @@ set_actual_props(apr_int64_t wc_id,
apr_pool_t *scratch_pool);
static svn_error_t *
-mark_conflict(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- const svn_skel_t *conflict_skel,
- apr_pool_t *scratch_pool);
-
-static svn_error_t *
insert_incomplete_children(svn_sqlite__db_t *sdb,
apr_int64_t wc_id,
const char *local_relpath,
@@ -342,7 +319,7 @@ read_info(svn_wc__db_status_t *status,
svn_revnum_t *original_revision,
svn_wc__db_lock_t **lock,
svn_filesize_t *recorded_size,
- apr_time_t *recorded_mod_time,
+ apr_time_t *recorded_time,
const char **changelist,
svn_boolean_t *conflicted,
svn_boolean_t *op_root,
@@ -383,19 +360,14 @@ wclock_owns_lock(svn_boolean_t *own_lock
svn_boolean_t exact,
apr_pool_t *scratch_pool);
-/* Baton for db_is_switched */
-struct db_is_switched_baton_t
-{
- svn_boolean_t *is_switched;
- svn_kind_t *kind;
-};
-
static svn_error_t *
-db_is_switched(void *baton,
+db_is_switched(svn_boolean_t *is_switched,
+ svn_kind_t *kind,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *scratch_pool);
-
+
+
/* Return the absolute path, in local path style, of LOCAL_RELPATH
in WCROOT. */
static const char *
@@ -493,11 +465,11 @@ fetch_repos_info(const char **repos_root
}
-/* Set *REPOS_ID, *REVISION and *REPOS_RELPATH from the
- given columns of the SQLITE statement STMT, or to NULL if the respective
+/* Set *REPOS_ID, *REVISION and *REPOS_RELPATH from the given columns of the
+ SQLITE statement STMT, or to NULL/SVN_INVALID_REVNUM if the respective
column value is null. Any of the output parameters may be NULL if not
required. */
-static svn_error_t *
+static void
repos_location_from_columns(apr_int64_t *repos_id,
svn_revnum_t *revision,
const char **repos_relpath,
@@ -507,8 +479,6 @@ repos_location_from_columns(apr_int64_t
int col_repos_relpath,
apr_pool_t *result_pool)
{
- svn_error_t *err = SVN_NO_ERROR;
-
if (repos_id)
{
/* Fetch repository information via REPOS_ID. */
@@ -526,8 +496,6 @@ repos_location_from_columns(apr_int64_t
*repos_relpath = svn_sqlite__column_text(stmt, col_repos_relpath,
result_pool);
}
-
- return err;
}
@@ -614,6 +582,12 @@ blank_ibb(insert_base_baton_t *pibb)
/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
+ ### What about KIND and OP_DEPTH? KIND ought to be redundant; I'm
+ discussing on dev@ whether we can let that be null for presence
+ == base-deleted. OP_DEPTH is the op-depth of what, and why?
+ It is used to select the lowest working node higher than OP_DEPTH,
+ so, in terms of the API, OP_DEPTH means ...?
+
Given a wc:
0 1 2 3 4
@@ -637,17 +611,19 @@ blank_ibb(insert_base_baton_t *pibb)
A/B/C/D normal base-del normal
A/B/C/D/E normal base-del
- When adding a base node if the parent has a working node then the
- parent base is deleted and this must be extended to cover new base
- node.
+ When adding a node if the parent has a higher working node then the
+ parent node is deleted (or replaced) and the delete must be extended
+ to cover new node.
In the example above A/B/C/D and A/B/C/D/E are the nodes that get
the extended delete, A/B/C is already deleted.
*/
-static svn_error_t *
-extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ svn_kind_t kind,
+ int op_depth,
+ apr_pool_t *scratch_pool)
{
svn_boolean_t have_row;
svn_sqlite__stmt_t *stmt;
@@ -658,28 +634,29 @@ extend_parent_delete(svn_wc__db_wcroot_t
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_LOWEST_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, parent_relpath));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, parent_relpath,
+ op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (have_row)
parent_op_depth = svn_sqlite__column_int(stmt, 0);
SVN_ERR(svn_sqlite__reset(stmt));
if (have_row)
{
- int op_depth;
+ int existing_op_depth;
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
+ op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (have_row)
- op_depth = svn_sqlite__column_int(stmt, 0);
+ existing_op_depth = svn_sqlite__column_int(stmt, 0);
SVN_ERR(svn_sqlite__reset(stmt));
- if (!have_row || parent_op_depth < op_depth)
+ if (!have_row || parent_op_depth < existing_op_depth)
{
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_INSTALL_WORKING_NODE_FOR_DELETE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isdt", wcroot->wc_id,
+ STMT_INSTALL_WORKING_NODE_FOR_DELETE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdst", wcroot->wc_id,
local_relpath, parent_op_depth,
- presence_map,
- svn_wc__db_status_base_deleted));
+ parent_relpath, kind_map, kind));
SVN_ERR(svn_sqlite__update(NULL, stmt));
}
}
@@ -688,22 +665,24 @@ extend_parent_delete(svn_wc__db_wcroot_t
}
-/* This is the reverse of extend_parent_delete.
+/* This is the reverse of svn_wc__db_extend_parent_delete.
- When removing a base node if the parent has a working node then the
- parent base and this node are both deleted and so the delete of
- this node must be removed.
+ When removing a node if the parent has a higher working node then
+ the parent node and this node are both deleted or replaced and any
+ delete over this node must be removed.
*/
-static svn_error_t *
-retract_parent_delete(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__db_retract_parent_delete(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ int op_depth,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_DELETE_LOWEST_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
+ op_depth));
SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
@@ -711,7 +690,9 @@ retract_parent_delete(svn_wc__db_wcroot_
-/* */
+/* Insert the base row represented by (insert_base_baton_t *) BATON.
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
insert_base_node(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -722,7 +703,7 @@ insert_base_node(void *baton,
apr_int64_t repos_id = pibb->repos_id;
svn_sqlite__stmt_t *stmt;
svn_filesize_t recorded_size = SVN_INVALID_FILESIZE;
- apr_int64_t recorded_mod_time;
+ apr_int64_t recorded_time;
/* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
bind the appropriate parent_relpath. */
@@ -748,7 +729,7 @@ insert_base_node(void *baton,
{
/* Preserve size and modification time if caller asked us to. */
recorded_size = get_recorded_size(stmt, 6);
- recorded_mod_time = svn_sqlite__column_int64(stmt, 12);
+ recorded_time = svn_sqlite__column_int64(stmt, 12);
}
SVN_ERR(svn_sqlite__reset(stmt));
}
@@ -766,7 +747,7 @@ insert_base_node(void *baton,
pibb->revision,
presence_map, pibb->status, /* 8 */
(pibb->kind == svn_kind_dir) ? /* 9 */
- svn_depth_to_word(pibb->depth) : NULL,
+ svn_token__to_word(depth_map, pibb->depth) : NULL,
kind_map, pibb->kind, /* 10 */
pibb->changed_rev, /* 11 */
pibb->changed_date, /* 12 */
@@ -790,10 +771,14 @@ insert_base_node(void *baton,
if (recorded_size != SVN_INVALID_FILESIZE)
{
SVN_ERR(svn_sqlite__bind_int64(stmt, 16, recorded_size));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 17, recorded_mod_time));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 17, recorded_time));
}
}
+ /* Set properties. Must be null if presence not normal or incomplete. */
+ 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));
@@ -850,13 +835,16 @@ insert_base_node(void *baton,
|| (pibb->status == svn_wc__db_status_incomplete))
&& ! pibb->file_external)
{
- SVN_ERR(extend_parent_delete(wcroot, local_relpath, scratch_pool));
+ SVN_ERR(svn_wc__db_extend_parent_delete(wcroot, local_relpath,
+ pibb->kind, 0,
+ scratch_pool));
}
else if (pibb->status == svn_wc__db_status_not_present
|| pibb->status == svn_wc__db_status_server_excluded
|| pibb->status == svn_wc__db_status_excluded)
{
- SVN_ERR(retract_parent_delete(wcroot, local_relpath, scratch_pool));
+ SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, 0,
+ scratch_pool));
}
}
@@ -879,12 +867,15 @@ insert_base_node(void *baton,
SVN_ERR(add_work_items(wcroot->sdb, pibb->work_items, scratch_pool));
if (pibb->conflict)
- SVN_ERR(mark_conflict(wcroot, local_relpath, pibb->conflict, scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ pibb->conflict, scratch_pool));
return SVN_NO_ERROR;
}
+/* Initialize the baton with appropriate "blank" values. This allows the
+ insertion function to leave certain columns null. */
static void
blank_iwb(insert_working_baton_t *piwb)
{
@@ -987,7 +978,9 @@ insert_incomplete_children(svn_sqlite__d
}
-/* */
+/* Insert the working row represented by (insert_working_baton_t *) BATON.
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
insert_working_node(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -1013,7 +1006,7 @@ insert_working_node(void *baton,
parent_relpath,
presence_map, piwb->presence,
(piwb->kind == svn_kind_dir)
- ? svn_depth_to_word(piwb->depth) : NULL,
+ ? svn_token__to_word(depth_map, piwb->depth) : NULL,
kind_map, piwb->kind,
piwb->changed_rev,
piwb->changed_date,
@@ -1036,6 +1029,10 @@ insert_working_node(void *baton,
SVN_ERR(svn_sqlite__bind_revnum(stmt, 7, piwb->original_revnum));
}
+ /* Set properties. Must be null if presence not normal or incomplete. */
+ 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));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -1113,8 +1110,8 @@ insert_working_node(void *baton,
SVN_ERR(add_work_items(wcroot->sdb, piwb->work_items, scratch_pool));
if (piwb->conflict)
- SVN_ERR(mark_conflict(wcroot, local_relpath, piwb->conflict,
- scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ piwb->conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1237,6 +1234,41 @@ gather_repo_children(const apr_array_hea
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_get_children_op_depth(apr_hash_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)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ *children = apr_hash_make(result_pool);
+
+ 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));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ while (have_row)
+ {
+ const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ svn_kind_t *child_kind = apr_palloc(result_pool, sizeof(svn_kind_t));
+
+ *child_kind = svn_sqlite__column_token(stmt, 1, kind_map);
+ apr_hash_set(*children,
+ svn_relpath_basename(child_relpath, result_pool),
+ APR_HASH_KEY_STRING, child_kind);
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
+
/* Return TRUE if CHILD_ABSPATH is an immediate child of PARENT_ABSPATH.
* Else, return FALSE. */
@@ -1390,25 +1422,21 @@ does_node_exist(svn_boolean_t *exists,
return svn_error_trace(svn_sqlite__reset(stmt));
}
-/* baton for init_db */
-struct init_db_baton
-{
- /* output values */
- apr_int64_t wc_id;
- apr_int64_t repos_id;
- /* input values */
- const char *repos_root_url;
- const char *repos_uuid;
- const char *root_node_repos_relpath;
- svn_revnum_t root_node_revision;
- svn_depth_t root_node_depth;
-};
-
-/* Helper for create_db(). Initializes our wc.db schema */
+/* Helper for create_db(). Initializes our wc.db schema.
+ */
static svn_error_t *
-init_db( void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
+init_db(/* output values */
+ apr_int64_t *repos_id,
+ apr_int64_t *wc_id,
+ /* input values */
+ svn_sqlite__db_t *db,
+ const char *repos_root_url,
+ const char *repos_uuid,
+ const char *root_node_repos_relpath,
+ svn_revnum_t root_node_revision,
+ svn_depth_t root_node_depth,
+ apr_pool_t *scratch_pool)
{
- struct init_db_baton *idb = baton;
svn_sqlite__stmt_t *stmt;
/* Create the database's schema. */
@@ -1418,32 +1446,33 @@ init_db( void *baton, svn_sqlite__db_t *
SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_EXTERNALS));
/* Insert the repository. */
- SVN_ERR(create_repos_id(&idb->repos_id, idb->repos_root_url, idb->repos_uuid,
+ SVN_ERR(create_repos_id(repos_id, repos_root_url, repos_uuid,
db, scratch_pool));
/* Insert the wcroot. */
/* ### Right now, this just assumes wc metadata is being stored locally. */
SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_WCROOT));
- SVN_ERR(svn_sqlite__insert(&idb->wc_id, stmt));
+ SVN_ERR(svn_sqlite__insert(wc_id, stmt));
- if (idb->root_node_repos_relpath)
+ if (root_node_repos_relpath)
{
svn_wc__db_status_t status = svn_wc__db_status_normal;
- if (idb->root_node_revision > 0)
+ if (root_node_revision > 0)
status = svn_wc__db_status_incomplete; /* Will be filled by update */
SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isdsisrtst",
- idb->wc_id, /* 1 */
+ *wc_id, /* 1 */
"", /* 2 */
0, /* op_depth is 0 for base */
NULL, /* 4 */
- idb->repos_id,
- idb->root_node_repos_relpath,
- idb->root_node_revision,
+ *repos_id,
+ root_node_repos_relpath,
+ root_node_revision,
presence_map, status, /* 8 */
- svn_depth_to_word(idb->root_node_depth),
+ svn_token__to_word(depth_map,
+ root_node_depth),
kind_map, svn_kind_dir /* 10 */));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -1476,23 +1505,16 @@ create_db(svn_sqlite__db_t **sdb,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- struct init_db_baton idb;
-
SVN_ERR(svn_wc__db_util_open_db(sdb, dir_abspath, sdb_fname,
svn_sqlite__mode_rwcreate, exclusive,
NULL /* my_statements */,
result_pool, scratch_pool));
- idb.repos_root_url = repos_root_url;
- idb.repos_uuid = repos_uuid;
- idb.root_node_repos_relpath = root_node_repos_relpath;
- idb.root_node_revision = root_node_revision;
- idb.root_node_depth = root_node_depth;
-
- SVN_ERR(svn_sqlite__with_lock(*sdb, init_db, &idb, scratch_pool));
-
- *repos_id = idb.repos_id;
- *wc_id = idb.wc_id;
+ SVN_SQLITE__WITH_LOCK(init_db(repos_id, wc_id,
+ *sdb, repos_root_url, repos_uuid,
+ root_node_repos_relpath, root_node_revision,
+ root_node_depth, scratch_pool),
+ *sdb);
return SVN_NO_ERROR;
}
@@ -2058,26 +2080,20 @@ svn_wc__db_base_add_not_present_node(svn
kind, svn_wc__db_status_not_present, conflict, work_items, scratch_pool);
}
-/* Baton for db_base_remove */
-struct base_remove_baton
-{
- svn_wc__db_t *db; /* For checking conflicts */
- svn_boolean_t keep_as_working;
- svn_revnum_t not_present_revision;
- svn_skel_t *conflict;
- svn_skel_t *work_items;
-};
-
-/* This implements svn_wc__db_txn_callback_t */
+/* The body of svn_wc__db_base_remove().
+ */
static svn_error_t *
-db_base_remove(void *baton,
- svn_wc__db_wcroot_t *wcroot,
+db_base_remove(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ svn_wc__db_t *db, /* For checking conflicts */
+ svn_boolean_t keep_as_working,
+ svn_revnum_t not_present_revision,
+ svn_skel_t *conflict,
+ svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- struct base_remove_baton *rb = baton;
svn_wc__db_status_t status;
apr_int64_t repos_id;
const char *repos_relpath;
@@ -2087,14 +2103,14 @@ db_base_remove(void *baton,
SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, NULL,
&repos_relpath, &repos_id,
NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
wcroot, local_relpath,
scratch_pool, scratch_pool));
if (status == svn_wc__db_status_normal
- && rb->keep_as_working)
+ && keep_as_working)
{
- SVN_ERR(svn_wc__db_op_make_copy(rb->db,
+ SVN_ERR(svn_wc__db_op_make_copy(db,
svn_dirent_join(wcroot->abspath,
local_relpath,
scratch_pool),
@@ -2148,12 +2164,12 @@ db_base_remove(void *baton,
if (node_kind == svn_kind_dir)
SVN_ERR(svn_wc__wq_build_dir_remove(&work_item,
- rb->db, wcroot->abspath,
+ db, wcroot->abspath,
node_abspath, FALSE,
iterpool, iterpool));
else
SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
- rb->db,
+ db,
wcroot->abspath,
node_abspath,
iterpool, iterpool));
@@ -2166,14 +2182,14 @@ db_base_remove(void *baton,
SVN_ERR(svn_sqlite__reset(stmt));
SVN_ERR(svn_wc__wq_build_dir_remove(&work_item,
- rb->db, wcroot->abspath,
+ db, wcroot->abspath,
local_abspath, FALSE,
scratch_pool, iterpool));
svn_pool_destroy(iterpool);
}
else
SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
- rb->db, wcroot->abspath,
+ db, wcroot->abspath,
local_abspath,
scratch_pool, scratch_pool));
@@ -2190,7 +2206,7 @@ db_base_remove(void *baton,
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
}
- else if (! rb->keep_as_working)
+ else if (! keep_as_working)
{
/* Delete only the ACTUAL nodes that apply to a delete of a BASE node */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -2229,7 +2245,8 @@ db_base_remove(void *baton,
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
- SVN_ERR(retract_parent_delete(wcroot, local_relpath, scratch_pool));
+ SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, 0,
+ scratch_pool));
/* Step 6: Delete actual node if we don't keep working */
if (! keep_working)
@@ -2240,7 +2257,7 @@ db_base_remove(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
- if (SVN_IS_VALID_REVNUM(rb->not_present_revision))
+ if (SVN_IS_VALID_REVNUM(not_present_revision))
{
struct insert_base_baton_t ibb;
blank_ibb(&ibb);
@@ -2249,7 +2266,7 @@ db_base_remove(void *baton,
ibb.status = svn_wc__db_status_not_present;
ibb.kind = kind;
ibb.repos_relpath = repos_relpath;
- ibb.revision = rb->not_present_revision;
+ ibb.revision = not_present_revision;
/* Depending upon KIND, any of these might get used. */
ibb.children = NULL;
@@ -2260,9 +2277,10 @@ db_base_remove(void *baton,
SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
}
- SVN_ERR(add_work_items(wcroot->sdb, rb->work_items, scratch_pool));
- if (rb->conflict)
- SVN_ERR(mark_conflict(wcroot, local_relpath, rb->conflict, 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,
+ conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -2279,7 +2297,6 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- struct base_remove_baton rb;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -2287,14 +2304,10 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- rb.db = db;
- rb.keep_as_working = keep_as_working;
- rb.not_present_revision = not_present_revision;
- rb.conflict = conflict;
- rb.work_items = work_items;
-
- SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_base_remove, &rb,
- scratch_pool));
+ SVN_WC__DB_WITH_TXN(db_base_remove(wcroot, local_relpath,
+ db, keep_as_working, not_present_revision,
+ conflict, work_items, scratch_pool),
+ wcroot);
/* If this used to be a directory we should remove children so pass
* depth infinity. */
@@ -2319,6 +2332,7 @@ svn_wc__db_base_get_info_internal(svn_wc
const char **target,
svn_wc__db_lock_t **lock,
svn_boolean_t *had_props,
+ apr_hash_t **props,
svn_boolean_t *update_root,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
@@ -2337,8 +2351,9 @@ svn_wc__db_base_get_info_internal(svn_wc
if (have_row)
{
- svn_kind_t node_kind = svn_sqlite__column_token(stmt, 3,
- kind_map);
+ svn_wc__db_status_t node_status = svn_sqlite__column_token(stmt, 2,
+ presence_map);
+ svn_kind_t node_kind = svn_sqlite__column_token(stmt, 3, kind_map);
if (kind)
{
@@ -2346,10 +2361,10 @@ svn_wc__db_base_get_info_internal(svn_wc
}
if (status)
{
- *status = svn_sqlite__column_token(stmt, 2, presence_map);
+ *status = node_status;
}
- err = repos_location_from_columns(repos_id, revision, repos_relpath,
- stmt, 0, 4, 1, result_pool);
+ repos_location_from_columns(repos_id, revision, repos_relpath,
+ stmt, 0, 4, 1, result_pool);
SVN_ERR_ASSERT(!repos_id || *repos_id != INVALID_REPOS_ID);
SVN_ERR_ASSERT(!repos_relpath || *repos_relpath);
if (lock)
@@ -2377,12 +2392,8 @@ svn_wc__db_base_get_info_internal(svn_wc
}
else
{
- const char *depth_str = svn_sqlite__column_text(stmt, 10, NULL);
-
- if (depth_str == NULL)
- *depth = svn_depth_unknown;
- else
- *depth = svn_depth_from_word(depth_str);
+ *depth = svn_sqlite__column_token_null(stmt, 10, depth_map,
+ svn_depth_unknown);
}
}
if (checksum)
@@ -2414,8 +2425,25 @@ svn_wc__db_base_get_info_internal(svn_wc
{
*had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 13);
}
+ if (props)
+ {
+ if (node_status == svn_wc__db_status_normal
+ || node_status == svn_wc__db_status_incomplete)
+ {
+ SVN_ERR(svn_sqlite__column_properties(props, stmt, 13,
+ result_pool, scratch_pool));
+ if (*props == NULL)
+ *props = apr_hash_make(result_pool);
+ }
+ else
+ {
+ assert(svn_sqlite__column_is_null(stmt, 13));
+ *props = NULL;
+ }
+ }
if (update_root)
{
+ /* It's an update root iff it's a file external. */
*update_root = svn_sqlite__column_boolean(stmt, 14);
}
}
@@ -2447,6 +2475,7 @@ svn_wc__db_base_get_info(svn_wc__db_stat
const char **target,
svn_wc__db_lock_t **lock,
svn_boolean_t *had_props,
+ apr_hash_t **props,
svn_boolean_t *update_root,
svn_wc__db_t *db,
const char *local_abspath,
@@ -2468,7 +2497,7 @@ svn_wc__db_base_get_info(svn_wc__db_stat
changed_rev, changed_date,
changed_author, depth,
checksum, target, lock,
- had_props, update_root,
+ had_props, props, update_root,
wcroot, local_relpath,
result_pool, scratch_pool));
SVN_ERR_ASSERT(repos_id != INVALID_REPOS_ID);
@@ -2509,7 +2538,6 @@ svn_wc__db_base_get_children_info(apr_ha
struct svn_wc__db_base_info_t *info;
svn_error_t *err;
apr_int64_t repos_id;
- const char *depth_str;
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
const char *name = svn_relpath_basename(child_relpath, result_pool);
@@ -2521,10 +2549,8 @@ svn_wc__db_base_get_children_info(apr_ha
info->kind = svn_sqlite__column_token(stmt, 4, kind_map);
info->revnum = svn_sqlite__column_revnum(stmt, 5);
- depth_str = svn_sqlite__column_text(stmt, 6, NULL);
-
- info->depth = (depth_str != NULL) ? svn_depth_from_word(depth_str)
- : svn_depth_unknown;
+ info->depth = svn_sqlite__column_token_null(stmt, 6, depth_map,
+ svn_depth_unknown);
info->update_root = svn_sqlite__column_boolean(stmt, 7);
@@ -2557,32 +2583,24 @@ svn_wc__db_base_get_props(apr_hash_t **p
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
- svn_error_t *err;
+ svn_wc__db_status_t presence;
- SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
- STMT_SELECT_BASE_PROPS, scratch_pool));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (!have_row)
+ SVN_ERR(svn_wc__db_base_get_info(&presence, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, props, NULL,
+ db, local_abspath,
+ result_pool, scratch_pool));
+ if (presence != svn_wc__db_status_normal
+ && presence != svn_wc__db_status_incomplete)
{
- err = svn_sqlite__reset(stmt);
- return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, err,
- _("The node '%s' was not found."),
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+ _("The node '%s' has a BASE status that"
+ " has no properties."),
svn_dirent_local_style(local_abspath,
scratch_pool));
}
- err = svn_sqlite__column_properties(props, stmt, 0, result_pool,
- scratch_pool);
- if (err == NULL && *props == NULL)
- {
- /* ### is this a DB constraint violation? the column "probably" should
- ### never be null. */
- *props = apr_hash_make(result_pool);
- }
-
- return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+ return SVN_NO_ERROR;
}
@@ -2697,6 +2715,7 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
const svn_checksum_t **checksum,
const char **target,
svn_boolean_t *had_props,
+ apr_hash_t **props,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
int op_depth,
@@ -2715,8 +2734,9 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
if (have_row)
{
- svn_kind_t node_kind = svn_sqlite__column_token(stmt, 3,
- kind_map);
+ svn_wc__db_status_t node_status = svn_sqlite__column_token(stmt, 2,
+ presence_map);
+ svn_kind_t node_kind = svn_sqlite__column_token(stmt, 3, kind_map);
if (kind)
{
@@ -2724,13 +2744,13 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
}
if (status)
{
- *status = svn_sqlite__column_token(stmt, 2, presence_map);
+ *status = node_status;
if (op_depth > 0)
SVN_ERR(convert_to_working_status(status, *status));
}
- err = repos_location_from_columns(repos_id, revision, repos_relpath,
- stmt, 0, 4, 1, result_pool);
+ repos_location_from_columns(repos_id, revision, repos_relpath,
+ stmt, 0, 4, 1, result_pool);
if (changed_rev)
{
@@ -2753,12 +2773,8 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
}
else
{
- const char *depth_str = svn_sqlite__column_text(stmt, 10, NULL);
-
- if (depth_str == NULL)
- *depth = svn_depth_unknown;
- else
- *depth = svn_depth_from_word(depth_str);
+ *depth = svn_sqlite__column_token_null(stmt, 10, depth_map,
+ svn_depth_unknown);
}
}
if (checksum)
@@ -2790,6 +2806,22 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
{
*had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 13);
}
+ if (props)
+ {
+ if (node_status == svn_wc__db_status_normal
+ || node_status == svn_wc__db_status_incomplete)
+ {
+ SVN_ERR(svn_sqlite__column_properties(props, stmt, 13,
+ result_pool, scratch_pool));
+ if (*props == NULL)
+ *props = apr_hash_make(result_pool);
+ }
+ else
+ {
+ assert(svn_sqlite__column_is_null(stmt, 13));
+ *props = NULL;
+ }
+ }
}
else
{
@@ -2804,11 +2836,7 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
}
-/* Helper for creating SQLite triggers, running the main transaction
- callback, and then dropping the triggers. It guarantees that the
- triggers will not survive the transaction. This could be used for
- any general prefix/postscript statements where the postscript
- *must* be executed if the transaction completes. */
+/* Baton for passing args to with_triggers(). */
struct with_triggers_baton_t {
int create_trigger;
int drop_trigger;
@@ -2816,7 +2844,13 @@ struct with_triggers_baton_t {
void *cb_baton;
};
-/* conforms to svn_wc__db_txn_callback_t */
+/* Helper for creating SQLite triggers, running the main transaction
+ callback, and then dropping the triggers. It guarantees that the
+ triggers will not survive the transaction. This could be used for
+ any general prefix/postscript statements where the postscript
+ *must* be executed if the transaction completes.
+
+ Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
with_triggers(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -2895,6 +2929,8 @@ with_finalization(svn_wc__db_wcroot_t *w
}
+/* Initialize the baton with appropriate "blank" values. This allows the
+ insertion function to leave certain columns null. */
static void
blank_ieb(insert_external_baton_t *ieb)
{
@@ -2907,6 +2943,9 @@ blank_ieb(insert_external_baton_t *ieb)
ieb->recorded_revision = SVN_INVALID_REVNUM;
}
+/* Insert the externals row represented by (insert_external_baton_t *) BATON.
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
insert_external_node(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -2929,7 +2968,7 @@ insert_external_node(void *baton,
/* And there must be no existing BASE node or it must be a file external */
err = svn_wc__db_base_get_info_internal(&status, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, &update_root,
+ NULL, NULL, NULL, NULL, &update_root,
wcroot, local_relpath,
scratch_pool, scratch_pool);
if (err)
@@ -3246,25 +3285,21 @@ svn_wc__db_external_add_dir(svn_wc__db_t
&ieb, scratch_pool));
}
-/* Baton for db_external_remove */
-struct external_remove_baton
-{
- const svn_skel_t *work_items;
-};
-
+/* The body of svn_wc__db_external_remove(). */
static svn_error_t *
-db_external_remove(void *baton, svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath, apr_pool_t *scratch_pool)
+db_external_remove(const svn_skel_t *work_items,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
- struct external_remove_baton *rb = baton;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_DELETE_EXTERNAL));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
- SVN_ERR(add_work_items(wcroot->sdb, rb->work_items, scratch_pool));
+ SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
/* ### What about actual? */
return SVN_NO_ERROR;
@@ -3279,7 +3314,6 @@ svn_wc__db_external_remove(svn_wc__db_t
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- struct external_remove_baton rb;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -3294,9 +3328,9 @@ svn_wc__db_external_remove(svn_wc__db_t
local_relpath = svn_dirent_skip_ancestor(wcroot->abspath, local_abspath);
- rb.work_items = work_items;
- SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_external_remove,
- &rb, scratch_pool));
+ SVN_WC__DB_WITH_TXN(db_external_remove(work_items, wcroot, local_relpath,
+ scratch_pool),
+ wcroot);
return SVN_NO_ERROR;
}
@@ -3552,15 +3586,14 @@ svn_wc__db_externals_gather_definitions(
if (depths)
{
- const char *depth_word = svn_sqlite__column_text(stmt, 2, NULL);
- svn_depth_t depth = svn_depth_unknown;
-
- if (depth_word)
- depth = svn_depth_from_word(depth_word);
+ svn_depth_t depth
+ = svn_sqlite__column_token_null(stmt, 2, depth_map,
+ svn_depth_unknown);
apr_hash_set(*depths, node_abspath,
APR_HASH_KEY_STRING,
- svn_depth_to_word(depth)); /* Use static string */
+ svn_token__to_word(depth_map,
+ depth)); /* Use static string */
}
}
@@ -3781,7 +3814,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
copyfrom_relpath,
copyfrom_id, NULL, NULL,
NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
wcroot, local_relpath,
result_pool,
scratch_pool));
@@ -3802,15 +3835,44 @@ get_info_for_copy(apr_int64_t *copyfrom_
}
-/* Forward declarations for db_op_copy() to use.
-
- ### these are just to avoid churn. a future commit should shuffle the
- ### functions around. */
+/* Set *OP_DEPTH to the highest op depth of WCROOT:LOCAL_RELPATH. */
static svn_error_t *
op_depth_of(int *op_depth,
svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath);
+ const char *local_relpath)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ 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_ASSERT(have_row);
+ *op_depth = svn_sqlite__column_int(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
+
+
+/* Determine at which OP_DEPTH a copy of COPYFROM_REPOS_ID, COPYFROM_RELPATH at
+ revision COPYFROM_REVISION should be inserted as LOCAL_RELPATH. Do this
+ by checking if this would be a direct child of a copy of its parent
+ directory. If it is then set *OP_DEPTH to the op_depth of its parent.
+
+ If the node is not a direct copy at the same revision of the parent
+ *NP_OP_DEPTH will be set to the op_depth of the parent when a not-present
+ node should be inserted at this op_depth. This will be the case when the
+ parent already defined an incomplete child with the same name. Otherwise
+ *NP_OP_DEPTH will be set to -1.
+
+ If the parent node is not the parent of the to be copied node, then
+ *OP_DEPTH will be set to the proper op_depth for a new operation root.
+
+ Set *PARENT_OP_DEPTH to the op_depth of the parent.
+
+ */
static svn_error_t *
op_depth_for_copy(int *op_depth,
int *np_op_depth,
@@ -3820,7 +3882,86 @@ op_depth_for_copy(int *op_depth,
svn_revnum_t copyfrom_revision,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
- apr_pool_t *scratch_pool);
+ apr_pool_t *scratch_pool)
+{
+ const char *parent_relpath, *name;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ int incomplete_op_depth = -1;
+ int min_op_depth = 1; /* Never touch BASE */
+
+ *op_depth = relpath_depth(local_relpath);
+ *np_op_depth = -1;
+
+ svn_relpath_split(&parent_relpath, &name, local_relpath, scratch_pool);
+ *parent_op_depth = relpath_depth(parent_relpath);
+
+ if (!copyfrom_relpath)
+ return SVN_NO_ERROR;
+
+ 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(&have_row, stmt));
+ if (have_row)
+ {
+ svn_wc__db_status_t status = svn_sqlite__column_token(stmt, 1,
+ presence_map);
+
+ min_op_depth = svn_sqlite__column_int(stmt, 0);
+ if (status == svn_wc__db_status_incomplete)
+ incomplete_op_depth = min_op_depth;
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, parent_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ {
+ svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 1,
+ presence_map);
+
+ *parent_op_depth = svn_sqlite__column_int(stmt, 0);
+ if (*parent_op_depth < min_op_depth)
+ {
+ /* We want to create a copy; not overwrite the lower layers */
+ SVN_ERR(svn_sqlite__reset(stmt));
+ return SVN_NO_ERROR;
+ }
+
+ /* You can only add children below a node that exists.
+ In WORKING that must be status added, which is represented
+ as presence normal */
+ SVN_ERR_ASSERT(presence == svn_wc__db_status_normal);
+
+ if ((incomplete_op_depth < 0)
+ || (incomplete_op_depth == *parent_op_depth))
+ {
+ apr_int64_t parent_copyfrom_repos_id
+ = svn_sqlite__column_int64(stmt, 10);
+ const char *parent_copyfrom_relpath
+ = svn_sqlite__column_text(stmt, 11, NULL);
+ svn_revnum_t parent_copyfrom_revision
+ = svn_sqlite__column_revnum(stmt, 12);
+
+ if (parent_copyfrom_repos_id == copyfrom_repos_id)
+ {
+ if (copyfrom_revision == parent_copyfrom_revision
+ && !strcmp(copyfrom_relpath,
+ svn_relpath_join(parent_copyfrom_relpath, name,
+ scratch_pool)))
+ *op_depth = *parent_op_depth;
+ else if (incomplete_op_depth > 0)
+ *np_op_depth = incomplete_op_depth;
+ }
+ }
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
/* Like svn_wc__db_op_copy(), but with WCROOT+LOCAL_RELPATH
@@ -4070,7 +4211,7 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro
return SVN_NO_ERROR;
}
-/* Baton for op_copy_txn */
+/* Baton for passing args to op_copy_txn(). */
struct op_copy_baton
{
svn_wc__db_wcroot_t *src_wcroot;
@@ -4085,10 +4226,13 @@ struct op_copy_baton
const char *dst_op_root_relpath;
};
-/* Helper for svn_wc__db_op_copy.
- Implements svn_sqlite__transaction_callback_t */
+/* Helper for svn_wc__db_op_copy().
+ *
+ * Implements svn_sqlite__transaction_callback_t. */
static svn_error_t *
-op_copy_txn(void * baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
+op_copy_txn(void * baton,
+ svn_sqlite__db_t *sdb,
+ apr_pool_t *scratch_pool)
{
struct op_copy_baton *ocb = baton;
int move_op_depth;
@@ -4191,7 +4335,8 @@ db_op_copy_shadowed_layer(svn_wc__db_wcr
svn_error_t *err;
err = svn_wc__db_depth_get_info(&status, &kind, &node_revision,
&node_repos_relpath, &node_repos_id,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL,
src_wcroot, src_relpath, src_op_depth,
scratch_pool, scratch_pool);
@@ -4361,10 +4506,12 @@ db_op_copy_shadowed_layer(svn_wc__db_wcr
return SVN_NO_ERROR;
}
-/* Helper for svn_wc__db_op_copy_shadowed_layer.
- Implements svn_sqlite__transaction_callback_t */
+/* Helper for svn_wc__db_op_copy_shadowed_layer().
+ *
+ * Implements svn_sqlite__transaction_callback_t. */
static svn_error_t *
-op_copy_shadowed_layer_txn(void * baton, svn_sqlite__db_t *sdb,
+op_copy_shadowed_layer_txn(void *baton,
+ svn_sqlite__db_t *sdb,
apr_pool_t *scratch_pool)
{
struct op_copy_baton *ocb = baton;
@@ -4408,7 +4555,8 @@ op_copy_shadowed_layer_txn(void * baton,
/* Get some information from the parent */
SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, &revision, &repos_relpath,
&repos_id, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, ocb->src_wcroot,
+ NULL, NULL, NULL,
+ ocb->src_wcroot,
src_parent_relpath, src_op_depth,
scratch_pool, scratch_pool));
@@ -4474,162 +4622,33 @@ svn_wc__db_op_copy_shadowed_layer(svn_wc
}
-/* Set *OP_DEPTH to the highest op depth of WCROOT:LOCAL_RELPATH. */
-static svn_error_t *
-op_depth_of(int *op_depth,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
-
- 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_ASSERT(have_row);
- *op_depth = svn_sqlite__column_int(stmt, 0);
- SVN_ERR(svn_sqlite__reset(stmt));
-
- return SVN_NO_ERROR;
-}
-
-
/* If there are any server-excluded base nodes then the copy must fail
as it's not possible to commit such a copy.
Return an error if there are any server-excluded nodes. */
static svn_error_t *
catch_copy_of_server_excluded(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
- const char *server_excluded_relpath;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_HAS_SERVER_EXCLUDED_DESCENDANTS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is",
- wcroot->wc_id,
- local_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (have_row)
- server_excluded_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
- SVN_ERR(svn_sqlite__reset(stmt));
- if (have_row)
- return svn_error_createf(SVN_ERR_AUTHZ_UNREADABLE, NULL,
- _("Cannot copy '%s' excluded by server"),
- path_for_error_message(wcroot,
- server_excluded_relpath,
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-
-/* Determine at which OP_DEPTH a copy of COPYFROM_REPOS_ID, COPYFROM_RELPATH at
- revision COPYFROM_REVISION should be inserted as LOCAL_RELPATH. Do this
- by checking if this would be a direct child of a copy of its parent
- directory. If it is then set *OP_DEPTH to the op_depth of its parent.
-
- If the node is not a direct copy at the same revision of the parent
- *NP_OP_DEPTH will be set to the op_depth of the parent when a not-present
- node should be inserted at this op_depth. This will be the case when the
- parent already defined an incomplete child with the same name. Otherwise
- *NP_OP_DEPTH will be set to -1.
-
- If the parent node is not the parent of the to be copied node, then
- *OP_DEPTH will be set to the proper op_depth for a new operation root.
-
- Set *PARENT_OP_DEPTH to the op_depth of the parent.
-
- */
-static svn_error_t *
-op_depth_for_copy(int *op_depth,
- int *np_op_depth,
- int *parent_op_depth,
- apr_int64_t copyfrom_repos_id,
- const char *copyfrom_relpath,
- svn_revnum_t copyfrom_revision,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
{
- const char *parent_relpath, *name;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- int incomplete_op_depth = -1;
- int min_op_depth = 1; /* Never touch BASE */
-
- *op_depth = relpath_depth(local_relpath);
- *np_op_depth = -1;
-
- svn_relpath_split(&parent_relpath, &name, local_relpath, scratch_pool);
- *parent_op_depth = relpath_depth(parent_relpath);
-
- if (!copyfrom_relpath)
- return SVN_NO_ERROR;
+ const char *server_excluded_relpath;
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));
+ STMT_HAS_SERVER_EXCLUDED_DESCENDANTS));
+ 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 status = svn_sqlite__column_token(stmt, 1,
- presence_map);
-
- min_op_depth = svn_sqlite__column_int(stmt, 0);
- if (status == svn_wc__db_status_incomplete)
- incomplete_op_depth = min_op_depth;
- }
+ server_excluded_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
SVN_ERR(svn_sqlite__reset(stmt));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, parent_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (have_row)
- {
- svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 1,
- presence_map);
-
- *parent_op_depth = svn_sqlite__column_int(stmt, 0);
- if (*parent_op_depth < min_op_depth)
- {
- /* We want to create a copy; not overwrite the lower layers */
- SVN_ERR(svn_sqlite__reset(stmt));
- return SVN_NO_ERROR;
- }
-
- /* You can only add children below a node that exists.
- In WORKING that must be status added, which is represented
- as presence normal */
- SVN_ERR_ASSERT(presence == svn_wc__db_status_normal);
-
- if ((incomplete_op_depth < 0)
- || (incomplete_op_depth == *parent_op_depth))
- {
- apr_int64_t parent_copyfrom_repos_id
- = svn_sqlite__column_int64(stmt, 10);
- const char *parent_copyfrom_relpath
- = svn_sqlite__column_text(stmt, 11, NULL);
- svn_revnum_t parent_copyfrom_revision
- = svn_sqlite__column_revnum(stmt, 12);
-
- if (parent_copyfrom_repos_id == copyfrom_repos_id)
- {
- if (copyfrom_revision == parent_copyfrom_revision
- && !strcmp(copyfrom_relpath,
- svn_relpath_join(parent_copyfrom_relpath, name,
- scratch_pool)))
- *op_depth = *parent_op_depth;
- else if (incomplete_op_depth > 0)
- *np_op_depth = incomplete_op_depth;
- }
- }
- }
- SVN_ERR(svn_sqlite__reset(stmt));
+ return svn_error_createf(SVN_ERR_AUTHZ_UNREADABLE, NULL,
+ _("Cannot copy '%s' excluded by server"),
+ path_for_error_message(wcroot,
+ server_excluded_relpath,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -4868,6 +4887,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
svn_error_t *
svn_wc__db_op_add_directory(svn_wc__db_t *db,
const char *local_abspath,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -4891,6 +4911,11 @@ svn_wc__db_op_add_directory(svn_wc__db_t
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_kind_dir;
iwb.op_depth = relpath_depth(local_relpath);
+ if (props && apr_hash_count((apr_hash_t *)props))
+ {
+ iwb.update_actual_props = TRUE;
+ iwb.new_actual_props = props;
+ }
iwb.work_items = work_items;
@@ -4908,6 +4933,7 @@ svn_wc__db_op_add_directory(svn_wc__db_t
svn_error_t *
svn_wc__db_op_add_file(svn_wc__db_t *db,
const char *local_abspath,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -4931,6 +4957,11 @@ svn_wc__db_op_add_file(svn_wc__db_t *db,
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_kind_file;
iwb.op_depth = relpath_depth(local_relpath);
+ if (props && apr_hash_count((apr_hash_t *)props))
+ {
+ iwb.update_actual_props = TRUE;
+ iwb.new_actual_props = props;
+ }
iwb.work_items = work_items;
@@ -4946,6 +4977,7 @@ svn_error_t *
svn_wc__db_op_add_symlink(svn_wc__db_t *db,
const char *local_abspath,
const char *target,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -4972,6 +5004,11 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_kind_symlink;
iwb.op_depth = relpath_depth(local_relpath);
+ if (props && apr_hash_count((apr_hash_t *)props))
+ {
+ iwb.update_actual_props = TRUE;
+ iwb.new_actual_props = props;
+ }
iwb.target = target;
@@ -4984,13 +5021,14 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
return SVN_NO_ERROR;
}
+/* Baton for passing args to db_record_fileinfo(). */
struct record_baton_t {
- svn_filesize_t translated_size;
- apr_time_t last_mod_time;
+ svn_filesize_t recorded_size;
+ apr_time_t recorded_time;
};
-/* Record TRANSLATED_SIZE and LAST_MOD_TIME into top layer in NODES */
+/* Record RECORDED_SIZE and RECORDED_TIME into top layer in NODES */
static svn_error_t *
db_record_fileinfo(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -5004,7 +5042,7 @@ db_record_fileinfo(void *baton,
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_UPDATE_NODE_FILEINFO));
SVN_ERR(svn_sqlite__bindf(stmt, "isii", wcroot->wc_id, local_relpath,
- rb->translated_size, rb->last_mod_time));
+ rb->recorded_size, rb->recorded_time));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
SVN_ERR_ASSERT(affected_rows == 1);
@@ -5016,8 +5054,8 @@ db_record_fileinfo(void *baton,
svn_error_t *
svn_wc__db_global_record_fileinfo(svn_wc__db_t *db,
const char *local_abspath,
- svn_filesize_t translated_size,
- apr_time_t last_mod_time,
+ svn_filesize_t recorded_size,
+ apr_time_t recorded_time,
apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
@@ -5030,8 +5068,8 @@ svn_wc__db_global_record_fileinfo(svn_wc
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- rb.translated_size = translated_size;
- rb.last_mod_time = last_mod_time;
+ rb.recorded_size = recorded_size;
+ rb.recorded_time = recorded_time;
SVN_ERR(db_record_fileinfo(&rb, wcroot, local_relpath, scratch_pool));
@@ -5042,18 +5080,12 @@ svn_wc__db_global_record_fileinfo(svn_wc
}
-struct set_props_baton_t
-{
- apr_hash_t *props;
- svn_boolean_t clear_recorded_info;
-
- const svn_skel_t *conflict;
- const svn_skel_t *work_items;
-};
-
-
/* Set the ACTUAL_NODE properties column for (WC_ID, LOCAL_RELPATH) to
- * PROPS. */
+ * PROPS.
+ *
+ * Note: PROPS=NULL means the actual props are the same as the pristine
+ * 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,
const char *local_relpath,
@@ -5085,18 +5117,23 @@ set_actual_props(apr_int64_t wc_id,
}
-/* Set the 'properties' column in the 'ACTUAL_NODE' table to BATON->props.
+/* The body of svn_wc__db_op_set_props().
+
+ Set the 'properties' column in the 'ACTUAL_NODE' table to BATON->props.
Create an entry in the ACTUAL table for the node if it does not yet
have one.
To specify no properties, BATON->props must be an empty hash, not NULL.
- BATON is of type 'struct set_props_baton_t'. */
+ BATON is of type 'struct set_props_baton_t'.
+*/
static svn_error_t *
-set_props_txn(void *baton,
- svn_wc__db_wcroot_t *wcroot,
+set_props_txn(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ apr_hash_t *props,
+ svn_boolean_t clear_recorded_info,
+ const svn_skel_t *conflict,
+ const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
- struct set_props_baton_t *spb = baton;
apr_hash_t *pristine_props;
/* Check if the props are modified. If no changes, then wipe out the
@@ -5104,31 +5141,32 @@ set_props_txn(void *baton,
ACTUAL props are okay as provided, so go ahead and set them. */
SVN_ERR(db_read_pristine_props(&pristine_props, wcroot, local_relpath, FALSE,
scratch_pool, scratch_pool));
- if (spb->props && pristine_props)
+ if (props && pristine_props)
{
apr_array_header_t *prop_diffs;
- SVN_ERR(svn_prop_diffs(&prop_diffs, spb->props, pristine_props,
+ SVN_ERR(svn_prop_diffs(&prop_diffs, props, pristine_props,
scratch_pool));
if (prop_diffs->nelts == 0)
- spb->props = NULL;
+ props = NULL;
}
SVN_ERR(set_actual_props(wcroot->wc_id, local_relpath,
- spb->props, wcroot->sdb, scratch_pool));
+ props, wcroot->sdb, scratch_pool));
- if (spb->clear_recorded_info)
+ if (clear_recorded_info)
{
struct record_baton_t rb;
- rb.translated_size = SVN_INVALID_FILESIZE;
- rb.last_mod_time = 0;
+ rb.recorded_size = SVN_INVALID_FILESIZE;
+ rb.recorded_time = 0;
SVN_ERR(db_record_fileinfo(&rb, wcroot, local_relpath, scratch_pool));
}
/* And finally. */
- SVN_ERR(add_work_items(wcroot->sdb, spb->work_items, scratch_pool));
- if (spb->conflict)
- SVN_ERR(mark_conflict(wcroot, local_relpath, spb->conflict, scratch_pool));
+ SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
+ if (conflict)
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -5143,7 +5181,6 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
- struct set_props_baton_t spb;
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
@@ -5153,77 +5190,13 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
db, local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- spb.props = props;
- spb.clear_recorded_info = clear_recorded_info;
- spb.conflict = conflict;
- spb.work_items = work_items;
-
- return svn_error_trace(svn_wc__db_with_txn(wcroot, local_relpath,
- set_props_txn, &spb,
- scratch_pool));
-}
-
-
-#ifdef SVN__SUPPORT_BASE_MERGE
-
-/* Set properties in a given table. The row must exist. */
-static svn_error_t *
-set_properties(svn_wc__db_t *db,
- const char *local_abspath,
- const apr_hash_t *props,
- int stmt_idx,
- const char *table_name,
- apr_pool_t *scratch_pool)
-{
- svn_sqlite__stmt_t *stmt;
- int affected_rows;
-
- SVN_ERR_ASSERT(props != NULL);
-
- SVN_ERR(get_statement_for_path(&stmt, db, local_abspath, stmt_idx,
- scratch_pool));
-
- SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
- SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
-
- if (affected_rows != 1)
- return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
- _("Can't store properties for '%s' in '%s'."),
- svn_dirent_local_style(local_abspath,
- scratch_pool),
- table_name);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_temp_base_set_props(svn_wc__db_t *db,
- const char *local_abspath,
- const apr_hash_t *props,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR(set_properties(db, local_abspath, props,
- STMT_UPDATE_NODE_BASE_PROPS,
- "base node", scratch_pool));
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_temp_working_set_props(svn_wc__db_t *db,
- const char *local_abspath,
- const apr_hash_t *props,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR(set_properties(db, local_abspath, props,
- STMT_UPDATE_NODE_WORKING_PROPS,
- "working node", scratch_pool));
+ SVN_WC__DB_WITH_TXN(set_props_txn(wcroot, local_relpath, props,
+ clear_recorded_info, conflict, work_items,
+ scratch_pool),
+ wcroot);
return SVN_NO_ERROR;
}
-#endif /* SVN__SUPPORT_BASE_MERGE */
-
svn_error_t *
svn_wc__db_op_modified(svn_wc__db_t *db,
@@ -5400,7 +5373,9 @@ struct set_changelist_baton_t
};
-/* */
+/* The main part of svn_wc__db_op_set_changelist().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
set_changelist_txn(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -5458,7 +5433,9 @@ set_changelist_txn(void *baton,
}
-/* Implement work_callback_t. */
+/* Send notifications for svn_wc__db_op_set_changelist().
+ *
+ * Implements work_callback_t. */
static svn_error_t *
do_changelist_notify(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -5554,11 +5531,11 @@ svn_wc__db_op_set_changelist(svn_wc__db_
}
/* Implementation of svn_wc__db_op_mark_conflict() */
-static svn_error_t *
-mark_conflict(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- const svn_skel_t *conflict_skel,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__db_mark_conflict_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const svn_skel_t *conflict_skel,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t got_row;
@@ -5617,7 +5594,8 @@ svn_wc__db_op_mark_conflict(svn_wc__db_t
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- SVN_ERR(mark_conflict(wcroot, local_relpath, conflict_skel, scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ conflict_skel, scratch_pool));
/* ### Should be handled in the same transaction as setting the conflict */
if (work_items)
@@ -5629,24 +5607,18 @@ svn_wc__db_op_mark_conflict(svn_wc__db_t
}
-/* Baton for db_op_mark_resolved */
-struct op_mark_resolved_baton
-{
- svn_boolean_t resolved_text;
- svn_boolean_t resolved_props;
- svn_boolean_t resolved_tree;
- const svn_skel_t *work_items;
- svn_wc__db_t *db;
-};
-
-/* Helper for svn_wc__db_op_mark_resolved */
+/* The body of svn_wc__db_op_mark_resolved().
+ */
static svn_error_t *
-db_op_mark_resolved(void *baton,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
+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)
{
- struct op_mark_resolved_baton *rb = baton;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
int total_affected_rows = 0;
@@ -5690,10 +5662,10 @@ db_op_mark_resolved(void *baton,
SVN_ERR(svn_sqlite__reset(stmt));
SVN_ERR(svn_wc__conflict_skel_resolve(&resolved_all, conflicts,
- rb->db, wcroot->abspath,
- rb->resolved_text,
- rb->resolved_props ? "" : NULL,
- rb->resolved_tree,
+ db, wcroot->abspath,
+ resolved_text,
+ resolved_props ? "" : NULL,
+ resolved_tree,
scratch_pool, scratch_pool));
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -5719,7 +5691,7 @@ db_op_mark_resolved(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
- SVN_ERR(add_work_items(wcroot->sdb, rb->work_items, scratch_pool));
+ SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
return SVN_NO_ERROR;
}
@@ -5735,7 +5707,6 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- struct op_mark_resolved_baton rb;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -5743,14 +5714,11 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- rb.resolved_props = resolved_props;
- rb.resolved_text = resolved_text;
- rb.resolved_tree = resolved_tree;
- rb.work_items = work_items;
- rb.db = db;
-
- SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_op_mark_resolved,
- &rb, scratch_pool));
+ SVN_WC__DB_WITH_TXN(
+ db_op_mark_resolved(wcroot, local_relpath, db,
+ resolved_text, resolved_props, resolved_tree,
+ work_items, scratch_pool),
+ wcroot);
SVN_ERR(flush_entries(wcroot, local_abspath, svn_depth_empty, scratch_pool));
return SVN_NO_ERROR;
@@ -5782,14 +5750,17 @@ clear_moved_to(const char *local_relpath
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_CLEAR_MOVED_TO_RELPATH));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
- moved_from_relpath));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ moved_from_relpath,
+ relpath_depth(moved_from_relpath)));
SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
}
-/* This implements svn_wc__db_txn_callback_t */
+/* One of the two alternative bodies of svn_wc__db_op_revert().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
op_revert_txn(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -5906,7 +5877,9 @@ op_revert_txn(void *baton,
}
-/* This implements svn_wc__db_txn_callback_t */
+/* One of the two alternative bodies of svn_wc__db_op_revert().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
op_revert_recursive_txn(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -6066,29 +6039,26 @@ svn_wc__db_op_revert(svn_wc__db_t *db,
return SVN_NO_ERROR;
}
-struct revert_list_read_baton {
- svn_boolean_t *reverted;
- apr_array_header_t *marker_paths;
- svn_boolean_t *copied_here;
- svn_kind_t *kind;
- apr_pool_t *result_pool;
- svn_wc__db_t *db;
-};
-
+/* The body of svn_wc__db_revert_list_read().
+ */
static svn_error_t *
-revert_list_read(void *baton,
+revert_list_read(svn_boolean_t *reverted,
+ const apr_array_header_t **marker_paths,
+ svn_boolean_t *copied_here,
+ svn_kind_t *kind,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ svn_wc__db_t *db,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- struct revert_list_read_baton *b = baton;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- *(b->reverted) = FALSE;
- b->marker_paths = NULL;
- *(b->copied_here) = FALSE;
- *(b->kind) = svn_kind_unknown;
+ *reverted = FALSE;
+ *marker_paths = NULL;
+ *copied_here = FALSE;
+ *kind = svn_kind_unknown;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_REVERT_LIST));
@@ -6108,35 +6078,32 @@ revert_list_read(void *baton,
scratch_pool);
if (conflict_data)
{
- const apr_array_header_t *marker_paths;
svn_skel_t *conflicts = svn_skel__parse(conflict_data,
conflict_len,
scratch_pool);
- SVN_ERR(svn_wc__conflict_read_markers(&marker_paths,
- b->db, wcroot->abspath,
+ SVN_ERR(svn_wc__conflict_read_markers(marker_paths,
+ db, wcroot->abspath,
conflicts,
- b->result_pool,
+ result_pool,
scratch_pool));
- /* De-const-ify. */
- b->marker_paths = (apr_array_header_t *)marker_paths;
}
if (!svn_sqlite__column_is_null(stmt, 1)) /* notify */
- *(b->reverted) = TRUE;
+ *reverted = TRUE;
SVN_ERR(svn_sqlite__step(&another_row, stmt));
}
if (!is_actual || another_row)
{
- *(b->reverted) = TRUE;
+ *reverted = TRUE;
if (!svn_sqlite__column_is_null(stmt, 4)) /* repos_id */
{
int op_depth = svn_sqlite__column_int(stmt, 3);
- *(b->copied_here) = (op_depth == relpath_depth(local_relpath));
+ *copied_here = (op_depth == relpath_depth(local_relpath));
}
- *(b->kind) = svn_sqlite__column_token(stmt, 2, kind_map);
+ *kind = svn_sqlite__column_token(stmt, 2, kind_map);
}
}
@@ -6165,43 +6132,35 @@ svn_wc__db_revert_list_read(svn_boolean_
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- struct revert_list_read_baton b;
-
- b.reverted = reverted;
- b.copied_here = copied_here;
- b.kind = kind;
- b.result_pool = result_pool;
- b.db = db;
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_wc__db_with_txn(wcroot, local_relpath, revert_list_read, &b,
- scratch_pool));
- *marker_files = b.marker_paths;
+ SVN_WC__DB_WITH_TXN(
+ revert_list_read(reverted, marker_files, copied_here, kind,
+ wcroot, local_relpath, db,
+ result_pool, scratch_pool),
+ wcroot);
return SVN_NO_ERROR;
}
-struct revert_list_read_copied_children_baton {
- const apr_array_header_t **children;
- apr_pool_t *result_pool;
-};
-
+/* The body of svn_wc__db_revert_list_read_copied_children().
+ */
static svn_error_t *
-revert_list_read_copied_children(void *baton,
- svn_wc__db_wcroot_t *wcroot,
+revert_list_read_copied_children(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ const apr_array_header_t **children_p,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- struct revert_list_read_copied_children_baton *b = baton;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
apr_array_header_t *children;
children =
- apr_array_make(b->result_pool, 0,
+ apr_array_make(result_pool, 0,
sizeof(svn_wc__db_revert_list_copied_child_info_t *));
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -6214,11 +6173,11 @@ revert_list_read_copied_children(void *b
svn_wc__db_revert_list_copied_child_info_t *child_info;
const char *child_relpath;
- child_info = apr_palloc(b->result_pool, sizeof(*child_info));
+ child_info = apr_palloc(result_pool, sizeof(*child_info));
child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
child_info->abspath = svn_dirent_join(wcroot->abspath, child_relpath,
- b->result_pool);
+ result_pool);
child_info->kind = svn_sqlite__column_token(stmt, 1, kind_map);
APR_ARRAY_PUSH(
children,
@@ -6228,7 +6187,7 @@ revert_list_read_copied_children(void *b
}
SVN_ERR(svn_sqlite__reset(stmt));
- *b->children = children;
+ *children_p = children;
return SVN_NO_ERROR;
}
@@ -6243,18 +6202,15 @@ svn_wc__db_revert_list_read_copied_child
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- struct revert_list_read_copied_children_baton b;
-
- b.children = children;
- b.result_pool = result_pool;
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_wc__db_with_txn(wcroot, local_relpath,
- revert_list_read_copied_children, &b,
- scratch_pool));
+ SVN_WC__DB_WITH_TXN(
+ revert_list_read_copied_children(wcroot, local_relpath, children,
+ result_pool, scratch_pool),
+ wcroot);
return SVN_NO_ERROR;
}
@@ -6327,30 +6283,24 @@ svn_wc__db_revert_list_done(svn_wc__db_t
return SVN_NO_ERROR;
}
-/* Baton for remove_node_txn */
-struct remove_node_baton
-{
- svn_wc__db_t *db;
- svn_boolean_t left_changes;
- 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_kind_t not_present_kind;
- const svn_skel_t *conflict;
- const svn_skel_t *work_items;
- svn_cancel_func_t cancel_func;
- void *cancel_baton;
-};
-
-/* Implements svn_wc__db_txn_callback_t for svn_wc__db_op_remove_node */
+/* The body of svn_wc__db_op_remove_node().
+ */
static svn_error_t *
-remove_node_txn(void *baton,
+remove_node_txn(svn_boolean_t *left_changes,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ 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_kind_t not_present_kind,
+ const svn_skel_t *conflict,
+ const svn_skel_t *work_items,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *scratch_pool)
{
- struct remove_node_baton *rnb = baton;
svn_sqlite__stmt_t *stmt;
apr_int64_t repos_id;
@@ -6360,19 +6310,22 @@ remove_node_txn(void *baton,
function to be called on a wcroot! */
/* db set when destroying wc */
- SVN_ERR_ASSERT(!rnb->destroy_wc || rnb->db != NULL);
+ SVN_ERR_ASSERT(!destroy_wc || db != NULL);
+
+ if (left_changes)
+ *left_changes = FALSE;
/* Need info for not_present node? */
- if (SVN_IS_VALID_REVNUM(rnb->not_present_rev))
+ 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, NULL, NULL, NULL, NULL,
wcroot, local_relpath,
scratch_pool, scratch_pool));
- if (rnb->destroy_wc
- && (!rnb->destroy_changes || *local_relpath == '\0'))
+ if (destroy_wc
+ && (!destroy_changes || *local_relpath == '\0'))
{
svn_boolean_t have_row;
apr_pool_t *iterpool;
@@ -6395,7 +6348,7 @@ remove_node_txn(void *baton,
svn_kind_t child_kind;
svn_boolean_t have_checksum;
svn_filesize_t recorded_size;
- apr_int64_t recorded_mod_time;
+ apr_int64_t recorded_time;
const svn_io_dirent2_t *dirent;
svn_boolean_t modified_p = TRUE;
svn_skel_t *work_item = NULL;
@@ -6412,11 +6365,11 @@ remove_node_txn(void *baton,
{
have_checksum = !svn_sqlite__column_is_null(stmt, 2);
recorded_size = get_recorded_size(stmt, 3);
- recorded_mod_time = svn_sqlite__column_int64(stmt, 4);
+ recorded_time = svn_sqlite__column_int64(stmt, 4);
}
- if (rnb->cancel_func)
- err = rnb->cancel_func(rnb->cancel_baton);
+ if (cancel_func)
+ err = cancel_func(cancel_baton);
if (err)
break;
@@ -6427,7 +6380,7 @@ remove_node_txn(void *baton,
if (err)
break;
- if (rnb->destroy_changes
+ if (destroy_changes
|| dirent->kind != svn_node_file
|| child_kind != svn_kind_file)
{
@@ -6437,31 +6390,34 @@ remove_node_txn(void *baton,
else if (child_kind == svn_kind_file
&& dirent->kind == svn_node_file
&& dirent->filesize == recorded_size
- && dirent->mtime == recorded_mod_time)
+ && dirent->mtime == recorded_time)
{
modified_p = FALSE; /* File matches recorded state */
}
else if (have_checksum)
err = svn_wc__internal_file_modified_p(&modified_p,
- rnb->db, child_abspath,
+ db, child_abspath,
FALSE, iterpool);
if (err)
break;
if (modified_p)
- rnb->left_changes = TRUE;
+ {
+ if (left_changes)
+ *left_changes = TRUE;
+ }
else if (child_kind == svn_kind_dir)
{
err = svn_wc__wq_build_dir_remove(&work_item,
- rnb->db, wcroot->abspath,
+ db, wcroot->abspath,
child_abspath, FALSE,
iterpool, iterpool);
}
else /* svn_kind_file || svn_kind_symlink */
{
err = svn_wc__wq_build_file_remove(&work_item,
- rnb->db, wcroot->abspath,
+ db, wcroot->abspath,
child_abspath,
iterpool, iterpool);
}
@@ -6483,7 +6439,7 @@ remove_node_txn(void *baton,
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
}
- if (rnb->destroy_wc && *local_relpath != '\0')
+ if (destroy_wc && *local_relpath != '\0')
{
/* Create work item for destroying the root */
svn_wc__db_status_t status;
@@ -6506,9 +6462,9 @@ remove_node_txn(void *baton,
if (kind == svn_kind_dir)
{
SVN_ERR(svn_wc__wq_build_dir_remove(&work_item,
- rnb->db, wcroot->abspath,
+ db, wcroot->abspath,
local_abspath,
- rnb->destroy_changes
+ destroy_changes
/* recursive */,
scratch_pool, scratch_pool));
}
@@ -6516,23 +6472,25 @@ remove_node_txn(void *baton,
{
svn_boolean_t modified_p = FALSE;
- if (!rnb->destroy_changes)
+ if (!destroy_changes)
{
SVN_ERR(svn_wc__internal_file_modified_p(&modified_p,
- rnb->db,
- local_abspath,
+ db, local_abspath,
FALSE,
scratch_pool));
}
if (!modified_p)
SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
- rnb->db, wcroot->abspath,
+ db, wcroot->abspath,
local_abspath,
scratch_pool,
scratch_pool));
else
- rnb->left_changes = TRUE;
+ {
+ if (left_changes)
+ *left_changes = TRUE;
+ }
[... 3063 lines stripped ...]