You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2015/03/04 16:56:21 UTC
svn commit: r1664059 [3/11] - in /subversion/branches/reuse-ra-session: ./
build/generator/ doc/ subversion/bindings/javahl/native/
subversion/bindings/swig/ subversion/bindings/swig/include/
subversion/bindings/swig/python/libsvn_swig_py/ subversion/b...
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c Wed Mar 4 15:56:18 2015
@@ -53,6 +53,26 @@
#include "private/svn_editor.h"
+/* The file internal variant of svn_wc_status3_t, with slightly more
+ data.
+
+ Instead of directly creating svn_wc_status3_t instances, we really
+ create instances of this struct with slightly more data for processing
+ by the status walker and status editor.
+
+ svn_wc_status3_dup() allocates space for this struct, but doesn't
+ copy the actual data. The remaining fields are copied by hash_stash(),
+ which is where the status editor stashes information for producing
+ later. */
+typedef struct svn_wc__internal_status_t
+{
+ svn_wc_status3_t s; /* First member; same pointer*/
+
+ svn_boolean_t has_descendants;
+
+ /* Make sure to update hash_stash() when adding values here */
+} svn_wc__internal_status_t;
+
/*** Baton used for walking the local status */
struct walk_status_baton
@@ -126,7 +146,7 @@ struct edit_baton
const apr_array_header_t *ignores;
/* Status item for the path represented by the anchor of the edit. */
- svn_wc_status3_t *anchor_status;
+ svn_wc__internal_status_t *anchor_status;
/* Was open_root() called for this edit drive? */
svn_boolean_t root_opened;
@@ -288,7 +308,7 @@ get_repos_root_url_relpath(const char **
}
static svn_error_t *
-internal_status(svn_wc_status3_t **status,
+internal_status(svn_wc__internal_status_t **status,
svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t check_working_copy,
@@ -315,7 +335,7 @@ internal_status(svn_wc_status3_t **statu
The status struct's repos_lock field will be set to REPOS_LOCK.
*/
static svn_error_t *
-assemble_status(svn_wc_status3_t **status,
+assemble_status(svn_wc__internal_status_t **status,
svn_wc__db_t *db,
const char *local_abspath,
const char *parent_repos_root_url,
@@ -330,6 +350,7 @@ assemble_status(svn_wc_status3_t **statu
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_wc__internal_status_t *inner_stat;
svn_wc_status3_t *stat;
svn_boolean_t switched_p = FALSE;
svn_boolean_t copied = FALSE;
@@ -582,7 +603,9 @@ assemble_status(svn_wc_status3_t **statu
/* 6. Build and return a status structure. */
- stat = apr_pcalloc(result_pool, sizeof(**status));
+ inner_stat = apr_pcalloc(result_pool, sizeof(*inner_stat));
+ stat = &inner_stat->s;
+ inner_stat->has_descendants = info->has_descendants;
switch (info->kind)
{
@@ -598,6 +621,7 @@ assemble_status(svn_wc_status3_t **statu
stat->kind = svn_node_unknown;
}
stat->depth = info->depth;
+
if (dirent)
{
stat->filesize = (dirent->kind == svn_node_file)
@@ -670,7 +694,7 @@ assemble_status(svn_wc_status3_t **statu
stat->file_external = info->file_external;
- *status = stat;
+ *status = inner_stat;
return SVN_NO_ERROR;
}
@@ -684,7 +708,7 @@ assemble_status(svn_wc_status3_t **statu
node_status to svn_wc_status_unversioned.
*/
static svn_error_t *
-assemble_unversioned(svn_wc_status3_t **status,
+assemble_unversioned(svn_wc__internal_status_t **status,
svn_wc__db_t *db,
const char *local_abspath,
const svn_io_dirent2_t *dirent,
@@ -693,10 +717,12 @@ assemble_unversioned(svn_wc_status3_t **
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_wc__internal_status_t *inner_status;
svn_wc_status3_t *stat;
/* return a fairly blank structure. */
- stat = apr_pcalloc(result_pool, sizeof(*stat));
+ inner_status = apr_pcalloc(result_pool, sizeof(*inner_status));
+ stat = &inner_status->s;
/*stat->versioned = FALSE;*/
stat->kind = svn_node_unknown; /* not versioned */
@@ -751,7 +777,7 @@ assemble_unversioned(svn_wc_status3_t **
stat->conflicted = tree_conflicted;
stat->changelist = NULL;
- *status = stat;
+ *status = inner_status;
return SVN_NO_ERROR;
}
@@ -772,7 +798,7 @@ send_status_structure(const struct walk_
void *status_baton,
apr_pool_t *scratch_pool)
{
- svn_wc_status3_t *statstruct;
+ svn_wc__internal_status_t *statstruct;
const svn_lock_t *repos_lock = NULL;
/* Check for a repository lock. */
@@ -806,7 +832,8 @@ send_status_structure(const struct walk_
if (statstruct && status_func)
return svn_error_trace((*status_func)(status_baton, local_abspath,
- statstruct, scratch_pool));
+ &statstruct->s,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -962,7 +989,7 @@ send_unversioned_item(const struct walk_
{
svn_boolean_t is_ignored;
svn_boolean_t is_external;
- svn_wc_status3_t *status;
+ svn_wc__internal_status_t *status;
const char *base_name = svn_dirent_basename(local_abspath, NULL);
is_ignored = svn_wc_match_ignore_list(base_name, patterns, scratch_pool);
@@ -974,12 +1001,12 @@ send_unversioned_item(const struct walk_
is_external = is_external_path(wb->externals, local_abspath, scratch_pool);
if (is_external)
- status->node_status = svn_wc_status_external;
+ status->s.node_status = svn_wc_status_external;
/* We can have a tree conflict on an unversioned path, i.e. an incoming
* delete on a locally deleted path during an update. Don't ever ignore
* those! */
- if (status->conflicted)
+ if (status->s.conflicted)
is_ignored = FALSE;
/* If we aren't ignoring it, or if it's an externals path, pass this
@@ -988,7 +1015,7 @@ send_unversioned_item(const struct walk_
|| !is_ignored
|| is_external)
return svn_error_trace((*status_func)(status_baton, local_abspath,
- status, scratch_pool));
+ &status->s, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1091,7 +1118,7 @@ one_child_status(const struct walk_statu
/* Descend in subdirectories. */
if (depth == svn_depth_infinity
- && info->kind == svn_node_dir)
+ && info->has_descendants /* is dir, or was dir and tc descendants */)
{
SVN_ERR(get_dir_status(wb, local_abspath, TRUE,
dir_repos_root_url, dir_repos_relpath,
@@ -1451,9 +1478,15 @@ hash_stash(void *baton,
{
apr_hash_t *stat_hash = baton;
apr_pool_t *hash_pool = apr_hash_pool_get(stat_hash);
+ void *new_status = svn_wc_dup_status3(status, hash_pool);
+ const svn_wc__internal_status_t *old_status = (const void*)status;
+
+ /* Copy the internal/private data. */
+ svn_wc__internal_status_t *is = new_status;
+ is->has_descendants = old_status->has_descendants;
+
assert(! svn_hash_gets(stat_hash, path));
- svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path),
- svn_wc_dup_status3(status, hash_pool));
+ svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path), new_status);
return SVN_NO_ERROR;
}
@@ -1518,6 +1551,7 @@ tweak_statushash(void *baton,
/* If not, make it so. */
if (! statstruct)
{
+ svn_wc__internal_status_t *i_stat;
/* If this item isn't being added, then we're most likely
dealing with a non-recursive (or at least partially
non-recursive) working copy. Due to bugs in how the client
@@ -1533,8 +1567,9 @@ tweak_statushash(void *baton,
return SVN_NO_ERROR;
/* Use the public API to get a statstruct, and put it into the hash. */
- SVN_ERR(internal_status(&statstruct, db, local_abspath,
+ SVN_ERR(internal_status(&i_stat, db, local_abspath,
check_working_copy, pool, scratch_pool));
+ statstruct = &i_stat->s;
statstruct->repos_lock = repos_lock;
svn_hash_sets(statushash, apr_pstrdup(pool, local_abspath), statstruct);
}
@@ -1573,9 +1608,9 @@ tweak_statushash(void *baton,
statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
statstruct->repos_root_url =
- b->edit_baton->anchor_status->repos_root_url;
+ b->edit_baton->anchor_status->s.repos_root_url;
statstruct->repos_uuid =
- b->edit_baton->anchor_status->repos_uuid;
+ b->edit_baton->anchor_status->s.repos_uuid;
}
/* The last committed date, and author for deleted items
@@ -1615,9 +1650,9 @@ tweak_statushash(void *baton,
{
statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
statstruct->repos_root_url =
- b->edit_baton->anchor_status->repos_root_url;
+ b->edit_baton->anchor_status->s.repos_root_url;
statstruct->repos_uuid =
- b->edit_baton->anchor_status->repos_uuid;
+ b->edit_baton->anchor_status->s.repos_uuid;
}
statstruct->ood_kind = b->ood_kind;
if (b->ood_changed_author)
@@ -1633,7 +1668,7 @@ find_dir_repos_relpath(const struct dir_
{
/* If we have no name, we're the root, return the anchor URL. */
if (! db->name)
- return db->edit_baton->anchor_status->repos_relpath;
+ return db->edit_baton->anchor_status->s.repos_relpath;
else
{
const char *repos_relpath;
@@ -1665,7 +1700,7 @@ make_dir_baton(void **dir_baton,
struct edit_baton *eb = edit_baton;
struct dir_baton *d;
const char *local_abspath;
- const svn_wc_status3_t *status_in_parent;
+ const svn_wc__internal_status_t *status_in_parent;
apr_pool_t *dir_pool;
if (parent_baton)
@@ -1724,8 +1759,7 @@ make_dir_baton(void **dir_baton,
status_in_parent = eb->anchor_status;
if (status_in_parent
- && status_in_parent->versioned
- && (status_in_parent->kind == svn_node_dir)
+ && (status_in_parent->has_descendants)
&& (! d->excluded)
&& (d->depth == svn_depth_unknown
|| d->depth == svn_depth_infinity
@@ -1737,9 +1771,9 @@ make_dir_baton(void **dir_baton,
const apr_array_header_t *ignores = eb->ignores;
SVN_ERR(get_dir_status(&eb->wb, local_abspath, TRUE,
- status_in_parent->repos_root_url,
+ status_in_parent->s.repos_root_url,
NULL /*parent_repos_relpath*/,
- status_in_parent->repos_uuid,
+ status_in_parent->s.repos_uuid,
NULL,
NULL /* dirent */, ignores,
d->depth == svn_depth_files
@@ -1754,7 +1788,7 @@ make_dir_baton(void **dir_baton,
this_dir_status = svn_hash_gets(d->statii, d->local_abspath);
if (this_dir_status && this_dir_status->versioned
&& (d->depth == svn_depth_unknown
- || d->depth > status_in_parent->depth))
+ || d->depth > status_in_parent->s.depth))
{
d->depth = this_dir_status->depth;
}
@@ -1800,10 +1834,11 @@ make_file_baton(struct dir_baton *parent
* This implementation should match the filter in assemble_status()
*/
static svn_boolean_t
-is_sendable_status(const svn_wc_status3_t *status,
+is_sendable_status(const svn_wc__internal_status_t *i_status,
svn_boolean_t no_ignore,
svn_boolean_t get_all)
{
+ const svn_wc_status3_t *status = &i_status->s;
/* If the repository status was touched at all, it's interesting. */
if (status->repos_node_status != svn_wc_status_none)
return TRUE;
@@ -1829,8 +1864,8 @@ is_sendable_status(const svn_wc_status3_
return TRUE;
/* If the text, property or tree state is interesting, send it. */
- if ((status->node_status != svn_wc_status_none
- && (status->node_status != svn_wc_status_normal)))
+ if ((status->node_status != svn_wc_status_none)
+ && (status->node_status != svn_wc_status_normal))
return TRUE;
/* If it's switched, send it. */
@@ -1913,14 +1948,14 @@ handle_statii(struct edit_baton *eb,
for (hi = apr_hash_first(pool, statii); hi; hi = apr_hash_next(hi))
{
const char *local_abspath = apr_hash_this_key(hi);
- svn_wc_status3_t *status = apr_hash_this_val(hi);
+ svn_wc__internal_status_t *status = apr_hash_this_val(hi);
/* Clear the subpool. */
svn_pool_clear(iterpool);
/* Now, handle the status. We don't recurse for svn_depth_immediates
because we already have the subdirectories' statii. */
- if (status->versioned && status->kind == svn_node_dir
+ if (status->has_descendants
&& (depth == svn_depth_unknown
|| depth == svn_depth_infinity))
{
@@ -1936,9 +1971,9 @@ handle_statii(struct edit_baton *eb,
iterpool));
}
if (dir_was_deleted)
- status->repos_node_status = svn_wc_status_deleted;
+ status->s.repos_node_status = svn_wc_status_deleted;
if (is_sendable_status(status, eb->no_ignore, eb->get_all))
- SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, status,
+ SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, &status->s,
iterpool));
}
@@ -2138,17 +2173,17 @@ close_directory(void *dir_baton,
/* We're editing the root dir of the WC. As its repos
status info isn't otherwise set, set it directly to
trigger invocation of the status callback below. */
- eb->anchor_status->repos_node_status = repos_node_status;
- eb->anchor_status->repos_prop_status = repos_prop_status;
- eb->anchor_status->repos_text_status = repos_text_status;
+ eb->anchor_status->s.repos_node_status = repos_node_status;
+ eb->anchor_status->s.repos_prop_status = repos_prop_status;
+ eb->anchor_status->s.repos_text_status = repos_text_status;
/* If the root dir is out of date set the ood info directly too. */
- if (db->ood_changed_rev != eb->anchor_status->revision)
+ if (db->ood_changed_rev != eb->anchor_status->s.revision)
{
- eb->anchor_status->ood_changed_rev = db->ood_changed_rev;
- eb->anchor_status->ood_changed_date = db->ood_changed_date;
- eb->anchor_status->ood_kind = db->ood_kind;
- eb->anchor_status->ood_changed_author =
+ eb->anchor_status->s.ood_changed_rev = db->ood_changed_rev;
+ eb->anchor_status->s.ood_changed_date = db->ood_changed_date;
+ eb->anchor_status->s.ood_kind = db->ood_kind;
+ eb->anchor_status->s.ood_changed_author =
apr_pstrdup(pool, db->ood_changed_author);
}
}
@@ -2159,25 +2194,25 @@ close_directory(void *dir_baton,
if (pb && ! db->excluded)
{
svn_boolean_t was_deleted = FALSE;
- const svn_wc_status3_t *dir_status;
+ svn_wc__internal_status_t *dir_status;
/* See if the directory was deleted or replaced. */
dir_status = svn_hash_gets(pb->statii, db->local_abspath);
if (dir_status &&
- ((dir_status->repos_node_status == svn_wc_status_deleted)
- || (dir_status->repos_node_status == svn_wc_status_replaced)))
+ ((dir_status->s.repos_node_status == svn_wc_status_deleted)
+ || (dir_status->s.repos_node_status == svn_wc_status_replaced)))
was_deleted = TRUE;
/* Now do the status reporting. */
SVN_ERR(handle_statii(eb,
- dir_status ? dir_status->repos_root_url : NULL,
- dir_status ? dir_status->repos_relpath : NULL,
- dir_status ? dir_status->repos_uuid : NULL,
+ dir_status ? dir_status->s.repos_root_url : NULL,
+ dir_status ? dir_status->s.repos_relpath : NULL,
+ dir_status ? dir_status->s.repos_uuid : NULL,
db->statii, was_deleted, db->depth, scratch_pool));
if (dir_status && is_sendable_status(dir_status, eb->no_ignore,
eb->get_all))
SVN_ERR((eb->status_func)(eb->status_baton, db->local_abspath,
- dir_status, scratch_pool));
+ &dir_status->s, scratch_pool));
svn_hash_sets(pb->statii, db->local_abspath, NULL);
}
else if (! pb)
@@ -2186,13 +2221,12 @@ close_directory(void *dir_baton,
target, we should only report the target. */
if (*eb->target_basename)
{
- const svn_wc_status3_t *tgt_status;
+ const svn_wc__internal_status_t *tgt_status;
tgt_status = svn_hash_gets(db->statii, eb->target_abspath);
if (tgt_status)
{
- if (tgt_status->versioned
- && tgt_status->kind == svn_node_dir)
+ if (tgt_status->has_descendants)
{
SVN_ERR(get_dir_status(&eb->wb,
eb->target_abspath, TRUE,
@@ -2207,7 +2241,7 @@ close_directory(void *dir_baton,
}
if (is_sendable_status(tgt_status, eb->no_ignore, eb->get_all))
SVN_ERR((eb->status_func)(eb->status_baton, eb->target_abspath,
- tgt_status, scratch_pool));
+ &tgt_status->s, scratch_pool));
}
}
else
@@ -2216,15 +2250,15 @@ close_directory(void *dir_baton,
Note that our directory couldn't have been deleted,
because it is the root of the edit drive. */
SVN_ERR(handle_statii(eb,
- eb->anchor_status->repos_root_url,
- eb->anchor_status->repos_relpath,
- eb->anchor_status->repos_uuid,
+ eb->anchor_status->s.repos_root_url,
+ eb->anchor_status->s.repos_relpath,
+ eb->anchor_status->s.repos_uuid,
db->statii, FALSE, eb->default_depth,
scratch_pool));
if (is_sendable_status(eb->anchor_status, eb->no_ignore,
eb->get_all))
SVN_ERR((eb->status_func)(eb->status_baton, db->local_abspath,
- eb->anchor_status, scratch_pool));
+ &eb->anchor_status->s, scratch_pool));
eb->anchor_status = NULL;
}
}
@@ -2645,7 +2679,7 @@ svn_wc__internal_walk_status(svn_wc__db_
}
if (info
- && info->kind == svn_node_dir
+ && info->has_descendants /* is dir, or was dir and has tc descendants */
&& info->status != svn_wc__db_status_not_present
&& info->status != svn_wc__db_status_excluded
&& info->status != svn_wc__db_status_server_excluded)
@@ -2765,7 +2799,7 @@ svn_wc_get_default_ignores(apr_array_hea
/* */
static svn_error_t *
-internal_status(svn_wc_status3_t **status,
+internal_status(svn_wc__internal_status_t **status,
svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t check_working_copy,
@@ -2872,17 +2906,21 @@ svn_wc_status3(svn_wc_status3_t **status
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- return svn_error_trace(
- internal_status(status, wc_ctx->db, local_abspath,
- TRUE /* check_working_copy */,
- result_pool, scratch_pool));
+ svn_wc__internal_status_t *stat;
+ SVN_ERR(internal_status(&stat, wc_ctx->db, local_abspath,
+ TRUE /* check_working_copy */,
+ result_pool, scratch_pool));
+ *status = &stat->s;
+ return SVN_NO_ERROR;
}
svn_wc_status3_t *
svn_wc_dup_status3(const svn_wc_status3_t *orig_stat,
apr_pool_t *pool)
{
- svn_wc_status3_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
+ /* Allocate slightly more room */
+ svn_wc__internal_status_t *new_istat = apr_palloc(pool, sizeof(*new_istat));
+ svn_wc_status3_t *new_stat = &new_istat->s;
/* Shallow copy all members. */
*new_stat = *orig_stat;
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c Wed Mar 4 15:56:18 2015
@@ -1937,7 +1937,12 @@ add_directory(const char *path,
}
else if (status == svn_wc__db_status_normal)
{
- if (wc_kind == svn_node_dir)
+ svn_boolean_t root;
+
+ SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, db->local_abspath,
+ scratch_pool));
+
+ if (root)
{
/* !! We found the root of a working copy obstructing the wc !!
@@ -1949,9 +1954,16 @@ add_directory(const char *path,
resolved. Note that svn_wc__db_base_add_not_present_node()
explicitly adds the node into the parent's node database. */
- svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, db->name),
+ svn_hash_sets(pb->not_present_nodes,
+ apr_pstrdup(pb->pool, db->name),
svn_node_kind_to_word(svn_node_dir));
}
+ else if (wc_kind == svn_node_dir)
+ {
+ /* We have an editor violation. Github sometimes does this
+ in its subversion compatibility code, when changing the
+ depth of a working copy, or on updates from incomplete */
+ }
else
{
/* We found a file external occupating the place we need in BASE.
@@ -3108,18 +3120,32 @@ add_file(const char *path,
}
else if (status == svn_wc__db_status_normal)
{
- if (wc_kind == svn_node_dir)
+ svn_boolean_t root;
+
+ SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, fb->local_abspath,
+ scratch_pool));
+
+ if (root)
{
/* !! We found the root of a working copy obstructing the wc !!
If the directory would be part of our own working copy then
- we wouldn't have been called as an add_file().
+ we wouldn't have been called as an add_directory().
The only thing we can do is add a not-present node, to allow
a future update to bring in the new files when the problem is
- resolved. */
- svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
- svn_node_kind_to_word(svn_node_file));
+ resolved. Note that svn_wc__db_base_add_not_present_node()
+ explicitly adds the node into the parent's node database. */
+
+ svn_hash_sets(pb->not_present_nodes,
+ apr_pstrdup(pb->pool, fb->name),
+ svn_node_kind_to_word(svn_node_dir));
+ }
+ else if (wc_kind == svn_node_dir)
+ {
+ /* We have an editor violation. Github sometimes does this
+ in its subversion compatibility code, when changing the
+ depth of a working copy, or on updates from incomplete */
}
else
{
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c Wed Mar 4 15:56:18 2015
@@ -2366,40 +2366,6 @@ is_old_wcroot(const char *local_abspath,
svn_dirent_local_style(parent_abspath, scratch_pool));
}
-/* Data for upgrade_working_copy_txn(). */
-typedef struct upgrade_working_copy_baton_t
-{
- svn_wc__db_t *db;
- const char *dir_abspath;
- svn_wc_upgrade_get_repos_info_t repos_info_func;
- void *repos_info_baton;
- apr_hash_t *repos_cache;
- const struct upgrade_data_t *data;
- svn_cancel_func_t cancel_func;
- void *cancel_baton;
- svn_wc_notify_func2_t notify_func;
- void *notify_baton;
- apr_pool_t *result_pool;
-} upgrade_working_copy_baton_t;
-
-
-/* Helper for svn_wc_upgrade. Implements svn_sqlite__transaction_callback_t */
-static svn_error_t *
-upgrade_working_copy_txn(void *baton,
- svn_sqlite__db_t *sdb,
- apr_pool_t *scratch_pool)
-{
- upgrade_working_copy_baton_t *b = baton;
-
- /* Upgrade the pre-wcng into a wcng in a temporary location. */
- return(upgrade_working_copy(NULL, b->db, b->dir_abspath,
- b->repos_info_func, b->repos_info_baton,
- b->repos_cache, b->data,
- b->cancel_func, b->cancel_baton,
- b->notify_func, b->notify_baton,
- b->result_pool, scratch_pool));
-}
-
svn_error_t *
svn_wc_upgrade(svn_wc_context_t *wc_ctx,
const char *local_abspath,
@@ -2419,7 +2385,6 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
svn_wc_entry_t *this_dir;
apr_hash_t *entries;
const char *root_adm_abspath;
- upgrade_working_copy_baton_t cb_baton;
svn_error_t *err;
int result_format;
svn_boolean_t bumped_format;
@@ -2517,22 +2482,14 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
SVN_ERR(svn_wc__db_wclock_obtain(db, data.root_abspath, 0, FALSE,
scratch_pool));
- cb_baton.db = db;
- cb_baton.dir_abspath = local_abspath;
- cb_baton.repos_info_func = repos_info_func;
- cb_baton.repos_info_baton = repos_info_baton;
- cb_baton.repos_cache = repos_cache;
- cb_baton.data = &data;
- cb_baton.cancel_func = cancel_func;
- cb_baton.cancel_baton = cancel_baton;
- cb_baton.notify_func = notify_func;
- cb_baton.notify_baton = notify_baton;
- cb_baton.result_pool = scratch_pool;
-
- SVN_ERR(svn_sqlite__with_lock(data.sdb,
- upgrade_working_copy_txn,
- &cb_baton,
- scratch_pool));
+ SVN_SQLITE__WITH_LOCK(
+ upgrade_working_copy(NULL, db, local_abspath,
+ repos_info_func, repos_info_baton,
+ repos_cache, &data,
+ cancel_func, cancel_baton,
+ notify_func, notify_baton,
+ scratch_pool, scratch_pool),
+ data.sdb);
/* A workqueue item to move the pristine dir into place */
pristine_from = svn_wc__adm_child(data.root_abspath, PRISTINE_STORAGE_RELPATH,
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql Wed Mar 4 15:56:18 2015
@@ -46,7 +46,7 @@ SELECT op_depth, nodes.repos_id, nodes.r
lock_token, lock_owner, lock_comment, lock_date
FROM nodes
LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
- AND nodes.repos_path = lock.repos_relpath
+ AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth=0
WHERE wc_id = ?1 AND local_relpath = ?2
ORDER BY op_depth DESC
@@ -134,7 +134,7 @@ SELECT op_depth, nodes.repos_id, nodes.r
lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external
FROM nodes
LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
- AND nodes.repos_path = lock.repos_relpath AND op_depth = 0
+ AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth = 0
WHERE wc_id = ?1 AND parent_relpath = ?2
ORDER BY local_relpath DESC, op_depth DESC
@@ -148,7 +148,7 @@ SELECT op_depth, nodes.repos_id, nodes.r
lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external
FROM nodes
LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
- AND nodes.repos_path = lock.repos_relpath AND op_depth = 0
+ AND nodes.repos_path = lock.repos_relpath
WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0
ORDER BY local_relpath DESC
@@ -249,7 +249,8 @@ WHERE wc_id = ?1 AND IS_STRICT_DESCENDAN
-- STMT_DELETE_BASE_RECURSIVE
DELETE FROM nodes
-WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+WHERE wc_id = ?1 AND (local_relpath = ?2
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = 0
-- STMT_DELETE_WORKING_OP_DEPTH
@@ -954,6 +955,14 @@ SELECT local_dir_relpath FROM wc_lock
WHERE wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(local_dir_relpath, ?2)
+-- STMT_FIND_CONFLICT_DESCENDANT
+SELECT 1 FROM actual_node
+WHERE wc_id = ?1
+ AND local_relpath > (?2 || '/')
+ AND local_relpath < (?2 || '0') /* '0' = ascii('/') +1 */
+ AND conflict_data IS NOT NULL
+LIMIT 1
+
-- STMT_DELETE_WC_LOCK_ORPHAN
DELETE FROM wc_lock
WHERE wc_id = ?1 AND local_dir_relpath = ?2
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c Wed Mar 4 15:56:18 2015
@@ -2125,11 +2125,13 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
int op_depth;
svn_node_kind_t wrk_kind;
svn_boolean_t no_delete_wc = FALSE;
+ svn_boolean_t file_external;
SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, &revision,
&repos_relpath, &repos_id,
NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ &file_external,
wcroot, local_relpath,
scratch_pool, scratch_pool));
@@ -2360,35 +2362,69 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
- /* Step 5: handle the BASE node itself */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_DELETE_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
SVN_ERR(db_retract_parent_delete(wcroot, local_relpath, 0, scratch_pool));
if (mark_not_present || mark_excluded)
{
struct insert_base_baton_t ibb;
- blank_ibb(&ibb);
+ svn_boolean_t no_marker = FALSE;
- ibb.repos_id = repos_id;
- ibb.status = mark_excluded ? svn_wc__db_status_excluded
- : svn_wc__db_status_not_present;
- ibb.kind = kind;
- ibb.repos_relpath = repos_relpath;
- ibb.revision = SVN_IS_VALID_REVNUM(marker_revision)
- ? marker_revision
- : revision;
-
- /* Depending upon KIND, any of these might get used. */
- ibb.children = NULL;
- ibb.depth = svn_depth_unknown;
- ibb.checksum = NULL;
- ibb.target = NULL;
+ if (file_external)
+ {
+ const char *parent_local_relpath;
+ const char *name;
+ svn_error_t *err;
- SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+ /* For file externals we only want to place a not present marker
+ if there is a BASE parent */
+
+ svn_relpath_split(&parent_local_relpath, &name, local_relpath,
+ scratch_pool);
+
+ err = svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
+ &repos_relpath, &repos_id,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ wcroot, parent_local_relpath,
+ scratch_pool, scratch_pool);
+
+ if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_trace(err);
+ else if (err)
+ {
+ svn_error_clear(err);
+ no_marker = TRUE;
+ }
+ else
+ {
+ /* Replace the repos_relpath with something more expected than
+ the unrelated old file external repository relpath, which
+ one day may come from a different repository */
+ repos_relpath = svn_relpath_join(repos_relpath, name, scratch_pool);
+ }
+ }
+
+ if (!no_marker)
+ {
+ blank_ibb(&ibb);
+
+ ibb.repos_id = repos_id;
+ ibb.status = mark_excluded ? svn_wc__db_status_excluded
+ : svn_wc__db_status_not_present;
+ ibb.kind = kind;
+ ibb.repos_relpath = repos_relpath;
+ ibb.revision = SVN_IS_VALID_REVNUM(marker_revision)
+ ? marker_revision
+ : revision;
+
+ /* Depending upon KIND, any of these might get used. */
+ ibb.children = NULL;
+ ibb.depth = svn_depth_unknown;
+ ibb.checksum = NULL;
+ ibb.target = NULL;
+
+ SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+ }
}
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
@@ -3007,6 +3043,11 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
}
+/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
+typedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool);
/* Baton for passing args to with_triggers(). */
struct with_triggers_baton_t {
@@ -3083,8 +3124,13 @@ with_finalization(svn_wc__db_wcroot_t *w
svn_error_t *err1;
svn_error_t *err2;
- err1 = svn_wc__db_with_txn(wcroot, local_relpath, txn_cb, txn_baton,
- scratch_pool);
+ err1 = svn_sqlite__begin_savepoint(wcroot->sdb);
+ if (!err1)
+ {
+ err1 = txn_cb(txn_baton, wcroot, local_relpath, scratch_pool);
+
+ err1 = svn_sqlite__finish_savepoint(wcroot->sdb, err1);
+ }
if (err1 == NULL && notify_func != NULL)
{
@@ -3470,11 +3516,18 @@ db_external_remove(const svn_skel_t *wor
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
+ int affected_rows;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_DELETE_EXTERNAL));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+ if (!affected_rows)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' is not an external."),
+ path_for_error_message(wcroot, local_relpath,
+ scratch_pool));
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
@@ -3957,14 +4010,14 @@ get_moved_to(const char **moved_to_relpa
/* The body of svn_wc__db_scan_deletion().
*/
static svn_error_t *
-scan_deletion_txn(const char **base_del_relpath,
- const char **moved_to_relpath,
- const char **work_del_relpath,
- const char **moved_to_op_root_relpath,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+scan_deletion(const char **base_del_relpath,
+ const char **moved_to_relpath,
+ const char **work_del_relpath,
+ const char **moved_to_op_root_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
const char *current_relpath = local_relpath;
svn_sqlite__stmt_t *stmt;
@@ -4109,6 +4162,25 @@ scan_deletion_txn(const char **base_del_
}
svn_error_t *
+svn_wc__db_scan_deletion_internal(
+ const char **base_del_relpath,
+ const char **moved_to_relpath,
+ const char **work_del_relpath,
+ const char **moved_to_op_root_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(
+ scan_deletion(base_del_relpath, moved_to_relpath, work_del_relpath,
+ moved_to_op_root_relpath,
+ wcroot, local_relpath,
+ result_pool, scratch_pool));
+}
+
+
+svn_error_t *
svn_wc__db_scan_deletion(const char **base_del_abspath,
const char **moved_to_abspath,
const char **work_del_abspath,
@@ -4130,9 +4202,9 @@ svn_wc__db_scan_deletion(const char **ba
VERIFY_USABLE_WCROOT(wcroot);
SVN_WC__DB_WITH_TXN(
- scan_deletion_txn(&base_del_relpath, &moved_to_relpath,
- &work_del_relpath, &moved_to_op_root_relpath,
- wcroot, local_relpath, result_pool, scratch_pool),
+ scan_deletion(&base_del_relpath, &moved_to_relpath,
+ &work_del_relpath, &moved_to_op_root_relpath,
+ wcroot, local_relpath, result_pool, scratch_pool),
wcroot);
if (base_del_abspath)
@@ -4230,10 +4302,10 @@ get_info_for_copy(apr_int64_t *copyfrom_
{
const char *base_del_relpath, *work_del_relpath;
- SVN_ERR(scan_deletion_txn(&base_del_relpath, NULL,
- &work_del_relpath,
- NULL, src_wcroot, local_relpath,
- scratch_pool, scratch_pool));
+ SVN_ERR(scan_deletion(&base_del_relpath, NULL,
+ &work_del_relpath,
+ NULL, src_wcroot, local_relpath,
+ scratch_pool, scratch_pool));
if (work_del_relpath)
{
const char *op_root_relpath;
@@ -8990,10 +9062,8 @@ read_info(svn_wc__db_status_t *status,
err = svn_error_compose_create(err, svn_sqlite__reset(stmt_act));
if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- err = svn_error_quick_wrap(err,
- apr_psprintf(scratch_pool,
- _("Error reading node '%s'"),
- local_relpath));
+ err = svn_error_quick_wrapf(err, _("Error reading node '%s'"),
+ local_relpath);
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt_info)));
@@ -9113,6 +9183,27 @@ is_wclocked(svn_boolean_t *locked,
const char *dir_relpath,
apr_pool_t *scratch_pool);
+/* Helper for read_children_info and single variant */
+static svn_error_t *
+find_conflict_descendants(svn_boolean_t *conflict_exists,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+
+ /* Only used on files, so certainly not wcroot*/
+ assert(local_relpath[0] != '\0');
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_FIND_CONFLICT_DESCENDANT));
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(conflict_exists, stmt));
+
+ return svn_error_trace(svn_sqlite__reset(stmt));
+}
+
/* What we really want to store about a node. This relies on the
offset of svn_wc__db_info_t being zero. */
struct read_children_info_item_t
@@ -9120,6 +9211,7 @@ struct read_children_info_item_t
struct svn_wc__db_info_t info;
int op_depth;
int nr_layers;
+ svn_boolean_t was_dir;
};
/* Implementation of svn_wc__db_read_children_info */
@@ -9169,7 +9261,7 @@ read_children_info(svn_wc__db_wcroot_t *
op_depth = svn_sqlite__column_int(stmt, 0);
/* Do we have new or better information? */
- if (new_child || op_depth > child_item->op_depth)
+ if (new_child)
{
struct svn_wc__db_info_t *child = &child_item->info;
child_item->op_depth = op_depth;
@@ -9250,6 +9342,8 @@ read_children_info(svn_wc__db_wcroot_t *
child->depth = svn_depth_unknown;
else
{
+ child->has_descendants = TRUE;
+ child_item->was_dir = TRUE;
child->depth = svn_sqlite__column_token_null(stmt, 11, depth_map,
svn_depth_unknown);
if (new_child)
@@ -9292,6 +9386,17 @@ read_children_info(svn_wc__db_wcroot_t *
if (new_child)
svn_hash_sets(nodes, apr_pstrdup(result_pool, name), child);
}
+ else if (!child_item->was_dir
+ && svn_sqlite__column_token(stmt, 4, kind_map) == svn_node_dir)
+ {
+ child_item->was_dir = TRUE;
+
+ err = find_conflict_descendants(&child_item->info.has_descendants,
+ wcroot, child_relpath,
+ scratch_pool);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ }
if (op_depth == 0)
{
@@ -9600,6 +9705,12 @@ read_single_info(const struct svn_wc__db
if (!base_tree_only && mtb->kind == svn_node_dir)
SVN_ERR(is_wclocked(&mtb->locked, wcroot, local_relpath, scratch_pool));
+ if (mtb->kind == svn_node_dir)
+ mtb->has_descendants = TRUE;
+ else
+ SVN_ERR(find_conflict_descendants(&mtb->has_descendants,
+ wcroot, local_relpath, scratch_pool));
+
*info = mtb;
return SVN_NO_ERROR;
@@ -9965,12 +10076,12 @@ db_read_repos_info(svn_revnum_t *revisio
const char *base_del_relpath;
const char *work_del_relpath;
- SVN_ERR(scan_deletion_txn(&base_del_relpath, NULL,
- &work_del_relpath,
- NULL, wcroot,
- local_relpath,
- scratch_pool,
- scratch_pool));
+ SVN_ERR(scan_deletion(&base_del_relpath, NULL,
+ &work_del_relpath,
+ NULL, wcroot,
+ local_relpath,
+ scratch_pool,
+ scratch_pool));
if (work_del_relpath)
{
@@ -11197,11 +11308,11 @@ relocate_txn(svn_wc__db_wcroot_t *wcroot
{
const char *work_del_relpath;
- SVN_ERR(scan_deletion_txn(NULL, NULL,
- &work_del_relpath, NULL,
- wcroot, local_dir_relpath,
- scratch_pool,
- scratch_pool));
+ SVN_ERR(scan_deletion(NULL, NULL,
+ &work_del_relpath, NULL,
+ wcroot, local_dir_relpath,
+ scratch_pool,
+ scratch_pool));
if (work_del_relpath)
{
/* Deleted within a copy/move */
@@ -11289,59 +11400,86 @@ svn_wc__db_global_relocate(svn_wc__db_t
}
-/* Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
+/* Helper for commit_node()
+ Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
(WCROOT, LOCAL_RELPATH), directly if its BASE row exists or implied from
its parent's BASE row if not. In the latter case, error if the parent
BASE row does not exist. */
static svn_error_t *
-determine_repos_info(apr_int64_t *repos_id,
- const char **repos_relpath,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+determine_commit_repos_info(apr_int64_t *repos_id,
+ const char **repos_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ 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? */
+ int op_depth;
/* Prefer the current node's repository information. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_BASE_NODE));
+ STMT_SELECT_NODE_INFO));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (have_row)
+ 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));
+
+ op_depth = svn_sqlite__column_int(stmt, 0);
+
+ if (op_depth > 0)
{
- SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
- SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+ svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 3,
+ presence_map);
- *repos_id = svn_sqlite__column_int64(stmt, 0);
- *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+ if (presence == svn_wc__db_status_base_deleted)
+ {
+ SVN_ERR(svn_sqlite__step_row(stmt)); /* There must be a row */
+ op_depth = svn_sqlite__column_int(stmt, 0);
+ }
+ else
+ {
+ const char *parent_repos_relpath;
+ const char *parent_relpath;
+ const char *name;
- return svn_error_trace(svn_sqlite__reset(stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ /* The repository relative path of an add/copy is based on its
+ ancestor, not on the shadowed base layer.
+
+ As this function is only used from the commit processing we know
+ the parent directory has only a BASE row, so we can just obtain
+ the information directly by recursing (once!) */
+
+ svn_relpath_split(&parent_relpath, &name, local_relpath,
+ scratch_pool);
+
+ SVN_ERR(determine_commit_repos_info(repos_id, &parent_repos_relpath,
+ wcroot, parent_relpath,
+ scratch_pool, scratch_pool));
+
+ *repos_relpath = svn_relpath_join(parent_repos_relpath, name,
+ result_pool);
+ return SVN_NO_ERROR;
+ }
}
- SVN_ERR(svn_sqlite__reset(stmt));
- /* This was a child node within this wcroot. We want to look at the
- BASE node of the directory. */
- svn_relpath_split(&local_parent_relpath, &name, local_relpath, scratch_pool);
+ SVN_ERR_ASSERT(op_depth == 0); /* And that row must be BASE */
- /* The REPOS_ID will be the same (### until we support mixed-repos) */
- SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
- &repos_parent_relpath, repos_id,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- wcroot, local_parent_relpath,
- scratch_pool, scratch_pool));
+ SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+ SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 2));
- *repos_relpath = svn_relpath_join(repos_parent_relpath, name, result_pool);
+ *repos_id = svn_sqlite__column_int64(stmt, 1);
+ *repos_relpath = svn_sqlite__column_text(stmt, 2, result_pool);
- return SVN_NO_ERROR;
+ return svn_error_trace(svn_sqlite__reset(stmt));
}
static svn_error_t *
@@ -11548,9 +11686,9 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
For existing nodes, we should retain the (potentially-switched)
repository information. */
- SVN_ERR(determine_repos_info(&repos_id, &repos_relpath,
- wcroot, local_relpath,
- scratch_pool, scratch_pool));
+ SVN_ERR(determine_commit_repos_info(&repos_id, &repos_relpath,
+ wcroot, local_relpath,
+ scratch_pool, scratch_pool));
/* ### is it better to select only the data needed? */
SVN_ERR(svn_sqlite__get_statement(&stmt_info, wcroot->sdb,
@@ -12747,6 +12885,27 @@ scan_addition(svn_wc__db_status_t *statu
}
svn_error_t *
+svn_wc__db_scan_addition_internal(
+ svn_wc__db_status_t *status,
+ const char **op_root_relpath_p,
+ const char **repos_relpath,
+ apr_int64_t *repos_id,
+ const char **original_repos_relpath,
+ apr_int64_t *original_repos_id,
+ svn_revnum_t *original_revision,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(
+ scan_addition(status, op_root_relpath_p, repos_relpath, repos_id,
+ original_repos_relpath, original_repos_id,
+ original_revision, NULL, NULL, NULL,
+ wcroot, local_relpath, result_pool, scratch_pool));
+}
+
+svn_error_t *
svn_wc__db_scan_addition(svn_wc__db_status_t *status,
const char **op_root_abspath,
const char **repos_relpath,
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h Wed Mar 4 15:56:18 2015
@@ -20,7 +20,7 @@
* ====================================================================
* @endcopyright
*
- * @file svn_wc_db.h
+ * @file wc_db.h
* @brief The Subversion Working Copy Library - Metadata/Base-Text Support
*
* Requires:
@@ -2019,6 +2019,7 @@ struct svn_wc__db_info_t {
svn_boolean_t moved_here; /* Only on op-roots. */
svn_boolean_t file_external;
+ svn_boolean_t has_descendants; /* Is dir, or has tc descendants */
};
/* Return in *NODES a hash mapping name->struct svn_wc__db_info_t for
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h Wed Mar 4 15:56:18 2015
@@ -313,6 +313,32 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+svn_error_t *
+svn_wc__db_scan_addition_internal(
+ svn_wc__db_status_t *status,
+ const char **op_root_relpath_p,
+ const char **repos_relpath,
+ apr_int64_t *repos_id,
+ const char **original_repos_relpath,
+ apr_int64_t *original_repos_id,
+ svn_revnum_t *original_revision,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+svn_error_t *
+svn_wc__db_scan_deletion_internal(
+ const char **base_del_relpath,
+ const char **moved_to_relpath,
+ const char **work_del_relpath,
+ const char **moved_to_op_root_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
/* Look up REPOS_ID in WCROOT->SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID
to its root URL and UUID respectively. If REPOS_ID is INVALID_REPOS_ID,
use NULL for both URL and UUID. Either or both output parameters may be
@@ -345,23 +371,6 @@ svn_wc__db_mark_conflict_internal(svn_wc
/* Transaction handling */
-/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
-typedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool);
-
-
-/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and
- LOCAL_RELPATH. If callbacks require additional information, they may
- provide it using CB_BATON. */
-svn_error_t *
-svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- svn_wc__db_txn_callback_t cb_func,
- void *cb_baton,
- apr_pool_t *scratch_pool);
-
/* Evaluate the expression EXPR within a transaction.
*
* Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which would
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c Wed Mar 4 15:56:18 2015
@@ -400,7 +400,7 @@ create_tree_conflict(svn_skel_t **confli
if (conflict_operation != svn_wc_operation_update
&& conflict_operation != svn_wc_operation_switch)
- return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
_("'%s' already in conflict"),
path_for_error_message(wcroot, local_relpath,
scratch_pool));
@@ -424,7 +424,7 @@ create_tree_conflict(svn_skel_t **confli
&& strcmp(move_src_op_root_relpath,
svn_dirent_skip_ancestor(wcroot->abspath,
existing_abspath))))
- return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+ return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
_("'%s' already in conflict"),
path_for_error_message(wcroot,
local_relpath,
@@ -2487,7 +2487,7 @@ static svn_error_t *
break_moved_away(svn_wc__db_wcroot_t *wcroot,
svn_wc__db_t *db,
const char *local_relpath,
- int src_op_depth,
+ int parent_src_op_depth,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
@@ -2501,7 +2501,7 @@ break_moved_away(svn_wc__db_wcroot_t *wc
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_MOVED_DESCENDANTS_SRC));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
- src_op_depth));
+ parent_src_op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
iterpool = svn_pool_create(scratch_pool);
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c Wed Mar 4 15:56:18 2015
@@ -152,63 +152,3 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
return SVN_NO_ERROR;
}
-
-/* Some helpful transaction helpers.
-
- Instead of directly using SQLite transactions, these wrappers
- relieve the consumer from the need to wrap the wcroot and
- local_relpath, which are almost always used within the transaction.
-
- This also means if we later want to implement some wc_db-specific txn
- handling, we have a convenient place to do it.
- */
-
-/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
-typedef svn_error_t *(*db_txn_callback_t)(void *baton,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool);
-
-/* Baton for use with run_txn() and with_db_txn(). */
-struct txn_baton_t
-{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath;
-
- db_txn_callback_t cb_func;
- void *cb_baton;
-};
-
-
-/* Unwrap the sqlite transaction into a wc_db txn.
- Implements svn_sqlite__transaction_callback_t. */
-static svn_error_t *
-run_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
-{
- struct txn_baton_t *tb = baton;
-
- return svn_error_trace(
- tb->cb_func(tb->cb_baton, tb->wcroot, tb->local_relpath, scratch_pool));
-}
-
-
-/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and
- LOCAL_RELPATH. If callbacks require additional information, they may
- provide it using CB_BATON. */
-svn_error_t *
-svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- svn_wc__db_txn_callback_t cb_func,
- void *cb_baton,
- apr_pool_t *scratch_pool)
-{
- struct txn_baton_t tb;
-
- tb.wcroot = wcroot;
- tb.local_relpath = local_relpath;
- tb.cb_func = cb_func;
- tb.cb_baton = cb_baton;
-
- return svn_error_trace(
- svn_sqlite__with_lock(wcroot->sdb, run_txn, &tb, scratch_pool));
-}
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c Wed Mar 4 15:56:18 2015
@@ -702,11 +702,9 @@ try_symlink_as_dir:
if (err)
{
if (err->apr_err == SVN_ERR_WC_CORRUPT)
- return svn_error_quick_wrap(
- err, apr_psprintf(scratch_pool,
- _("Missing a row in WCROOT for '%s'."),
- svn_dirent_local_style(original_abspath,
- scratch_pool)));
+ return svn_error_quick_wrapf(
+ err, _("Missing a row in WCROOT for '%s'."),
+ svn_dirent_local_style(original_abspath, scratch_pool));
return svn_error_trace(err);
}
Modified: subversion/branches/reuse-ra-session/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/svn/cl.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/svn/cl.h (original)
+++ subversion/branches/reuse-ra-session/subversion/svn/cl.h Wed Mar 4 15:56:18 2015
@@ -167,7 +167,6 @@ typedef struct svn_cl__opt_state_t
svn_boolean_t version; /* print version information */
svn_boolean_t verbose; /* be verbose */
svn_boolean_t update; /* contact the server for the full story */
- svn_boolean_t strict; /* do strictly what was requested */
svn_stringbuf_t *filedata; /* contents of file used as option data
(not converted to UTF-8) */
const char *encoding; /* the locale/encoding of 'message' and of
@@ -249,6 +248,7 @@ typedef struct svn_cl__opt_state_t
svn_boolean_t no_newline; /* do not output the trailing newline */
svn_boolean_t show_passwords; /* show cached passwords */
svn_boolean_t pin_externals; /* pin externals to last-changed revisions */
+ const char *show_item; /* print only the given item */
} svn_cl__opt_state_t;
@@ -855,6 +855,48 @@ svn_cl__deprecated_merge_reintegrate(con
svn_client_ctx_t *ctx,
apr_pool_t *pool);
+
+/* Forward declaration of the similarity check context. */
+typedef struct svn_cl__simcheck_context_t svn_cl__simcheck_context_t;
+
+/* Token definition for the similarity check. */
+typedef struct svn_cl__simcheck_t
+{
+ /* The token we're checking for similarity. */
+ svn_string_t token;
+
+ /* User data associated with this token. */
+ const void *data;
+
+ /*
+ * The following fields are populated by svn_cl__similarity_check.
+ */
+
+ /* Similarity score [0..SVN_STRING__SIM_RANGE_MAX] */
+ apr_size_t score;
+
+ /* Number of characters of difference from the key. */
+ apr_size_t diff;
+
+ /* Similarity check context (private) */
+ svn_cl__simcheck_context_t *context;
+} svn_cl__simcheck_t;
+
+/* Find the entries in TOKENS that are most similar to KEY.
+ * TOKEN_COUNT is the number of entries in the (mutable) TOKENS array.
+ * Use SCRATCH_POOL for temporary allocations.
+ *
+ * On return, the TOKENS array will be sorted according to similarity
+ * to KEY, in descending order. The return value will be zero if the
+ * first token is an exact match; otherwise, it will be one more than
+ * the number of tokens that are at least two-thirds similar to KEY.
+ */
+apr_size_t
+svn_cl__similarity_check(const char *key,
+ svn_cl__simcheck_t **tokens,
+ apr_size_t token_count,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c (original)
+++ subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c Wed Mar 4 15:56:18 2015
@@ -76,6 +76,168 @@ schedule_str(svn_wc_schedule_t schedule)
}
}
+/* Return a relative URL from information in INFO using POOL for
+ temporary allocation. */
+static const char*
+relative_url(const svn_client_info2_t *info, apr_pool_t *pool)
+{
+ return apr_pstrcat(pool, "^/",
+ svn_path_uri_encode(
+ svn_uri_skip_ancestor(info->repos_root_URL,
+ info->URL, pool),
+ pool), SVN_VA_NULL);
+}
+
+
+/* The kinds of items for print_info_item(). */
+typedef enum
+{
+ /* Entry kind */
+ info_item_kind,
+
+ /* Repository location. */
+ info_item_url,
+ info_item_relative_url,
+ info_item_repos_root_url,
+ info_item_repos_uuid,
+
+ /* Working copy revision or repository HEAD revision */
+ info_item_revision,
+
+ /* Commit details. */
+ info_item_last_changed_rev,
+ info_item_last_changed_date,
+ info_item_last_changed_author,
+
+ /* Working copy information */
+ info_item_wc_root
+} info_item_t;
+
+/* Mapping between option keywords and info_item_t. */
+typedef struct info_item_map_t
+{
+ const svn_string_t keyword;
+ const info_item_t print_what;
+} info_item_map_t;
+
+#define MAKE_STRING(x) { x, sizeof(x) - 1 }
+static const info_item_map_t info_item_map[] =
+ {
+ { MAKE_STRING("kind"), info_item_kind },
+ { MAKE_STRING("url"), info_item_url },
+ { MAKE_STRING("relative-url"), info_item_relative_url },
+ { MAKE_STRING("repos-root-url"), info_item_repos_root_url },
+ { MAKE_STRING("repos-uuid"), info_item_repos_uuid },
+ { MAKE_STRING("revision"), info_item_revision },
+ { MAKE_STRING("last-changed-revision"),
+ info_item_last_changed_rev },
+ { MAKE_STRING("last-changed-date"), info_item_last_changed_date },
+ { MAKE_STRING("last-changed-author"), info_item_last_changed_author },
+ { MAKE_STRING("wc-root"), info_item_wc_root }
+ };
+#undef MAKE_STRING
+
+static const apr_size_t info_item_map_len =
+ (sizeof(info_item_map) / sizeof(info_item_map[0]));
+
+
+/* The baton type used by the info receiver functions. */
+typedef struct print_info_baton_t
+{
+ /* The path prefix that output paths should be normalized to. */
+ const char *path_prefix;
+
+ /*
+ * The following fields are used by print_info_item().
+ */
+
+ /* Which item to print. */
+ info_item_t print_what;
+
+ /* Do we expect to show info for multiple targets? */
+ svn_boolean_t multiple_targets;
+
+ /* TRUE iff the current is a local path. */
+ svn_boolean_t target_is_path;
+
+ /* Did we already print a line of output? */
+ svn_boolean_t start_new_line;
+} print_info_baton_t;
+
+
+/* Find the appropriate info_item_t for KEYWORD and initialize
+ * RECEIVER_BATON for print_info_item(). Use SCRATCH_POOL for
+ * temporary allocation.
+ */
+static svn_error_t *
+find_print_what(const char *keyword,
+ print_info_baton_t *receiver_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_cl__simcheck_t **keywords = apr_palloc(
+ scratch_pool, info_item_map_len * sizeof(svn_cl__simcheck_t*));
+ svn_cl__simcheck_t *kwbuf = apr_palloc(
+ scratch_pool, info_item_map_len * sizeof(svn_cl__simcheck_t));
+ apr_size_t i;
+
+ for (i = 0; i < info_item_map_len; ++i)
+ {
+ keywords[i] = &kwbuf[i];
+ kwbuf[i].token.data = info_item_map[i].keyword.data;
+ kwbuf[i].token.len = info_item_map[i].keyword.len;
+ kwbuf[i].data = &info_item_map[i];
+ }
+
+ switch (svn_cl__similarity_check(keyword, keywords,
+ info_item_map_len, scratch_pool))
+ {
+ const info_item_map_t *kw0;
+ const info_item_map_t *kw1;
+ const info_item_map_t *kw2;
+
+ case 0: /* Exact match. */
+ kw0 = keywords[0]->data;
+ receiver_baton->print_what = kw0->print_what;
+ return SVN_NO_ERROR;
+
+ case 1:
+ /* The best alternative isn't good enough */
+ return svn_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid value for --show-item"),
+ keyword);
+
+ case 2:
+ /* There is only one good candidate */
+ kw0 = keywords[0]->data;
+ return svn_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid value for --show-item;"
+ " did you mean '%s'?"),
+ keyword, kw0->keyword.data);
+
+ case 3:
+ /* Suggest a list of the most likely candidates */
+ kw0 = keywords[0]->data;
+ kw1 = keywords[1]->data;
+ return svn_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid value for --show-item;"
+ " did you mean '%s' or '%s'?"),
+ keyword, kw0->keyword.data, kw1->keyword.data);
+
+ default:
+ /* Never suggest more than three candidates */
+ kw0 = keywords[0]->data;
+ kw1 = keywords[1]->data;
+ kw2 = keywords[2]->data;
+ return svn_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid value for --show-item;"
+ " did you mean '%s', '%s' or '%s'?"),
+ keyword, kw0->keyword.data, kw1->keyword.data, kw2->keyword.data);
+ }
+}
/* A callback of type svn_client_info_receiver2_t.
Prints svn info in xml mode to standard out */
@@ -87,7 +249,7 @@ print_info_xml(void *baton,
{
svn_stringbuf_t *sb = svn_stringbuf_create_empty(pool);
const char *rev_str;
- const char *path_prefix = baton;
+ print_info_baton_t *const receiver_baton = baton;
if (SVN_IS_VALID_REVNUM(info->rev))
rev_str = apr_psprintf(pool, "%ld", info->rev);
@@ -97,7 +259,7 @@ print_info_xml(void *baton,
/* "<entry ...>" */
svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
"path", svn_cl__local_style_skip_ancestor(
- path_prefix, target, pool),
+ receiver_baton->path_prefix, target, pool),
"kind", svn_cl__node_kind_str_xml(info->kind),
"revision", rev_str,
SVN_VA_NULL);
@@ -109,13 +271,7 @@ print_info_xml(void *baton,
{
/* "<relative-url> xx </relative-url>" */
svn_cl__xml_tagged_cdata(&sb, pool, "relative-url",
- apr_pstrcat(pool, "^/",
- svn_path_uri_encode(
- svn_uri_skip_ancestor(
- info->repos_root_URL,
- info->URL, pool),
- pool),
- SVN_VA_NULL));
+ relative_url(info, pool));
}
if (info->repos_root_URL || info->repos_UUID)
@@ -263,11 +419,11 @@ print_info(void *baton,
const svn_client_info2_t *info,
apr_pool_t *pool)
{
- const char *path_prefix = baton;
+ print_info_baton_t *const receiver_baton = baton;
SVN_ERR(svn_cmdline_printf(pool, _("Path: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix, target, pool)));
+ receiver_baton->path_prefix, target, pool)));
/* ### remove this someday: it's only here for cmdline output
compatibility with svn 1.1 and older. */
@@ -285,11 +441,8 @@ print_info(void *baton,
SVN_ERR(svn_cmdline_printf(pool, _("URL: %s\n"), info->URL));
if (info->URL && info->repos_root_URL)
- SVN_ERR(svn_cmdline_printf(pool, _("Relative URL: ^/%s\n"),
- svn_path_uri_encode(
- svn_uri_skip_ancestor(info->repos_root_URL,
- info->URL, pool),
- pool)));
+ SVN_ERR(svn_cmdline_printf(pool, _("Relative URL: %s\n"),
+ relative_url(info, pool)));
if (info->repos_root_URL)
SVN_ERR(svn_cmdline_printf(pool, _("Repository Root: %s\n"),
@@ -391,14 +544,14 @@ print_info(void *baton,
if (info->wc_info->moved_from_abspath)
SVN_ERR(svn_cmdline_printf(pool, _("Moved From: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix,
+ receiver_baton->path_prefix,
info->wc_info->moved_from_abspath,
pool)));
if (info->wc_info->moved_to_abspath)
SVN_ERR(svn_cmdline_printf(pool, _("Moved To: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix,
+ receiver_baton->path_prefix,
info->wc_info->moved_to_abspath,
pool)));
}
@@ -446,21 +599,24 @@ print_info(void *baton,
SVN_ERR(svn_cmdline_printf(pool,
_("Conflict Previous Base File: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix, conflict->base_abspath,
+ receiver_baton->path_prefix,
+ conflict->base_abspath,
pool)));
if (conflict->my_abspath)
SVN_ERR(svn_cmdline_printf(pool,
_("Conflict Previous Working File: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix, conflict->my_abspath,
+ receiver_baton->path_prefix,
+ conflict->my_abspath,
pool)));
if (conflict->their_abspath)
SVN_ERR(svn_cmdline_printf(pool,
_("Conflict Current Base File: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix, conflict->their_abspath,
+ receiver_baton->path_prefix,
+ conflict->their_abspath,
pool)));
break;
@@ -469,7 +625,7 @@ print_info(void *baton,
SVN_ERR(svn_cmdline_printf(pool,
_("Conflict Properties File: %s\n"),
svn_cl__local_style_skip_ancestor(
- path_prefix,
+ receiver_baton->path_prefix,
conflict->prop_reject_abspath,
pool)));
printed_prop_conflict_file = TRUE;
@@ -577,6 +733,123 @@ print_info(void *baton,
}
+/* Helper for print_info_item(): Print the value TEXT for TARGET_PATH,
+ either of which may be NULL. Use POOL for temporary allocation. */
+static svn_error_t *
+print_info_item_string(const char *text, const char *target_path,
+ apr_pool_t *pool)
+{
+ if (text)
+ {
+ if (target_path)
+ SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", text, target_path));
+ else
+ SVN_ERR(svn_cmdline_fputs(text, stdout, pool));
+ }
+ else if (target_path)
+ SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", "", target_path));
+
+ return SVN_NO_ERROR;
+}
+
+/* Helper for print_info_item(): Print the revision number REV, which
+ may be SVN_INVALID_REVNUM, for TARGET_PATH, which may be NULL. Use
+ POOL for temporary allocation. */
+static svn_error_t *
+print_info_item_revision(svn_revnum_t rev, const char *target_path,
+ apr_pool_t *pool)
+{
+ if (SVN_IS_VALID_REVNUM(rev))
+ {
+ if (target_path)
+ SVN_ERR(svn_cmdline_printf(pool, "%-10ld %s", rev, target_path));
+ else
+ SVN_ERR(svn_cmdline_printf(pool, "%-10ld", rev));
+ }
+ else if (target_path)
+ SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", "", target_path));
+
+ return SVN_NO_ERROR;
+}
+
+/* A callback of type svn_client_info_receiver2_t. */
+static svn_error_t *
+print_info_item(void *baton,
+ const char *target,
+ const svn_client_info2_t *info,
+ apr_pool_t *pool)
+{
+ print_info_baton_t *const receiver_baton = baton;
+ const char *const target_path =
+ (!receiver_baton->multiple_targets ? NULL
+ : (!receiver_baton->target_is_path ? info->URL
+ : svn_cl__local_style_skip_ancestor(
+ receiver_baton->path_prefix, target, pool)));
+
+ if (receiver_baton->start_new_line)
+ SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
+
+ switch (receiver_baton->print_what)
+ {
+ case info_item_kind:
+ SVN_ERR(print_info_item_string(svn_node_kind_to_word(info->kind),
+ target_path, pool));
+ break;
+
+ case info_item_url:
+ SVN_ERR(print_info_item_string(info->URL, target_path, pool));
+ break;
+
+ case info_item_relative_url:
+ SVN_ERR(print_info_item_string(relative_url(info, pool),
+ target_path, pool));
+ break;
+
+ case info_item_repos_root_url:
+ SVN_ERR(print_info_item_string(info->repos_root_URL, target_path, pool));
+ break;
+
+ case info_item_repos_uuid:
+ SVN_ERR(print_info_item_string(info->repos_UUID, target_path, pool));
+ break;
+
+ case info_item_revision:
+ SVN_ERR(print_info_item_revision(info->rev, target_path, pool));
+ break;
+
+ case info_item_last_changed_rev:
+ SVN_ERR(print_info_item_revision(info->last_changed_rev,
+ target_path, pool));
+ break;
+
+ case info_item_last_changed_date:
+ SVN_ERR(print_info_item_string(
+ (!info->last_changed_date ? NULL
+ : svn_time_to_cstring(info->last_changed_date, pool)),
+ target_path, pool));
+ break;
+
+ case info_item_last_changed_author:
+ SVN_ERR(print_info_item_string(info->last_changed_author,
+ target_path, pool));
+ break;
+
+ case info_item_wc_root:
+ SVN_ERR(print_info_item_string(
+ (info->wc_info && info->wc_info->wcroot_abspath
+ ? info->wc_info->wcroot_abspath : NULL),
+ target_path, pool));
+ break;
+
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+
+ receiver_baton->start_new_line = TRUE;
+ return SVN_NO_ERROR;
+}
+
+
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__info(apr_getopt_t *os,
@@ -592,7 +865,7 @@ svn_cl__info(apr_getopt_t *os,
svn_boolean_t seen_nonexistent_target = FALSE;
svn_opt_revision_t peg_revision;
svn_client_info_receiver2_t receiver;
- const char *path_prefix;
+ print_info_baton_t receiver_baton = { 0 };
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -605,26 +878,59 @@ svn_cl__info(apr_getopt_t *os,
{
receiver = print_info_xml;
+ if (opt_state->show_item)
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--show-item is not valid in --xml mode"));
+ if (opt_state->no_newline)
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--no-newline is not valid in --xml mode"));
+
/* If output is not incremental, output the XML header and wrap
everything in a top-level element. This makes the output in
its entirety a well-formed XML document. */
if (! opt_state->incremental)
SVN_ERR(svn_cl__xml_print_header("info", pool));
}
+ else if (opt_state->show_item)
+ {
+ receiver = print_info_item;
+
+ if (opt_state->incremental)
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--incremental is only valid in --xml mode"));
+
+ receiver_baton.multiple_targets = (opt_state->depth > svn_depth_empty
+ || targets->nelts > 1);
+ if (receiver_baton.multiple_targets && opt_state->no_newline)
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--no-newline is only available for single-target,"
+ " non-recursive info operations"));
+
+ SVN_ERR(find_print_what(opt_state->show_item, &receiver_baton, pool));
+ receiver_baton.start_new_line = FALSE;
+ }
else
{
receiver = print_info;
if (opt_state->incremental)
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("'incremental' option only valid in XML "
- "mode"));
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--incremental is only valid in --xml mode"));
+ if (opt_state->no_newline)
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--no-newline' is only valid with --show-item"));
}
if (opt_state->depth == svn_depth_unknown)
opt_state->depth = svn_depth_empty;
- SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", pool));
+ SVN_ERR(svn_dirent_get_absolute(&receiver_baton.path_prefix, "", pool));
for (i = 0; i < targets->nelts; i++)
{
@@ -642,10 +948,12 @@ svn_cl__info(apr_getopt_t *os,
{
if (peg_revision.kind == svn_opt_revision_unspecified)
peg_revision.kind = svn_opt_revision_head;
+ receiver_baton.target_is_path = FALSE;
}
else
{
SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));
+ receiver_baton.target_is_path = TRUE;
}
err = svn_client_info4(truepath,
@@ -655,7 +963,7 @@ svn_cl__info(apr_getopt_t *os,
TRUE /* fetch_actual_only */,
opt_state->include_externals,
opt_state->changelists,
- receiver, (void *) path_prefix,
+ receiver, &receiver_baton,
ctx, subpool);
if (err)
@@ -682,6 +990,9 @@ svn_cl__info(apr_getopt_t *os,
if (opt_state->xml && (! opt_state->incremental))
SVN_ERR(svn_cl__xml_print_footer("info", pool));
+ else if (opt_state->show_item && !opt_state->no_newline
+ && receiver_baton.start_new_line)
+ SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
if (seen_nonexistent_target)
return svn_error_create(
Modified: subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c (original)
+++ subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c Wed Mar 4 15:56:18 2015
@@ -322,11 +322,11 @@ svn_cl__propget(apr_getopt_t *os,
svn_stream_t *out;
svn_boolean_t warned = FALSE;
- if (opt_state->verbose && (opt_state->revprop || opt_state->strict
+ if (opt_state->verbose && (opt_state->revprop || opt_state->no_newline
|| opt_state->xml))
return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
_("--verbose cannot be used with --revprop or "
- "--strict or --xml"));
+ "--no-newline or --xml"));
/* PNAME is first argument (and PNAME_UTF8 will be a UTF-8 version
thereof) */
@@ -411,7 +411,7 @@ svn_cl__propget(apr_getopt_t *os,
SVN_ERR(stream_write(out, printable_val->data,
printable_val->len));
- if (! opt_state->strict)
+ if (! opt_state->no_newline)
SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR)));
}
}
@@ -427,16 +427,16 @@ svn_cl__propget(apr_getopt_t *os,
if (opt_state->depth == svn_depth_unknown)
opt_state->depth = svn_depth_empty;
- /* Strict mode only makes sense for a single target. So make
+ /* No-newline mode only makes sense for a single target. So make
sure we have only a single target, and that we're not being
asked to recurse on that target. */
- if (opt_state->strict
+ if (opt_state->no_newline
&& ((targets->nelts > 1) || (opt_state->depth != svn_depth_empty)
|| (opt_state->show_inherited_props)))
return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Strict output of property values only available for single-"
- "target, non-recursive propget operations"));
+ _("--no-newline is only available for single-target,"
+ " non-recursive propget operations"));
for (i = 0; i < targets->nelts; i++)
{
@@ -472,15 +472,15 @@ svn_cl__propget(apr_getopt_t *os,
/* Any time there is more than one thing to print, or where
the path associated with a printed thing is not obvious,
we'll print filenames. That is, unless we've been told
- not to do so with the --strict option. */
+ not to do so with the --no-newline option. */
print_filenames = ((opt_state->depth > svn_depth_empty
|| targets->nelts > 1
|| apr_hash_count(props) > 1
|| opt_state->verbose
|| opt_state->show_inherited_props)
- && (! opt_state->strict));
- omit_newline = opt_state->strict;
- like_proplist = opt_state->verbose && !opt_state->strict;
+ && (! opt_state->no_newline));
+ omit_newline = opt_state->no_newline;
+ like_proplist = opt_state->verbose && !opt_state->no_newline;
/* If there are no properties, and exactly one node was queried,
then warn. */