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/03/06 12:10:05 UTC
svn commit: r1453290 [7/15] - in /subversion/branches/fsfs-format7: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindin...
Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/diff_editor.c?rev=1453290&r1=1453289&r2=1453290&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_wc/diff_editor.c Wed Mar 6 11:10:01 2013
@@ -62,6 +62,7 @@
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_hash.h"
+#include "svn_sorts.h"
#include "private/svn_subr_private.h"
#include "private/svn_wc_private.h"
@@ -72,134 +73,10 @@
#include "props.h"
#include "adm_files.h"
#include "translate.h"
+#include "diff.h"
#include "svn_private_config.h"
-
-/*-------------------------------------------------------------------------*/
-/* A little helper function.
-
- You see, when we ask the server to update us to a certain revision,
- we construct the new fulltext, and then run
-
- 'diff <repos_fulltext> <working_fulltext>'
-
- which is, of course, actually backwards from the repository's point
- of view. It thinks we want to move from working->repos.
-
- So when the server sends property changes, they're effectively
- backwards from what we want. We don't want working->repos, but
- repos->working. So this little helper "reverses" the value in
- BASEPROPS and PROPCHANGES before we pass them off to the
- prop_changed() diff-callback. */
-static void
-reverse_propchanges(apr_hash_t *baseprops,
- apr_array_header_t *propchanges,
- apr_pool_t *pool)
-{
- int i;
-
- /* ### todo: research lifetimes for property values below */
-
- for (i = 0; i < propchanges->nelts; i++)
- {
- svn_prop_t *propchange
- = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
-
- const svn_string_t *original_value =
- apr_hash_get(baseprops, propchange->name, APR_HASH_KEY_STRING);
-
- if ((original_value == NULL) && (propchange->value != NULL))
- {
- /* found an addition. make it look like a deletion. */
- apr_hash_set(baseprops, propchange->name, APR_HASH_KEY_STRING,
- svn_string_dup(propchange->value, pool));
- propchange->value = NULL;
- }
-
- else if ((original_value != NULL) && (propchange->value == NULL))
- {
- /* found a deletion. make it look like an addition. */
- propchange->value = svn_string_dup(original_value, pool);
- apr_hash_set(baseprops, propchange->name, APR_HASH_KEY_STRING,
- NULL);
- }
-
- else if ((original_value != NULL) && (propchange->value != NULL))
- {
- /* found a change. just swap the values. */
- const svn_string_t *str = svn_string_dup(propchange->value, pool);
- propchange->value = svn_string_dup(original_value, pool);
- apr_hash_set(baseprops, propchange->name, APR_HASH_KEY_STRING, str);
- }
- }
-}
-
-
-/* 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.
-
- If USE_BASE is FALSE it gets the pristine text of what is currently in the
- working copy. (So it returns the pristine file of a copy).
-
- If USE_BASE is TRUE, it looks in the lowest layer of the working copy and
- shows exactly what was originally checked out (or updated to).
-
- Rationale:
-
- Which text-base do we want to use for the diff? If the node is replaced
- by a new file, then the base of the replaced file is called (in WC-1) the
- "revert base". If the replacement is a copy or move, then there is also
- the base of the copied file to consider.
-
- One could argue that we should never diff against the revert
- base, and instead diff against the empty-file for both types of
- replacement. After all, there is no ancestry relationship
- between the working file and the base file. But my guess is that
- in practice, users want to see the diff between their working
- file and "the nearest versioned thing", whatever that is. I'm
- not 100% sure this is the right decision, but it at least seems
- to match our test suite's expectations. */
-static svn_error_t *
-get_pristine_file(const char **result_abspath,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_boolean_t use_base,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const svn_checksum_t *checksum;
-
- if (!use_base)
- {
- SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, NULL, NULL, NULL, NULL,
- &checksum, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
- }
- else
- {
- SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &checksum,
- NULL, NULL, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
- }
-
- if (checksum != NULL)
- {
- SVN_ERR(svn_wc__db_pristine_get_path(result_abspath, db, local_abspath,
- checksum,
- result_pool, scratch_pool));
- return SVN_NO_ERROR;
- }
-
- *result_abspath = NULL;
- return SVN_NO_ERROR;
-}
-
-
/*-------------------------------------------------------------------------*/
@@ -234,9 +111,6 @@ struct edit_baton_t
/* Should this diff ignore node ancestry? */
svn_boolean_t ignore_ancestry;
- /* Should this diff not compare copied files with their source? */
- svn_boolean_t show_copies_as_adds;
-
/* Possibly diff repos against text-bases instead of working files. */
svn_boolean_t diff_pristine;
@@ -254,9 +128,6 @@ struct edit_baton_t
*/
struct dir_baton_t
{
- /* Gets set if the directory is added rather than replaced/unchanged. */
- svn_boolean_t added;
-
/* Reference to parent directory baton (or NULL for the root) */
struct dir_baton_t *parent_baton;
@@ -268,7 +139,13 @@ struct dir_baton_t
const char *name;
const char *relpath;
const char *local_abspath;
- svn_boolean_t shadowed;
+
+ /* TRUE if the file is added by the editor drive. */
+ svn_boolean_t added;
+ /* TRUE if the node exists only on the repository side (op_depth 0 or added) */
+ svn_boolean_t repos_only;
+ /* TRUE if the node is to be compared with an unrelated node*/
+ svn_boolean_t ignoring_ancestry;
/* Processor state */
void *pdb;
@@ -311,9 +188,6 @@ struct dir_baton_t
*/
struct file_baton_t
{
- /* Gets set if the file is added rather than replaced. */
- svn_boolean_t added;
-
struct dir_baton_t *parent_baton;
/* The name and path of this file as if they would be/are in the
@@ -321,20 +195,21 @@ struct file_baton_t
const char *name;
const char *relpath;
const char *local_abspath;
- svn_boolean_t shadowed;
/* Processor state */
void *pfb;
svn_boolean_t skip;
+ /* TRUE if the file is added by the editor drive. */
+ svn_boolean_t added;
+ /* TRUE if the node exists only on the repository side (op_depth 0 or added) */
+ svn_boolean_t repos_only;
+ /* TRUE if the node is to be compared with an unrelated node*/
+ svn_boolean_t ignoring_ancestry;
+
const svn_diff_source_t *left_src;
const svn_diff_source_t *right_src;
-
- /* When constructing the requested repository version of the file, we
- drop the result into a file at TEMP_FILE_PATH. */
- const char *temp_file_path;
-
/* The list of incoming BASE->repos propchanges. */
apr_array_header_t *propchanges;
@@ -345,9 +220,9 @@ struct file_baton_t
const svn_checksum_t *base_checksum;
apr_hash_t *base_props;
- /* The resulting checksum from apply_textdelta */
+ /* The resulting from apply_textdelta */
+ const char *temp_file_path;
unsigned char result_digest[APR_MD5_DIGESTSIZE];
- svn_boolean_t got_textdelta;
/* The overall crawler editor baton. */
struct edit_baton_t *eb;
@@ -379,7 +254,6 @@ make_edit_baton(struct edit_baton_t **ed
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
svn_boolean_t show_copies_as_adds,
- svn_boolean_t use_git_diff_format,
svn_boolean_t use_text_base,
svn_boolean_t reverse_order,
const apr_array_header_t *changelist_filter,
@@ -404,7 +278,11 @@ make_edit_baton(struct edit_baton_t **ed
if (reverse_order)
processor = svn_diff__tree_processor_reverse_create(processor, NULL, pool);
- if (! show_copies_as_adds && !use_git_diff_format)
+ /* --show-copies-as-adds implies --notice-ancestry */
+ if (show_copies_as_adds)
+ ignore_ancestry = FALSE;
+
+ if (! show_copies_as_adds)
processor = svn_diff__tree_processor_copy_as_changed_create(processor,
pool);
@@ -415,7 +293,6 @@ make_edit_baton(struct edit_baton_t **ed
eb->processor = processor;
eb->depth = depth;
eb->ignore_ancestry = ignore_ancestry;
- eb->show_copies_as_adds = show_copies_as_adds;
eb->local_before_remote = reverse_order;
eb->diff_pristine = use_text_base;
eb->changelist_hash = changelist_hash;
@@ -464,7 +341,6 @@ make_dir_baton(const char *path,
if (parent_baton != NULL)
{
parent_baton->users++;
- db->shadowed = parent_baton->shadowed;
}
db->users = 1;
@@ -495,7 +371,6 @@ make_file_baton(const char *path,
fb->local_abspath = svn_dirent_join(eb->anchor_abspath, path, file_pool);
fb->relpath = svn_dirent_skip_ancestor(eb->anchor_abspath, fb->local_abspath);
fb->name = svn_dirent_basename(fb->relpath, NULL);
- fb->shadowed = parent_baton->shadowed;
fb->added = added;
fb->pool = file_pool;
@@ -523,304 +398,183 @@ maybe_done(struct dir_baton_t *db)
return SVN_NO_ERROR;
}
-/* Diff the file PATH against its text base. At this
- * stage we are dealing with a file that does exist in the working copy.
- *
- * DIR_BATON is the parent directory baton, PATH is the path to the file to
- * be compared.
- *
- * Do all allocation in POOL.
- *
- * ### TODO: Need to work on replace if the new filename used to be a
- * directory.
- */
-static svn_error_t *
-file_diff(struct edit_baton_t *eb,
- const char *local_abspath,
- const char *path,
- void *dir_baton,
- apr_pool_t *scratch_pool)
+/* Standard check to see if a node is represented in the local working copy */
+#define NOT_PRESENT(status) \
+ ((status) == svn_wc__db_status_not_present \
+ || (status) == svn_wc__db_status_excluded \
+ || (status) == svn_wc__db_status_server_excluded)
+
+svn_error_t *
+svn_wc__diff_base_working_diff(svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *relpath,
+ svn_revnum_t revision,
+ apr_hash_t *changelist_hash,
+ const svn_diff_tree_processor_t *processor,
+ void *processor_dir_baton,
+ svn_boolean_t diff_pristine,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_t *db = eb->db;
- const char *textbase;
- svn_boolean_t replaced;
+ void *file_baton = NULL;
+ svn_boolean_t skip = FALSE;
svn_wc__db_status_t status;
- svn_revnum_t original_revision;
- const char *original_repos_relpath;
- svn_revnum_t revision;
- svn_revnum_t revert_base_revnum;
- svn_boolean_t have_base;
+ svn_revnum_t db_revision;
+ svn_boolean_t had_props;
+ svn_boolean_t props_mod;
+ svn_boolean_t files_same = FALSE;
svn_wc__db_status_t base_status;
- svn_boolean_t use_base = FALSE;
+ const svn_checksum_t *working_checksum;
+ const svn_checksum_t *checksum;
+ svn_filesize_t recorded_size;
+ apr_time_t recorded_time;
+ const char *pristine_file;
+ const char *local_file;
+ svn_diff_source_t *left_src;
+ svn_diff_source_t *right_src;
+ apr_hash_t *base_props;
+ apr_hash_t *local_props;
+ apr_array_header_t *prop_changes;
+ const char *changelist;
- SVN_ERR_ASSERT(! eb->diff_pristine);
+ SVN_ERR(svn_wc__db_read_info(&status, NULL, &db_revision, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, &working_checksum, NULL,
+ NULL, NULL, NULL, NULL, NULL, &recorded_size,
+ &recorded_time, &changelist, NULL, NULL,
+ &had_props, &props_mod, NULL, NULL, NULL,
+ db, local_abspath, scratch_pool, scratch_pool));
+ checksum = working_checksum;
+
+ assert(status == svn_wc__db_status_normal
+ || status == svn_wc__db_status_added
+ || (status == svn_wc__db_status_deleted && diff_pristine));
/* If the item is not a member of a specified changelist (and there are
some specified changelists), skip it. */
- if (! svn_wc__internal_changelist_match(db, local_abspath,
- eb->changelist_hash, scratch_pool))
+ if (changelist_hash && !svn_hash_gets(changelist_hash, changelist))
return SVN_NO_ERROR;
- SVN_ERR(svn_wc__db_read_info(&status, NULL, &revision, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- &original_repos_relpath, NULL, NULL,
- &original_revision, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, &have_base, NULL, NULL,
- db, local_abspath, scratch_pool, scratch_pool));
- if (have_base)
- SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &revert_base_revnum,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
- replaced = ((status == svn_wc__db_status_added)
- && have_base
- && base_status != svn_wc__db_status_not_present);
-
- /* A wc-wc diff of replaced files actually shows a diff against the
- * revert-base, showing all previous lines as removed and adding all new
- * lines. This does not happen for copied/moved-here files, not even with
- * show_copies_as_adds == TRUE (in which case copy/move is really shown as
- * an add, diffing against the empty file).
- * So show the revert-base revision for plain replaces. */
- if (replaced
- && ! original_repos_relpath)
- {
- use_base = TRUE;
- revision = revert_base_revnum;
- }
-
- /* Set TEXTBASE to the path to the text-base file that we want to diff
- against.
-
- ### There shouldn't be cases where the result is NULL, but at present
- there might be - see get_nearest_pristine_text_as_file(). */
- SVN_ERR(get_pristine_file(&textbase, db, local_abspath,
- use_base, scratch_pool, scratch_pool));
-
- /* Delete compares text-base against empty file, modifications to the
- * working-copy version of the deleted file are not wanted.
- * Replace is treated like a delete plus an add: two comparisons are
- * generated, first one for the delete and then one for the add.
- * However, if this file was replaced and we are ignoring ancestry,
- * report it as a normal file modification instead. */
- if ((! replaced && status == svn_wc__db_status_deleted) ||
- (replaced && ! eb->ignore_ancestry))
+ if (status != svn_wc__db_status_normal)
{
- apr_hash_t *left_props;
- void *file_baton = NULL;
- svn_boolean_t skip = FALSE;
- svn_diff_source_t *left_src = svn_diff__source_create(revision,
- scratch_pool);
-
- /* Get svn:mime-type from pristine props (in BASE or WORKING) of PATH. */
- SVN_ERR(svn_wc__db_read_pristine_props(&left_props, db, local_abspath,
- scratch_pool, scratch_pool));
-
- SVN_ERR(eb->processor->file_opened(&file_baton,
- &skip,
- path,
- left_src,
- NULL /* right_source */,
- NULL /* copyfrom_source */,
- dir_baton,
- eb->processor,
- scratch_pool,
- scratch_pool));
+ SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db_revision,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, &checksum, NULL, NULL, &had_props,
+ NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ recorded_size = SVN_INVALID_FILESIZE;
+ recorded_time = 0;
+ props_mod = TRUE; /* Requires compare */
+ }
+ else if (diff_pristine)
+ files_same = TRUE;
+ else
+ {
+ const svn_io_dirent2_t *dirent;
- if (!skip)
- SVN_ERR(eb->processor->file_deleted(path,
- left_src,
- textbase,
- left_props,
- file_baton,
- eb->processor,
- scratch_pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath,
+ FALSE /* verify truename */,
+ TRUE /* ingore_enoent */,
+ scratch_pool, scratch_pool));
- if (! (replaced && ! eb->ignore_ancestry))
+ if (dirent->kind == svn_node_file
+ && dirent->filesize == recorded_size
+ && dirent->mtime == recorded_time)
{
- /* We're here only for showing a delete, so we're done. */
- return SVN_NO_ERROR;
+ files_same = TRUE;
}
}
- /* Now deal with showing additions, or the add-half of replacements.
- * If the item is schedule-add *with history*, then we usually want
- * to see the usual working vs. text-base comparison, which will show changes
- * made since the file was copied. But in case we're showing copies as adds,
- * we need to compare the copied file to the empty file. If we're doing a git
- * diff, and the file was copied, we need to report the file as added and
- * diff it against the text base, so that a "copied" git diff header, and
- * possibly a diff against the copy source, will be generated for it. */
- if (status == svn_wc__db_status_added
- && !(eb->ignore_ancestry && replaced))
- {
- void *file_baton = NULL;
- svn_boolean_t skip = FALSE;
- const char *translated = NULL;
- svn_diff_source_t *copyfrom_src = NULL;
- svn_diff_source_t *right_src = svn_diff__source_create(
- SVN_INVALID_REVNUM,
- scratch_pool);
+ if (files_same && !props_mod)
+ return SVN_NO_ERROR; /* Cheap exit */
- if (original_repos_relpath)
- {
- copyfrom_src = svn_diff__source_create(original_revision,
- scratch_pool);
- copyfrom_src->repos_relpath = original_repos_relpath;
- }
+ assert(checksum);
- SVN_ERR(eb->processor->file_opened(&file_baton, &skip,
- path,
- NULL /* left source */,
- right_src,
- copyfrom_src,
- dir_baton,
- eb->processor,
- scratch_pool, scratch_pool));
+ if (!SVN_IS_VALID_REVNUM(revision))
+ revision = db_revision;
- if (!skip)
- {
- apr_hash_t *right_props;
- apr_hash_t *copyfrom_props = NULL;
-
- /* Get svn:mime-type from ACTUAL props of PATH. */
- SVN_ERR(svn_wc__db_read_props(&right_props, db, local_abspath,
- scratch_pool, scratch_pool));
+ left_src = svn_diff__source_create(revision, scratch_pool);
+ right_src = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
- if (copyfrom_src)
- {
- SVN_ERR(svn_wc__db_read_pristine_props(©from_props,
- db, local_abspath,
- scratch_pool,
- scratch_pool));
- }
+ SVN_ERR(processor->file_opened(&file_baton, &skip, relpath,
+ left_src,
+ right_src,
+ NULL /* copyfrom_src */,
+ processor_dir_baton,
+ processor,
+ scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__internal_translated_file(&translated, local_abspath,
- db, local_abspath,
- SVN_WC_TRANSLATE_TO_NF
- | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
- eb->cancel_func,
- eb->cancel_baton,
- scratch_pool,
- scratch_pool));
+ if (skip)
+ return SVN_NO_ERROR;
- SVN_ERR(eb->processor->file_added(path,
- copyfrom_src,
- right_src,
- copyfrom_src
- ? textbase
- : NULL,
- translated,
- copyfrom_props,
- right_props,
- file_baton,
- eb->processor,
- scratch_pool));
- }
- }
- else
- {
- const char *translated = NULL;
- 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(svn_wc__db_pristine_get_path(&pristine_file,
+ db, local_abspath, checksum,
+ scratch_pool, scratch_pool));
- SVN_ERR(eb->processor->file_opened(&file_baton, &skip,
- path,
- left_src,
- right_src,
- NULL,
- dir_baton,
- eb->processor,
+ if (diff_pristine)
+ SVN_ERR(svn_wc__db_pristine_get_path(&local_file,
+ db, local_abspath,
+ working_checksum,
scratch_pool, scratch_pool));
+ else if (! (had_props || props_mod))
+ local_file = local_abspath;
+ else if (files_same)
+ local_file = pristine_file;
+ else
+ SVN_ERR(svn_wc__internal_translated_file(
+ &local_file, local_abspath,
+ db, local_abspath,
+ SVN_WC_TRANSLATE_TO_NF
+ | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
+
+ if (! files_same)
+ SVN_ERR(svn_io_files_contents_same_p(&files_same, local_file,
+ pristine_file, 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,
- FALSE, scratch_pool));
- if (modified)
- {
- /* Note that this might be the _second_ time we translate
- the file, as svn_wc__text_modified_internal_p() might have used a
- tmp translated copy too. But what the heck, diff is
- already expensive, translating twice for the sake of code
- modularity is liveable. */
- SVN_ERR(svn_wc__internal_translated_file(
- &translated, local_abspath, db, local_abspath,
- SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
- eb->cancel_func, eb->cancel_baton,
- scratch_pool, scratch_pool));
- }
-
- /* Get the properties, the svn:mime-type values, and compute the
- differences between the two. */
- if (replaced
- && eb->ignore_ancestry)
- {
- /* 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(&left_props,
- db, local_abspath,
- scratch_pool, scratch_pool));
- }
- else
- {
- /* We can only fetch the pristine props (from BASE or WORKING) if
- the node has not been replaced, or it was copied/moved here. */
- SVN_ERR_ASSERT(!replaced
- || status == svn_wc__db_status_copied
- || status == svn_wc__db_status_moved_here);
-
- 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 (!left_props)
- left_props = apr_hash_make(scratch_pool);
- }
+ if (had_props)
+ SVN_ERR(svn_wc__db_base_get_props(&base_props, db, local_abspath,
+ scratch_pool, scratch_pool));
+ else
+ base_props = apr_hash_make(scratch_pool);
- SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath,
- scratch_pool, scratch_pool));
+ if (status == svn_wc__db_status_normal && (diff_pristine || !props_mod))
+ local_props = base_props;
+ else if (diff_pristine)
+ SVN_ERR(svn_wc__db_read_pristine_props(&local_props, db, local_abspath,
+ scratch_pool, scratch_pool));
+ else
+ SVN_ERR(svn_wc__db_read_props(&local_props, db, local_abspath,
+ scratch_pool, scratch_pool));
- SVN_ERR(svn_prop_diffs(&propchanges, right_props, left_props,
- scratch_pool));
+ SVN_ERR(svn_prop_diffs(&prop_changes, local_props, base_props, scratch_pool));
- if (modified || propchanges->nelts > 0)
- {
- SVN_ERR(eb->processor->file_changed(path,
- left_src,
- right_src,
- textbase,
- translated,
- 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));
+ if (prop_changes->nelts || !files_same)
+ {
+ SVN_ERR(processor->file_changed(relpath,
+ left_src,
+ right_src,
+ pristine_file,
+ local_file,
+ base_props,
+ local_props,
+ ! files_same,
+ prop_changes,
+ file_baton,
+ processor,
+ scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(processor->file_closed(relpath,
+ left_src,
+ right_src,
+ file_baton,
+ processor,
+ scratch_pool));
}
return SVN_NO_ERROR;
@@ -888,10 +642,13 @@ walk_local_nodes_diff(struct edit_baton_
db, local_abspath, scratch_pool, scratch_pool));
left_src = svn_diff__source_create(revision, scratch_pool);
- right_src = svn_diff__source_create(0, scratch_pool);
+ right_src = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
if (compared)
- dir_baton = parent_baton;
+ {
+ dir_baton = parent_baton;
+ skip = TRUE;
+ }
else if (!in_anchor_not_target)
SVN_ERR(eb->processor->dir_opened(&dir_baton, &skip, &skip_children,
path,
@@ -905,19 +662,41 @@ walk_local_nodes_diff(struct edit_baton_
if (!skip_children && depth != svn_depth_empty)
{
- const apr_array_header_t *children;
+ apr_hash_t *nodes;
+ apr_hash_t *conflicts;
+ apr_array_header_t *children;
+ svn_depth_t depth_below_here = depth;
+ svn_boolean_t diff_files;
+ svn_boolean_t diff_dirs;
int i;
- SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
- scratch_pool, iterpool));
+
+ if (depth_below_here == svn_depth_immediates)
+ depth_below_here = svn_depth_empty;
+
+ diff_files = (depth == svn_depth_unknown
+ || depth >= svn_depth_files);
+ diff_dirs = (depth == svn_depth_unknown
+ || depth >= svn_depth_immediates);
+
+ SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
+ db, local_abspath,
+ scratch_pool, iterpool));
+
+ children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
+ scratch_pool);
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);
+ svn_sort__item_t *item = &APR_ARRAY_IDX(children, i,
+ svn_sort__item_t);
+ const char *name = item->key;
+ struct svn_wc__db_info_t *info = item->value;
+
+ const char *child_abspath;
+ const char *child_relpath;
+ svn_boolean_t repos_only;
+ svn_boolean_t local_only;
+ svn_kind_t base_kind;
if (eb->cancel_func)
SVN_ERR(eb->cancel_func(eb->cancel_baton));
@@ -932,67 +711,155 @@ walk_local_nodes_diff(struct edit_baton_
if (compared && svn_hash_gets(compared, 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)
+ if (NOT_PRESENT(info->status))
continue;
- child_path = svn_relpath_join(path, name, iterpool);
+ assert(info->status == svn_wc__db_status_normal
+ || info->status == svn_wc__db_status_added
+ || info->status == svn_wc__db_status_deleted);
- /* 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;
+ svn_pool_clear(iterpool);
+ child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+ child_relpath = svn_relpath_join(path, name, iterpool);
+
+ repos_only = FALSE;
+ local_only = FALSE;
- switch (kind)
+ if (!info->have_base)
{
- case svn_kind_file:
- case svn_kind_symlink:
- SVN_ERR(file_diff(eb, child_abspath, child_path, dir_baton,
- iterpool));
- break;
+ local_only = TRUE; /* Only report additions */
+ }
+ else if (info->status == svn_wc__db_status_normal)
+ {
+ /* Simple diff */
+ base_kind = info->kind;
+ }
+ else if (info->status == svn_wc__db_status_deleted
+ && (!eb->diff_pristine || !info->have_more_work))
+ {
+ svn_wc__db_status_t base_status;
+ repos_only = TRUE;
+ SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ db, child_abspath,
+ iterpool, iterpool));
- 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))
+ if (NOT_PRESENT(base_status))
+ continue;
+ }
+ else
+ {
+ /* working status is either added or deleted */
+ svn_wc__db_status_t base_status;
+
+ SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ db, child_abspath,
+ iterpool, iterpool));
+
+ if (NOT_PRESENT(base_status))
+ local_only = TRUE;
+ else if (base_kind != info->kind || !eb->ignore_ancestry)
{
- svn_depth_t depth_below_here = depth;
+ repos_only = TRUE;
+ local_only = TRUE;
+ }
+ }
- if (depth_below_here == svn_depth_immediates)
- depth_below_here = svn_depth_empty;
+ if (eb->local_before_remote && local_only)
+ {
+ if (info->kind == svn_kind_file && diff_files)
+ SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
+ child_relpath,
+ eb->processor, dir_baton,
+ eb->changelist_hash,
+ eb->diff_pristine,
+ eb->cancel_func,
+ eb->cancel_baton,
+ iterpool));
+ else if (info->kind == svn_kind_dir && diff_dirs)
+ SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
+ child_relpath,
+ depth_below_here,
+ eb->processor, dir_baton,
+ eb->changelist_hash,
+ eb->diff_pristine,
+ eb->cancel_func,
+ eb->cancel_baton,
+ iterpool));
+ }
- SVN_ERR(walk_local_nodes_diff(eb,
- child_abspath,
- child_path,
- depth_below_here,
- NULL /* compared */,
- dir_baton,
- iterpool));
+ if (repos_only)
+ {
+ /* Report repository form deleted */
+ if (base_kind == svn_kind_file && diff_files)
+ SVN_ERR(svn_wc__diff_base_only_file(db, child_abspath,
+ child_relpath, eb->revnum,
+ eb->processor, dir_baton,
+ iterpool));
+ else if (base_kind == svn_kind_dir && diff_dirs)
+ SVN_ERR(svn_wc__diff_base_only_dir(db, child_abspath,
+ child_relpath, eb->revnum,
+ depth_below_here,
+ eb->processor, dir_baton,
+ eb->cancel_func,
+ eb->cancel_baton,
+ iterpool));
+ }
+ else if (!local_only) /* Not local only nor remote only */
+ {
+ /* Diff base against actual */
+ if (info->kind == svn_kind_file && diff_files)
+ {
+ if (info->status != svn_wc__db_status_normal
+ || !eb->diff_pristine)
+ {
+ SVN_ERR(svn_wc__diff_base_working_diff(
+ db, child_abspath,
+ child_relpath,
+ eb->revnum,
+ eb->changelist_hash,
+ eb->processor, dir_baton,
+ eb->diff_pristine,
+ eb->cancel_func,
+ eb->cancel_baton,
+ scratch_pool));
+ }
}
- break;
+ else if (info->kind == svn_kind_dir && diff_dirs)
+ SVN_ERR(walk_local_nodes_diff(eb, child_abspath,
+ child_relpath,
+ depth_below_here,
+ NULL /* compared */,
+ dir_baton,
+ scratch_pool));
+ }
- default:
- break;
- }
+ if (!eb->local_before_remote && local_only)
+ {
+ if (info->kind == svn_kind_file && diff_files)
+ SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
+ child_relpath,
+ eb->processor, dir_baton,
+ eb->changelist_hash,
+ eb->diff_pristine,
+ eb->cancel_func,
+ eb->cancel_baton,
+ iterpool));
+ else if (info->kind == svn_kind_dir && diff_dirs)
+ SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
+ child_relpath, depth_below_here,
+ eb->processor, dir_baton,
+ eb->changelist_hash,
+ eb->diff_pristine,
+ eb->cancel_func,
+ eb->cancel_baton,
+ iterpool));
+ }
}
}
@@ -1004,11 +871,10 @@ walk_local_nodes_diff(struct edit_baton_
### 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
+ if (! skip
+ && ! eb->changelist_hash
&& ! in_anchor_not_target
- && (!compared || ! svn_hash_gets(compared, ""))
- && props_mod
- && ! skip)
+ && props_mod)
{
apr_array_header_t *propchanges;
apr_hash_t *left_props;
@@ -1043,131 +909,164 @@ walk_local_nodes_diff(struct edit_baton_
return SVN_NO_ERROR;
}
-/* Report the local version of a file in the working copy as added.
- * This file can be in either WORKING or BASE, as for the repository
- * it does not exist.
- */
-static svn_error_t *
-report_local_only_file(struct edit_baton_t *eb,
- const char *local_abspath,
- const char *path,
- void *parent_baton,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__diff_local_only_file(svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *relpath,
+ const svn_diff_tree_processor_t *processor,
+ void *processor_parent_baton,
+ apr_hash_t *changelist_hash,
+ svn_boolean_t diff_pristine,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_t *db = eb->db;
svn_diff_source_t *right_src;
+ svn_diff_source_t *copyfrom_src = NULL;
+ svn_wc__db_status_t status;
+ svn_kind_t kind;
+ const svn_checksum_t *checksum;
+ const char *original_repos_relpath;
+ svn_revnum_t original_revision;
const char *changelist;
+ svn_boolean_t had_props;
+ svn_boolean_t props_mod;
+ apr_hash_t *pristine_props;
apr_hash_t *right_props = NULL;
- const char *source_file;
+ const char *pristine_file;
const char *translated_file;
- svn_wc__db_status_t status;
svn_revnum_t revision;
void *file_baton = NULL;
svn_boolean_t skip = FALSE;
+ svn_boolean_t file_mod = TRUE;
- SVN_ERR(svn_wc__db_read_info(&status, NULL, &revision, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, &changelist,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, &checksum, NULL,
+ &original_repos_relpath, NULL, NULL,
+ &original_revision, NULL, NULL, NULL,
+ &changelist, NULL, NULL, &had_props,
+ &props_mod, NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
- if (changelist && eb->changelist_hash
- && !svn_hash_gets(eb->changelist_hash, changelist))
+ assert(kind == svn_kind_file
+ && (status == svn_wc__db_status_normal
+ || status == svn_wc__db_status_added
+ || (status == svn_wc__db_status_deleted && diff_pristine)));
+
+
+ if (changelist && changelist_hash
+ && !svn_hash_gets(changelist_hash, changelist))
return SVN_NO_ERROR;
- if (status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, db,
- local_abspath, scratch_pool, scratch_pool));
-
- /* We can't show additions for files that don't exist. */
- SVN_ERR_ASSERT(status != svn_wc__db_status_deleted || eb->diff_pristine);
-
- /* If the file was added *with history*, then we don't want to
- see a comparison to the empty file; we want the usual working
- vs. text-base comparison. */
- if (status == svn_wc__db_status_copied ||
- status == svn_wc__db_status_moved_here)
+ if (status == svn_wc__db_status_deleted)
{
- /* Don't show anything if we're comparing to BASE, since by
- definition there can't be any local modifications. */
- if (eb->diff_pristine)
- return SVN_NO_ERROR;
+ assert(diff_pristine);
+
+ SVN_ERR(svn_wc__db_read_pristine_info(&status, &kind, NULL, NULL, NULL,
+ NULL, &checksum, NULL, &had_props,
+ &pristine_props,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ props_mod = FALSE;
+ }
+ else if (!had_props)
+ pristine_props = apr_hash_make(scratch_pool);
+ else
+ SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
- /* Otherwise show just the local modifications. */
- return file_diff(eb, local_abspath, path, parent_baton, scratch_pool);
+ if (original_repos_relpath)
+ {
+ copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
+ copyfrom_src->repos_relpath = original_repos_relpath;
}
- right_src = svn_diff__source_create(revision, scratch_pool);
+ if (props_mod || !SVN_IS_VALID_REVNUM(revision))
+ right_src = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
+ else
+ {
+ if (diff_pristine)
+ file_mod = FALSE;
+ else
+ SVN_ERR(svn_wc__internal_file_modified_p(&file_mod, db, local_abspath,
+ FALSE, scratch_pool));
- SVN_ERR(eb->processor->file_opened(&file_baton, &skip,
- path,
- NULL,
- right_src,
- NULL,
- parent_baton,
- eb->processor,
- scratch_pool, scratch_pool));
+ if (!file_mod)
+ right_src = svn_diff__source_create(revision, scratch_pool);
+ else
+ right_src = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
+ }
+
+ SVN_ERR(processor->file_opened(&file_baton, &skip,
+ relpath,
+ NULL /* left_source */,
+ right_src,
+ copyfrom_src,
+ processor_parent_baton,
+ processor,
+ scratch_pool, scratch_pool));
if (skip)
return SVN_NO_ERROR;
- if (eb->diff_pristine)
- SVN_ERR(svn_wc__db_read_pristine_props(&right_props, db, local_abspath,
- scratch_pool, scratch_pool));
- else
+ if (props_mod && !diff_pristine)
SVN_ERR(svn_wc__db_read_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
+ else
+ right_props = svn_prop_hash_dup(pristine_props, scratch_pool);
- if (eb->diff_pristine)
+ if (checksum)
+ SVN_ERR(svn_wc__db_pristine_get_path(&pristine_file, db, local_abspath,
+ checksum, scratch_pool, scratch_pool));
+ else
+ pristine_file = NULL;
+
+ if (diff_pristine)
{
- SVN_ERR(get_pristine_file(&source_file, db, local_abspath,
- FALSE, scratch_pool, scratch_pool));
- translated_file = source_file; /* No translation needed */
+ translated_file = pristine_file; /* No translation needed */
}
else
{
- source_file = local_abspath;
-
SVN_ERR(svn_wc__internal_translated_file(
- &translated_file, source_file, db, local_abspath,
+ &translated_file, local_abspath, db, local_abspath,
SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
- eb->cancel_func, eb->cancel_baton,
+ cancel_func, cancel_baton,
scratch_pool, scratch_pool));
}
- SVN_ERR(eb->processor->file_added(path,
- NULL /* copyfrom source */,
- right_src,
- NULL /* copyfrom file */,
- translated_file,
- NULL /* copyfrom props */,
- right_props,
- file_baton,
- eb->processor,
- scratch_pool));
+ SVN_ERR(processor->file_added(relpath,
+ copyfrom_src,
+ right_src,
+ copyfrom_src
+ ? pristine_file
+ : NULL,
+ translated_file,
+ copyfrom_src
+ ? pristine_props
+ : NULL,
+ right_props,
+ file_baton,
+ processor,
+ scratch_pool));
return SVN_NO_ERROR;
}
-/* Report an existing directory in the working copy (either in BASE
- * or WORKING) as having been added. If recursing, also report any
- * subdirectories as added.
- *
- * DIR_BATON is the baton for the directory.
- *
- * Do all allocation in POOL.
- */
-static svn_error_t *
-report_local_only_dir(struct edit_baton_t *eb,
- const char *local_abspath,
- const char *path,
- svn_depth_t depth,
- void *parent_baton,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__diff_local_only_dir(svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *relpath,
+ svn_depth_t depth,
+ const svn_diff_tree_processor_t *processor,
+ void *processor_parent_baton,
+ apr_hash_t *changelist_hash,
+ svn_boolean_t diff_pristine,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_t *db = eb->db;
const apr_array_header_t *children;
int i;
apr_pool_t *iterpool;
@@ -1176,79 +1075,81 @@ report_local_only_dir(struct edit_baton_
svn_boolean_t skip_children = FALSE;
svn_diff_source_t *right_src = svn_diff__source_create(SVN_INVALID_REVNUM,
scratch_pool);
+ svn_depth_t depth_below_here = depth;
+ apr_hash_t *nodes;
+ apr_hash_t *conflicts;
/* Report the addition of the directory's contents. */
iterpool = svn_pool_create(scratch_pool);
- SVN_ERR(eb->processor->dir_opened(&pdb, &skip, &skip_children,
- path,
- NULL,
- right_src,
- NULL /* copyfrom_src */,
- parent_baton,
- eb->processor,
- scratch_pool, scratch_pool));
+ SVN_ERR(processor->dir_opened(&pdb, &skip, &skip_children,
+ relpath,
+ NULL,
+ right_src,
+ NULL /* copyfrom_src */,
+ processor_parent_baton,
+ processor,
+ scratch_pool, iterpool));
+ SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts, db, local_abspath,
+ scratch_pool, iterpool));
- SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
- scratch_pool, iterpool));
+ if (depth_below_here == svn_depth_immediates)
+ depth_below_here = svn_depth_empty;
+
+ children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
+ scratch_pool);
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_sort__item_t *item = &APR_ARRAY_IDX(children, i, svn_sort__item_t);
+ const char *name = item->key;
+ struct svn_wc__db_info_t *info = item->value;
+ const char *child_abspath;
+ const char *child_relpath;
svn_pool_clear(iterpool);
- if (eb->cancel_func)
- SVN_ERR(eb->cancel_func(eb->cancel_baton));
+ if (cancel_func)
+ SVN_ERR(cancel_func(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_server_excluded)
+ if (NOT_PRESENT(info->status))
{
continue;
}
/* If comparing against WORKING, skip entries that are
schedule-deleted - they don't really exist. */
- if (!eb->diff_pristine && status == svn_wc__db_status_deleted)
+ if (!diff_pristine && info->status == svn_wc__db_status_deleted)
continue;
- child_path = svn_relpath_join(path, name, iterpool);
+ child_relpath = svn_relpath_join(relpath, name, iterpool);
- switch (kind)
+ switch (info->kind)
{
case svn_kind_file:
case svn_kind_symlink:
- SVN_ERR(report_local_only_file(eb, child_abspath, child_path,
- pdb, iterpool));
+ SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
+ child_relpath,
+ processor, pdb,
+ changelist_hash,
+ diff_pristine,
+ cancel_func, cancel_baton,
+ scratch_pool));
break;
case svn_kind_dir:
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(report_local_only_dir(eb,
- child_abspath,
- child_path,
- depth_below_here,
- pdb,
- iterpool));
+ SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
+ child_relpath, depth_below_here,
+ processor, pdb,
+ changelist_hash,
+ diff_pristine,
+ cancel_func, cancel_baton,
+ iterpool));
}
break;
@@ -1260,33 +1161,32 @@ report_local_only_dir(struct edit_baton_
if (!skip)
{
apr_hash_t *right_props;
- if (eb->diff_pristine)
+ if (diff_pristine)
SVN_ERR(svn_wc__db_read_pristine_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
else
SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
- SVN_ERR(eb->processor->dir_added(path,
- NULL /* copyfrom_src */,
- right_src,
- NULL,
- right_props,
- pdb,
- eb->processor,
- iterpool));
+ SVN_ERR(processor->dir_added(relpath,
+ NULL /* copyfrom_src */,
+ right_src,
+ NULL,
+ right_props,
+ pdb,
+ processor,
+ iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
-/* Ensures that local changes are reported to pb->eb->processor if there
- are any. */
+/* Reports local changes. */
static svn_error_t *
-ensure_local_only_handled(struct dir_baton_t *pb,
- const char *name,
- apr_pool_t *scratch_pool)
+handle_local_only(struct dir_baton_t *pb,
+ const char *name,
+ apr_pool_t *scratch_pool)
{
struct edit_baton_t *eb = pb->eb;
const struct svn_wc__db_info_t *info;
@@ -1296,23 +1196,18 @@ ensure_local_only_handled(struct dir_bat
assert(!strchr(name, '/'));
assert(!pb->added || eb->ignore_ancestry);
- if (svn_hash_gets(pb->compared, name))
+ if (pb->skip_children)
return SVN_NO_ERROR;
- svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, name), "");
-
SVN_ERR(ensure_local_info(pb, scratch_pool));
info = svn_hash_gets(pb->local_info, name);
- if (info == NULL)
+ if (info == NULL || NOT_PRESENT(info->status))
return SVN_NO_ERROR;
switch (info->status)
{
- case svn_wc__db_status_not_present:
- case svn_wc__db_status_excluded:
- case svn_wc__db_status_server_excluded:
case svn_wc__db_status_incomplete:
return SVN_NO_ERROR; /* Not local only */
@@ -1341,25 +1236,211 @@ ensure_local_only_handled(struct dir_bat
else
depth = svn_depth_empty;
- SVN_ERR(report_local_only_dir(
- eb,
+ SVN_ERR(svn_wc__diff_local_only_dir(
+ eb->db,
svn_dirent_join(pb->local_abspath, name, scratch_pool),
svn_relpath_join(pb->relpath, name, scratch_pool),
repos_delete ? svn_depth_infinity : depth,
- pb->pdb,
+ eb->processor, pb->pdb,
+ eb->changelist_hash,
+ eb->diff_pristine,
+ eb->cancel_func, eb->cancel_baton,
scratch_pool));
}
else
- SVN_ERR(report_local_only_file(
- eb,
+ SVN_ERR(svn_wc__diff_local_only_file(
+ eb->db,
svn_dirent_join(pb->local_abspath, name, scratch_pool),
svn_relpath_join(pb->relpath, name, scratch_pool),
- pb->pdb,
+ eb->processor, pb->pdb,
+ eb->changelist_hash,
+ eb->diff_pristine,
+ eb->cancel_func, eb->cancel_baton,
scratch_pool));
return SVN_NO_ERROR;
}
+/* Reports a file LOCAL_ABSPATH in BASE as deleted */
+svn_error_t *
+svn_wc__diff_base_only_file(svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *relpath,
+ svn_revnum_t revision,
+ const svn_diff_tree_processor_t *processor,
+ void *processor_parent_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_status_t status;
+ svn_kind_t kind;
+ const svn_checksum_t *checksum;
+ apr_hash_t *props;
+ void *file_baton = NULL;
+ svn_boolean_t skip = FALSE;
+ svn_diff_source_t *left_src;
+ const char *pristine_file;
+
+ SVN_ERR(svn_wc__db_base_get_info(&status, &kind,
+ SVN_IS_VALID_REVNUM(revision)
+ ? NULL : &revision,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &checksum, NULL, NULL, NULL, &props, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR_ASSERT(status == svn_wc__db_status_normal
+ && kind == svn_kind_file
+ && checksum);
+
+ left_src = svn_diff__source_create(revision, scratch_pool);
+
+ SVN_ERR(processor->file_opened(&file_baton, &skip,
+ relpath,
+ left_src,
+ NULL /* right_src */,
+ NULL /* copyfrom_source */,
+ processor_parent_baton,
+ processor,
+ scratch_pool, scratch_pool));
+
+ if (skip)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__db_pristine_get_path(&pristine_file,
+ db, local_abspath, checksum,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(processor->file_deleted(relpath,
+ left_src,
+ pristine_file,
+ props,
+ file_baton,
+ processor,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__diff_base_only_dir(svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *relpath,
+ svn_revnum_t revision,
+ svn_depth_t depth,
+ const svn_diff_tree_processor_t *processor,
+ void *processor_parent_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ void *dir_baton = NULL;
+ svn_boolean_t skip = FALSE;
+ svn_boolean_t skip_children = FALSE;
+ svn_diff_source_t *left_src;
+ svn_revnum_t report_rev = revision;
+
+ if (!SVN_IS_VALID_REVNUM(report_rev))
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &report_rev, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ left_src = svn_diff__source_create(report_rev, scratch_pool);
+
+ SVN_ERR(processor->dir_opened(&dir_baton, &skip, &skip_children,
+ relpath,
+ left_src,
+ NULL /* right_src */,
+ NULL /* copyfrom_src */,
+ processor_parent_baton,
+ processor,
+ scratch_pool, scratch_pool));
+
+ if (!skip_children && (depth == svn_depth_unknown || depth > svn_depth_empty))
+ {
+ apr_hash_t *nodes;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_array_header_t *children;
+ int i;
+
+ SVN_ERR(svn_wc__db_base_get_children_info(&nodes, db, local_abspath,
+ scratch_pool, iterpool));
+
+ children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
+ scratch_pool);
+
+ for (i = 0; i < children->nelts; i++)
+ {
+ svn_sort__item_t *item = &APR_ARRAY_IDX(children, i,
+ svn_sort__item_t);
+ const char *name = item->key;
+ struct svn_wc__db_base_info_t *info = item->value;
+ const char *child_abspath;
+ const char *child_relpath;
+
+ if (info->status != svn_wc__db_status_normal)
+ continue;
+
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ svn_pool_clear(iterpool);
+
+ child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+ child_relpath = svn_relpath_join(relpath, name, iterpool);
+
+ switch (info->kind)
+ {
+ case svn_kind_file:
+ case svn_kind_symlink:
+ SVN_ERR(svn_wc__diff_base_only_file(db, child_abspath,
+ child_relpath,
+ revision,
+ processor, dir_baton,
+ iterpool));
+ break;
+ case svn_kind_dir:
+ 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(svn_wc__diff_base_only_dir(db, child_abspath,
+ child_relpath,
+ revision,
+ depth_below_here,
+ processor, dir_baton,
+ cancel_func,
+ cancel_baton,
+ iterpool));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (!skip)
+ {
+ apr_hash_t *props;
+ SVN_ERR(svn_wc__db_base_get_props(&props, db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(processor->dir_deleted(relpath,
+ left_src,
+ props,
+ dir_baton,
+ processor,
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
/* An svn_delta_editor_t function. */
static svn_error_t *
@@ -1387,6 +1468,24 @@ open_root(void *edit_baton,
db = make_dir_baton("", NULL, eb, FALSE, eb->depth, dir_pool);
*root_baton = db;
+ if (eb->target[0] == '\0')
+ {
+ db->left_src = svn_diff__source_create(eb->revnum, db->pool);
+ db->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, db->pool);
+
+ SVN_ERR(eb->processor->dir_opened(&db->pdb, &db->skip,
+ &db->skip_children,
+ "",
+ db->left_src,
+ db->right_src,
+ NULL /* copyfrom_source */,
+ NULL /* parent_baton */,
+ eb->processor,
+ db->pool, db->pool));
+ }
+ else
+ db->skip = TRUE; /* Skip this, but not the children */
+
return SVN_NO_ERROR;
}
@@ -1422,37 +1521,43 @@ add_directory(const char *path,
svn_depth_t subdir_depth = (pb->depth == svn_depth_immediates)
? svn_depth_empty : pb->depth;
- /* ### TODO: support copyfrom? */
-
db = make_dir_baton(path, pb, pb->eb, TRUE, subdir_depth,
dir_pool);
*child_baton = db;
- if (!db->shadowed)
+ if (pb->repos_only || !eb->ignore_ancestry)
+ db->repos_only = TRUE;
+ else
{
struct svn_wc__db_info_t *info;
SVN_ERR(ensure_local_info(pb, dir_pool));
info = svn_hash_gets(pb->local_info, db->name);
- if (!info || info->kind != svn_kind_dir)
- db->shadowed = TRUE;
- }
+ if (!info || info->kind != svn_kind_dir || NOT_PRESENT(info->status))
+ db->repos_only = TRUE;
+
+ if (!db->repos_only && info->status != svn_wc__db_status_added)
+ db->repos_only = TRUE;
- if (eb->local_before_remote && !eb->ignore_ancestry && !db->shadowed)
- SVN_ERR(ensure_local_only_handled(pb, db->name, dir_pool));
+ if (!db->repos_only)
+ {
+ db->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, db->pool);
+ db->ignoring_ancestry = TRUE;
+
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, db->name), "");
+ }
+ }
- /* Issue #3797: Don't add this filename to the parent directory's list of
- elements that have been compared, to show local additions via the local
- diff. The repository node is unrelated from the working copy version
- (similar to not-present in the working copy) */
+ db->left_src = svn_diff__source_create(eb->revnum, db->pool);
- db->left_src = svn_diff__source_create(eb->revnum, db->pool);
+ if (eb->local_before_remote && !db->repos_only && !db->ignoring_ancestry)
+ SVN_ERR(handle_local_only(pb, db->name, dir_pool));
SVN_ERR(eb->processor->dir_opened(&db->pdb, &db->skip, &db->skip_children,
db->relpath,
db->left_src,
- NULL /* right_source */,
+ db->right_src,
NULL /* copyfrom src */,
pb->pdb,
eb->processor,
@@ -1480,26 +1585,51 @@ open_directory(const char *path,
db = make_dir_baton(path, pb, pb->eb, FALSE, subdir_depth, dir_pool);
*child_baton = db;
- if (!db->shadowed)
+ if (pb->repos_only)
+ db->repos_only = TRUE;
+ else
{
struct svn_wc__db_info_t *info;
SVN_ERR(ensure_local_info(pb, dir_pool));
info = svn_hash_gets(pb->local_info, db->name);
- if (!info || info->kind != svn_kind_dir)
- db->shadowed = TRUE;
- }
+ if (!info || info->kind != svn_kind_dir || NOT_PRESENT(info->status))
+ db->repos_only = TRUE;
+
+ if (!db->repos_only)
+ switch (info->status)
+ {
+ case svn_wc__db_status_normal:
+ break;
+ case svn_wc__db_status_deleted:
+ db->repos_only = TRUE;
+
+ if (!info->have_more_work)
+ svn_hash_sets(pb->compared,
+ apr_pstrdup(pb->pool, db->name), "");
+ break;
+ case svn_wc__db_status_added:
+ if (eb->ignore_ancestry)
+ db->ignoring_ancestry = TRUE;
+ else
+ db->repos_only = TRUE;
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
- if (eb->local_before_remote && !eb->ignore_ancestry && !db->shadowed)
- SVN_ERR(ensure_local_only_handled(pb, db->name, dir_pool));
+ if (!db->repos_only)
+ {
+ db->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, db->pool);
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, db->name), "");
+ }
+ }
- db->left_src = svn_diff__source_create(eb->revnum, db->pool);
- db->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, db->pool);
+ db->left_src = svn_diff__source_create(eb->revnum, db->pool);
- /* Add this path to the parent directory's list of elements that
- have been compared. */
- svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, db->name), "");
+ if (eb->local_before_remote && !db->repos_only && !db->ignoring_ancestry)
+ SVN_ERR(handle_local_only(pb, db->name, dir_pool));
SVN_ERR(eb->processor->dir_opened(&db->pdb, &db->skip, &db->skip_children,
db->relpath,
@@ -1523,22 +1653,29 @@ close_directory(void *dir_baton,
apr_pool_t *pool)
{
struct dir_baton_t *db = dir_baton;
+ struct dir_baton_t *pb = db->parent_baton;
struct edit_baton_t *eb = db->eb;
apr_pool_t *scratch_pool = db->pool;
svn_boolean_t reported_closed = FALSE;
- if (db->deletes)
+ if (!db->skip_children && db->deletes && apr_hash_count(db->deletes))
{
- apr_hash_index_t *hi;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_array_header_t *children;
+ int i;
+ children = svn_sort__hash(db->deletes, svn_sort_compare_items_lexically,
+ scratch_pool);
- for (hi = apr_hash_first(scratch_pool, db->deletes); hi;
- hi = apr_hash_next(hi))
+ for (i = 0; i < children->nelts; i++)
{
- const char *name = svn__apr_hash_index_key(hi);
+ svn_sort__item_t *item = &APR_ARRAY_IDX(children, i,
+ svn_sort__item_t);
+ const char *name = item->key;
svn_pool_clear(iterpool);
- SVN_ERR(ensure_local_only_handled(db, name, iterpool));
+ SVN_ERR(handle_local_only(db, name, iterpool));
+
+ svn_hash_sets(db->compared, name, "");
}
svn_pool_destroy(iterpool);
@@ -1547,92 +1684,94 @@ close_directory(void *dir_baton,
/* Report local modifications for this directory. Skip added
directories since they can only contain added elements, all of
which have already been diff'd. */
- if (!db->added)
+ if (!db->repos_only && !db->skip_children)
+ {
SVN_ERR(walk_local_nodes_diff(eb,
db->local_abspath,
db->relpath,
db->depth,
db->compared,
- NULL /* ### parent_baton */,
+ db->pdb,
scratch_pool));
-
+ }
/* Report the property changes on the directory itself, if necessary. */
- if (db->propchanges->nelts > 0)
+ if (db->skip)
+ {
+ /* Diff processor requested no directory details */
+ }
+ else if (db->propchanges->nelts > 0 || db->repos_only)
{
- /* The working copy properties at the base of the wc->repos comparison:
- either BASE or WORKING. */
- apr_hash_t *originalprops;
+ apr_hash_t *repos_props;
if (db->added)
{
- originalprops = apr_hash_make(scratch_pool);
+ repos_props = apr_hash_make(scratch_pool);
}
else
{
- if (db->eb->diff_pristine)
- {
- SVN_ERR(svn_wc__db_read_pristine_props(&originalprops,
- eb->db, db->local_abspath,
- scratch_pool,
- scratch_pool));
- }
- else
- {
- apr_hash_t *base_props, *repos_props;
-
- SVN_ERR(svn_wc__get_actual_props(&originalprops,
- eb->db, db->local_abspath,
- scratch_pool, scratch_pool));
-
- /* Load the BASE and repository directory properties. */
- SVN_ERR(svn_wc__db_base_get_props(&base_props,
- eb->db, db->local_abspath,
- scratch_pool, scratch_pool));
-
- repos_props = svn_prop__patch(base_props, db->propchanges,
- scratch_pool);
-
- /* Recalculate b->propchanges as the change between WORKING
- and repos. */
- SVN_ERR(svn_prop_diffs(&db->propchanges, repos_props,
- originalprops, scratch_pool));
- }
+ SVN_ERR(svn_wc__db_base_get_props(&repos_props,
+ eb->db, db->local_abspath,
+ scratch_pool, scratch_pool));
}
- if (!db->added)
- {
- reverse_propchanges(originalprops, db->propchanges, db->pool);
+ /* Add received property changes and entry props */
+ if (db->propchanges->nelts)
+ repos_props = svn_prop__patch(repos_props, db->propchanges,
+ scratch_pool);
- SVN_ERR(eb->processor->dir_changed(db->relpath,
+ if (db->repos_only)
+ {
+ SVN_ERR(eb->processor->dir_deleted(db->relpath,
db->left_src,
- db->right_src,
- originalprops,
- svn_prop__patch(originalprops,
- db->propchanges,
- scratch_pool),
- db->propchanges,
+ repos_props,
db->pdb,
eb->processor,
scratch_pool));
+ reported_closed = TRUE;
}
else
{
- SVN_ERR(eb->processor->dir_deleted(db->relpath,
- db->left_src,
- svn_prop__patch(originalprops,
- db->propchanges,
- scratch_pool),
- db->pdb,
- eb->processor,
- scratch_pool));
+ apr_hash_t *local_props;
+ apr_array_header_t *prop_changes;
+
+ if (eb->diff_pristine)
+ SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ &local_props,
+ eb->db, db->local_abspath,
+ scratch_pool, scratch_pool));
+ else
+ SVN_ERR(svn_wc__db_read_props(&local_props,
+ eb->db, db->local_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_prop_diffs(&prop_changes, local_props, repos_props,
+ scratch_pool));
+
+ /* ### as a good diff processor we should now only report changes
+ if there are non-entry changes, but for now we stick to
+ compatibility */
+
+ if (prop_changes->nelts)
+ {
+ SVN_ERR(eb->processor->dir_changed(db->relpath,
+ db->left_src,
+ db->right_src,
+ repos_props,
+ local_props,
+ prop_changes,
+ db->pdb,
+ eb->processor,
+ scratch_pool));
+ reported_closed = TRUE;
+ }
}
- reported_closed = TRUE;
}
/* Mark this directory as compared in the parent directory's baton,
unless this is the root of the comparison. */
- if (!reported_closed)
+ if (!reported_closed && !db->skip)
SVN_ERR(eb->processor->dir_closed(db->relpath,
db->left_src,
db->right_src,
@@ -1640,9 +1779,9 @@ close_directory(void *dir_baton,
eb->processor,
scratch_pool));
- if (db->parent_baton)
- SVN_ERR(ensure_local_only_handled(db->parent_baton, db->name,
- scratch_pool));
+ if (pb && !eb->local_before_remote && !db->repos_only && !db->ignoring_ancestry)
+ SVN_ERR(handle_local_only(pb, db->name, scratch_pool));
+
SVN_ERR(maybe_done(db)); /* destroys scratch_pool */
return SVN_NO_ERROR;
@@ -1661,29 +1800,41 @@ add_file(const char *path,
struct edit_baton_t *eb = pb->eb;
struct file_baton_t *fb;
- /* ### TODO: support copyfrom? */
-
fb = make_file_baton(path, TRUE, pb, file_pool);
*file_baton = fb;
- if (!fb->shadowed)
+ if (pb->skip_children)
+ {
+ fb->skip = TRUE;
+ return SVN_NO_ERROR;
+ }
+ else if (pb->repos_only || !eb->ignore_ancestry)
+ fb->repos_only = TRUE;
+ else
{
struct svn_wc__db_info_t *info;
SVN_ERR(ensure_local_info(pb, file_pool));
info = svn_hash_gets(pb->local_info, fb->name);
- if (!info || info->kind != svn_kind_file)
- fb->shadowed = TRUE;
- }
+ if (!info || info->kind != svn_kind_file || NOT_PRESENT(info->status))
+ fb->repos_only = TRUE;
- /* Issue #3797: Don't add this filename to the parent directory's list of
- elements that have been compared, to show local additions via the local
- diff. The repository node is unrelated from the working copy version
- (similar to not-present in the working copy) */
+ if (!fb->repos_only && info->status != svn_wc__db_status_added)
+ fb->repos_only = TRUE;
+
+ if (!fb->repos_only)
+ {
+ /* Add this path to the parent directory's list of elements that
+ have been compared. */
+ fb->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, fb->pool);
+ fb->ignoring_ancestry = TRUE;
+
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, fb->name), "");
+ }
+ }
fb->left_src = svn_diff__source_create(eb->revnum, fb->pool);
- fb->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, fb->pool);
SVN_ERR(eb->processor->file_opened(&fb->pfb, &fb->skip,
fb->relpath,
@@ -1712,20 +1863,51 @@ open_file(const char *path,
fb = make_file_baton(path, FALSE, pb, file_pool);
*file_baton = fb;
- if (!fb->shadowed)
+ if (pb->skip_children)
+ fb->skip = TRUE;
+ else if (pb->repos_only)
+ fb->repos_only = TRUE;
+ else
{
struct svn_wc__db_info_t *info;
SVN_ERR(ensure_local_info(pb, file_pool));
info = svn_hash_gets(pb->local_info, fb->name);
- if (!info || info->kind != svn_kind_file)
- fb->shadowed = TRUE;
+ if (!info || info->kind != svn_kind_file || NOT_PRESENT(info->status))
+ fb->repos_only = TRUE;
+
+ if (!fb->repos_only)
+ switch (info->status)
+ {
+ case svn_wc__db_status_normal:
+ break;
+ case svn_wc__db_status_deleted:
+ fb->repos_only = TRUE;
+ if (!info->have_more_work)
+ svn_hash_sets(pb->compared,
+ apr_pstrdup(pb->pool, fb->name), "");
+ break;
+ case svn_wc__db_status_added:
+ if (eb->ignore_ancestry)
+ fb->ignoring_ancestry = TRUE;
+ else
+ fb->repos_only = TRUE;
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+
+ if (!fb->repos_only)
+ {
+ /* Add this path to the parent directory's list of elements that
+ have been compared. */
+ fb->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, fb->pool);
+ svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, fb->name), "");
+ }
}
- /* Add this filename to the parent directory's list of elements that
- have been compared. */
- svn_hash_sets(pb->compared, apr_pstrdup(pb->pool, fb->name), "");
+ fb->left_src = svn_diff__source_create(eb->revnum, fb->pool);
SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, &fb->base_checksum, NULL,
@@ -1733,9 +1915,6 @@ open_file(const char *path,
eb->db, fb->local_abspath,
fb->pool, fb->pool));
- fb->left_src = svn_diff__source_create(eb->revnum, fb->pool);
[... 417 lines stripped ...]