Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A6F8EE4ED for ; Tue, 5 Feb 2013 19:57:38 +0000 (UTC) Received: (qmail 2021 invoked by uid 500); 5 Feb 2013 19:57:38 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 1991 invoked by uid 500); 5 Feb 2013 19:57:38 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 1980 invoked by uid 99); 5 Feb 2013 19:57:38 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Feb 2013 19:57:38 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Feb 2013 19:57:37 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 21FE4238896F; Tue, 5 Feb 2013 19:57:18 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1442718 - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/diff.c libsvn_client/diff_local.c Date: Tue, 05 Feb 2013 19:57:17 -0000 To: commits@subversion.apache.org From: stsp@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130205195718.21FE4238896F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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