You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/02/05 20:57:17 UTC
svn commit: r1442718 - in /subversion/trunk/subversion:
include/private/svn_client_private.h libsvn_client/diff.c
libsvn_client/diff_local.c
Author: stsp
Date: Tue Feb 5 19:57:17 2013
New Revision: 1442718
URL: http://svn.apache.org/viewvc?rev=1442718&view=rev
Log:
Add depth support to the 'arbitrary diff' mode of 'svn diff'.
Previously, arbitrary diffs could only be made with depth infinity, which
put arbitrary difff mode at odds with other modes in terms of feature parity.
* subversion/include/private/svn_client_private.h
(svn_client__arbitrary_nodes_diff): Add DEPTH parameter, adjust docstring.
* subversion/libsvn_client/diff.c
(do_diff,
do_diff_summarize): Pass DEPTH to svn_client__arbitrary_nodes_diff().
* subversion/libsvn_client/diff_local.c
(do_arbitrary_dirs_diff): Add DEPTH parameter, adjust docstring.
(arbitrary_diff_this_dir): New helper, extract from arbitrary_diff_walker().
The arbitrary_diff_walker() uses svn_io_dir_walk2() which doesn't support
depth restriction. This helper function was factored out so that single
directories can be diffed with distinct levels of depth.
Use the io walker when diffing with depth infinity, else just use
arbitrary_diff_this_dir() since we don't need to walk the filesystem.
(arbitrary_diff_walker): Re-implement as wrapper of arbitrary_diff_this_dir().
(svn_client__arbitrary_nodes_diff): Add DEPTH parameter. If DEPTH is unknown,
default to depth infinity.
Modified:
subversion/trunk/subversion/include/private/svn_client_private.h
subversion/trunk/subversion/libsvn_client/diff.c
subversion/trunk/subversion/libsvn_client/diff_local.c
Modified: subversion/trunk/subversion/include/private/svn_client_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1442718&r1=1442717&r2=1442718&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Tue Feb 5 19:57:17 2013
@@ -226,14 +226,15 @@ svn_client__wc_node_get_origin(svn_clien
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
-/* 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. */
+/* Produce a diff with depth DEPTH 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. */
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 *callback_baton,
svn_client_ctx_t *ctx,
Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1442718&r1=1442717&r2=1442718&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Tue Feb 5 19:57:17 2013
@@ -2479,6 +2479,7 @@ do_diff(const svn_wc_diff_callbacks4_t *
SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, pool));
SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+ depth,
callbacks,
callback_baton,
ctx, pool));
@@ -2784,6 +2785,7 @@ do_diff_summarize(svn_client_diff_summar
summarize_func, summarize_baton, pool));
SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+ depth,
callbacks,
callback_baton,
ctx, pool));
Modified: subversion/trunk/subversion/libsvn_client/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff_local.c?rev=1442718&r1=1442717&r2=1442718&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff_local.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff_local.c Tue Feb 5 19:57:17 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