Author: rhuijben
Date: Fri Apr 29 09:32:53 2011
New Revision: 1097745
URL: http://svn.apache.org/viewvc?rev=1097745&view=rev
Log:
In the local diff handler: Use the standard status walker instead of a local
node walker implementation to decide what to show a diff of.
* subversion/libsvn_wc/diff_local.c
(header): Remove todo.
(includes): Remove adm_files.h
(diff_baton): Reintroduce anchor_abspath.
(walk_local_nodes_diff): Remove function.
(diff_status_callback): New function.
(svn_wc_diff6): Call status instead of our own node walker.
* subversion/tests/cmdline/diff_tests.py
(diff_git_format_wc_wc): Expect diff in a different order now.
Modified:
subversion/trunk/subversion/libsvn_wc/diff_local.c
subversion/trunk/subversion/tests/cmdline/diff_tests.py
Modified: subversion/trunk/subversion/libsvn_wc/diff_local.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_local.c?rev=1097745&r1=1097744&r2=1097745&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_local.c Fri Apr 29 09:32:53 2011
@@ -27,8 +27,6 @@
* restructuring operations.
*
* You can look at this as another form of the status walker.
- *
- * ### TODO: Simply use svn_wc_walk_status() to provide this diff.
*/
#include <apr_hash.h>
@@ -43,15 +41,12 @@
#include "wc.h"
#include "props.h"
-#include "adm_files.h"
#include "translate.h"
#include "svn_private_config.h"
-
-
/* Set *RESULT_ABSPATH to the absolute path to a readable file containing
the pristine text of LOCAL_ABSPATH in DB, or to NULL if it does not have
any pristine text.
@@ -126,6 +121,9 @@ struct diff_baton
/* A wc db. */
svn_wc__db_t *db;
+ /* Report editor paths relative from this directory */
+ const char *anchor_abspath;
+
/* The callbacks and callback argument that implement the file comparison
functions */
const svn_wc_diff_callbacks4_t *callbacks;
@@ -448,46 +446,67 @@ file_diff(struct diff_baton *eb,
return SVN_NO_ERROR;
}
-/* Called when the directory is closed to compare any elements that have
- * not yet been compared. This identifies local, working copy only
- * changes. At this stage we are dealing with files/directories that do
- * exist in the working copy.
- *
- * DIR_BATON is the baton for the directory.
- */
+/* Implements svn_wc_status_func3_t */
static svn_error_t *
-walk_local_nodes_diff(struct diff_baton *eb,
- const char *local_abspath,
- const char *path,
- svn_depth_t depth,
- apr_hash_t *compared,
- apr_pool_t *scratch_pool)
+diff_status_callback(void *baton,
+ const char *local_abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_t *db = eb->db;
- const apr_array_header_t *children;
- int i;
- apr_pool_t *iterpool;
-
- /* Check for local property mods on this directory, if we haven't
- already reported them and we aren't changelist-filted.
- ### it should be noted that we do not currently allow directories
- ### to be part of changelists, so if a changelist is provided, the
- ### changelist check will always fail. */
- if (svn_wc__internal_changelist_match(db, local_abspath,
- eb->changelist_hash, scratch_pool)
- && (!compared || ! apr_hash_get(compared, path, 0)))
+ struct diff_baton *eb = baton;
+ switch (status->node_status)
{
- svn_boolean_t modified;
+ case svn_wc_status_unversioned:
+ case svn_wc_status_ignored:
+ return SVN_NO_ERROR; /* No diff */
+
+ case svn_wc_status_obstructed:
+ case svn_wc_status_missing:
+ return SVN_NO_ERROR; /* ### What should we do here? */
+ }
+
+ if (eb->changelist_hash != NULL
+ && (!status->changelist
+ || ! apr_hash_get(eb->changelist_hash, status->changelist,
+ APR_HASH_KEY_STRING)))
+ return SVN_NO_ERROR; /* Filtered via changelist */
+
+ if (status->kind == svn_node_file)
+ {
+ /* Show a diff when
+ * - The text is modified
+ * - Or the properties are modified
+ * - Or when the node has been replaced
+ * - Or (if in copies as adds or git mode) when a node is copied */
+ if (status->text_status == svn_wc_status_modified
+ || status->prop_status == svn_wc_status_modified
+ || status->node_status == svn_wc_status_deleted
+ || status->node_status == svn_wc_status_replaced
+ || ((eb->show_copies_as_adds || eb->use_git_diff_format)
+ && status->copied))
+ {
+ const char *path = svn_dirent_skip_ancestor(eb->anchor_abspath,
+ local_abspath);
- SVN_ERR(svn_wc__props_modified(&modified, db, local_abspath,
- scratch_pool));
- if (modified)
+ SVN_ERR(file_diff(eb, local_abspath, path, scratch_pool));
+ }
+ }
+ else
+ {
+ /* ### This case should probably be extended for git-diff, but this
+ is what the old diff code provided */
+ if (status->node_status == svn_wc_status_deleted
+ || status->node_status == svn_wc_status_replaced
+ || status->prop_status == svn_wc_status_modified)
{
apr_array_header_t *propchanges;
apr_hash_t *baseprops;
+ const char *path = svn_dirent_skip_ancestor(eb->anchor_abspath,
+ local_abspath);
+
SVN_ERR(svn_wc__internal_propdiff(&propchanges, &baseprops,
- db, local_abspath,
+ eb->db, local_abspath,
scratch_pool, scratch_pool));
SVN_ERR(eb->callbacks->dir_props_changed(NULL, NULL,
@@ -497,88 +516,6 @@ walk_local_nodes_diff(struct diff_baton
scratch_pool));
}
}
-
- if (depth == svn_depth_empty)
- return SVN_NO_ERROR;
-
- iterpool = svn_pool_create(scratch_pool);
-
- SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
- scratch_pool, iterpool));
-
- for (i = 0; i < children->nelts; i++)
- {
- const char *name = APR_ARRAY_IDX(children, i, const char*);
- const char *child_abspath, *child_path;
- svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
-
- svn_pool_clear(iterpool);
-
- if (eb->cancel_func)
- SVN_ERR(eb->cancel_func(eb->cancel_baton));
-
- child_abspath = svn_dirent_join(local_abspath, name, iterpool);
-
- SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- db, child_abspath,
- iterpool, iterpool));
-
- if (status == svn_wc__db_status_not_present
- || status == svn_wc__db_status_excluded
- || status == svn_wc__db_status_absent)
- continue;
-
- child_path = svn_relpath_join(path, name, iterpool);
-
- /* Skip this node if it is in the list of nodes already diff'd. */
- if (compared && apr_hash_get(compared, child_path, APR_HASH_KEY_STRING))
- continue;
-
- switch (kind)
- {
- case svn_wc__db_kind_file:
- case svn_wc__db_kind_symlink:
- SVN_ERR(file_diff(eb, child_abspath, child_path, iterpool));
- break;
-
- case svn_wc__db_kind_dir:
- /* ### TODO: Don't know how to do replaced dirs. How do I get
- information about what is being replaced? If it was a
- directory then the directory elements are also going to be
- deleted. We need to show deletion diffs for these
- files. If it was a file we need to show a deletion diff
- for that file. */
-
- /* Check the subdir if in the anchor (the subdir is the target), or
- if recursive */
- if ((depth > svn_depth_files)
- || (depth == svn_depth_unknown))
- {
- svn_depth_t depth_below_here = depth;
-
- if (depth_below_here == svn_depth_immediates)
- depth_below_here = svn_depth_empty;
-
- SVN_ERR(walk_local_nodes_diff(eb,
- child_abspath,
- child_path,
- depth_below_here,
- NULL,
- iterpool));
- }
- break;
-
- default:
- break;
- }
- }
-
- svn_pool_destroy(iterpool);
-
return SVN_NO_ERROR;
}
@@ -586,7 +523,7 @@ walk_local_nodes_diff(struct diff_baton
/* Public Interface */
svn_error_t *
svn_wc_diff6(svn_wc_context_t *wc_ctx,
- const char *target_abspath,
+ const char *local_abspath,
const svn_wc_diff_callbacks4_t *callbacks,
void *callback_baton,
svn_depth_t depth,
@@ -599,21 +536,17 @@ svn_wc_diff6(svn_wc_context_t *wc_ctx,
apr_pool_t *scratch_pool)
{
struct diff_baton eb = { 0 };
- const char *target;
- const char *anchor_abspath;
svn_wc__db_kind_t kind;
+ svn_boolean_t get_all;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
- SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, target_abspath, FALSE,
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, FALSE,
scratch_pool));
if (kind == svn_wc__db_kind_dir)
- {
- anchor_abspath = target_abspath;
- target = "";
- }
+ eb.anchor_abspath = local_abspath;
else
- svn_dirent_split(&anchor_abspath, &target, target_abspath, scratch_pool);
+ eb.anchor_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
eb.db = wc_ctx->db;
eb.callbacks = callbacks;
@@ -622,29 +555,28 @@ svn_wc_diff6(svn_wc_context_t *wc_ctx,
eb.show_copies_as_adds = show_copies_as_adds;
eb.use_git_diff_format = use_git_diff_format;
eb.empty_file = NULL;
+ eb.pool = scratch_pool;
if (changelists && changelists->nelts)
SVN_ERR(svn_hash_from_cstring_keys(&eb.changelist_hash, changelists,
scratch_pool));
- if (kind == svn_wc__db_kind_dir)
- SVN_ERR(walk_local_nodes_diff(&eb,
- anchor_abspath,
- "",
- depth,
- NULL,
- scratch_pool));
+ if (show_copies_as_adds || use_git_diff_format)
+ get_all = TRUE; /* We need unmodified descendants of copies */
else
- {
- svn_wc_status3_t *status;
- SVN_ERR(svn_wc_status3(&status, wc_ctx, target_abspath,
- scratch_pool, scratch_pool));
+ get_all = FALSE;
- if (status->node_status == svn_wc_status_deleted
- || status->text_status != svn_wc_status_normal
- || status->prop_status == svn_wc_status_modified)
- SVN_ERR(file_diff(&eb, target_abspath, target, scratch_pool));
- }
+ /* Walk status handles files and directories */
+ SVN_ERR(svn_wc_walk_status(wc_ctx, local_abspath, depth,
+ get_all,
+ TRUE /* no_ignore */,
+ FALSE /* ignore_text_mods */,
+ NULL /* ignore_patterns */,
+ diff_status_callback,
+ &eb,
+ NULL, NULL, /* external func & baton */
+ cancel_func, cancel_baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/tests/cmdline/diff_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/diff_tests.py?rev=1097745&r1=1097744&r2=1097745&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/diff_tests.py Fri Apr 29 09:32:53
2011
@@ -3402,18 +3402,18 @@ def diff_git_format_wc_wc(sbox):
"revision 1", "working copy",
copyfrom_path="A/B/lambda", cp=True,
text_changes=False) \
- + make_git_diff_header(alpha_copied_path, "A/B/E/alpha_copied",
+ + make_git_diff_header(mu_path, "A/mu", "revision 1",
+ "working copy",
+ delete=True) + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'mu'.\n",
+ ] + make_git_diff_header(alpha_copied_path, "A/B/E/alpha_copied",
"revision 0", "working copy",
copyfrom_path="A/B/E/alpha", cp=True,
text_changes=True) + [
"@@ -1 +1,2 @@\n",
" This is the file 'alpha'.\n",
"+This is a copy of 'alpha'.\n",
- ] + make_git_diff_header(mu_path, "A/mu", "revision 1",
- "working copy",
- delete=True) + [
- "@@ -1 +0,0 @@\n",
- "-This is the file 'mu'.\n",
] + make_git_diff_header(new_path, "new", "revision 0",
"working copy", add=True) + [
"@@ -0,0 +1 @@\n",