You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pr...@apache.org on 2013/02/13 11:21:36 UTC
svn commit: r1445542 [3/16] - in /subversion/branches/verify-keep-going: ./
build/generator/ build/generator/swig/ build/generator/templates/
build/win32/ contrib/server-side/fsfsfixer/fixer/
contrib/server-side/svncutter/ notes/ notes/api-errata/1.7/ ...
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c Wed Feb 13 10:21:33 2013
@@ -287,9 +287,16 @@ arbitrary_diff_walker(void *baton, const
const apr_finfo_t *finfo,
apr_pool_t *scratch_pool);
-/* Produce a diff between two arbitrary directories at LOCAL_ABSPATH1 and
- * LOCAL_ABSPATH2, using the provided diff callbacks to show file changes
- * and, for versioned nodes, property changes.
+/* Another forward declaration. */
+static svn_error_t *
+arbitrary_diff_this_dir(struct arbitrary_diff_walker_baton *b,
+ const char *local_abspath,
+ svn_depth_t depth,
+ apr_pool_t *scratch_pool);
+
+/* Produce a diff of depth DEPTH between two arbitrary directories at
+ * LOCAL_ABSPATH1 and LOCAL_ABSPATH2, using the provided diff callbacks
+ * to show file changes and, for versioned nodes, property changes.
*
* If ROOT_ABSPATH1 and ROOT_ABSPATH2 are not NULL, show paths in diffs
* relative to these roots, rather than relative to LOCAL_ABSPATH1 and
@@ -300,6 +307,7 @@ do_arbitrary_dirs_diff(const char *local
const char *local_abspath2,
const char *root_abspath1,
const char *root_abspath2,
+ svn_depth_t depth,
const svn_wc_diff_callbacks4_t *callbacks,
void *diff_baton,
svn_client_ctx_t *ctx,
@@ -331,22 +339,25 @@ do_arbitrary_dirs_diff(const char *local
NULL, svn_io_file_del_on_pool_cleanup,
scratch_pool, scratch_pool));
- SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
- : local_abspath1,
- 0, arbitrary_diff_walker, &b, scratch_pool));
-
+ if (depth <= svn_depth_immediates)
+ SVN_ERR(arbitrary_diff_this_dir(&b, local_abspath1, depth, scratch_pool));
+ else if (depth == svn_depth_infinity)
+ SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
+ : local_abspath1,
+ 0, arbitrary_diff_walker, &b, scratch_pool));
return SVN_NO_ERROR;
}
-/* An implementation of svn_io_walk_func_t.
- * Note: LOCAL_ABSPATH is the path being crawled and can be on either side
+/* Produce a diff of depth DEPTH for the directory at LOCAL_ABSPATH,
+ * using information from the arbitrary_diff_walker_baton B.
+ * LOCAL_ABSPATH is the path being crawled and can be on either side
* of the diff depending on baton->recursing_within_added_subtree. */
static svn_error_t *
-arbitrary_diff_walker(void *baton, const char *local_abspath,
- const apr_finfo_t *finfo,
- apr_pool_t *scratch_pool)
+arbitrary_diff_this_dir(struct arbitrary_diff_walker_baton *b,
+ const char *local_abspath,
+ svn_depth_t depth,
+ apr_pool_t *scratch_pool)
{
- struct arbitrary_diff_walker_baton *b = baton;
const char *local_abspath1;
const char *local_abspath2;
svn_node_kind_t kind1;
@@ -359,12 +370,6 @@ arbitrary_diff_walker(void *baton, const
int i;
apr_pool_t *iterpool;
- if (b->ctx->cancel_func)
- SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
-
- if (finfo->filetype != APR_DIR)
- return SVN_NO_ERROR;
-
if (b->recursing_within_adm_dir)
{
if (svn_dirent_skip_ancestor(b->adm_dir_abspath, local_abspath))
@@ -398,12 +403,15 @@ arbitrary_diff_walker(void *baton, const
scratch_pool);
SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool));
- if (kind1 == svn_node_dir)
- SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1,
- TRUE, /* only_check_type */
- scratch_pool, scratch_pool));
- else
- dirents1 = apr_hash_make(scratch_pool);
+ if (depth > svn_depth_empty)
+ {
+ if (kind1 == svn_node_dir)
+ SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1,
+ TRUE, /* only_check_type */
+ scratch_pool, scratch_pool));
+ else
+ dirents1 = apr_hash_make(scratch_pool);
+ }
if (kind2 == svn_node_dir)
{
@@ -425,14 +433,20 @@ arbitrary_diff_walker(void *baton, const
b->diff_baton,
scratch_pool));
- /* Read directory entries. */
- SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2,
- TRUE, /* only_check_type */
- scratch_pool, scratch_pool));
+ if (depth > svn_depth_empty)
+ {
+ /* Read directory entries. */
+ SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2,
+ TRUE, /* only_check_type */
+ scratch_pool, scratch_pool));
+ }
}
- else
+ else if (depth > svn_depth_empty)
dirents2 = apr_hash_make(scratch_pool);
+ if (depth <= svn_depth_empty)
+ return SVN_NO_ERROR;
+
/* Compare dirents1 to dirents2 and show added/deleted/changed files. */
merged_dirents = apr_hash_merge(scratch_pool, dirents1, dirents2,
NULL, NULL);
@@ -482,7 +496,25 @@ arbitrary_diff_walker(void *baton, const
if (dirent1->kind == svn_node_dir &&
dirent2->kind == svn_node_dir)
- continue;
+ {
+ if (depth == svn_depth_immediates)
+ {
+ /* Not using the walker, so show property diffs on these dirs. */
+ SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath,
+ b->root1_abspath, b->root2_abspath,
+ svn_depth_empty,
+ b->callbacks, b->diff_baton,
+ b->ctx, iterpool));
+ }
+ else
+ {
+ /* Either the walker will visit these directories (with
+ * depth=infinity) and they will be processed as 'this dir'
+ * later, or we're showing file children only (depth=files). */
+ continue;
+ }
+
+ }
/* Files that exist only in dirents1. */
if (dirent1->kind == svn_node_file &&
@@ -521,10 +553,14 @@ arbitrary_diff_walker(void *baton, const
/* Directories that only exist in dirents2. These aren't crawled
* by this walker so we have to crawl them separately. */
- if (dirent2->kind == svn_node_dir &&
+ if (depth > svn_depth_files &&
+ dirent2->kind == svn_node_dir &&
(dirent1->kind == svn_node_file || dirent1->kind == svn_node_none))
SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath,
b->root1_abspath, b->root2_abspath,
+ depth <= svn_depth_immediates
+ ? svn_depth_empty
+ : svn_depth_infinity ,
b->callbacks, b->diff_baton,
b->ctx, iterpool));
}
@@ -534,14 +570,32 @@ arbitrary_diff_walker(void *baton, const
return SVN_NO_ERROR;
}
-/* Produce a diff between two files or two directories at LOCAL_ABSPATH1
- * and LOCAL_ABSPATH2, using the provided diff callbacks to show changes
- * in files. The files and directories involved may be part of a working
- * copy or they may be unversioned. For versioned files, show property
- * changes, too. */
+/* An implementation of svn_io_walk_func_t.
+ * Note: LOCAL_ABSPATH is the path being crawled and can be on either side
+ * of the diff depending on baton->recursing_within_added_subtree. */
+static svn_error_t *
+arbitrary_diff_walker(void *baton, const char *local_abspath,
+ const apr_finfo_t *finfo,
+ apr_pool_t *scratch_pool)
+{
+ struct arbitrary_diff_walker_baton *b = baton;
+
+ if (b->ctx->cancel_func)
+ SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
+
+ if (finfo->filetype != APR_DIR)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(arbitrary_diff_this_dir(b, local_abspath, svn_depth_infinity,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client__arbitrary_nodes_diff(const char *local_abspath1,
const char *local_abspath2,
+ svn_depth_t depth,
const svn_wc_diff_callbacks4_t *callbacks,
void *diff_baton,
svn_client_ctx_t *ctx,
@@ -558,6 +612,9 @@ svn_client__arbitrary_nodes_diff(const c
_("'%s' is not the same node kind as '%s'"),
local_abspath1, local_abspath2);
+ if (depth == svn_depth_unknown)
+ depth = svn_depth_infinity;
+
if (kind1 == svn_node_file)
SVN_ERR(do_arbitrary_files_diff(local_abspath1, local_abspath2,
svn_dirent_basename(local_abspath1,
@@ -567,7 +624,7 @@ svn_client__arbitrary_nodes_diff(const c
ctx, scratch_pool));
else if (kind1 == svn_node_dir)
SVN_ERR(do_arbitrary_dirs_diff(local_abspath1, local_abspath2,
- NULL, NULL,
+ NULL, NULL, depth,
callbacks, diff_baton,
ctx, scratch_pool));
else
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c Wed Feb 13 10:21:33 2013
@@ -212,9 +212,21 @@ switch_dir_external(const char *local_ab
To do so, we need to know the repository root URL of the
external working copy as it currently sits. */
- SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, &repos_uuid,
- ctx->wc_ctx, local_abspath,
- pool, subpool));
+ err = svn_wc__node_get_repos_info(NULL, NULL,
+ &repos_root_url, &repos_uuid,
+ ctx->wc_ctx, local_abspath,
+ pool, subpool);
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
+ && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ repos_root_url = NULL;
+ repos_uuid = NULL;
+ }
+
if (repos_root_url)
{
/* If the new external target URL is not obviously a
@@ -315,7 +327,8 @@ switch_dir_external(const char *local_ab
FALSE, FALSE, timestamp_sleep,
ctx, pool));
- SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url,
+ SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL,
+ &repos_root_url,
&repos_uuid,
ctx->wc_ctx, local_abspath,
pool, pool));
@@ -739,6 +752,7 @@ handle_external_item_change(svn_client_c
const char *local_repos_root_url;
const char *local_repos_uuid;
const char *ext_repos_relpath;
+ svn_error_t *err;
/*
* The working copy library currently requires that all files
@@ -749,11 +763,22 @@ handle_external_item_change(svn_client_c
* sure both URLs point to the same repository. See issue #4087.
*/
- SVN_ERR(svn_wc__node_get_repos_info(&local_repos_root_url,
- &local_repos_uuid,
- ctx->wc_ctx,
- parent_dir_abspath,
- scratch_pool, scratch_pool));
+ err = svn_wc__node_get_repos_info(NULL, NULL,
+ &local_repos_root_url,
+ &local_repos_uuid,
+ ctx->wc_ctx, parent_dir_abspath,
+ scratch_pool, scratch_pool);
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
+ && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ local_repos_root_url = NULL;
+ local_repos_uuid = NULL;
+ }
+
ext_repos_relpath = svn_uri_skip_ancestor(new_loc->repos_root_url,
new_url, scratch_pool);
if (local_repos_uuid == NULL || local_repos_root_url == NULL ||
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c Wed Feb 13 10:21:33 2013
@@ -189,6 +189,14 @@ condense_targets(const char **common_par
return SVN_NO_ERROR;
}
+/* Lock info. Used in organize_lock_targets.
+ ### Maybe return this instead of the ugly hashes? */
+struct wc_lock_item_t
+{
+ svn_revnum_t revision;
+ const char *lock_token;
+};
+
/* Set *COMMON_PARENT_URL to the nearest common parent URL of all TARGETS.
* If TARGETS are local paths, then the entry for each path is examined
* and *COMMON_PARENT is set to the common parent URL for all the
@@ -225,7 +233,7 @@ organize_lock_targets(const char **commo
const apr_array_header_t *targets,
svn_boolean_t do_lock,
svn_boolean_t force,
- svn_client_ctx_t *ctx,
+ svn_wc_context_t *wc_ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -234,6 +242,7 @@ organize_lock_targets(const char **commo
apr_hash_t *rel_targets_ret = apr_hash_make(result_pool);
apr_hash_t *rel_fs_paths = NULL;
apr_array_header_t *rel_targets;
+ apr_hash_t *wc_info = apr_hash_make(scratch_pool);
svn_boolean_t url_mode;
int i;
@@ -289,20 +298,38 @@ organize_lock_targets(const char **commo
sizeof(const char *));
for (i = 0; i < rel_targets->nelts; i++)
{
- const char *rel_target, *local_abspath, *target_url;
+ const char *rel_target;
+ const char *repos_relpath;
+ const char *repos_root_url;
+ const char *target_url;
+ struct wc_lock_item_t *wli;
+ const char *local_abspath;
svn_pool_clear(iterpool);
rel_target = APR_ARRAY_IDX(rel_targets, i, const char *);
- local_abspath = svn_dirent_join(common_dirent, rel_target, iterpool);
- SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
- scratch_pool, iterpool));
- if (! target_url)
- return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
- _("'%s' has no URL"),
+ local_abspath = svn_dirent_join(common_dirent, rel_target, scratch_pool);
+ wli = apr_pcalloc(scratch_pool, sizeof(*wli));
+
+ SVN_ERR(svn_wc__node_get_base(&wli->revision, &repos_relpath,
+ &repos_root_url, NULL,
+ &wli->lock_token,
+ wc_ctx, local_abspath,
+ result_pool, iterpool));
+
+ /* Node exists in BASE? */
+ if (! repos_root_url || !repos_relpath)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
svn_dirent_local_style(local_abspath,
iterpool));
+ apr_hash_set(wc_info, local_abspath, APR_HASH_KEY_STRING, wli);
+
+ target_url = svn_path_url_add_component2(repos_root_url,
+ repos_relpath,
+ scratch_pool);
+
APR_ARRAY_PUSH(target_urls, const char *) = target_url;
}
@@ -320,7 +347,8 @@ organize_lock_targets(const char **commo
rel_fs_paths = apr_hash_make(result_pool);
for (i = 0; i < rel_targets->nelts; i++)
{
- const char *rel_target, *rel_url, *abs_path;
+ const char *rel_target, *rel_url;
+ const char *local_abspath;
svn_pool_clear(iterpool);
@@ -336,35 +364,49 @@ organize_lock_targets(const char **commo
revision of the dirent target with which it is associated
(if our caller is locking) or to a (possible empty) lock
token string (if the caller is unlocking). */
- abs_path = svn_dirent_join(common_dirent, rel_target, iterpool);
+ local_abspath = svn_dirent_join(common_dirent, rel_target, iterpool);
if (do_lock) /* Lock. */
{
svn_revnum_t *revnum;
+ struct wc_lock_item_t *wli;
revnum = apr_palloc(result_pool, sizeof(* revnum));
- SVN_ERR(svn_wc__node_get_base(revnum, NULL, NULL, NULL,
- ctx->wc_ctx, abs_path,
- result_pool, iterpool));
+
+ wli = apr_hash_get(wc_info, local_abspath, APR_HASH_KEY_STRING);
+
+ SVN_ERR_ASSERT(wli != NULL);
+
+ *revnum = wli->revision;
+
apr_hash_set(rel_targets_ret, rel_url,
APR_HASH_KEY_STRING, revnum);
}
else /* Unlock. */
{
- const char *lock_token = NULL;
+ const char *lock_token;
+ struct wc_lock_item_t *wli;
/* If not forcing the unlock, get the lock token. */
if (! force)
{
- SVN_ERR(svn_wc__node_get_lock_info(&lock_token, NULL, NULL,
- NULL, ctx->wc_ctx,
- abs_path, result_pool,
- iterpool));
- if (! lock_token)
+ wli = apr_hash_get(wc_info, local_abspath,
+ APR_HASH_KEY_STRING);
+
+ SVN_ERR_ASSERT(wli != NULL);
+
+ if (! wli->lock_token)
return svn_error_createf(
SVN_ERR_CLIENT_MISSING_LOCK_TOKEN, NULL,
_("'%s' is not locked in this working copy"),
- abs_path);
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
+ lock_token = wli->lock_token
+ ? apr_pstrdup(result_pool, wli->lock_token)
+ : NULL;
}
+ else
+ lock_token = NULL;
/* If breaking a lock, we shouldn't pass any lock token. */
apr_hash_set(rel_targets_ret, rel_url, APR_HASH_KEY_STRING,
@@ -444,7 +486,7 @@ svn_client_lock(const apr_array_header_t
SVN_ERR(organize_lock_targets(&common_parent_url, &base_dir, &path_revs,
&urls_to_paths, targets, TRUE, steal_lock,
- ctx, pool, pool));
+ ctx->wc_ctx, pool, pool));
/* Open an RA session to the common parent of TARGETS. */
if (base_dir)
@@ -484,7 +526,7 @@ svn_client_unlock(const apr_array_header
SVN_ERR(organize_lock_targets(&common_parent_url, &base_dir, &path_tokens,
&urls_to_paths, targets, FALSE, break_lock,
- ctx, pool, pool));
+ ctx->wc_ctx, pool, pool));
/* Open an RA session. */
if (base_dir)