You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/12/27 05:03:55 UTC
svn commit: r1426116 [9/16] - in /subversion/branches/javahl-ra: ./ build/
build/ac-macros/ build/generator/ build/win32/
contrib/server-side/svncutter/ notes/ subversion/bindings/cxxhl/
subversion/bindings/swig/ subversion/bindings/swig/perl/native/ s...
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.c Thu Dec 27 04:03:49 2012
@@ -32,6 +32,7 @@
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_hash.h"
+#include "svn_sorts.h"
#include "svn_wc.h"
#include "svn_checksum.h"
#include "svn_pools.h"
@@ -45,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"
@@ -103,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)
@@ -116,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;
@@ -174,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;
@@ -215,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;
@@ -265,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,
@@ -300,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,
@@ -320,6 +298,7 @@ static svn_error_t *
db_read_pristine_props(apr_hash_t **props,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ svn_boolean_t deleted_ok,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
@@ -340,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,
@@ -381,8 +360,20 @@ wclock_owns_lock(svn_boolean_t *own_lock
svn_boolean_t exact,
apr_pool_t *scratch_pool);
+/* Baton for passing args to 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,
+ 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 *
@@ -480,11 +471,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,
@@ -494,8 +485,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. */
@@ -513,8 +502,6 @@ repos_location_from_columns(apr_int64_t
*repos_relpath = svn_sqlite__column_text(stmt, col_repos_relpath,
result_pool);
}
-
- return err;
}
@@ -624,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;
@@ -645,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));
}
}
@@ -675,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;
@@ -698,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,
@@ -709,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. */
@@ -735,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));
}
@@ -753,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 */
@@ -777,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));
@@ -837,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));
}
}
@@ -866,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)
{
@@ -974,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,
@@ -1000,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,
@@ -1023,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));
@@ -1100,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;
}
@@ -1224,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. */
@@ -1377,7 +1422,7 @@ does_node_exist(svn_boolean_t *exists,
return svn_error_trace(svn_sqlite__reset(stmt));
}
-/* baton for init_db */
+/* Baton for passing args to init_db(). */
struct init_db_baton
{
/* output values */
@@ -1391,9 +1436,13 @@ struct init_db_baton
svn_depth_t root_node_depth;
};
-/* Helper for create_db(). Initializes our wc.db schema */
+/* Helper for create_db(). Initializes our wc.db schema.
+ *
+ * Implements svn_sqlite__transaction_callback_t. */
static svn_error_t *
-init_db( void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
+init_db(void *baton,
+ svn_sqlite__db_t *db,
+ apr_pool_t *scratch_pool)
{
struct init_db_baton *idb = baton;
svn_sqlite__stmt_t *stmt;
@@ -1430,7 +1479,8 @@ init_db( void *baton, svn_sqlite__db_t *
idb->root_node_repos_relpath,
idb->root_node_revision,
presence_map, status, /* 8 */
- svn_depth_to_word(idb->root_node_depth),
+ svn_token__to_word(depth_map,
+ idb->root_node_depth),
kind_map, svn_kind_dir /* 10 */));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -1778,6 +1828,7 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
svn_boolean_t delete_working,
svn_boolean_t update_actual_props,
apr_hash_t *new_actual_props,
+ apr_array_header_t *new_iprops,
svn_boolean_t keep_recorded_info,
svn_boolean_t insert_base_deleted,
const svn_skel_t *conflict,
@@ -1821,6 +1872,7 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
ibb.checksum = checksum;
ibb.dav_cache = dav_cache;
+ ibb.iprops = new_iprops;
if (update_actual_props)
{
@@ -1863,6 +1915,7 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
svn_boolean_t delete_working,
svn_boolean_t update_actual_props,
apr_hash_t *new_actual_props,
+ apr_array_header_t *new_iprops,
svn_boolean_t keep_recorded_info,
svn_boolean_t insert_base_deleted,
const svn_skel_t *conflict,
@@ -1905,6 +1958,7 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
ibb.target = target;
ibb.dav_cache = dav_cache;
+ ibb.iprops = new_iprops;
if (update_actual_props)
{
@@ -2041,7 +2095,7 @@ 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 */
+/* Baton for passing args to db_base_remove(). */
struct base_remove_baton
{
svn_wc__db_t *db; /* For checking conflicts */
@@ -2051,7 +2105,9 @@ struct base_remove_baton
svn_skel_t *work_items;
};
-/* This implements svn_wc__db_txn_callback_t */
+/* The body of svn_wc__db_base_remove().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
db_base_remove(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -2070,7 +2126,7 @@ 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));
@@ -2212,7 +2268,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)
@@ -2245,7 +2302,8 @@ db_base_remove(void *baton,
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(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ rb->conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -2302,6 +2360,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,
@@ -2320,8 +2379,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)
{
@@ -2329,10 +2389,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)
@@ -2360,12 +2420,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)
@@ -2397,8 +2453,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);
}
}
@@ -2430,6 +2503,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,
@@ -2451,7 +2525,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);
@@ -2492,7 +2566,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);
@@ -2504,10 +2577,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);
@@ -2540,32 +2611,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;
}
@@ -2680,6 +2743,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,
@@ -2698,8 +2762,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)
{
@@ -2707,13 +2772,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)
{
@@ -2736,12 +2801,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)
@@ -2773,6 +2834,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
{
@@ -2787,11 +2864,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;
@@ -2799,7 +2872,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,
@@ -2878,6 +2957,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)
{
@@ -2890,6 +2971,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,
@@ -2912,7 +2996,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)
@@ -3229,15 +3313,20 @@ svn_wc__db_external_add_dir(svn_wc__db_t
&ieb, scratch_pool));
}
-/* Baton for db_external_remove */
+/* Baton for passing args to db_external_remove(). */
struct external_remove_baton
{
const svn_skel_t *work_items;
};
+/* The body of svn_wc__db_external_remove().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
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(void *baton,
+ 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;
@@ -3535,15 +3624,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 */
}
}
@@ -3636,7 +3724,7 @@ cross_db_copy(svn_wc__db_wcroot_t *src_w
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
src_wcroot, src_relpath, scratch_pool, scratch_pool));
- SVN_ERR(db_read_pristine_props(&props, src_wcroot, src_relpath,
+ SVN_ERR(db_read_pristine_props(&props, src_wcroot, src_relpath, FALSE,
scratch_pool, scratch_pool));
blank_iwb(&iwb);
@@ -3764,7 +3852,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));
@@ -3785,15 +3873,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,
@@ -3803,7 +3920,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
@@ -4053,7 +4249,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;
@@ -4068,10 +4264,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;
@@ -4174,7 +4373,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);
@@ -4344,10 +4544,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;
@@ -4391,7 +4593,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));
@@ -4457,27 +4660,6 @@ 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. */
@@ -4493,126 +4675,18 @@ catch_copy_of_server_excluded(svn_wc__db
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 *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;
- }
- }
- }
+ 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;
}
@@ -4967,13 +5041,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,
@@ -4987,7 +5062,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);
@@ -4999,8 +5074,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;
@@ -5013,8 +5088,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));
@@ -5025,16 +5100,6 @@ 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. */
static svn_error_t *
@@ -5068,11 +5133,27 @@ set_actual_props(apr_int64_t wc_id,
}
-/* Set the 'properties' column in the 'ACTUAL_NODE' table to BATON->props.
+/* Baton for passing args to set_props_txn(). */
+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;
+};
+
+
+/* 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'.
+
+ Implements svn_wc__db_txn_callback_t.
+*/
static svn_error_t *
set_props_txn(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -5085,7 +5166,7 @@ set_props_txn(void *baton,
/* Check if the props are modified. If no changes, then wipe out the
ACTUAL props. PRISTINE_PROPS==NULL means that any
ACTUAL props are okay as provided, so go ahead and set them. */
- SVN_ERR(db_read_pristine_props(&pristine_props, wcroot, local_relpath,
+ SVN_ERR(db_read_pristine_props(&pristine_props, wcroot, local_relpath, FALSE,
scratch_pool, scratch_pool));
if (spb->props && pristine_props)
{
@@ -5103,15 +5184,16 @@ set_props_txn(void *baton,
if (spb->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(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ spb->conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -5147,67 +5229,6 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
}
-#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));
- return SVN_NO_ERROR;
-}
-
-#endif /* SVN__SUPPORT_BASE_MERGE */
-
-
svn_error_t *
svn_wc__db_op_modified(svn_wc__db_t *db,
const char *local_abspath,
@@ -5383,7 +5404,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,
@@ -5441,7 +5464,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,
@@ -5537,11 +5562,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;
@@ -5600,7 +5625,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)
@@ -5612,7 +5638,7 @@ svn_wc__db_op_mark_conflict(svn_wc__db_t
}
-/* Baton for db_op_mark_resolved */
+/* Baton for passing args to db_op_mark_resolved(). */
struct op_mark_resolved_baton
{
svn_boolean_t resolved_text;
@@ -5622,7 +5648,9 @@ struct op_mark_resolved_baton
svn_wc__db_t *db;
};
-/* Helper for svn_wc__db_op_mark_resolved */
+/* The body of svn_wc__db_op_mark_resolved().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
db_op_mark_resolved(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -5772,7 +5800,9 @@ clear_moved_to(const char *local_relpath
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,
@@ -5889,7 +5919,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,
@@ -6049,15 +6081,19 @@ svn_wc__db_op_revert(svn_wc__db_t *db,
return SVN_NO_ERROR;
}
+/* Baton for passing args to revert_list_read(). */
struct revert_list_read_baton {
svn_boolean_t *reverted;
- apr_array_header_t *marker_paths;
+ const 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().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
revert_list_read(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -6091,18 +6127,15 @@ 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,
+ SVN_ERR(svn_wc__conflict_read_markers(&b->marker_paths,
b->db, wcroot->abspath,
conflicts,
b->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 */
@@ -6167,11 +6200,15 @@ svn_wc__db_revert_list_read(svn_boolean_
}
+/* Baton for passing args to revert_list_read_copied_children(). */
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().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
revert_list_read_copied_children(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -6310,7 +6347,7 @@ svn_wc__db_revert_list_done(svn_wc__db_t
return SVN_NO_ERROR;
}
-/* Baton for remove_node_txn */
+/* Baton for passing args to remove_node_txn(). */
struct remove_node_baton
{
svn_wc__db_t *db;
@@ -6326,7 +6363,9 @@ struct remove_node_baton
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().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
remove_node_txn(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -6350,7 +6389,7 @@ remove_node_txn(void *baton,
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));
@@ -6378,7 +6417,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;
@@ -6395,7 +6434,7 @@ 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)
@@ -6420,7 +6459,7 @@ 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 */
}
@@ -6567,7 +6606,8 @@ remove_node_txn(void *baton,
SVN_ERR(add_work_items(wcroot->sdb, rnb->work_items, scratch_pool));
if (rnb->conflict)
- SVN_ERR(mark_conflict(wcroot, local_relpath, rnb->conflict, scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ rnb->conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -6623,7 +6663,7 @@ svn_wc__db_op_remove_node(svn_boolean_t
}
-/* Baton for db_op_set_base_depth */
+/* Baton for passing args to db_op_set_base_depth(). */
struct set_base_depth_baton_t
{
svn_depth_t depth;
@@ -6643,7 +6683,7 @@ db_op_set_base_depth(void *baton,
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_UPDATE_NODE_BASE_DEPTH));
SVN_ERR(svn_sqlite__bindf(stmt, "iss", wcroot->wc_id, local_relpath,
- svn_depth_to_word(sbd->depth)));
+ svn_token__to_word(depth_map, sbd->depth)));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
if (affected_rows == 0)
@@ -7192,7 +7232,8 @@ delete_node(void *baton,
SVN_ERR(add_work_items(wcroot->sdb, b->work_items, scratch_pool));
if (b->conflict)
- SVN_ERR(mark_conflict(wcroot, local_relpath, b->conflict, scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+ b->conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -7471,7 +7512,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,
@@ -7551,9 +7592,8 @@ read_info(svn_wc__db_status_t *status,
WORKING_NODE (and have been added), then the repository
we're being added to will be dependent upon a parent. The
caller can scan upwards to locate the repository. */
- err = svn_error_compose_create(
- err, repos_location_from_columns(repos_id, revision, repos_relpath,
- stmt_info, 1, 5, 2, result_pool));
+ repos_location_from_columns(repos_id, revision, repos_relpath,
+ stmt_info, 1, 5, 2, result_pool);
}
if (changed_rev)
{
@@ -7568,9 +7608,9 @@ read_info(svn_wc__db_status_t *status,
*changed_author = svn_sqlite__column_text(stmt_info, 10,
result_pool);
}
- if (recorded_mod_time)
+ if (recorded_time)
{
- *recorded_mod_time = svn_sqlite__column_int64(stmt_info, 13);
+ *recorded_time = svn_sqlite__column_int64(stmt_info, 13);
}
if (depth)
{
@@ -7580,14 +7620,8 @@ read_info(svn_wc__db_status_t *status,
}
else
{
- const char *depth_str;
-
- depth_str = svn_sqlite__column_text(stmt_info, 11, NULL);
-
- if (depth_str == NULL)
- *depth = svn_depth_unknown;
- else
- *depth = svn_depth_from_word(depth_str);
+ *depth = svn_sqlite__column_token_null(stmt_info, 11, depth_map,
+ svn_depth_unknown);
}
}
if (checksum)
@@ -7633,11 +7667,10 @@ read_info(svn_wc__db_status_t *status,
}
else
{
- err = svn_error_compose_create(
- err, repos_location_from_columns(original_repos_id,
- original_revision,
- original_repos_relpath,
- stmt_info, 1, 5, 2, result_pool));
+ repos_location_from_columns(original_repos_id,
+ original_revision,
+ original_repos_relpath,
+ stmt_info, 1, 5, 2, result_pool);
}
if (props_mod)
{
@@ -7663,7 +7696,7 @@ read_info(svn_wc__db_status_t *status,
if (op_depth != 0)
*lock = NULL;
else
- *lock = lock_from_columns(stmt_info, 16, 17, 18, 19, result_pool);
+ *lock = lock_from_columns(stmt_info, 17, 18, 19, 20, result_pool);
}
if (have_work)
@@ -7750,8 +7783,8 @@ read_info(svn_wc__db_status_t *status,
*lock = NULL;
if (recorded_size)
*recorded_size = 0;
- if (recorded_mod_time)
- *recorded_mod_time = 0;
+ if (recorded_time)
+ *recorded_time = 0;
if (changelist)
*changelist = svn_sqlite__column_text(stmt_act, 0, result_pool);
if (op_root)
@@ -7809,7 +7842,7 @@ svn_wc__db_read_info_internal(svn_wc__db
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,
@@ -7828,7 +7861,7 @@ svn_wc__db_read_info_internal(svn_wc__db
changed_rev, changed_date, changed_author,
depth, checksum, target, original_repos_relpath,
original_repos_id, original_revision, lock,
- recorded_size, recorded_mod_time, changelist, conflicted,
+ recorded_size, recorded_time, changelist, conflicted,
op_root, had_props, props_mod,
have_base, have_more_work, have_work,
wcroot, local_relpath, result_pool, scratch_pool));
@@ -7854,7 +7887,7 @@ svn_wc__db_read_info(svn_wc__db_status_t
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,
@@ -7882,7 +7915,7 @@ svn_wc__db_read_info(svn_wc__db_status_t
changed_rev, changed_date, changed_author,
depth, checksum, target, original_repos_relpath,
&original_repos_id, original_revision, lock,
- recorded_size, recorded_mod_time, changelist, conflicted,
+ recorded_size, recorded_time, changelist, conflicted,
op_root, have_props, props_mod,
have_base, have_more_work, have_work,
wcroot, local_relpath, result_pool, scratch_pool));
@@ -8042,19 +8075,14 @@ read_children_info(void *baton,
child->depth = svn_depth_unknown;
else
{
- const char *depth = svn_sqlite__column_text(stmt, 11,
- scratch_pool);
- if (depth)
- child->depth = svn_depth_from_word(depth);
- else
- child->depth = svn_depth_unknown;
-
+ child->depth = svn_sqlite__column_token_null(stmt, 11, depth_map,
+ svn_depth_unknown);
if (new_child)
SVN_ERR(is_wclocked(&child->locked, wcroot, child_relpath,
scratch_pool));
}
- child->recorded_mod_time = svn_sqlite__column_int64(stmt, 13);
+ child->recorded_time = svn_sqlite__column_int64(stmt, 13);
child->recorded_size = get_recorded_size(stmt, 7);
child->has_checksum = !svn_sqlite__column_is_null(stmt, 6);
child->copied = op_depth > 0 && !svn_sqlite__column_is_null(stmt, 2);
@@ -8210,6 +8238,7 @@ svn_wc__db_read_pristine_info(svn_wc__db
const svn_checksum_t **checksum, /* files only */
const char **target, /* symlinks only */
svn_boolean_t *had_props,
+ apr_hash_t **props,
svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *result_pool,
@@ -8298,14 +8327,8 @@ svn_wc__db_read_pristine_info(svn_wc__db
}
else
{
- const char *depth_str;
-
- depth_str = svn_sqlite__column_text(stmt, 11, NULL);
-
- if (depth_str == NULL)
- *depth = svn_depth_unknown;
- else
- *depth = svn_depth_from_word(depth_str);
+ *depth = svn_sqlite__column_token_null(stmt, 11, depth_map,
+ svn_depth_unknown);
}
}
if (checksum)
@@ -8345,6 +8368,22 @@ svn_wc__db_read_pristine_info(svn_wc__db
{
*had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 14);
}
+ if (props)
+ {
+ if (raw_status == svn_wc__db_status_normal
+ || raw_status == svn_wc__db_status_incomplete)
+ {
+ SVN_ERR(svn_sqlite__column_properties(props, stmt, 14,
+ result_pool, scratch_pool));
+ if (*props == NULL)
+ *props = apr_hash_make(result_pool);
+ }
+ else
+ {
+ assert(svn_sqlite__column_is_null(stmt, 14));
+ *props = NULL;
+ }
+ }
return svn_error_trace(
svn_error_compose_create(err,
@@ -8459,8 +8498,13 @@ svn_wc__db_read_node_install_info(const
err = svn_sqlite__column_checksum(sha1_checksum, stmt, 6, result_pool);
if (!err && pristine_props)
- err = svn_sqlite__column_properties(pristine_props, stmt, 14,
- result_pool, scratch_pool);
+ {
+ err = svn_sqlite__column_properties(pristine_props, stmt, 14,
+ result_pool, scratch_pool);
+ /* Null means no props (assuming presence normal or incomplete). */
+ if (*pristine_props == NULL)
+ *pristine_props = apr_hash_make(result_pool);
+ }
if (changed_date)
*changed_date = svn_sqlite__column_int64(stmt, 9);
@@ -8532,7 +8576,7 @@ read_url_txn(void *baton,
&repos_id,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
wcroot,
base_del_relpath,
scratch_pool,
@@ -8786,7 +8830,7 @@ svn_wc__db_read_props_streamily(svn_wc__
}
-/* Baton for db_read_props */
+/* Baton for passing args to db_read_props(). */
struct db_read_props_baton_t
{
apr_hash_t *props;
@@ -8794,7 +8838,9 @@ struct db_read_props_baton_t
};
-/* Helper for svn_wc__db_read_props(). Implements svn_wc__db_txn_callback_t */
+/* Helper for svn_wc__db_read_props().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
static svn_error_t *
db_read_props(void *baton,
svn_wc__db_wcroot_t *wcroot,
@@ -8825,7 +8871,7 @@ db_read_props(void *baton,
return SVN_NO_ERROR;
/* No local changes. Return the pristine props for this node. */
- SVN_ERR(db_read_pristine_props(&rpb->props, wcroot, local_relpath,
+ SVN_ERR(db_read_pristine_props(&rpb->props, wcroot, local_relpath, FALSE,
rpb->result_pool, scratch_pool));
if (rpb->props == NULL)
{
@@ -8873,6 +8919,7 @@ static svn_error_t *
db_read_pristine_props(apr_hash_t **props,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ svn_boolean_t deleted_ok,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -8900,9 +8947,8 @@ db_read_pristine_props(apr_hash_t **prop
presence = svn_sqlite__column_token(stmt, 1, presence_map);
/* For "base-deleted", it is obvious the pristine props are located
- in the BASE table. Fall through to fetch them.
- ### BH: Is this really the behavior we want here? */
- if (presence == svn_wc__db_status_base_deleted)
+ below the current node. Fetch the NODE from the next record. */
+ if (presence == svn_wc__db_status_base_deleted && deleted_ok)
{
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -8928,8 +8974,13 @@ db_read_pristine_props(apr_hash_t **prop
return SVN_NO_ERROR;
}
- *props = NULL;
- return svn_error_trace(svn_sqlite__reset(stmt));
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+ svn_sqlite__reset(stmt),
+ _("The node '%s' has a status that"
+ " has no properties."),
+ path_for_error_message(wcroot,
+ local_relpath,
+ scratch_pool));
}
@@ -8949,7 +9000,7 @@ svn_wc__db_read_pristine_props(apr_hash_
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- SVN_ERR(db_read_pristine_props(props, wcroot, local_relpath,
+ SVN_ERR(db_read_pristine_props(props, wcroot, local_relpath, TRUE,
result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -8987,127 +9038,349 @@ svn_wc__db_prop_retrieve_recursive(apr_h
apr_hash_t *node_props;
svn_string_t *value;
- svn_pool_clear(iterpool);
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_sqlite__column_properties(&node_props, stmt, 0,
+ iterpool, iterpool));
+
+ value = (node_props
+ ? apr_hash_get(node_props, propname, APR_HASH_KEY_STRING)
+ : NULL);
+
+ if (value)
+ {
+ apr_hash_set(*values,
+ svn_dirent_join(wcroot->abspath,
+ svn_sqlite__column_text(stmt, 1, NULL),
+ result_pool),
+ APR_HASH_KEY_STRING,
+ svn_string_dup(value, result_pool));
+ }
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return svn_error_trace(svn_sqlite__reset(stmt));
+}
+
+/* Baton for passing args to db_read_cached_iprops(). */
+struct read_cached_iprops_baton_t
+{
+ apr_array_header_t *iprops;
+ apr_pool_t *result_pool;
+};
+
+/* The body of svn_wc__db_read_cached_iprops().
+ *
+ * (Not called in a txn, but implements svn_wc__db_txn_callback_t anyway.) */
+static svn_error_t *
+db_read_cached_iprops(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ struct read_cached_iprops_baton_t *rib = baton;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_IPROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (!have_row)
+ {
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+ svn_sqlite__reset(stmt),
+ _("The node '%s' was not found."),
+ path_for_error_message(wcroot, local_relpath,
+ scratch_pool));
+ }
+
+ SVN_ERR(svn_sqlite__column_iprops(&rib->iprops, stmt, 0,
+ rib->result_pool, scratch_pool));
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_read_cached_iprops(apr_array_header_t **iprops,
+ 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;
+ struct read_cached_iprops_baton_t rcib;
+
+ 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);
+
+ rcib.result_pool = result_pool;
+
+ /* Don't use with_txn yet, as we perform just a single transaction */
+ SVN_ERR(db_read_cached_iprops(&rcib, wcroot, local_relpath, scratch_pool));
+
+ if (rcib.iprops)
+ *iprops = rcib.iprops;
+ else
+ {
+ *iprops = apr_array_make(result_pool, 0,
+ sizeof(svn_prop_inherited_item_t *));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Remove all prop name value pairs from PROP_HASH where the property
+ name is not PROPNAME. */
+static void
+filter_unwanted_props(apr_hash_t *prop_hash,
+ const char * propname,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, prop_hash);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *ipropname = svn__apr_hash_index_key(hi);
+
+ if (strcmp(ipropname, propname) != 0)
+ apr_hash_set(prop_hash, ipropname, APR_HASH_KEY_STRING, NULL);
+ }
+ return;
+}
+
+/* Baton for passing args to db_read_inherited_props(). */
+struct read_inherited_props_baton_t
+{
+ apr_array_header_t *iprops;
+ const char *propname;
+ apr_pool_t *result_pool;
+};
+
+/* The body of svn_wc__db_read_inherited_props().
+ *
+ * Implements svn_wc__db_txn_callback_t. */
+static svn_error_t *
+db_read_inherited_props(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ struct read_inherited_props_baton_t *ripb = baton;
+ int i;
+ apr_array_header_t *cached_iprops = NULL;
+ const char *parent_relpath = local_relpath;
+ svn_boolean_t is_wc_root = FALSE;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_pool_t *result_pool = ripb->result_pool;
+
+ ripb->iprops = apr_array_make(ripb->result_pool, 1,
+ sizeof(svn_prop_inherited_item_t *));
+
+ /* Walk up to the root of the WC looking for inherited properties. When we
+ reach the WC root also check for cached inherited properties. */
+ while (TRUE)
+ {
+ apr_hash_t *actual_props;
+ svn_boolean_t is_switched;
+ struct db_is_switched_baton_t swb;
+
+ svn_pool_clear(iterpool);
+
+ swb.is_switched = &is_switched;
+ swb.kind = NULL;
+
+ if (*parent_relpath == '\0')
+ {
+ is_switched = FALSE;
+ is_wc_root = TRUE;
+ }
+ else
+ SVN_ERR(db_is_switched(&swb, wcroot, parent_relpath, scratch_pool));
+
+ if (is_switched || is_wc_root)
+ {
+ struct read_cached_iprops_baton_t rib;
+ is_wc_root = TRUE;
+
+ rib.result_pool = scratch_pool;
+
+ /* If the WC root is also the root of the repository then by
+ definition there are no inheritable properties to be had,
+ but checking for that is just as expensive as fetching them
+ anyway. */
+
+ /* Grab the cached inherited properties for the WC root. */
+ SVN_ERR(db_read_cached_iprops(&rib, wcroot, parent_relpath,
+ iterpool));
+
+ cached_iprops = rib.iprops;
+ }
+
+ /* If PARENT_ABSPATH is a true parent of LOCAL_ABSPATH, then
+ LOCAL_ABSPATH can inherit properties from it. */
+ if (strcmp(local_relpath, parent_relpath) != 0)
+ {
+ struct db_read_props_baton_t rpb;
+ rpb.result_pool = result_pool;
+
+ SVN_ERR(db_read_props(&rpb, wcroot, parent_relpath, iterpool));
+
+ actual_props = rpb.props;
+
+ if (actual_props)
+ {
+ /* If we only want PROPNAME filter out any other properties. */
+ if (ripb->propname)
+ filter_unwanted_props(actual_props, ripb->propname, iterpool);
+
+ if (apr_hash_count(actual_props))
+ {
+ svn_prop_inherited_item_t *iprop_elt =
+ apr_pcalloc(ripb->result_pool,
+ sizeof(svn_prop_inherited_item_t));
+ iprop_elt->path_or_url = svn_dirent_join(wcroot->abspath,
+ parent_relpath,
+ result_pool);
+
+ iprop_elt->prop_hash = actual_props;
+ /* Build the output array in depth-first order. */
+ svn_sort__array_insert(&iprop_elt, ripb->iprops, 0);
+ }
+ }
+ }
+
+ /* Inheritance only goes as far as the nearest WC root. */
+ if (is_wc_root)
+ break;
- SVN_ERR(svn_sqlite__column_properties(&node_props, stmt, 0,
- iterpool, iterpool));
+ /* Keep looking for the WC root. */
+ parent_relpath = svn_relpath_dirname(parent_relpath, scratch_pool);
+ }
- value = (node_props
- ? apr_hash_get(node_props, propname, APR_HASH_KEY_STRING)
- : NULL);
+ if (cached_iprops)
+ {
+ for (i = cached_iprops->nelts - 1; i >= 0; i--)
+ {
+ svn_prop_inherited_item_t *cached_iprop =
+ APR_ARRAY_IDX(cached_iprops, i, svn_prop_inherited_item_t *);
- if (value)
- {
- apr_hash_set(*values,
- svn_dirent_join(wcroot->abspath,
- svn_sqlite__column_text(stmt, 1, NULL),
- result_pool),
- APR_HASH_KEY_STRING,
- svn_string_dup(value, result_pool));
- }
+ /* An empty property hash in the iprops cache means there are no
+ inherited properties. */
+ if (apr_hash_count(cached_iprop->prop_hash) == 0)
+ continue;
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- }
+ if (ripb->propname)
+ filter_unwanted_props(cached_iprop->prop_hash, ripb->propname,
+ scratch_pool);
- svn_pool_destroy(iterpool);
+ /* If we didn't filter everything then keep this iprop. */
+ if (apr_hash_count(cached_iprop->prop_hash))
+ svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+ }
+ }
- return svn_error_trace(svn_sqlite__reset(stmt));
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
}
svn_error_t *
-svn_wc__db_read_cached_iprops(apr_array_header_t **iprops,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_wc__db_read_inherited_props(apr_array_header_t **iprops,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *propname,
+ 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;
- const char *repos_root_url;
- svn_revnum_t revision;
- int op_depth;
- const char *repos_relpath;
+ struct read_inherited_props_baton_t ripb;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_read_info(NULL, NULL,
- &revision, &repos_relpath, &repos_root_url,
[... 910 lines stripped ...]