You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/10/20 19:57:43 UTC
svn commit: r1025655 [4/6] - in /subversion/branches/object-model: ./
build/win32/ notes/http-and-webdav/ notes/wc-ng/
subversion/bindings/ctypes-python/csvn/ subversion/include/
subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs_fs...
Modified: subversion/branches/object-model/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/wc_db.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/wc_db.c Wed Oct 20 17:57:41 2010
@@ -225,8 +225,38 @@ add_work_items(svn_sqlite__db_t *sdb,
const svn_skel_t *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,
+ svn_revnum_t revision,
+ const apr_array_header_t *children,
+ apr_int64_t op_depth,
+ apr_pool_t *scratch_pool);
-/* */
+static svn_error_t *
+db_read_pristine_props(apr_hash_t **props,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/* Return the absolute path, in local path style, of LOCAL_RELPATH in WCROOT. */
+static const char *
+path_for_error_message(const svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool)
+{
+ const char *local_abspath
+ = svn_dirent_join(wcroot->abspath, local_relpath, result_pool);
+
+ return svn_dirent_local_style(local_abspath, result_pool);
+}
+
+
+/* Return a file size from column SLOT of the SQLITE statement STMT, or
+ * SVN_INVALID_FILESIZE if the column value is NULL. */
static svn_filesize_t
get_translated_size(svn_sqlite__stmt_t *stmt, int slot)
{
@@ -236,6 +266,34 @@ get_translated_size(svn_sqlite__stmt_t *
}
+/* Return a lock info structure constructed from the given columns of the
+ * SQLITE statement STMT, or return NULL if the token column value is null. */
+static svn_wc__db_lock_t *
+lock_from_columns(svn_sqlite__stmt_t *stmt,
+ int col_token,
+ int col_owner,
+ int col_comment,
+ int col_date,
+ apr_pool_t *result_pool)
+{
+ svn_wc__db_lock_t *lock;
+
+ if (svn_sqlite__column_is_null(stmt, col_token))
+ {
+ lock = NULL;
+ }
+ else
+ {
+ lock = apr_pcalloc(result_pool, sizeof(svn_wc__db_lock_t));
+ lock->token = svn_sqlite__column_text(stmt, col_token, result_pool);
+ lock->owner = svn_sqlite__column_text(stmt, col_owner, result_pool);
+ lock->comment = svn_sqlite__column_text(stmt, col_comment, result_pool);
+ lock->date = svn_sqlite__column_int64(stmt, col_date);
+ }
+ return lock;
+}
+
+
/* */
static const char *
escape_sqlite_like(const char * const str, apr_pool_t *result_pool)
@@ -367,7 +425,9 @@ get_pristine_fname(const char **pristine
}
-/* */
+/* Look up REPOS_ID in SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID to
+ * its root URL and UUID respectively. Either output parameter may be
+ * NULL if not wanted. */
static svn_error_t *
fetch_repos_info(const char **repos_root_url,
const char **repos_uuid,
@@ -395,22 +455,69 @@ fetch_repos_info(const char **repos_root
return svn_error_return(svn_sqlite__reset(stmt));
}
+/* Set *REPOS_ROOT_URL, *REPOS_UUID, *REVISION and *REPOS_RELPATH from the
+ * given columns of the SQLITE statement STMT, or to NULL if the respective
+ * column value is null. Any of the output parameters may be NULL if not
+ * required. */
+static svn_error_t *
+repos_location_from_columns(const char **repos_root_url,
+ const char **repos_uuid,
+ svn_revnum_t *revision,
+ const char **repos_relpath,
+ svn_wc__db_pdh_t *pdh,
+ svn_sqlite__stmt_t *stmt,
+ int col_repos_id,
+ int col_revision,
+ int col_repos_relpath,
+ apr_pool_t *result_pool)
+{
+ svn_error_t *err = SVN_NO_ERROR;
+
+ if (repos_root_url || repos_uuid)
+ {
+ /* Fetch repository information via REPOS_ID. */
+ if (svn_sqlite__column_is_null(stmt, col_repos_id))
+ {
+ if (repos_root_url)
+ *repos_root_url = NULL;
+ if (repos_uuid)
+ *repos_uuid = NULL;
+ }
+ else
+ {
+ err = fetch_repos_info(repos_root_url, repos_uuid,
+ pdh->wcroot->sdb,
+ svn_sqlite__column_int64(stmt, col_repos_id),
+ result_pool);
+ }
+ }
+ if (revision)
+ {
+ *revision = svn_sqlite__column_revnum(stmt, col_revision);
+ }
+ if (repos_relpath)
+ {
+ *repos_relpath = svn_sqlite__column_text(stmt, col_repos_relpath,
+ result_pool);
+ }
+
+ return err;
+}
+
+
/* Scan from LOCAL_RELPATH upwards through parent nodes until we find a parent
that has values in the 'repos_id' and 'repos_relpath' columns. Return
- that information in REPOS_ID and REPOS_RELPATH (either may be NULL).
- Use LOCAL_ABSPATH for diagnostics */
+ that information in REPOS_ID and REPOS_RELPATH (either may be NULL). */
static svn_error_t *
scan_upwards_for_repos(apr_int64_t *repos_id,
const char **repos_relpath,
const svn_wc__db_wcroot_t *wcroot,
- const char *local_abspath,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *relpath_suffix = "";
- const char *current_basename = svn_dirent_basename(local_relpath,
- scratch_pool);
+ const char *current_basename = svn_dirent_basename(local_relpath, NULL);
const char *current_relpath = local_relpath;
svn_sqlite__stmt_t *stmt;
@@ -437,14 +544,14 @@ scan_upwards_for_repos(apr_int64_t *repo
err = svn_error_createf(
SVN_ERR_WC_CORRUPT, NULL,
_("Parent(s) of '%s' should have been present."),
- svn_dirent_local_style(local_abspath, scratch_pool));
+ path_for_error_message(wcroot, local_relpath, scratch_pool));
}
else
{
err = svn_error_createf(
SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("The node '%s' was not found."),
- svn_dirent_local_style(local_abspath, scratch_pool));
+ path_for_error_message(wcroot, local_relpath, scratch_pool));
}
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
@@ -478,7 +585,7 @@ scan_upwards_for_repos(apr_int64_t *repo
return svn_error_createf(
SVN_ERR_WC_CORRUPT, NULL,
_("Parent(s) of '%s' should have repository information."),
- svn_relpath_local_style(local_abspath, scratch_pool));
+ path_for_error_message(wcroot, local_relpath, scratch_pool));
}
/* Strip a path segment off the end, and append it to the suffix
@@ -631,28 +738,12 @@ insert_base_node(void *baton, svn_sqlite
SVN_ERR(svn_sqlite__insert(NULL, stmt));
if (pibb->kind == svn_wc__db_kind_dir && pibb->children)
- {
- int i;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
-
- for (i = pibb->children->nelts; i--; )
- {
- const char *name = APR_ARRAY_IDX(pibb->children, i, const char *);
-
- SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsns",
- pibb->wc_id,
- svn_relpath_join(pibb->local_relpath,
- name,
- scratch_pool),
- (apr_int64_t)0 /* BASE */,
- pibb->local_relpath, /* parent_relpath */
- pibb->revision,
- "incomplete",
- "unknown"));
- SVN_ERR(svn_sqlite__insert(NULL, stmt));
- }
- }
+ SVN_ERR(insert_incomplete_children(sdb, pibb->wc_id,
+ pibb->local_relpath,
+ pibb->revision,
+ pibb->children,
+ 0 /* BASE */,
+ scratch_pool));
SVN_ERR(add_work_items(sdb, pibb->work_items, scratch_pool));
@@ -740,16 +831,19 @@ copy_working_from_base(void *baton,
}
-/* Insert WORKING rows for each (const char *) child name in CHILDREN,
- whose parent directory is LOCAL_RELPATH. For each child, set
- presence='incomplete', kind='unknown', op_depth=OP_DEPTH. */
-static svn_error_t *
-insert_incomplete_working_children(svn_sqlite__db_t *sdb,
- apr_int64_t wc_id,
- const char *local_relpath,
- const apr_array_header_t *children,
- apr_int64_t op_depth,
- apr_pool_t *scratch_pool)
+/* Insert a row in NODES for each (const char *) child name in CHILDREN,
+ whose parent directory is LOCAL_RELPATH, at op_depth=OP_DEPTH. Set each
+ child's presence to 'incomplete', kind to 'unknown', and revision to
+ REVISION (which should match the parent's revision). The child's
+ repos_id and repos_relpath will be inherited from the parent. */
+static svn_error_t *
+insert_incomplete_children(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ svn_revnum_t revision,
+ const apr_array_header_t *children,
+ apr_int64_t op_depth,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
int i;
@@ -760,12 +854,13 @@ insert_incomplete_working_children(svn_s
{
const char *name = APR_ARRAY_IDX(children, i, const char *);
- SVN_ERR(svn_sqlite__bindf(stmt, "isisnnnsns",
+ SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsns",
wc_id,
svn_relpath_join(local_relpath, name,
scratch_pool),
op_depth,
local_relpath,
+ revision,
"incomplete", /* 8, presence */
"unknown")); /* 10, kind */
@@ -840,11 +935,12 @@ insert_working_node(void *baton,
(The only time we'd want a different depth is during a recursive
simple add, but we never insert children here during a simple add.) */
if (piwb->kind == svn_wc__db_kind_dir && piwb->children)
- SVN_ERR(insert_incomplete_working_children(sdb, piwb->wc_id,
- piwb->local_relpath,
- piwb->children,
- piwb->op_depth,
- scratch_pool));
+ SVN_ERR(insert_incomplete_children(sdb, piwb->wc_id,
+ piwb->local_relpath,
+ piwb->original_revnum,
+ piwb->children,
+ piwb->op_depth,
+ scratch_pool));
SVN_ERR(add_work_items(sdb, piwb->work_items, scratch_pool));
@@ -1762,51 +1858,12 @@ svn_wc__db_base_get_info(svn_wc__db_stat
{
*status = svn_sqlite__column_token(stmt, 2, presence_map);
}
- if (revision)
- {
- *revision = svn_sqlite__column_revnum(stmt, 4);
- }
- if (repos_relpath)
- {
- *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
- }
+ err = repos_location_from_columns(repos_root_url, repos_uuid, revision,
+ repos_relpath,
+ pdh, stmt, 0, 4, 1, result_pool);
if (lock)
{
- if (svn_sqlite__column_is_null(stmt, 14))
- {
- *lock = NULL;
- }
- else
- {
- *lock = apr_pcalloc(result_pool, sizeof(svn_wc__db_lock_t));
- (*lock)->token = svn_sqlite__column_text(stmt, 14, result_pool);
- if (!svn_sqlite__column_is_null(stmt, 15))
- (*lock)->owner = svn_sqlite__column_text(stmt, 15,
- result_pool);
- if (!svn_sqlite__column_is_null(stmt, 16))
- (*lock)->comment = svn_sqlite__column_text(stmt, 16,
- result_pool);
- if (!svn_sqlite__column_is_null(stmt, 17))
- (*lock)->date = svn_sqlite__column_int64(stmt, 17);
- }
- }
- if (repos_root_url || repos_uuid)
- {
- /* Fetch repository information via REPOS_ID. */
- if (svn_sqlite__column_is_null(stmt, 0))
- {
- if (repos_root_url)
- *repos_root_url = NULL;
- if (repos_uuid)
- *repos_uuid = NULL;
- }
- else
- {
- err = fetch_repos_info(repos_root_url, repos_uuid,
- pdh->wcroot->sdb,
- svn_sqlite__column_int64(stmt, 0),
- result_pool);
- }
+ *lock = lock_from_columns(stmt, 14, 15, 16, 17, result_pool);
}
if (changed_rev)
{
@@ -2513,27 +2570,6 @@ svn_wc__db_pristine_repair(svn_wc__db_t
}
-svn_error_t *
-svn_wc__db_repos_ensure(apr_int64_t *repos_id,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *repos_root_url,
- const char *repos_uuid,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
-
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- return svn_error_return(create_repos_id(repos_id, repos_root_url,
- repos_uuid, pdh->wcroot->sdb,
- scratch_pool));
-}
-
/* Helper for svn_wc__db_op_copy to handle copying from one db to
another */
static svn_error_t *
@@ -2931,12 +2967,13 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
SVN_ERR(svn_sqlite__step_done(stmt));
if (kind == svn_wc__db_kind_dir)
- SVN_ERR(insert_incomplete_working_children(dst_pdh->wcroot->sdb,
- dst_pdh->wcroot->wc_id,
- dst_relpath,
- children,
- op_depth,
- scratch_pool));
+ SVN_ERR(insert_incomplete_children(dst_pdh->wcroot->sdb,
+ dst_pdh->wcroot->wc_id,
+ dst_relpath,
+ copyfrom_rev,
+ children,
+ op_depth,
+ scratch_pool));
}
else
{
@@ -3087,7 +3124,16 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
iwb.original_revnum = original_revision;
}
+#ifdef SVN_WC__OP_DEPTH
+ iwb.op_depth = relpath_depth(local_relpath);
+
+ /* ### TODO? If the WC parent dir is already a copy from
+ * dirname(original_repos_relpath)@original_revision, then this is a
+ * redundant copy as far is the repos is concerned, so it should share
+ * the same op_depth. But that's a degenerate case. Is it needed? */
+#else
iwb.op_depth = 2; /* ### temporary op_depth */
+#endif
iwb.checksum = checksum;
@@ -3299,7 +3345,7 @@ struct set_props_baton
{
apr_hash_t *props;
- apr_int64_t wc_id;
+ svn_wc__db_pdh_t *pdh;
const char *local_relpath;
const svn_skel_t *conflict;
@@ -3307,6 +3353,38 @@ struct set_props_baton
};
+/* Set the ACTUAL_NODE properties column for (WC_ID, LOCAL_RELPATH) to
+ * PROPS. */
+static svn_error_t *
+set_actual_props(apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_hash_t *props,
+ svn_sqlite__db_t *db,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ int affected_rows;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_UPDATE_ACTUAL_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
+ SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+ if (affected_rows == 1 || !props)
+ return SVN_NO_ERROR; /* We are done */
+
+ /* We have to insert a row in ACTUAL */
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_ACTUAL_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ if (*local_relpath != '\0')
+ SVN_ERR(svn_sqlite__bind_text(stmt, 3,
+ svn_relpath_dirname(local_relpath,
+ scratch_pool)));
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool));
+ return svn_error_return(svn_sqlite__step_done(stmt));
+}
+
/* 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.
@@ -3316,8 +3394,7 @@ static svn_error_t *
set_props_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
{
struct set_props_baton *spb = baton;
- svn_sqlite__stmt_t *stmt;
- int affected_rows;
+ apr_hash_t *pristine_props;
/* ### we dunno what to do with CONFLICT yet. */
SVN_ERR_ASSERT(spb->conflict == NULL);
@@ -3325,24 +3402,25 @@ set_props_txn(void *baton, svn_sqlite__d
/* First order of business: insert all the work items. */
SVN_ERR(add_work_items(db, spb->work_items, scratch_pool));
- SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_UPDATE_ACTUAL_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", spb->wc_id, spb->local_relpath));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 3, spb->props, scratch_pool));
- SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+ /* 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, spb->pdh, spb->local_relpath,
+ scratch_pool, scratch_pool));
+ if (spb->props && pristine_props)
+ {
+ apr_array_header_t *prop_diffs;
- if (affected_rows == 1 || !spb->props)
- return SVN_NO_ERROR; /* We are done */
+ SVN_ERR(svn_prop_diffs(&prop_diffs, spb->props, pristine_props,
+ scratch_pool));
+ if (prop_diffs->nelts == 0)
+ spb->props = NULL;
+ }
- /* We have to insert a row in ACTUAL */
+ SVN_ERR(set_actual_props(spb->pdh->wcroot->wc_id, spb->local_relpath,
+ spb->props, db, scratch_pool));
- SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_ACTUAL_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", spb->wc_id, spb->local_relpath));
- if (*spb->local_relpath != '\0')
- SVN_ERR(svn_sqlite__bind_text(stmt, 3,
- svn_relpath_dirname(spb->local_relpath,
- scratch_pool)));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 4, spb->props, scratch_pool));
- return svn_error_return(svn_sqlite__step_done(stmt));
+ return SVN_NO_ERROR;
}
svn_error_t *
@@ -3364,7 +3442,7 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
VERIFY_USABLE_PDH(pdh);
spb.props = props;
- spb.wc_id = pdh->wcroot->wc_id;
+ spb.pdh = pdh;
spb.conflict = conflict;
spb.work_items = work_items;
@@ -3661,8 +3739,7 @@ set_tc_txn(void *baton, svn_sqlite__db_t
SVN_ERR(svn_wc__read_tree_conflicts(&conflicts, tree_conflict_data,
stb->parent_abspath, scratch_pool));
- apr_hash_set(conflicts, svn_dirent_basename(stb->local_abspath,
- scratch_pool),
+ apr_hash_set(conflicts, svn_dirent_basename(stb->local_abspath, NULL),
APR_HASH_KEY_STRING, stb->tree_conflict);
if (apr_hash_count(conflicts) == 0 && !have_row)
@@ -3691,6 +3768,11 @@ set_tc_txn(void *baton, svn_sqlite__db_t
SVN_ERR(svn_sqlite__bindf(stmt, "iss", stb->wc_id, stb->local_relpath,
tree_conflict_data));
+ if (!have_row && stb->local_relpath[0])
+ SVN_ERR(svn_sqlite__bind_text(stmt, 4,
+ svn_dirent_dirname(stb->local_relpath,
+ scratch_pool)));
+
return svn_error_return(svn_sqlite__step_done(stmt));
}
@@ -3836,31 +3918,32 @@ svn_wc__db_op_read_tree_conflict(
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- const char *parent_abspath;
- apr_hash_t *tree_conflicts;
- svn_error_t *err;
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
- err = svn_wc__db_op_read_all_tree_conflicts(&tree_conflicts, db,
- parent_abspath,
- result_pool, scratch_pool);
- if (err && SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+
+ if (local_relpath[0])
{
- /* We walked off the top of a working copy. */
- svn_error_clear(err);
- *tree_conflict = NULL;
- return SVN_NO_ERROR;
- }
- else if (err)
- return svn_error_return(err);
+ const char * parent_abspath;
+ apr_hash_t *tree_conflicts;
- if (tree_conflicts)
- *tree_conflict = apr_hash_get(tree_conflicts,
- svn_dirent_basename(local_abspath,
- scratch_pool),
- APR_HASH_KEY_STRING);
+ parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+
+ SVN_ERR(svn_wc__db_op_read_all_tree_conflicts(&tree_conflicts, db,
+ parent_abspath,
+ result_pool, scratch_pool));
+ if (tree_conflicts)
+ *tree_conflict = apr_hash_get(tree_conflicts,
+ svn_dirent_basename(local_abspath, NULL),
+ APR_HASH_KEY_STRING);
+ else
+ *tree_conflict = NULL;
+ }
else
*tree_conflict = NULL;
@@ -4434,47 +4517,31 @@ svn_wc__db_read_info(svn_wc__db_status_t
{
*kind = node_kind;
}
- if (revision)
+ if (op_depth != 0)
{
- if (op_depth != 0)
+ if (repos_root_url)
+ *repos_root_url = NULL;
+ if (repos_uuid)
+ *repos_uuid = NULL;
+ if (revision)
*revision = SVN_INVALID_REVNUM;
- else
- *revision = svn_sqlite__column_revnum(stmt_info, 5);
- }
- if (repos_relpath)
- {
- if (op_depth != 0)
- {
- /* Our path is implied by our parent somewhere up the tree.
- With the NULL value and status, the caller will know to
- search up the tree for the base of our path. */
- *repos_relpath = NULL;
- }
- else
- *repos_relpath = svn_sqlite__column_text(stmt_info, 2,
- result_pool);
+ if (repos_relpath)
+ /* Our path is implied by our parent somewhere up the tree.
+ With the NULL value and status, the caller will know to
+ search up the tree for the base of our path. */
+ *repos_relpath = NULL;
}
- if (repos_root_url || repos_uuid)
+ else
{
/* Fetch repository information via REPOS_ID. If we have a
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. */
- if (op_depth != 0 || svn_sqlite__column_is_null(stmt_info, 1))
- {
- if (repos_root_url)
- *repos_root_url = NULL;
- if (repos_uuid)
- *repos_uuid = NULL;
- }
- else
- err = svn_error_compose_create(
- err,
- fetch_repos_info(repos_root_url,
- repos_uuid,
- pdh->wcroot->sdb,
- svn_sqlite__column_int64(stmt_info, 1),
- result_pool));
+ err = svn_error_compose_create(
+ err, repos_location_from_columns(repos_root_url, repos_uuid,
+ revision, repos_relpath,
+ pdh, stmt_info, 1, 5, 2,
+ result_pool));
}
if (changed_rev)
{
@@ -4551,41 +4618,25 @@ svn_wc__db_read_info(svn_wc__db_status_t
else
*changelist = NULL;
}
- if (original_repos_relpath)
+ if (op_depth == 0)
{
- if (op_depth != 0)
- *original_repos_relpath = svn_sqlite__column_text(stmt_info, 2,
- result_pool);
- else
+ if (original_root_url)
+ *original_root_url = NULL;
+ if (original_uuid)
+ *original_uuid = NULL;
+ if (original_revision)
+ *original_revision = SVN_INVALID_REVNUM;
+ if (original_repos_relpath)
*original_repos_relpath = NULL;
}
-
- if (original_root_url || original_uuid)
- {
- if (op_depth == 0 || svn_sqlite__column_is_null(stmt_info, 1))
- {
- if (original_root_url)
- *original_root_url = NULL;
- if (original_uuid)
- *original_uuid = NULL;
- }
- else
- {
- /* Fetch repository information via COPYFROM_REPOS_ID. */
- err = svn_error_compose_create(
- err,
- fetch_repos_info(original_root_url, original_uuid,
- pdh->wcroot->sdb,
- svn_sqlite__column_int64(stmt_info, 1),
- result_pool));
- }
- }
- if (original_revision)
+ else
{
- if (op_depth != 0)
- *original_revision = svn_sqlite__column_revnum(stmt_info, 5);
- else
- *original_revision = SVN_INVALID_REVNUM;
+ err = svn_error_compose_create(
+ err, repos_location_from_columns(original_root_url, original_uuid,
+ original_revision,
+ original_repos_relpath,
+ pdh, stmt_info, 1, 5, 2,
+ result_pool));
}
if (props_mod)
{
@@ -4609,20 +4660,10 @@ svn_wc__db_read_info(svn_wc__db_status_t
if (lock)
{
- if (op_depth != 0 || svn_sqlite__column_is_null(stmt_info, 15))
- *lock = NULL;
- else
- {
- *lock = apr_pcalloc(result_pool, sizeof(svn_wc__db_lock_t));
- (*lock)->token = svn_sqlite__column_text(stmt_info, 15,
- result_pool);
- (*lock)->owner = svn_sqlite__column_text(stmt_info, 16,
- result_pool);
- (*lock)->comment = svn_sqlite__column_text(stmt_info, 17,
- result_pool);
- if (!svn_sqlite__column_is_null(stmt_info, 18))
- (*lock)->date = svn_sqlite__column_int64(stmt_info, 18);
- }
+ if (op_depth != 0)
+ *lock = NULL;
+ else
+ *lock = lock_from_columns(stmt_info, 15, 16, 17, 18, result_pool);
}
if (have_work)
@@ -4682,6 +4723,251 @@ svn_wc__db_read_info(svn_wc__db_status_t
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_read_children_info(apr_hash_t **nodes,
+ apr_hash_t **conflicts,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *dir_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ const char *repos_root_url = NULL;
+ apr_int64_t last_repos_id;
+ apr_hash_t *tree_conflicts;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &dir_relpath, db,
+ dir_abspath,
+ svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_NODE_CHILDREN_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, dir_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ *nodes = apr_hash_make(result_pool);
+ while (have_row)
+ {
+ struct svn_wc__db_info_t *child;
+ const char *child_relpath = svn_sqlite__column_text(stmt, 19, NULL);
+ const char *name = svn_relpath_basename(child_relpath, NULL);
+ svn_error_t *err;
+ int *op_depth, row_op_depth;
+ svn_boolean_t new_child;
+
+ child = apr_hash_get(*nodes, name, APR_HASH_KEY_STRING);
+ if (child)
+ new_child = FALSE;
+ else
+ {
+ child = apr_palloc(result_pool,
+ sizeof(struct svn_wc__db_info_t) + sizeof(int));
+ new_child = TRUE;
+ }
+
+ op_depth = (int *)(char*)(child + 1);
+ row_op_depth = svn_sqlite__column_int(stmt, 0);
+
+ if (new_child || *op_depth < row_op_depth)
+ {
+ apr_hash_t *properties;
+
+ *op_depth = row_op_depth;
+
+ child->kind = svn_sqlite__column_token(stmt, 4, kind_map);
+
+ child->status = svn_sqlite__column_token(stmt, 3, presence_map);
+ if (*op_depth != 0)
+ {
+ if (child->status == svn_wc__db_status_not_present
+ || child->status == svn_wc__db_status_base_deleted)
+ child->status = svn_wc__db_status_deleted;
+ else if (child->status == svn_wc__db_status_normal)
+ child->status = svn_wc__db_status_added;
+ }
+
+ if (*op_depth != 0)
+ child->revnum = SVN_INVALID_REVNUM;
+ else
+ child->revnum = svn_sqlite__column_revnum(stmt, 5);
+
+
+ if (*op_depth != 0)
+ child->repos_relpath = NULL;
+ else
+ child->repos_relpath = svn_sqlite__column_text(stmt, 2,
+ result_pool);
+
+ if (*op_depth != 0 || svn_sqlite__column_is_null(stmt, 1))
+ {
+ child->repos_root_url = NULL;
+ }
+ else
+ {
+ const char *repos_uuid;
+ apr_int64_t repos_id = svn_sqlite__column_int64(stmt, 1);
+ if (!repos_root_url)
+ {
+ err = fetch_repos_info(&repos_root_url, &repos_uuid,
+ pdh->wcroot->sdb, repos_id,
+ result_pool);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err,
+ svn_sqlite__reset(stmt)));
+ last_repos_id = repos_id;
+ }
+
+ /* Assume working copy is all one repos_id so that a
+ single cached value is sufficient. */
+ SVN_ERR_ASSERT(repos_id == last_repos_id);
+ child->repos_root_url = repos_root_url;
+ }
+
+ child->changed_rev = svn_sqlite__column_revnum(stmt, 8);
+
+ child->changed_date = svn_sqlite__column_int64(stmt, 9);
+
+ child->changed_author = svn_sqlite__column_text(stmt, 10,
+ result_pool);
+
+ child->last_mod_time = svn_sqlite__column_int64(stmt, 13);
+
+ if (child->kind != svn_wc__db_kind_dir)
+ 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->translated_size = get_translated_size(stmt, 7);
+
+ child->lock = lock_from_columns(stmt, 15, 16, 17, 18, result_pool);
+
+ err = svn_sqlite__column_properties(&properties, stmt, 14,
+ scratch_pool, scratch_pool);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ child->has_props = properties && !!apr_hash_count(properties);
+#ifdef HAVE_SYMLINK
+ child->special = (child->has_props
+ && apr_hash_get(properties, SVN_PROP_SPECIAL,
+ APR_HASH_KEY_STRING));
+#endif
+
+ child->changelist = NULL;
+ child->have_base = (*op_depth == 0);
+ child->props_mod = FALSE;
+ child->conflicted = FALSE;
+
+ apr_hash_set(*nodes, apr_pstrdup(result_pool, name),
+ APR_HASH_KEY_STRING, child);
+ }
+ else if (row_op_depth == 0)
+ {
+ child->have_base = TRUE;
+ }
+
+ err = svn_sqlite__step(&have_row, stmt);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_ACTUAL_CHILDREN_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, dir_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ while (have_row)
+ {
+ struct svn_wc__db_info_t *child;
+ const char *child_relpath = svn_sqlite__column_text(stmt, 7, NULL);
+ const char *name = svn_relpath_basename(child_relpath, NULL);
+ svn_error_t *err;
+
+ child = apr_hash_get(*nodes, name, APR_HASH_KEY_STRING);
+ if (!child)
+ {
+ err = svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+ _("Corrupt data for '%s'"),
+ svn_dirent_local_style(child_relpath,
+ scratch_pool));
+ SVN_ERR(svn_error_compose_create(err,
+ svn_sqlite__step(&have_row, stmt)));
+ }
+
+ child->changelist = svn_sqlite__column_text(stmt, 1, result_pool);
+
+ child->props_mod = !svn_sqlite__column_is_null(stmt, 6);
+ if (child->props_mod)
+ {
+ apr_hash_t *properties;
+
+ err = svn_sqlite__column_properties(&properties, stmt, 6,
+ scratch_pool, scratch_pool);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ child->has_props = properties && !!apr_hash_count(properties);
+#ifdef HAVE_SYMLINK
+ child->special = (child->has_props
+ && apr_hash_get(properties, SVN_PROP_SPECIAL,
+ APR_HASH_KEY_STRING));
+#endif
+ }
+
+
+ child->conflicted = (svn_sqlite__column_text(stmt, 2, NULL) /* old */
+ || svn_sqlite__column_text(stmt, 3, NULL) /* new */
+ || svn_sqlite__column_text(stmt, 4, NULL) /* work */
+ || svn_sqlite__column_text(stmt, 0, NULL));/* prop */
+
+ err = svn_sqlite__step(&have_row, stmt);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ SVN_ERR(svn_wc__db_op_read_all_tree_conflicts(&tree_conflicts, db,
+ dir_abspath,
+ scratch_pool, scratch_pool));
+ *conflicts = apr_hash_make(result_pool);
+ if (tree_conflicts)
+ {
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, tree_conflicts);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ struct svn_wc__db_info_t *child
+ = apr_hash_get(*nodes, name, APR_HASH_KEY_STRING);
+
+ if (child)
+ child->conflicted = TRUE;
+
+ apr_hash_set(*conflicts, apr_pstrdup(result_pool, name),
+ APR_HASH_KEY_STRING, "");
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__db_read_prop(const svn_string_t **propval,
@@ -4754,19 +5040,20 @@ svn_wc__db_read_props(apr_hash_t **props
}
-svn_error_t *
-svn_wc__db_read_pristine_props(apr_hash_t **props,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+db_read_pristine_props(apr_hash_t **props,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
svn_wc__db_status_t presence;
- SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
- STMT_SELECT_NODE_PROPS, scratch_pool));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb, STMT_SELECT_NODE_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (!have_row)
@@ -4774,7 +5061,8 @@ svn_wc__db_read_pristine_props(apr_hash_
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
svn_sqlite__reset(stmt),
_("The node '%s' was not found."),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(pdh->wcroot,
+ local_relpath,
scratch_pool));
}
@@ -4794,8 +5082,10 @@ svn_wc__db_read_pristine_props(apr_hash_
presence = svn_sqlite__column_token(stmt, 1, presence_map);
}
- /* normal or copied: Fetch properties */
- if (presence == svn_wc__db_status_normal)
+ /* normal or copied: Fetch properties (during update we want
+ properties for incomplete as well) */
+ if (presence == svn_wc__db_status_normal
+ || presence == svn_wc__db_status_incomplete)
{
svn_error_t *err;
@@ -4815,6 +5105,29 @@ svn_wc__db_read_pristine_props(apr_hash_
svn_error_t *
+svn_wc__db_read_pristine_props(apr_hash_t **props,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath, svn_sqlite__mode_readwrite,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(db_read_pristine_props(props, pdh, local_relpath,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
svn_wc__db_read_children(const apr_array_header_t **children,
svn_wc__db_t *db,
const char *local_abspath,
@@ -4868,8 +5181,6 @@ relocate_txn(void *baton, svn_sqlite__db
new_repos_id));
SVN_ERR(svn_sqlite__step_done(stmt));
- /* Do a bunch of stuff which is conditional on us actually having a
- base_node in the first place. */
if (rb->have_base_node)
{
/* Update any locks for the root or its children. */
@@ -5226,20 +5537,24 @@ commit_node(void *baton, svn_sqlite__db_
}
-/* */
+/* Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
+ * (PDH, LOCAL_RELPATH), scanning upwards through parents if no BASE row
+ * exists for this node or if it inherits the info.
+ *
+ * Similar to scan_upwards_for_repos() except that the node need not exist
+ * in BASE. */
static svn_error_t *
determine_repos_info(apr_int64_t *repos_id,
const char **repos_relpath,
- svn_wc__db_t *db,
svn_wc__db_pdh_t *pdh,
const char *local_relpath,
- const char *name,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
const char *repos_parent_relpath;
+ const char *local_parent_relpath, *name;
/* ### is it faster to fetch fewer columns? */
@@ -5264,12 +5579,11 @@ determine_repos_info(apr_int64_t *repos_
/* This was a child node within this wcroot. We want to look at the
BASE node of the directory. */
- local_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+ svn_relpath_split(&local_parent_relpath, &name, local_relpath, scratch_pool);
/* The REPOS_ID will be the same (### until we support mixed-repos) */
SVN_ERR(scan_upwards_for_repos(repos_id, &repos_parent_relpath,
- pdh->wcroot, pdh->local_abspath,
- local_relpath,
+ pdh->wcroot, local_parent_relpath,
scratch_pool, scratch_pool));
*repos_relpath = svn_relpath_join(repos_parent_relpath, name, result_pool);
@@ -5335,9 +5649,7 @@ svn_wc__db_global_commit(svn_wc__db_t *d
### this always returns values. we should switch to null if/when
### possible. */
SVN_ERR(determine_repos_info(&cb.repos_id, &cb.repos_relpath,
- db, pdh, local_relpath,
- svn_dirent_basename(local_abspath,
- scratch_pool),
+ pdh, local_relpath,
scratch_pool, scratch_pool));
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb, commit_node, &cb,
@@ -5442,14 +5754,11 @@ svn_wc__db_global_update(svn_wc__db_t *d
struct record_baton {
- apr_int64_t wc_id;
+ svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
svn_filesize_t translated_size;
apr_time_t last_mod_time;
-
- /* For error reporting. */
- const char *local_abspath;
};
@@ -5466,12 +5775,13 @@ record_fileinfo(void *baton, svn_sqlite_
int affected_rows;
SVN_ERR(which_trees_exist(&base_exists, &working_exists,
- sdb, rb->wc_id, rb->local_relpath));
+ sdb, rb->wcroot->wc_id, rb->local_relpath));
if (!base_exists && !working_exists)
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("Could not find node '%s' for recording file "
"information."),
- svn_dirent_local_style(rb->local_abspath,
+ path_for_error_message(rb->wcroot,
+ rb->local_relpath,
scratch_pool));
/* ### Instead of doing it this way, we just ought to update the highest
@@ -5482,7 +5792,7 @@ record_fileinfo(void *baton, svn_sqlite_
? STMT_UPDATE_WORKING_NODE_FILEINFO
: STMT_UPDATE_BASE_NODE_FILEINFO));
SVN_ERR(svn_sqlite__bindf(stmt, "isii",
- rb->wc_id, rb->local_relpath,
+ rb->wcroot->wc_id, rb->local_relpath,
rb->translated_size, rb->last_mod_time));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
@@ -5510,14 +5820,12 @@ svn_wc__db_global_record_fileinfo(svn_wc
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- rb.wc_id = pdh->wcroot->wc_id;
+ rb.wcroot = pdh->wcroot;
rb.local_relpath = local_relpath;
rb.translated_size = translated_size;
rb.last_mod_time = last_mod_time;
- rb.local_abspath = local_abspath;
-
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb, record_fileinfo, &rb,
scratch_pool));
@@ -5549,7 +5857,7 @@ svn_wc__db_lock_add(svn_wc__db_t *db,
VERIFY_USABLE_PDH(pdh);
SVN_ERR(scan_upwards_for_repos(&repos_id, &repos_relpath,
- pdh->wcroot, local_abspath, local_relpath,
+ pdh->wcroot, local_relpath,
scratch_pool, scratch_pool));
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
@@ -5594,7 +5902,7 @@ svn_wc__db_lock_remove(svn_wc__db_t *db,
VERIFY_USABLE_PDH(pdh);
SVN_ERR(scan_upwards_for_repos(&repos_id, &repos_relpath,
- pdh->wcroot, local_abspath, local_relpath,
+ pdh->wcroot, local_relpath,
scratch_pool, scratch_pool));
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
@@ -5631,7 +5939,7 @@ svn_wc__db_scan_base_repos(const char **
VERIFY_USABLE_PDH(pdh);
SVN_ERR(scan_upwards_for_repos(&repos_id, repos_relpath,
- pdh->wcroot, local_abspath, local_relpath,
+ pdh->wcroot, local_relpath,
result_pool, scratch_pool));
if (repos_root_url || repos_uuid)
@@ -5797,7 +6105,7 @@ svn_wc__db_scan_addition(svn_wc__db_stat
if (repos_relpath)
{
build_relpath = svn_relpath_join(svn_dirent_basename(current_abspath,
- scratch_pool),
+ NULL),
build_relpath,
scratch_pool);
}
@@ -6239,13 +6547,8 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
if (working_props != NULL)
{
- struct set_props_baton spb = { 0 };
-
- spb.props = working_props;
- spb.wc_id = wc_id;
- spb.local_relpath = local_relpath;
- /* NULL for .conflict and .work_items */
- SVN_ERR(set_props_txn(&spb, sdb, scratch_pool));
+ SVN_ERR(set_actual_props(wc_id, local_relpath, working_props,
+ sdb, scratch_pool));
}
return SVN_NO_ERROR;
@@ -6996,7 +7299,6 @@ struct wclock_obtain_baton
svn_wc__db_t *db;
svn_wc__db_pdh_t *pdh;
const char *local_relpath;
- const char *local_abspath;
int levels_to_lock;
svn_boolean_t steal_lock;
};
@@ -7050,7 +7352,8 @@ wclock_obtain_cb(void *baton,
return svn_error_createf(
SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("The node '%s' was not found."),
- svn_dirent_local_style(bt->local_abspath,
+ path_for_error_message(bt->pdh->wcroot,
+ bt->local_relpath,
scratch_pool));
}
@@ -7107,7 +7410,8 @@ wclock_obtain_cb(void *baton,
scratch_pool));
return svn_error_createf(SVN_ERR_WC_LOCKED, err,
_("Working copy '%s' locked."),
- svn_dirent_local_style(bt->local_abspath,
+ path_for_error_message(bt->pdh->wcroot,
+ bt->local_relpath,
scratch_pool));
}
else if (!own_lock)
@@ -7157,7 +7461,8 @@ wclock_obtain_cb(void *baton,
return svn_error_createf(
SVN_ERR_WC_LOCKED, err,
_("Working copy '%s' locked."),
- svn_dirent_local_style(bt->local_abspath,
+ path_for_error_message(bt->pdh->wcroot,
+ bt->local_relpath,
scratch_pool));
}
@@ -7181,7 +7486,8 @@ wclock_obtain_cb(void *baton,
if (err)
return svn_error_createf(SVN_ERR_WC_LOCKED, err,
_("Working copy '%s' locked"),
- svn_dirent_local_style(bt->local_abspath,
+ path_for_error_message(bt->pdh->wcroot,
+ bt->local_relpath,
scratch_pool));
/* And finally store that we obtained the lock */
@@ -7243,7 +7549,6 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *d
}
baton.db = db;
- baton.local_abspath = local_abspath;
baton.steal_lock = steal_lock;
baton.levels_to_lock = levels_to_lock;
@@ -7486,42 +7791,22 @@ start_directory_update_txn(void *baton,
apr_pool_t *scratch_pool)
{
struct start_directory_update_baton *du = baton;
- const char *repos_relpath;
svn_sqlite__stmt_t *stmt;
- SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, NULL, NULL,
- du->db, du->local_abspath,
- scratch_pool, scratch_pool));
-
- if (strcmp(du->new_repos_relpath, repos_relpath) == 0)
- {
- /* Just update revision and status */
- SVN_ERR(svn_sqlite__get_statement(
- &stmt, db,
- STMT_UPDATE_BASE_NODE_PRESENCE_AND_REVNUM));
-
- SVN_ERR(svn_sqlite__bindf(stmt, "isti",
- du->wc_id,
- du->local_relpath,
- presence_map, svn_wc__db_status_incomplete,
- (apr_int64_t)du->new_rev));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
- else
- {
- /* ### TODO: Maybe check if we can make repos_relpath NULL. */
- SVN_ERR(svn_sqlite__get_statement(
- &stmt, db,
- STMT_UPDATE_BASE_NODE_PRESENCE_REVNUM_AND_REPOS_PATH));
+ /* Note: In the majority of calls, the repos_relpath is unchanged. */
+ /* ### TODO: Maybe check if we can make repos_relpath NULL. */
+ SVN_ERR(svn_sqlite__get_statement(
+ &stmt, db,
+ STMT_UPDATE_BASE_NODE_PRESENCE_REVNUM_AND_REPOS_PATH));
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "istis",
+ du->wc_id,
+ du->local_relpath,
+ presence_map, svn_wc__db_status_incomplete,
+ (apr_int64_t)du->new_rev,
+ du->new_repos_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
- SVN_ERR(svn_sqlite__bindf(stmt, "istis",
- du->wc_id,
- du->local_relpath,
- presence_map, svn_wc__db_status_incomplete,
- (apr_int64_t)du->new_rev,
- du->new_repos_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
return SVN_NO_ERROR;
}
Modified: subversion/branches/object-model/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/wc_db.h?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/wc_db.h Wed Oct 20 17:57:41 2010
@@ -46,6 +46,8 @@
#include "private/svn_skel.h"
#include "private/svn_sqlite.h"
+#include "svn_private_config.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -1004,28 +1006,6 @@ svn_wc__db_pristine_repair(svn_wc__db_t
/* @} */
-/* @defgroup svn_wc__db_repos Repository information management
- @{
-*/
-
-/* Ensure an entry for the repository at REPOS_ROOT_URL with UUID exists
- in DB for LOCAL_ABSPATH, either by finding the correct row, or inserting
- a new row. In either case return the id in *REPOS_ID.
-
- Use SCRATCH_POOL for temporary allocations.
-*/
-svn_error_t *
-svn_wc__db_repos_ensure(apr_int64_t *repos_id,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *repos_root_url,
- const char *repos_uuid,
- apr_pool_t *scratch_pool);
-
-
-/* @} */
-
-
/* @defgroup svn_wc__db_op Operations on WORKING tree
@{
*/
@@ -1142,10 +1122,8 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
To specify no properties, PROPS must be an empty hash, not NULL.
If the node is not present, return an error.
- ### All the callers are doing a comparison against the current 'pristine'
- props before calling this, and are passing NULL if the actual props
- are to be the same as the pristine props. This behaviour should be
- encapsulated.
+ If PROPS is NULL, set the properties to be the same as the pristine
+ properties.
CONFLICT is used to register a conflict on this node at the same time
the properties are changed.
@@ -1509,6 +1487,41 @@ svn_wc__db_read_info(svn_wc__db_status_t
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Structure returned by svn_wc__db_read_children_info. Only has the
+ fields needed by status. */
+struct svn_wc__db_info_t {
+ svn_wc__db_status_t status;
+ svn_wc__db_kind_t kind;
+ svn_revnum_t revnum;
+ const char *repos_relpath;
+ const char *repos_root_url;
+ svn_revnum_t changed_rev;
+ const char *changed_author;
+ apr_time_t changed_date;
+ apr_time_t last_mod_time;
+ svn_depth_t depth;
+ svn_filesize_t translated_size;
+ const char *changelist;
+ svn_boolean_t has_props;
+#ifdef HAVE_SYMLINK
+ svn_boolean_t special;
+#endif
+ svn_boolean_t props_mod;
+ svn_boolean_t have_base;
+ svn_boolean_t conflicted;
+ svn_wc__db_lock_t *lock;
+};
+
+/* Return in *NODES a hash mapping name->struct svn_wc__db_info_t for
+ the children of DIR_ABSPATH, and in *CONFLICTS a hash of names in
+ conflict. */
+svn_error_t *
+svn_wc__db_read_children_info(apr_hash_t **nodes,
+ apr_hash_t **conflicts,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Set *PROPVAL to the value of the property named PROPNAME of the node
LOCAL_ABSPATH in the ACTUAL tree (looking through to the WORKING or BASE
Modified: subversion/branches/object-model/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/workqueue.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/workqueue.c Wed Oct 20 17:57:41 2010
@@ -181,18 +181,23 @@ run_revert(svn_wc__db_t *db,
{
const svn_skel_t *arg1 = work_item->children->next;
const char *local_abspath;
- svn_boolean_t replaced;
svn_wc__db_kind_t kind;
svn_wc__db_status_t status;
const char *parent_abspath;
svn_boolean_t conflicted;
apr_int64_t val;
+ svn_boolean_t reinstall_working;
+ svn_boolean_t remove_working;
/* We need a NUL-terminated path, so copy it out of the skel. */
local_abspath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
+
SVN_ERR(svn_skel__parse_int(&val, arg1->next, scratch_pool));
- replaced = (val != 0);
- /* magic_changed is extracted further below. */
+ remove_working = (val != 0);
+
+ SVN_ERR(svn_skel__parse_int(&val, arg1->next->next, scratch_pool));
+ reinstall_working = (val != 0);
+
/* use_commit_times is extracted further below. */
/* NOTE: we can read KIND here since uncommitted kind changes are not
@@ -207,10 +212,13 @@ run_revert(svn_wc__db_t *db,
scratch_pool, scratch_pool));
if (kind == svn_wc__db_kind_dir)
- parent_abspath = local_abspath;
+ {
+ parent_abspath = local_abspath;
+ }
else
- parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
+ {
+ parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+ }
if (conflicted)
{
@@ -247,57 +255,6 @@ run_revert(svn_wc__db_t *db,
/* Deal with the working file, as needed. */
if (kind == svn_wc__db_kind_file)
{
- svn_boolean_t magic_changed;
- svn_boolean_t reinstall_working;
-
- SVN_ERR(svn_skel__parse_int(&val, arg1->next->next, scratch_pool));
- magic_changed = (val != 0);
-
- /* If there was a magic property change, then we'll reinstall the
- working-file to pick up any/all appropriate changes. If there was
- a replacement, then we definitely want to reinstall the working-file
- using the original base. */
- reinstall_working = magic_changed || replaced;
-
- if (!replaced && !reinstall_working)
- /* check for additional scenarios which need the actual re-installed */
- {
- svn_node_kind_t check_kind;
-
- /* If the working file is missing, we need to reinstall it. */
- SVN_ERR(svn_io_check_path(local_abspath, &check_kind,
- scratch_pool));
- reinstall_working = (check_kind == svn_node_none);
-
- if (!reinstall_working)
- {
- /* ### can we optimize this call? we already fetched some
- ### info about the node. and *definitely* never want a
- ### full file-scan. */
-
- /* ### for now, just always reinstall. without some extra work,
- ### we could end up in a situation where the file is copied
- ### from the base, but then something fails immediately
- ### after that. on the second time through here, we would
- ### see the file is "the same" and fail to complete those
- ### follow-on actions. in some future work, examine the
- ### points of failure, and possibly precompue the
- ### "reinstall_working" flag, or maybe do some follow-on
- ### actions unconditionally. */
-#if 1
- reinstall_working = TRUE;
-#endif
-#if 0
- /* ### try to avoid altering the timestamp if the intended
- ### contents are the same as current-contents. */
- SVN_ERR(svn_wc__text_modified_internal_p(&reinstall_working,
- db, local_abspath,
- FALSE, FALSE,
- scratch_pool));
-#endif
- }
- }
-
if (reinstall_working)
{
svn_boolean_t use_commit_times;
@@ -321,43 +278,24 @@ run_revert(svn_wc__db_t *db,
{
SVN__NOT_IMPLEMENTED();
}
- else if (kind == svn_wc__db_kind_dir)
+ else if (reinstall_working && kind == svn_wc__db_kind_dir)
{
- svn_node_kind_t disk_kind;
- SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool));
+ svn_node_kind_t on_disk;
- if (disk_kind == svn_node_none)
+ /* Unfortunately we need another stat(), because I don't want
+ to resort to APR error macros to see if we're creating a
+ directory on top of an existing path */
+ SVN_ERR(svn_io_check_path(local_abspath, &on_disk, scratch_pool));
+ if (on_disk == svn_node_none)
SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool));
}
- {
- svn_boolean_t is_wc_root;
-
- SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
- db, local_abspath, scratch_pool));
-
- /* Remove the WORKING_NODE from the node and (if there) its parent stub */
- /* ### A working copy root can't have a working node and trying
- ### to delete it fails because the root doesn't have a stub. */
- if (!is_wc_root)
- {
- const char *op_root_abspath = NULL;
-
- /* If the node is not the operation root, we should not delete
- the working node */
- if (status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
-
- if (!op_root_abspath
- || (strcmp(op_root_abspath, local_abspath) == 0))
- SVN_ERR(svn_wc__db_temp_op_remove_working(db, local_abspath,
- scratch_pool));
- }
- }
+ if (remove_working)
+ {
+ SVN_ERR(svn_wc__db_temp_op_remove_working(db, local_abspath,
+ scratch_pool));
+ }
return SVN_NO_ERROR;
}
@@ -407,6 +345,7 @@ verify_pristine_present(svn_wc__db_t *db
svn_error_t *
svn_wc__wq_add_revert(svn_boolean_t *will_revert,
svn_wc__db_t *db,
+ const char *revert_root,
const char *local_abspath,
svn_boolean_t use_commit_times,
apr_pool_t *scratch_pool)
@@ -414,7 +353,8 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
svn_wc__db_status_t status;
svn_wc__db_kind_t kind;
svn_boolean_t replaced;
- svn_boolean_t magic_changed = FALSE;
+ svn_boolean_t remove_working = FALSE;
+ svn_boolean_t reinstall_working;
SVN_ERR(svn_wc__db_read_info(
&status, &kind, NULL, NULL, NULL, NULL,
@@ -424,8 +364,11 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
db, local_abspath,
scratch_pool, scratch_pool));
- /* Special handling for issue #2101. */
- if (kind == svn_wc__db_kind_file)
+ /* Special handling for issue #2101, which is specifically
+ about reverting copies of 'deleted' files and dirs, being inserted
+ in the copy as a schedule-delete files, yet can't be reverted. */
+ if (kind == svn_wc__db_kind_file
+ && status == svn_wc__db_status_deleted)
SVN_ERR(verify_pristine_present(db, local_abspath, scratch_pool));
/* Gather a few items *before* the revert work-item has a chance to run.
@@ -436,9 +379,9 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
scratch_pool));
/* If a replacement has occurred, then a revert definitely happens. */
- *will_revert = replaced;
+ *will_revert = reinstall_working = replaced;
- if (!replaced)
+ if (status == svn_wc__db_status_normal)
{
apr_hash_t *base_props;
apr_hash_t *working_props;
@@ -452,51 +395,65 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
scratch_pool, scratch_pool));
SVN_ERR(svn_prop_diffs(&prop_diffs, working_props, base_props,
scratch_pool));
- magic_changed = svn_wc__has_magic_property(prop_diffs);
+ if (svn_wc__has_magic_property(prop_diffs))
+ reinstall_working = TRUE;
if (prop_diffs->nelts > 0)
{
/* Property changes cause a revert to occur. */
*will_revert = TRUE;
}
- else
- {
- /* There is nothing to do for NORMAL or ADDED nodes. Typically,
- we won't even be called for added nodes (since a revert
- simply removes it from version control), but it is possible
- that a parent replacement was turned from a replaced copy
- into a normal node, and the (broken) old ENTRY->COPIED logic
- then turns the copied children into typical ADDED nodes.
- Since the recursion has already started, these children are
- visited (unlike most added nodes). */
- if (status != svn_wc__db_status_normal
- && status != svn_wc__db_status_added)
- {
- *will_revert = TRUE;
- }
+ }
+ else
+ {
+ *will_revert = TRUE;
+ if (status != svn_wc__db_status_added)
+ reinstall_working = TRUE;
+ }
- /* We may need to restore a missing working file. */
- if (! *will_revert)
- {
- svn_node_kind_t on_disk;
+ /* We may need to restore a missing working file. */
+ if (! reinstall_working
+ && status != svn_wc__db_status_added)
+ {
+ svn_node_kind_t on_disk;
- SVN_ERR(svn_io_check_path(local_abspath, &on_disk,
- scratch_pool));
- *will_revert = on_disk == svn_node_none;
- }
+ SVN_ERR(svn_io_check_path(local_abspath, &on_disk, scratch_pool));
+ reinstall_working = on_disk == svn_node_none;
+ *will_revert = *will_revert || reinstall_working;
+ }
- if (! *will_revert)
- {
- /* ### there may be ways to simplify this test, rather than
- ### doing file comparisons and junk... */
- SVN_ERR(svn_wc__internal_text_modified_p(will_revert,
- db, local_abspath,
- FALSE, FALSE,
- scratch_pool));
- }
- }
+ if (! reinstall_working
+ && status == svn_wc__db_status_normal)
+ {
+ /* ### there may be ways to simplify this test, rather than
+ ### doing file comparisons and junk... */
+ SVN_ERR(svn_wc__internal_text_modified_p(&reinstall_working,
+ db, local_abspath,
+ FALSE, FALSE,
+ scratch_pool));
+ *will_revert = *will_revert || reinstall_working;
}
+
+ if (status == svn_wc__db_status_added)
+ {
+ /* When looking at an added, non-replacing node, it's entry
+ will have to be removed after revert: if not, it'll look
+ like it's still under version control. */
+ const char *op_root_abspath;
+
+ SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (svn_dirent_is_ancestor(revert_root, op_root_abspath))
+ remove_working = TRUE;
+ }
+ else
+ remove_working = TRUE;
+
+
/* Don't even bother to queue a work item if there is nothing to do. */
if (*will_revert)
{
@@ -507,8 +464,8 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
/* These skel atoms hold references to very transitory state, but
we only need the work_item to survive for the duration of wq_add. */
svn_skel__prepend_int(use_commit_times, work_item, scratch_pool);
- svn_skel__prepend_int(magic_changed, work_item, scratch_pool);
- svn_skel__prepend_int(replaced, work_item, scratch_pool);
+ svn_skel__prepend_int(reinstall_working, work_item, scratch_pool);
+ svn_skel__prepend_int(remove_working, work_item, scratch_pool);
svn_skel__prepend_str(local_abspath, work_item, scratch_pool);
svn_skel__prepend_str(OP_REVERT, work_item, scratch_pool);
Modified: subversion/branches/object-model/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/workqueue.h?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/workqueue.h Wed Oct 20 17:57:41 2010
@@ -188,10 +188,12 @@ svn_wc__wq_build_record_fileinfo(svn_ske
apr_pool_t *result_pool);
-/* Record a work item to revert LOCAL_ABSPATH. */
+/* Record a work item to revert LOCAL_ABSPATH;
+ REVERT_ROOT designates the root of the entire revert operation. */
svn_error_t *
svn_wc__wq_add_revert(svn_boolean_t *will_revert,
svn_wc__db_t *db,
+ const char *revert_root,
const char *local_abspath,
svn_boolean_t use_commit_times,
apr_pool_t *scratch_pool);