You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/02/09 00:44:42 UTC
svn commit: r1444288 - /subversion/trunk/subversion/libsvn_wc/diff_editor.c
Author: rhuijben
Date: Fri Feb 8 23:44:42 2013
New Revision: 1444288
URL: http://svn.apache.org/r1444288
Log:
Make the local changes walker in the repos-wc diff invoke the tree processor
instead of the old callbacks. This as another small step towards making
this code easier to understand, maintain, etc.
* subversion/libsvn_wc/diff_editor.c
(file_diff): Add parent baton argument and pass to processor.
Convert file-changed handling.
(walk_local_nodes_diff): Handle directory around children to
follow the processor/skip pattern. Handle processor batons during
recursion.
(report_wc_file_as_added,
report_wc_directory_as_added): Forward batons.
(delete_entry): Unconditionally call report_wc_file_as_added as the
reversing in the processor has no problem with that.
(open_directory,
close_directory): Set hash value using helper macro. Update caller.
(close_edit): Update caller.
Modified:
subversion/trunk/subversion/libsvn_wc/diff_editor.c
Modified: subversion/trunk/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_editor.c?rev=1444288&r1=1444287&r2=1444288&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_editor.c Fri Feb 8 23:44:42 2013
@@ -560,6 +560,7 @@ static svn_error_t *
file_diff(struct edit_baton *eb,
const char *local_abspath,
const char *path,
+ void *dir_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = eb->db;
@@ -656,7 +657,7 @@ file_diff(struct edit_baton *eb,
left_src,
NULL /* right_source */,
NULL /* copyfrom_source */,
- NULL /* ### dir_baton */,
+ dir_baton,
eb->processor,
scratch_pool,
scratch_pool));
@@ -710,7 +711,7 @@ file_diff(struct edit_baton *eb,
NULL /* left source */,
right_src,
copyfrom_src,
- NULL /* ### dir baton */,
+ dir_baton,
eb->processor,
scratch_pool, scratch_pool));
@@ -759,12 +760,29 @@ file_diff(struct edit_baton *eb,
else
{
const char *translated = NULL;
- apr_hash_t *baseprops;
- const char *base_mimetype;
- const char *working_mimetype;
- apr_hash_t *workingprops;
+ apr_hash_t *left_props;
+ apr_hash_t *right_props;
apr_array_header_t *propchanges;
svn_boolean_t modified;
+ void *file_baton = NULL;
+ svn_boolean_t skip = FALSE;
+ svn_diff_source_t *left_src = svn_diff__source_create(revision,
+ scratch_pool);
+ svn_diff_source_t *right_src = svn_diff__source_create(
+ SVN_INVALID_REVNUM,
+ scratch_pool);
+
+ SVN_ERR(eb->processor->file_opened(&file_baton, &skip,
+ path,
+ left_src,
+ right_src,
+ NULL,
+ dir_baton,
+ eb->processor,
+ scratch_pool, scratch_pool));
+
+ if (skip)
+ return SVN_NO_ERROR;
/* Here we deal with showing pure modifications. */
SVN_ERR(svn_wc__internal_file_modified_p(&modified, db, local_abspath,
@@ -791,7 +809,7 @@ file_diff(struct edit_baton *eb,
/* We don't want the normal pristine properties (which are
from the WORKING tree). We want the pristines associated
with the BASE tree, which are saved as "revert" props. */
- SVN_ERR(svn_wc__db_base_get_props(&baseprops,
+ SVN_ERR(svn_wc__db_base_get_props(&left_props,
db, local_abspath,
scratch_pool, scratch_pool));
}
@@ -803,35 +821,42 @@ file_diff(struct edit_baton *eb,
|| status == svn_wc__db_status_copied
|| status == svn_wc__db_status_moved_here);
- SVN_ERR(svn_wc__db_read_pristine_props(&baseprops, db, local_abspath,
+ SVN_ERR(svn_wc__db_read_pristine_props(&left_props, db, local_abspath,
scratch_pool, scratch_pool));
/* baseprops will be NULL for added nodes */
- if (!baseprops)
- baseprops = apr_hash_make(scratch_pool);
+ if (!left_props)
+ left_props = apr_hash_make(scratch_pool);
}
- base_mimetype = get_prop_mimetype(baseprops);
- SVN_ERR(svn_wc__get_actual_props(&workingprops, db, local_abspath,
+ SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
- working_mimetype = get_prop_mimetype(workingprops);
- SVN_ERR(svn_prop_diffs(&propchanges, workingprops, baseprops, scratch_pool));
+ SVN_ERR(svn_prop_diffs(&propchanges, right_props, left_props,
+ scratch_pool));
if (modified || propchanges->nelts > 0)
{
- SVN_ERR(eb->callbacks->file_changed(NULL, NULL, NULL,
- path,
- modified ? textbase : NULL,
+ SVN_ERR(eb->processor->file_changed(path,
+ left_src,
+ right_src,
+ textbase,
translated,
- revision,
- SVN_INVALID_REVNUM,
- base_mimetype,
- working_mimetype,
- propchanges, baseprops,
- eb->callback_baton,
+ left_props,
+ right_props,
+ modified,
+ propchanges,
+ file_baton,
+ eb->processor,
scratch_pool));
}
+ else
+ SVN_ERR(eb->processor->file_closed(path,
+ left_src,
+ right_src,
+ file_baton,
+ eb->processor,
+ scratch_pool));
}
return SVN_NO_ERROR;
@@ -850,13 +875,19 @@ walk_local_nodes_diff(struct edit_baton
const char *path,
svn_depth_t depth,
apr_hash_t *compared,
+ void *parent_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = eb->db;
- const apr_array_header_t *children;
- int i;
svn_boolean_t in_anchor_not_target;
apr_pool_t *iterpool;
+ void *dir_baton = NULL;
+ svn_boolean_t skip = FALSE;
+ svn_boolean_t skip_children = FALSE;
+ svn_revnum_t revision;
+ svn_boolean_t props_mod;
+ svn_diff_source_t *left_src;
+ svn_diff_source_t *right_src;
/* Everything we do below is useless if we are comparing to BASE. */
if (eb->use_text_base)
@@ -868,123 +899,157 @@ walk_local_nodes_diff(struct edit_baton
skipped. */
in_anchor_not_target = ((*path == '\0') && (*eb->target != '\0'));
- /* 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)
- && (! in_anchor_not_target)
- && (!compared || ! apr_hash_get(compared, path, 0)))
- {
- svn_boolean_t modified;
-
- SVN_ERR(svn_wc__props_modified(&modified, db, local_abspath,
- scratch_pool));
- if (modified)
- {
- apr_array_header_t *propchanges;
- apr_hash_t *baseprops;
-
- SVN_ERR(svn_wc__internal_propdiff(&propchanges, &baseprops,
- db, local_abspath,
- scratch_pool, scratch_pool));
-
- SVN_ERR(eb->callbacks->dir_props_changed(NULL, NULL,
- path, FALSE /* ### ? */,
- propchanges, baseprops,
- eb->callback_baton,
- scratch_pool));
- }
- }
-
- if (depth == svn_depth_empty && !in_anchor_not_target)
- 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_kind_t kind;
-
- svn_pool_clear(iterpool);
-
- if (eb->cancel_func)
- SVN_ERR(eb->cancel_func(eb->cancel_baton));
-
- /* In the anchor directory, if the anchor is not the target then all
- entries other than the target should not be diff'd. Running diff
- on one file in a directory should not diff other files in that
- directory. */
- if (in_anchor_not_target && strcmp(eb->target, name))
- continue;
-
- 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_server_excluded)
- continue;
+ SVN_ERR(svn_wc__db_read_info(NULL, NULL, &revision, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, &props_mod, NULL, NULL, NULL,
+ db, local_abspath, scratch_pool, scratch_pool));
- child_path = svn_relpath_join(path, name, iterpool);
+ left_src = svn_diff__source_create(revision, scratch_pool);
+ right_src = svn_diff__source_create(0, scratch_pool);
- /* 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;
+ if (!in_anchor_not_target)
+ SVN_ERR(eb->processor->dir_opened(&dir_baton, &skip, &skip_children,
+ path,
+ left_src,
+ right_src,
+ NULL /* copyfrom_src */,
+ parent_baton,
+ eb->processor,
+ scratch_pool, scratch_pool));
+
+
+ if (!skip_children && depth != svn_depth_empty)
+ {
+ const apr_array_header_t *children;
+ int i;
+ SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
+ scratch_pool, iterpool));
- switch (kind)
+ for (i = 0; i < children->nelts; i++)
{
- case svn_kind_file:
- case svn_kind_symlink:
- SVN_ERR(file_diff(eb, child_abspath, child_path, iterpool));
- break;
+ const char *name = APR_ARRAY_IDX(children, i, const char*);
+ const char *child_abspath, *child_path;
+ svn_wc__db_status_t status;
+ svn_kind_t kind;
+
+ svn_pool_clear(iterpool);
+
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
+
+ /* In the anchor directory, if the anchor is not the target then all
+ entries other than the target should not be diff'd. Running diff
+ on one file in a directory should not diff other files in that
+ directory. */
+ if (in_anchor_not_target && strcmp(eb->target, name))
+ continue;
+
+ 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_server_excluded)
+ 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;
- case svn_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 (in_anchor_not_target
- || (depth > svn_depth_files)
- || (depth == svn_depth_unknown))
+ switch (kind)
{
- svn_depth_t depth_below_here = depth;
+ case svn_kind_file:
+ case svn_kind_symlink:
+ SVN_ERR(file_diff(eb, child_abspath, child_path, dir_baton,
+ iterpool));
+ break;
+
+ case svn_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 (in_anchor_not_target
+ || (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,
+ dir_baton,
+ iterpool));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
- if (depth_below_here == svn_depth_immediates)
- depth_below_here = svn_depth_empty;
+ /* 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 (! eb->changelist_hash
+ && ! in_anchor_not_target
+ && (!compared || ! svn_hash_gets(compared, path))
+ && props_mod
+ && ! skip)
+ {
+ apr_array_header_t *propchanges;
+ apr_hash_t *left_props;
+ apr_hash_t *right_props;
+ SVN_DBG(("Handling: %s\n", local_abspath));
- SVN_ERR(walk_local_nodes_diff(eb,
- child_abspath,
- child_path,
- depth_below_here,
- NULL,
- iterpool));
- }
- break;
+ SVN_ERR(svn_wc__internal_propdiff(&propchanges, &left_props,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
- default:
- break;
- }
+ right_props = svn_prop__patch(left_props, propchanges, scratch_pool);
+
+ SVN_ERR(eb->processor->dir_changed(path,
+ left_src,
+ right_src,
+ left_props,
+ right_props,
+ propchanges,
+ dir_baton,
+ eb->processor,
+ scratch_pool));
}
+ else if (! skip)
+ SVN_ERR(eb->processor->dir_closed(path,
+ left_src,
+ right_src,
+ dir_baton,
+ eb->processor,
+ scratch_pool));
svn_pool_destroy(iterpool);
@@ -994,15 +1059,13 @@ walk_local_nodes_diff(struct edit_baton
/* Report an existing file in the working copy (either in BASE or WORKING)
* as having been added.
*
- * DIR_BATON is the parent directory baton, ADM_ACCESS/PATH is the path
- * to the file to be compared.
- *
* Do all allocation in POOL.
*/
static svn_error_t *
report_wc_file_as_added(struct edit_baton *eb,
const char *local_abspath,
const char *path,
+ void *parent_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = eb->db;
@@ -1047,7 +1110,7 @@ report_wc_file_as_added(struct edit_bato
return SVN_NO_ERROR;
/* Otherwise show just the local modifications. */
- return file_diff(eb, local_abspath, path, scratch_pool);
+ return file_diff(eb, local_abspath, path, parent_baton, scratch_pool);
}
right_src = svn_diff__source_create(revision, scratch_pool);
@@ -1057,7 +1120,7 @@ report_wc_file_as_added(struct edit_bato
NULL,
right_src,
NULL,
- NULL /* ### dir_baton */,
+ parent_baton,
eb->processor,
scratch_pool, scratch_pool));
@@ -1115,6 +1178,7 @@ report_wc_directory_as_added(struct edit
const char *local_abspath,
const char *path,
svn_depth_t depth,
+ void *parent_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = eb->db;
@@ -1197,7 +1261,7 @@ report_wc_directory_as_added(struct edit
case svn_kind_file:
case svn_kind_symlink:
SVN_ERR(report_wc_file_as_added(eb, child_abspath, child_path,
- iterpool));
+ parent_baton, iterpool));
break;
case svn_kind_dir:
@@ -1212,6 +1276,7 @@ report_wc_directory_as_added(struct edit
child_abspath,
child_path,
depth_below_here,
+ parent_baton,
iterpool));
}
break;
@@ -1273,8 +1338,7 @@ delete_entry(const char *path,
svn_kind_t kind;
/* Mark this node as compared in the parent directory's baton. */
- apr_hash_set(pb->compared, apr_pstrdup(pb->pool, path),
- APR_HASH_KEY_STRING, "");
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, path), "");
SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1294,40 +1358,10 @@ delete_entry(const char *path,
case svn_kind_symlink:
/* A delete is required to change working-copy into requested
revision, so diff should show this as an add. Thus compare
- the empty file against the current working copy. If
- 'reverse_order' is set, then show a deletion. */
-
- if (eb->reverse_order)
- {
- /* Whenever showing a deletion, we show the text-base vanishing. */
- /* ### This is wrong if we're diffing WORKING->repos. */
- const char *textbase;
-
- apr_hash_t *baseprops = NULL;
- const char *base_mimetype;
-
- SVN_ERR(get_pristine_file(&textbase, db, local_abspath,
- eb->use_text_base, pool, pool));
-
- SVN_ERR(svn_wc__db_read_pristine_props(&baseprops,
- eb->db, local_abspath,
- pool, pool));
- base_mimetype = get_prop_mimetype(baseprops);
-
- SVN_ERR(eb->callbacks->file_deleted(NULL, NULL, path,
- textbase,
- empty_file,
- base_mimetype,
- NULL,
- baseprops,
- eb->callback_baton,
- pool));
- }
- else
- {
- /* Or normally, show the working file being added. */
- SVN_ERR(report_wc_file_as_added(eb, local_abspath, path, pool));
- }
+ the empty file against the current working copy. */
+ SVN_ERR(report_wc_file_as_added(eb, local_abspath, path,
+ NULL /* ### parent_baton */,
+ pool));
break;
case svn_kind_dir:
/* A delete is required to change working-copy into requested
@@ -1336,6 +1370,7 @@ delete_entry(const char *path,
local_abspath,
path,
svn_depth_infinity,
+ NULL /* ### parent_baton */,
pool));
default:
@@ -1393,8 +1428,7 @@ open_directory(const char *path,
/* Add this path to the parent directory's list of elements that
have been compared. */
- apr_hash_set(pb->compared, apr_pstrdup(pb->pool, db->path),
- APR_HASH_KEY_STRING, "");
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, db->path), "");
SVN_ERR(db->eb->callbacks->dir_opened(NULL, NULL, NULL,
path, base_revision,
@@ -1473,7 +1507,7 @@ close_directory(void *dir_baton,
/* Mark the properties of this directory as having already been
compared so that we know not to show any local modifications
later on. */
- apr_hash_set(db->compared, db->path, 0, "");
+ svn_hash_sets(db->compared, db->path, "");
}
/* Report local modifications for this directory. Skip added
@@ -1485,6 +1519,7 @@ close_directory(void *dir_baton,
db->path,
db->depth,
db->compared,
+ NULL /* ### parent_baton */,
scratch_pool));
/* Mark this directory as compared in the parent directory's baton,
@@ -1540,8 +1575,7 @@ open_file(const char *path,
/* Add this filename to the parent directory's list of elements that
have been compared. */
- apr_hash_set(pb->compared, apr_pstrdup(pb->pool, path),
- APR_HASH_KEY_STRING, "");
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, path), "");
SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, &fb->base_checksum, NULL,
@@ -1979,6 +2013,7 @@ close_edit(void *edit_baton,
"",
eb->depth,
NULL,
+ NULL /* No parent_baton */,
eb->pool));
}