You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/02/04 21:48:13 UTC
svn commit: r1442344 [10/39] - in /subversion/branches/fsfs-format7: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/
contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ doc/...
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c Mon Feb 4 20:48:05 2013
@@ -34,6 +34,7 @@
#include <apr_uri.h>
#include <apr_md5.h>
+#include <assert.h>
#include "svn_checksum.h"
#include "svn_hash.h"
@@ -49,16 +50,15 @@
#include "private/svn_subr_private.h"
#include "private/svn_wc_private.h"
+#include "private/svn_editor.h"
/* Overall crawler editor baton. */
struct edit_baton {
/* The passed depth */
svn_depth_t depth;
- /* The callback and calback argument that implement the file comparison
- function */
- const svn_wc_diff_callbacks4_t *diff_callbacks;
- void *diff_cmd_baton;
+ /* The result processor */
+ const svn_diff_tree_processor_t *processor;
/* RA_SESSION is the open session for making requests to the RA layer */
svn_ra_session_t *ra_session;
@@ -78,19 +78,6 @@ struct edit_baton {
/* Empty hash used for adds. */
apr_hash_t *empty_hash;
- /* Hash used to check replaced paths. Key is path relative CWD,
- * Value is *deleted_path_notify_t.
- * All allocations are from edit_baton's pool. */
- apr_hash_t *deleted_paths;
-
- /* If the func is non-null, send notifications of actions. */
- svn_wc_notify_func2_t notify_func;
- void *notify_baton;
-
- /* TRUE if the operation needs to walk deleted dirs on the "old" side.
- FALSE otherwise. */
- svn_boolean_t walk_deleted_repos_dirs;
-
/* Whether to report text deltas */
svn_boolean_t text_deltas;
@@ -135,7 +122,7 @@ struct dir_baton {
/* The baton for the parent directory, or null if this is the root of the
hierarchy to be compared. */
- struct dir_baton *dir_baton;
+ struct dir_baton *parent_baton;
/* The overall crawler editor baton. */
struct edit_baton *edit_baton;
@@ -143,17 +130,31 @@ struct dir_baton {
/* A cache of any property changes (svn_prop_t) received for this dir. */
apr_array_header_t *propchanges;
+ /* Boolean indicating whether a node property was changed */
+ svn_boolean_t has_propchange;
+
+ /* Baton for svn_diff_tree_processor_t */
+ void *pdb;
+ svn_diff_source_t *left_source;
+ svn_diff_source_t *right_source;
+
/* The pool passed in by add_dir, open_dir, or open_root.
Also, the pool this dir baton is allocated in. */
apr_pool_t *pool;
/* Base revision of directory. */
svn_revnum_t base_revision;
+
+ /* Number of users of baton. Its pool will be destroyed 0 */
+ int users;
};
/* File level baton.
*/
struct file_baton {
+ /* Reference to parent baton */
+ struct dir_baton *parent_baton;
+
/* Gets set if the file is added rather than replaced. */
svn_boolean_t added;
@@ -199,6 +200,14 @@ struct file_baton {
/* A cache of any property changes (svn_prop_t) received for this file. */
apr_array_header_t *propchanges;
+ /* Boolean indicating whether a node property was changed */
+ svn_boolean_t has_propchange;
+
+ /* Baton for svn_diff_tree_processor_t */
+ void *pfb;
+ svn_diff_source_t *left_source;
+ svn_diff_source_t *right_source;
+
/* The pool passed in by add_file or open_file.
Also, the pool this file_baton is allocated in. */
apr_pool_t *pool;
@@ -217,12 +226,12 @@ make_dir_baton(const char *path,
struct edit_baton *edit_baton,
svn_boolean_t added,
svn_revnum_t base_revision,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
- apr_pool_t *dir_pool = svn_pool_create(pool);
+ apr_pool_t *dir_pool = svn_pool_create(result_pool);
struct dir_baton *dir_baton = apr_pcalloc(dir_pool, sizeof(*dir_baton));
- dir_baton->dir_baton = parent_baton;
+ dir_baton->parent_baton = parent_baton;
dir_baton->edit_baton = edit_baton;
dir_baton->added = added;
dir_baton->tree_conflicted = FALSE;
@@ -230,12 +239,38 @@ make_dir_baton(const char *path,
dir_baton->skip_children = FALSE;
dir_baton->pool = dir_pool;
dir_baton->path = apr_pstrdup(dir_pool, path);
- dir_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t));
+ dir_baton->propchanges = apr_array_make(dir_pool, 8, sizeof(svn_prop_t));
dir_baton->base_revision = base_revision;
+ dir_baton->users++;
+
+ if (parent_baton)
+ parent_baton->users++;
return dir_baton;
}
+/* New function. Called by everyone who has a reference when done */
+static svn_error_t *
+release_dir(struct dir_baton *db)
+{
+ assert(db->users > 0);
+
+ db->users--;
+ if (db->users)
+ return SVN_NO_ERROR;
+
+ {
+ struct dir_baton *pb = db->parent_baton;
+
+ svn_pool_destroy(db->pool);
+
+ if (pb != NULL)
+ SVN_ERR(release_dir(pb));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Create a new file baton for PATH in POOL, which is a child of
* directory PARENT_PATH. ADDED is set if this file is being added
* rather than replaced. EDIT_BATON is a pointer to the global edit
@@ -243,84 +278,44 @@ make_dir_baton(const char *path,
*/
static struct file_baton *
make_file_baton(const char *path,
+ struct dir_baton *parent_baton,
svn_boolean_t added,
- struct edit_baton *edit_baton,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
- apr_pool_t *file_pool = svn_pool_create(pool);
+ apr_pool_t *file_pool = svn_pool_create(result_pool);
struct file_baton *file_baton = apr_pcalloc(file_pool, sizeof(*file_baton));
- file_baton->edit_baton = edit_baton;
+ file_baton->parent_baton = parent_baton;
+ file_baton->edit_baton = parent_baton->edit_baton;
file_baton->added = added;
file_baton->tree_conflicted = FALSE;
file_baton->skip = FALSE;
file_baton->pool = file_pool;
file_baton->path = apr_pstrdup(file_pool, path);
- file_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t));
- file_baton->base_revision = edit_baton->revision;
+ file_baton->propchanges = apr_array_make(file_pool, 8, sizeof(svn_prop_t));
+ file_baton->base_revision = parent_baton->edit_baton->revision;
- return file_baton;
-}
+ parent_baton->users++;
-/* Helper function: return up to two svn:mime-type values buried
- * within a file baton. Set *MIMETYPE1 to the value within the file's
- * pristine properties, or NULL if not available. Set *MIMETYPE2 to
- * the value within the "new" file's propchanges, or NULL if not
- * available.
- */
-static void
-get_file_mime_types(const char **mimetype1,
- const char **mimetype2,
- struct file_baton *b)
-{
- /* Defaults */
- *mimetype1 = NULL;
- *mimetype2 = NULL;
-
- if (b->pristine_props)
- {
- svn_string_t *pristine_val;
- pristine_val = apr_hash_get(b->pristine_props, SVN_PROP_MIME_TYPE,
- strlen(SVN_PROP_MIME_TYPE));
- if (pristine_val)
- *mimetype2 = *mimetype1 = pristine_val->data;
- }
-
- if (b->propchanges)
- {
- int i;
- svn_prop_t *propchange;
-
- for (i = 0; i < b->propchanges->nelts; i++)
- {
- propchange = &APR_ARRAY_IDX(b->propchanges, i, svn_prop_t);
- if (strcmp(propchange->name, SVN_PROP_MIME_TYPE) == 0)
- {
- if (propchange->value)
- *mimetype2 = propchange->value->data;
- break;
- }
- }
- }
+ return file_baton;
}
-
-/* Get revision B->base_revision of the file described by B from the
- * repository, through B->edit_baton->ra_session.
+/* Get revision FB->base_revision of the file described by FB from the
+ * repository, through FB->edit_baton->ra_session.
*
* Unless PROPS_ONLY is true:
- * Set B->path_start_revision to the path of a new temporary file containing
+ * Set FB->path_start_revision to the path of a new temporary file containing
* the file's text.
- * Set B->start_md5_checksum to that file's MD-5 checksum.
- * Install a pool cleanup handler on B->pool to delete the file.
+ * Set FB->start_md5_checksum to that file's MD-5 checksum.
+ * Install a pool cleanup handler on FB->pool to delete the file.
*
* Always:
- * Set B->pristine_props to a new hash containing the file's properties.
+ * Set FB->pristine_props to a new hash containing the file's properties.
*
- * Allocate all results in B->pool.
+ * Allocate all results in FB->pool.
*/
static svn_error_t *
-get_file_from_ra(struct file_baton *b,
+get_file_from_ra(struct file_baton *fb,
svn_boolean_t props_only,
apr_pool_t *scratch_pool)
{
@@ -328,30 +323,30 @@ get_file_from_ra(struct file_baton *b,
{
svn_stream_t *fstream;
- SVN_ERR(svn_stream_open_unique(&fstream, &(b->path_start_revision), NULL,
- svn_io_file_del_on_pool_cleanup,
- b->pool, scratch_pool));
+ SVN_ERR(svn_stream_open_unique(&fstream, &(fb->path_start_revision),
+ NULL, svn_io_file_del_on_pool_cleanup,
+ fb->pool, scratch_pool));
- fstream = svn_stream_checksummed2(fstream, NULL, &b->start_md5_checksum,
+ fstream = svn_stream_checksummed2(fstream, NULL, &fb->start_md5_checksum,
svn_checksum_md5, TRUE, scratch_pool);
/* Retrieve the file and its properties */
- SVN_ERR(svn_ra_get_file(b->edit_baton->ra_session,
- b->path,
- b->base_revision,
+ SVN_ERR(svn_ra_get_file(fb->edit_baton->ra_session,
+ fb->path,
+ fb->base_revision,
fstream, NULL,
- &(b->pristine_props),
- b->pool));
+ &(fb->pristine_props),
+ fb->pool));
SVN_ERR(svn_stream_close(fstream));
}
else
{
- SVN_ERR(svn_ra_get_file(b->edit_baton->ra_session,
- b->path,
- b->base_revision,
+ SVN_ERR(svn_ra_get_file(fb->edit_baton->ra_session,
+ fb->path,
+ fb->base_revision,
NULL, NULL,
- &(b->pristine_props),
- b->pool));
+ &(fb->pristine_props),
+ fb->pool));
}
return SVN_NO_ERROR;
@@ -420,7 +415,6 @@ remove_non_prop_changes(apr_hash_t *pris
}
}
-
/* Get the empty file associated with the edit baton. This is cached so
* that it can be reused, all empty files are the same.
*/
@@ -461,44 +455,68 @@ open_root(void *edit_baton,
void **root_baton)
{
struct edit_baton *eb = edit_baton;
- struct dir_baton *b = make_dir_baton("", NULL, eb, FALSE, base_revision,
- pool);
+ struct dir_baton *db = make_dir_baton("", NULL, eb, FALSE, base_revision,
+ eb->pool);
+
+ db->left_source = svn_diff__source_create(eb->revision, db->pool);
+ db->right_source = svn_diff__source_create(eb->target_revision, db->pool);
+
+ SVN_ERR(eb->processor->dir_opened(&db->pdb,
+ &db->skip,
+ &db->skip_children,
+ "",
+ db->left_source,
+ db->right_source,
+ NULL,
+ NULL,
+ eb->processor,
+ db->pool,
+ db->pool /* scratch_pool */));
- *root_baton = b;
+ *root_baton = db;
return SVN_NO_ERROR;
}
/* Compare a file being deleted against an empty file.
*/
static svn_error_t *
-diff_deleted_file(svn_wc_notify_state_t *state_p,
- svn_boolean_t *tree_conflicted_p,
- const char *path,
- struct edit_baton *eb,
+diff_deleted_file(const char *path,
+ struct dir_baton *db,
apr_pool_t *scratch_pool)
{
- struct file_baton *b = make_file_baton(path, FALSE, eb, scratch_pool);
-/* struct edit_baton *eb = b->edit_baton;*/
- const char *mimetype1, *mimetype2;
+ struct edit_baton *eb = db->edit_baton;
+ struct file_baton *fb = make_file_baton(path, db, FALSE, scratch_pool);
+ svn_boolean_t skip = FALSE;
+ svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
+ scratch_pool);
if (eb->cancel_func)
SVN_ERR(eb->cancel_func(eb->cancel_baton));
- if (eb->text_deltas)
- SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
- else
- SVN_ERR(get_empty_file(eb, &b->path_start_revision));
- SVN_ERR(get_empty_file(eb, &b->path_end_revision));
- get_file_mime_types(&mimetype1, &mimetype2, b);
-
- SVN_ERR(eb->diff_callbacks->file_deleted(state_p, tree_conflicted_p,
- b->path,
- b->path_start_revision,
- b->path_end_revision,
- mimetype1, mimetype2,
- b->pristine_props,
- eb->diff_cmd_baton,
- scratch_pool));
+ SVN_ERR(eb->processor->file_opened(&fb->pfb, &skip, path,
+ left_source,
+ NULL /* right_source */,
+ NULL /* copyfrom_source */,
+ db->pdb,
+ eb->processor,
+ scratch_pool, scratch_pool));
+
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
+
+ if (skip)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(get_file_from_ra(fb, ! eb->text_deltas, scratch_pool));
+
+ SVN_ERR(eb->processor->file_deleted(fb->path,
+ left_source,
+ fb->path_start_revision,
+ fb->pristine_props,
+ fb->pfb,
+ eb->processor,
+ scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -512,65 +530,88 @@ diff_deleted_file(svn_wc_notify_state_t
*/
/* ### TODO: Handle depth. */
static svn_error_t *
-diff_deleted_dir(svn_wc_notify_state_t *state_p,
- svn_boolean_t *tree_conflicted_p,
- const char *dir,
- struct edit_baton *eb,
- apr_pool_t *pool)
+diff_deleted_dir(const char *path,
+ struct dir_baton *pb,
+ apr_pool_t *scratch_pool)
{
- apr_hash_t *dirents;
- apr_pool_t *iterpool = svn_pool_create(pool);
- apr_hash_index_t *hi;
+ struct edit_baton *eb = pb->edit_baton;
+ struct dir_baton *db;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ svn_boolean_t skip = FALSE;
+ svn_boolean_t skip_children = FALSE;
+ apr_hash_t *dirents = NULL;
+ apr_hash_t *left_props = NULL;
+ svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
+ scratch_pool);
+ db = make_dir_baton(path, pb, pb->edit_baton, FALSE, SVN_INVALID_REVNUM,
+ scratch_pool);
SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(eb->revision));
if (eb->cancel_func)
SVN_ERR(eb->cancel_func(eb->cancel_baton));
- SVN_ERR(eb->diff_callbacks->dir_deleted(
- state_p, tree_conflicted_p, dir,
- eb->diff_cmd_baton, pool));
+ SVN_ERR(eb->processor->dir_opened(&db->pdb, &skip, &skip_children,
+ path,
+ left_source,
+ NULL /* right_source */,
+ NULL /* copyfrom_source */,
+ pb->pdb,
+ eb->processor,
+ scratch_pool, iterpool));
+
+ if (!skip || !skip_children)
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session,
+ skip_children ? NULL : &dirents,
+ NULL,
+ skip ? NULL : &left_props,
+ path,
+ eb->revision,
+ SVN_DIRENT_KIND,
+ scratch_pool));
/* The "old" dir will be skipped by the repository report. If required,
* crawl it recursively, diffing each file against the empty file. This
* is a workaround for issue 2333 "'svn diff URL1 URL2' not reverse of
* 'svn diff URL2 URL1'". */
- if (! eb->walk_deleted_repos_dirs)
+ if (! skip_children)
{
- svn_pool_destroy(iterpool);
- return SVN_NO_ERROR;
- }
+ apr_hash_index_t *hi;
- SVN_ERR(svn_ra_get_dir2(eb->ra_session,
- &dirents,
- NULL, NULL,
- dir,
- eb->revision,
- SVN_DIRENT_KIND,
- pool));
-
- for (hi = apr_hash_first(pool, dirents); hi;
- hi = apr_hash_next(hi))
- {
- const char *path;
- const char *name = svn__apr_hash_index_key(hi);
- svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
+ for (hi = apr_hash_first(scratch_pool, dirents); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *child_path;
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
- svn_pool_clear(iterpool);
+ svn_pool_clear(iterpool);
- path = svn_relpath_join(dir, name, iterpool);
+ child_path = svn_relpath_join(path, name, iterpool);
- if (dirent->kind == svn_node_file)
- {
- SVN_ERR(diff_deleted_file(NULL, NULL, path, eb, iterpool));
+ if (dirent->kind == svn_node_file)
+ {
+ SVN_ERR(diff_deleted_file(child_path, db, iterpool));
+ }
+ else if (dirent->kind == svn_node_dir)
+ {
+ SVN_ERR(diff_deleted_dir(child_path, db, iterpool));
+ }
}
+ }
- if (dirent->kind == svn_node_dir)
- {
- SVN_ERR(diff_deleted_dir(NULL, NULL, path, eb, iterpool));
- }
+ if (! skip)
+ {
+ SVN_ERR(eb->processor->dir_deleted(path,
+ left_source,
+ left_props,
+ db->pdb,
+ eb->processor,
+ scratch_pool));
}
+ SVN_ERR(release_dir(db));
+
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -585,14 +626,10 @@ delete_entry(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
svn_node_kind_t kind;
- svn_wc_notify_state_t state = svn_wc_notify_state_inapplicable;
- svn_wc_notify_action_t action = svn_wc_notify_skip;
- svn_boolean_t tree_conflicted = FALSE;
apr_pool_t *scratch_pool;
- /* Skip *everything* within a newly tree-conflicted directory,
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process skips. */
+ if (pb->skip_children)
return SVN_NO_ERROR;
scratch_pool = svn_pool_create(eb->pool);
@@ -605,39 +642,18 @@ delete_entry(const char *path,
{
case svn_node_file:
{
- SVN_ERR(diff_deleted_file(&state, &tree_conflicted, path, eb,
- scratch_pool));
+ SVN_ERR(diff_deleted_file(path, pb, scratch_pool));
break;
}
case svn_node_dir:
{
- SVN_ERR(diff_deleted_dir(&state, &tree_conflicted, path, eb,
- scratch_pool));
+ SVN_ERR(diff_deleted_dir(path, pb, scratch_pool));
break;
}
default:
break;
}
- if ((state != svn_wc_notify_state_missing)
- && (state != svn_wc_notify_state_obstructed)
- && !tree_conflicted)
- {
- action = svn_wc_notify_update_delete;
- }
-
- if (eb->notify_func)
- {
- const char *deleted_path = apr_pstrdup(eb->pool, path);
- deleted_path_notify_t *dpn = apr_pcalloc(eb->pool, sizeof(*dpn));
-
- dpn->kind = kind;
- dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action;
- dpn->state = state;
- dpn->tree_conflicted = tree_conflicted;
- apr_hash_set(eb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn);
- }
-
svn_pool_destroy(scratch_pool);
return SVN_NO_ERROR;
@@ -654,80 +670,35 @@ add_directory(const char *path,
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- struct dir_baton *b;
- svn_wc_notify_state_t state;
+ struct dir_baton *db;
/* ### TODO: support copyfrom? */
- b = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pool);
- *child_baton = b;
+ db = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pb->pool);
+ *child_baton = db;
/* Skip *everything* within a newly tree-conflicted directory,
* and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ if (pb->skip_children)
{
- b->skip = TRUE;
+ db->skip = TRUE;
+ db->skip_children = TRUE;
return SVN_NO_ERROR;
}
+ db->right_source = svn_diff__source_create(eb->target_revision,
+ db->pool);
- SVN_ERR(eb->diff_callbacks->dir_added(
- &state, &b->tree_conflicted,
- &b->skip, &b->skip_children, b->path,
- eb->target_revision, copyfrom_path, copyfrom_revision,
- eb->diff_cmd_baton, pool));
-
- /* Notifications for directories are done at close_directory time.
- * But for paths at which the editor drive adds directories, we make an
- * exception to this rule, so that the path appears in the output before
- * any children of the newly added directory. Since a deletion at this path
- * must have happened before this addition, we can safely notify about
- * replaced directories here, too. */
- if (eb->notify_func)
- {
- deleted_path_notify_t *dpn;
- svn_wc_notify_t *notify;
- svn_wc_notify_action_t action;
- svn_node_kind_t kind = svn_node_dir;
-
- /* Find out if a pending delete notification for this path is
- * still around. */
- dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING);
- if (dpn)
- {
- /* If any was found, we will handle the pending 'deleted path
- * notification' (DPN) here. Remove it from the list. */
- apr_hash_set(eb->deleted_paths, b->path,
- APR_HASH_KEY_STRING, NULL);
-
- /* the pending delete might be on a different node kind. */
- kind = dpn->kind;
- state = dpn->state;
- }
-
- /* Determine what the notification (ACTION) should be.
- * In case of a pending 'delete', this might become a 'replace'. */
- if (b->tree_conflicted)
- action = svn_wc_notify_tree_conflict;
- else if (dpn)
- {
- if (dpn->action == svn_wc_notify_update_delete)
- action = svn_wc_notify_update_replace;
- else
- /* Note: dpn->action might be svn_wc_notify_tree_conflict */
- action = dpn->action;
- }
- else if (state == svn_wc_notify_state_missing ||
- state == svn_wc_notify_state_obstructed)
- action = svn_wc_notify_skip;
- else
- action = svn_wc_notify_update_add;
-
- notify = svn_wc_create_notify(b->path, action, pool);
- notify->kind = kind;
- notify->content_state = notify->prop_state = state;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- }
+ SVN_ERR(eb->processor->dir_opened(&db->pdb,
+ &db->skip,
+ &db->skip_children,
+ db->path,
+ NULL,
+ db->right_source,
+ NULL /* copyfrom_source */,
+ pb->pdb,
+ eb->processor,
+ db->pool, db->pool));
return SVN_NO_ERROR;
}
@@ -742,24 +713,32 @@ open_directory(const char *path,
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- struct dir_baton *b;
+ struct dir_baton *db;
- b = make_dir_baton(path, pb, pb->edit_baton, FALSE, base_revision, pool);
+ db = make_dir_baton(path, pb, eb, FALSE, base_revision, pb->pool);
- *child_baton = b;
+ *child_baton = db;
- /* Skip *everything* within a newly tree-conflicted directory
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process Skips. */
+ if (pb->skip_children)
{
- b->skip = TRUE;
+ db->skip = TRUE;
+ db->skip_children = TRUE;
return SVN_NO_ERROR;
}
- SVN_ERR(eb->diff_callbacks->dir_opened(
- &b->tree_conflicted, &b->skip,
- &b->skip_children, b->path, base_revision,
- b->edit_baton->diff_cmd_baton, pool));
+ db->left_source = svn_diff__source_create(eb->revision, db->pool);
+ db->right_source = svn_diff__source_create(eb->target_revision, db->pool);
+
+ SVN_ERR(eb->processor->dir_opened(&db->pdb,
+ &db->skip, &db->skip_children,
+ path,
+ db->left_source,
+ db->right_source,
+ NULL /* copyfrom */,
+ pb ? pb->pdb : NULL,
+ eb->processor,
+ db->pool, db->pool));
return SVN_NO_ERROR;
}
@@ -775,22 +754,34 @@ add_file(const char *path,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
- struct file_baton *b;
+ struct edit_baton *eb = pb->edit_baton;
+ struct file_baton *fb;
/* ### TODO: support copyfrom? */
- b = make_file_baton(path, TRUE, pb->edit_baton, pool);
- *file_baton = b;
+ fb = make_file_baton(path, pb, TRUE, pb->pool);
+ *file_baton = fb;
- /* Skip *everything* within a newly tree-conflicted directory.
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process Skips. */
+ if (pb->skip_children)
{
- b->skip = TRUE;
+ fb->skip = TRUE;
return SVN_NO_ERROR;
}
- b->pristine_props = pb->edit_baton->empty_hash;
+ fb->pristine_props = pb->edit_baton->empty_hash;
+
+ fb->right_source = svn_diff__source_create(eb->target_revision, fb->pool);
+
+ SVN_ERR(eb->processor->file_opened(&fb->pfb,
+ &fb->skip,
+ path,
+ NULL,
+ fb->right_source,
+ NULL /* copy source */,
+ pb->pdb,
+ eb->processor,
+ fb->pool, fb->pool));
return SVN_NO_ERROR;
}
@@ -804,24 +795,32 @@ open_file(const char *path,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
- struct file_baton *b;
+ struct file_baton *fb;
struct edit_baton *eb = pb->edit_baton;
- b = make_file_baton(path, FALSE, pb->edit_baton, pool);
- *file_baton = b;
+ fb = make_file_baton(path, pb, FALSE, pb->pool);
+ *file_baton = fb;
- /* Skip *everything* within a newly tree-conflicted directory
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process Skips. */
+ if (pb->skip_children)
{
- b->skip = TRUE;
+ fb->skip = TRUE;
return SVN_NO_ERROR;
}
- b->base_revision = base_revision;
+ fb->base_revision = base_revision;
+
+ fb->left_source = svn_diff__source_create(eb->revision, fb->pool);
+ fb->right_source = svn_diff__source_create(eb->target_revision, fb->pool);
- SVN_ERR(eb->diff_callbacks->file_opened(
- &b->tree_conflicted, &b->skip,
- b->path, base_revision, eb->diff_cmd_baton, pool));
+ SVN_ERR(eb->processor->file_opened(&fb->pfb,
+ &fb->skip,
+ path,
+ fb->left_source,
+ fb->right_source,
+ NULL /* copy source */,
+ pb->pdb,
+ eb->processor,
+ fb->pool, fb->pool));
return SVN_NO_ERROR;
}
@@ -831,14 +830,15 @@ static svn_error_t *
window_handler(svn_txdelta_window_t *window,
void *window_baton)
{
- struct file_baton *b = window_baton;
+ struct file_baton *fb = window_baton;
- SVN_ERR(b->apply_handler(window, b->apply_baton));
+ SVN_ERR(fb->apply_handler(window, fb->apply_baton));
if (!window)
{
- b->result_md5_checksum = svn_checksum__from_digest_md5(b->result_digest,
- b->pool);
+ fb->result_md5_checksum = svn_checksum__from_digest_md5(
+ fb->result_digest,
+ fb->pool);
}
return SVN_NO_ERROR;
@@ -852,13 +852,13 @@ apply_textdelta(void *file_baton,
svn_txdelta_window_handler_t *handler,
void **handler_baton)
{
- struct file_baton *b = file_baton;
+ struct file_baton *fb = file_baton;
svn_stream_t *src_stream;
svn_stream_t *result_stream;
- apr_pool_t *scratch_pool = b->pool;
+ apr_pool_t *scratch_pool = fb->pool;
/* Skip *everything* within a newly tree-conflicted directory. */
- if (b->skip)
+ if (fb->skip)
{
*handler = svn_delta_noop_window_handler;
*handler_baton = NULL;
@@ -866,11 +866,11 @@ apply_textdelta(void *file_baton,
}
/* If we're not sending file text, then ignore any that we receive. */
- if (! b->edit_baton->text_deltas)
+ if (! fb->edit_baton->text_deltas)
{
/* Supply valid paths to indicate there is a text change. */
- SVN_ERR(get_empty_file(b->edit_baton, &b->path_start_revision));
- SVN_ERR(get_empty_file(b->edit_baton, &b->path_end_revision));
+ SVN_ERR(get_empty_file(fb->edit_baton, &fb->path_start_revision));
+ SVN_ERR(get_empty_file(fb->edit_baton, &fb->path_end_revision));
*handler = svn_delta_noop_window_handler;
*handler_baton = NULL;
@@ -879,12 +879,12 @@ apply_textdelta(void *file_baton,
}
/* We need the expected pristine file, so go get it */
- if (!b->added)
- SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
+ if (!fb->added)
+ SVN_ERR(get_file_from_ra(fb, FALSE, scratch_pool));
else
- SVN_ERR(get_empty_file(b->edit_baton, &(b->path_start_revision)));
+ SVN_ERR(get_empty_file(fb->edit_baton, &(fb->path_start_revision)));
- SVN_ERR_ASSERT(b->path_start_revision != NULL);
+ SVN_ERR_ASSERT(fb->path_start_revision != NULL);
if (base_md5_digest != NULL)
{
@@ -893,30 +893,30 @@ apply_textdelta(void *file_baton,
SVN_ERR(svn_checksum_parse_hex(&base_md5_checksum, svn_checksum_md5,
base_md5_digest, scratch_pool));
- if (!svn_checksum_match(base_md5_checksum, b->start_md5_checksum))
+ if (!svn_checksum_match(base_md5_checksum, fb->start_md5_checksum))
return svn_error_trace(svn_checksum_mismatch_err(
base_md5_checksum,
- b->start_md5_checksum,
+ fb->start_md5_checksum,
scratch_pool,
_("Base checksum mismatch for '%s'"),
- b->path));
+ fb->path));
}
/* Open the file to be used as the base for second revision */
- SVN_ERR(svn_stream_open_readonly(&src_stream, b->path_start_revision,
+ SVN_ERR(svn_stream_open_readonly(&src_stream, fb->path_start_revision,
scratch_pool, scratch_pool));
/* Open the file that will become the second revision after applying the
text delta, it starts empty */
- SVN_ERR(svn_stream_open_unique(&result_stream, &b->path_end_revision, NULL,
+ SVN_ERR(svn_stream_open_unique(&result_stream, &fb->path_end_revision, NULL,
svn_io_file_del_on_pool_cleanup,
scratch_pool, scratch_pool));
svn_txdelta_apply(src_stream,
result_stream,
- b->result_digest,
- b->path, b->pool,
- &(b->apply_handler), &(b->apply_baton));
+ fb->result_digest,
+ fb->path, fb->pool,
+ &(fb->apply_handler), &(fb->apply_baton));
*handler = window_handler;
*handler_baton = file_baton;
@@ -939,20 +939,20 @@ close_file(void *file_baton,
const char *expected_md5_digest,
apr_pool_t *pool)
{
- struct file_baton *b = file_baton;
- struct edit_baton *eb = b->edit_baton;
- svn_wc_notify_state_t content_state = svn_wc_notify_state_unknown;
- svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
+ struct file_baton *fb = file_baton;
+ struct dir_baton *pb = fb->parent_baton;
+ struct edit_baton *eb = fb->edit_baton;
apr_pool_t *scratch_pool;
/* Skip *everything* within a newly tree-conflicted directory. */
- if (b->skip)
+ if (fb->skip)
{
- svn_pool_destroy(b->pool);
+ svn_pool_destroy(fb->pool);
+ SVN_ERR(release_dir(pb));
return SVN_NO_ERROR;
}
- scratch_pool = b->pool;
+ scratch_pool = fb->pool;
if (expected_md5_digest && eb->text_deltas)
{
@@ -961,112 +961,63 @@ close_file(void *file_baton,
SVN_ERR(svn_checksum_parse_hex(&expected_md5_checksum, svn_checksum_md5,
expected_md5_digest, scratch_pool));
- if (!svn_checksum_match(expected_md5_checksum, b->result_md5_checksum))
+ if (!svn_checksum_match(expected_md5_checksum, fb->result_md5_checksum))
return svn_error_trace(svn_checksum_mismatch_err(
expected_md5_checksum,
- b->result_md5_checksum,
+ fb->result_md5_checksum,
pool,
_("Checksum mismatch for '%s'"),
- b->path));
+ fb->path));
}
- if (!b->added && b->propchanges->nelts > 0)
+ if (fb->added || fb->path_end_revision || fb->has_propchange)
{
- if (!b->pristine_props)
+ apr_hash_t *right_props;
+
+ if (!fb->added && !fb->pristine_props)
{
/* We didn't receive a text change, so we have no pristine props.
Retrieve just the props now. */
- SVN_ERR(get_file_from_ra(b, TRUE, scratch_pool));
+ SVN_ERR(get_file_from_ra(fb, TRUE, scratch_pool));
}
- remove_non_prop_changes(b->pristine_props, b->propchanges);
- }
+ if (fb->pristine_props)
+ remove_non_prop_changes(fb->pristine_props, fb->propchanges);
- if (b->path_end_revision || b->propchanges->nelts > 0)
- {
- const char *mimetype1, *mimetype2;
- get_file_mime_types(&mimetype1, &mimetype2, b);
+ right_props = svn_prop__patch(fb->pristine_props, fb->propchanges,
+ fb->pool);
-
- if (b->added)
- SVN_ERR(eb->diff_callbacks->file_added(
- &content_state, &prop_state, &b->tree_conflicted,
- b->path,
- b->path_end_revision ? b->path_start_revision : NULL,
- b->path_end_revision,
- 0,
- b->edit_baton->target_revision,
- mimetype1, mimetype2,
- NULL, SVN_INVALID_REVNUM,
- b->propchanges, b->pristine_props,
- b->edit_baton->diff_cmd_baton,
- scratch_pool));
+ if (fb->added)
+ SVN_ERR(eb->processor->file_added(fb->path,
+ NULL /* copyfrom_src */,
+ fb->right_source,
+ NULL /* copyfrom_file */,
+ fb->path_end_revision,
+ NULL /* copyfrom_props */,
+ right_props,
+ fb->pfb,
+ eb->processor,
+ fb->pool));
else
- SVN_ERR(eb->diff_callbacks->file_changed(
- &content_state, &prop_state,
- &b->tree_conflicted, b->path,
- b->path_end_revision ? b->path_start_revision : NULL,
- b->path_end_revision,
- b->edit_baton->revision,
- b->edit_baton->target_revision,
- mimetype1, mimetype2,
- b->propchanges, b->pristine_props,
- b->edit_baton->diff_cmd_baton,
- scratch_pool));
+ SVN_ERR(eb->processor->file_changed(fb->path,
+ fb->left_source,
+ fb->right_source,
+ fb->path_end_revision
+ ? fb->path_start_revision
+ : NULL,
+ fb->path_end_revision,
+ fb->pristine_props,
+ right_props,
+ (fb->path_end_revision != NULL),
+ fb->propchanges,
+ fb->pfb,
+ eb->processor,
+ fb->pool));
}
+ svn_pool_destroy(fb->pool); /* Destroy file and scratch pool */
- if (eb->notify_func)
- {
- deleted_path_notify_t *dpn;
- svn_wc_notify_t *notify;
- svn_wc_notify_action_t action;
- svn_node_kind_t kind = svn_node_file;
-
- /* Find out if a pending delete notification for this path is
- * still around. */
- dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING);
- if (dpn)
- {
- /* If any was found, we will handle the pending 'deleted path
- * notification' (DPN) here. Remove it from the list. */
- apr_hash_set(eb->deleted_paths, b->path,
- APR_HASH_KEY_STRING, NULL);
-
- /* the pending delete might be on a different node kind. */
- kind = dpn->kind;
- content_state = prop_state = dpn->state;
- }
-
- /* Determine what the notification (ACTION) should be.
- * In case of a pending 'delete', this might become a 'replace'. */
- if (b->tree_conflicted)
- action = svn_wc_notify_tree_conflict;
- else if (dpn)
- {
- if (dpn->action == svn_wc_notify_update_delete
- && b->added)
- action = svn_wc_notify_update_replace;
- else
- /* Note: dpn->action might be svn_wc_notify_tree_conflict */
- action = dpn->action;
- }
- else if ((content_state == svn_wc_notify_state_missing)
- || (content_state == svn_wc_notify_state_obstructed))
- action = svn_wc_notify_skip;
- else if (b->added)
- action = svn_wc_notify_update_add;
- else
- action = svn_wc_notify_update_update;
-
- notify = svn_wc_create_notify(b->path, action, scratch_pool);
- notify->kind = kind;
- notify->content_state = content_state;
- notify->prop_state = prop_state;
- (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
- }
-
- svn_pool_destroy(b->pool); /* Destroy file and scratch pool */
+ SVN_ERR(release_dir(pb));
return SVN_NO_ERROR;
}
@@ -1082,120 +1033,76 @@ static svn_error_t *
close_directory(void *dir_baton,
apr_pool_t *pool)
{
- struct dir_baton *b = dir_baton;
- struct edit_baton *eb = b->edit_baton;
- svn_wc_notify_state_t content_state = svn_wc_notify_state_unknown;
- svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
- svn_boolean_t skipped = FALSE;
+ struct dir_baton *db = dir_baton;
+ struct edit_baton *eb = db->edit_baton;
apr_pool_t *scratch_pool;
apr_hash_t *pristine_props;
+ svn_boolean_t send_changed = FALSE;
- /* Skip *everything* within a newly tree-conflicted directory. */
- if (b->skip)
- {
- svn_pool_destroy(b->pool);
- return SVN_NO_ERROR;
- }
-
- scratch_pool = b->pool;
+ scratch_pool = db->pool;
- if (b->added)
+ if ((db->has_propchange || db->added) && !db->skip)
{
- pristine_props = eb->empty_hash;
- }
- else
- {
- SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &pristine_props,
- b->path, b->base_revision, 0, scratch_pool));
- }
-
- if (b->propchanges->nelts > 0)
- {
- remove_non_prop_changes(pristine_props, b->propchanges);
- }
-
- if (b->propchanges->nelts > 0)
- {
- svn_boolean_t tree_conflicted = FALSE;
- SVN_ERR(eb->diff_callbacks->dir_props_changed(
- &prop_state, &tree_conflicted,
- b->path, b->added,
- b->propchanges, pristine_props,
- b->edit_baton->diff_cmd_baton, scratch_pool));
- if (tree_conflicted)
- b->tree_conflicted = TRUE;
-
- if (prop_state == svn_wc_notify_state_obstructed
- || prop_state == svn_wc_notify_state_missing)
+ if (db->added)
{
- content_state = prop_state;
- skipped = TRUE;
+ pristine_props = eb->empty_hash;
+ }
+ else
+ {
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &pristine_props,
+ db->path, db->base_revision, 0, scratch_pool));
}
- }
-
- SVN_ERR(eb->diff_callbacks->dir_closed(NULL, NULL, NULL,
- b->path, b->added,
- b->edit_baton->diff_cmd_baton,
- scratch_pool));
-
- /* Notify about any deleted paths within this directory that have not
- * already been notified. */
- if (!skipped && !b->added && eb->notify_func)
- {
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(pool, eb->deleted_paths); hi;
- hi = apr_hash_next(hi))
+ if (db->propchanges->nelts > 0)
{
- svn_wc_notify_t *notify;
- const char *deleted_path = svn__apr_hash_index_key(hi);
- deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
-
- /* Ignore paths which are not children of b->path. (There
- should be none due to editor ordering constraints, but
- ra_serf drops the ball here -- see issue #3802 for
- details.) */
- if (! svn_relpath_skip_ancestor(b->path, deleted_path))
- continue;
-
- notify = svn_wc_create_notify(deleted_path, dpn->action, pool);
- notify->kind = dpn->kind;
- notify->content_state = notify->prop_state = dpn->state;
- notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- apr_hash_set(eb->deleted_paths, deleted_path,
- APR_HASH_KEY_STRING, NULL);
+ remove_non_prop_changes(pristine_props, db->propchanges);
}
- }
- /* Notify about this directory itself (unless it was added, in which
- * case the notification was done at that time). */
- if (!b->added && eb->notify_func)
- {
- svn_wc_notify_t *notify;
- svn_wc_notify_action_t action;
-
- if (b->tree_conflicted)
- action = svn_wc_notify_tree_conflict;
- else if (skipped)
- action = svn_wc_notify_skip;
- else
- action = svn_wc_notify_update_update;
+ if (db->propchanges->nelts > 0 || db->added)
+ {
+ apr_hash_t *right_props;
- notify = svn_wc_create_notify(b->path, action, pool);
- notify->kind = svn_node_dir;
+ right_props = svn_prop__patch(pristine_props, db->propchanges,
+ scratch_pool);
- /* In case of a tree conflict during merge, the diff callback
- * sets content_state appropriately. So copy the state into the
- * notify_t to make sure conflicts get displayed. */
- notify->content_state = content_state;
+ if (db->added)
+ {
+ SVN_ERR(eb->processor->dir_added(db->path,
+ NULL /* copyfrom */,
+ db->right_source,
+ NULL /* copyfrom props */,
+ right_props,
+ db->pdb,
+ eb->processor,
+ db->pool));
+ }
+ else
+ {
+ SVN_ERR(eb->processor->dir_changed(db->path,
+ db->left_source,
+ db->right_source,
+ pristine_props,
+ right_props,
+ db->propchanges,
+ db->pdb,
+ eb->processor,
+ db->pool));
+ }
- notify->prop_state = prop_state;
- notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+ send_changed = TRUE; /* Skip dir_closed */
+ }
}
- svn_pool_destroy(b->pool); /* Destroy baton and scratch_pool */
+ if (! db->skip && !send_changed)
+ {
+ SVN_ERR(eb->processor->dir_closed(db->path,
+ db->left_source,
+ db->right_source,
+ db->pdb,
+ eb->processor,
+ db->pool));
+ }
+ SVN_ERR(release_dir(db));
return SVN_NO_ERROR;
}
@@ -1210,16 +1117,23 @@ change_file_prop(void *file_baton,
const svn_string_t *value,
apr_pool_t *pool)
{
- struct file_baton *b = file_baton;
+ struct file_baton *fb = file_baton;
svn_prop_t *propchange;
+ svn_prop_kind_t propkind;
/* Skip *everything* within a newly tree-conflicted directory. */
- if (b->skip)
+ if (fb->skip)
+ return SVN_NO_ERROR;
+
+ propkind = svn_property_kind2(name);
+ if (propkind == svn_prop_wc_kind)
return SVN_NO_ERROR;
+ else if (propkind == svn_prop_regular_kind)
+ fb->has_propchange = TRUE;
- propchange = apr_array_push(b->propchanges);
- propchange->name = apr_pstrdup(b->pool, name);
- propchange->value = value ? svn_string_dup(value, b->pool) : NULL;
+ propchange = apr_array_push(fb->propchanges);
+ propchange->name = apr_pstrdup(fb->pool, name);
+ propchange->value = value ? svn_string_dup(value, fb->pool) : NULL;
return SVN_NO_ERROR;
}
@@ -1235,11 +1149,18 @@ change_dir_prop(void *dir_baton,
{
struct dir_baton *db = dir_baton;
svn_prop_t *propchange;
+ svn_prop_kind_t propkind;
/* Skip *everything* within a newly tree-conflicted directory. */
if (db->skip)
return SVN_NO_ERROR;
+ propkind = svn_property_kind2(name);
+ if (propkind == svn_prop_wc_kind)
+ return SVN_NO_ERROR;
+ else if (propkind == svn_prop_regular_kind)
+ db->has_propchange = TRUE;
+
propchange = apr_array_push(db->propchanges);
propchange->name = apr_pstrdup(db->pool, name);
propchange->value = value ? svn_string_dup(value, db->pool) : NULL;
@@ -1270,18 +1191,7 @@ absent_directory(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- /* ### TODO: Raise a tree-conflict?? I sure hope not.*/
-
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
-
- notify->kind = svn_node_dir;
- notify->content_state = notify->prop_state
- = svn_wc_notify_state_missing;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- }
+ SVN_ERR(eb->processor->node_absent(path, pb->pdb, eb->processor, pool));
return SVN_NO_ERROR;
}
@@ -1297,18 +1207,7 @@ absent_file(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- /* ### TODO: Raise a tree-conflict?? I sure hope not.*/
-
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
-
- notify->kind = svn_node_file;
- notify->content_state = notify->prop_state
- = svn_wc_notify_state_missing;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- }
+ SVN_ERR(eb->processor->node_absent(path, pb->pdb, eb->processor, pool));
return SVN_NO_ERROR;
}
@@ -1414,20 +1313,16 @@ fetch_base_func(const char **filename,
/* Create a repository diff editor and baton. */
svn_error_t *
-svn_client__get_diff_editor(const svn_delta_editor_t **editor,
- void **edit_baton,
- svn_depth_t depth,
- svn_ra_session_t *ra_session,
- svn_revnum_t revision,
- svn_boolean_t walk_deleted_dirs,
- svn_boolean_t text_deltas,
- const svn_wc_diff_callbacks4_t *diff_callbacks,
- void *diff_cmd_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *result_pool)
+svn_client__get_diff_editor2(const svn_delta_editor_t **editor,
+ void **edit_baton,
+ svn_ra_session_t *ra_session,
+ svn_depth_t depth,
+ svn_revnum_t revision,
+ svn_boolean_t text_deltas,
+ const svn_diff_tree_processor_t *processor,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool)
{
apr_pool_t *editor_pool = svn_pool_create(result_pool);
svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
@@ -1437,17 +1332,14 @@ svn_client__get_diff_editor(const svn_de
eb->pool = editor_pool;
eb->depth = depth;
- eb->diff_callbacks = diff_callbacks;
- eb->diff_cmd_baton = diff_cmd_baton;
+
+ eb->processor = processor;
+
eb->ra_session = ra_session;
eb->revision = revision;
eb->empty_file = NULL;
eb->empty_hash = apr_hash_make(eb->pool);
- eb->deleted_paths = apr_hash_make(eb->pool);
- eb->notify_func = notify_func;
- eb->notify_baton = notify_baton;
- eb->walk_deleted_repos_dirs = walk_deleted_dirs;
eb->text_deltas = text_deltas;
eb->cancel_func = cancel_func;
eb->cancel_baton = cancel_baton;
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/resolved.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/resolved.c Mon Feb 4 20:48:05 2013
@@ -55,17 +55,19 @@ svn_client_resolve(const char *path,
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
- SVN_ERR(svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
- depth,
- TRUE /* resolve_text */,
- "" /* resolve_prop (ALL props) */,
- TRUE /* resolve_tree */,
- conflict_choice,
- ctx->conflict_func2,
- ctx->conflict_baton2,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- pool));
+ SVN_WC__CALL_WITH_WRITE_LOCK(
+ svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
+ depth,
+ TRUE /* resolve_text */,
+ "" /* resolve_prop (ALL props) */,
+ TRUE /* resolve_tree */,
+ conflict_choice,
+ ctx->conflict_func2,
+ ctx->conflict_baton2,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
+ pool),
+ ctx->wc_ctx, local_abspath, TRUE, pool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/revert.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/revert.c Mon Feb 4 20:48:05 2013
@@ -166,8 +166,8 @@ svn_client_revert2(const apr_array_heade
baton.changelists = changelists;
baton.ctx = ctx;
- SVN_ERR(svn_wc__strictly_is_wc_root(&wc_root, ctx->wc_ctx,
- local_abspath, pool));
+ SVN_ERR(svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath,
+ pool));
lock_target = wc_root ? local_abspath
: svn_dirent_dirname(local_abspath, pool);
err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx,
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/status.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/status.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/status.c Mon Feb 4 20:48:05 2013
@@ -85,23 +85,12 @@ tweak_status(void *baton,
/* If the status item has an entry, but doesn't belong to one of the
changelists our caller is interested in, we filter out this status
transmission. */
- /* ### duplicated in ../libsvn_wc/diff_local.c */
- if (sb->changelist_hash)
+ if (sb->changelist_hash
+ && (! status->changelist
+ || ! apr_hash_get(sb->changelist_hash, status->changelist,
+ APR_HASH_KEY_STRING)))
{
- if (status->changelist)
- {
- /* Skip unless the caller requested this changelist. */
- if (! apr_hash_get(sb->changelist_hash, status->changelist,
- APR_HASH_KEY_STRING))
- return SVN_NO_ERROR;
- }
- else
- {
- /* Skip unless the caller requested changelist-lacking items. */
- if (! apr_hash_get(sb->changelist_hash, "",
- APR_HASH_KEY_STRING))
- return SVN_NO_ERROR;
- }
+ return SVN_NO_ERROR;
}
/* If we know that the target was deleted in HEAD of the repository,
@@ -541,6 +530,7 @@ svn_client_status5(svn_revnum_t *result_
SVN_ERR(svn_client__do_external_status(ctx, external_map,
depth, get_all,
update, no_ignore,
+ sb.anchor_abspath, sb.anchor_relpath,
status_func, status_baton, pool));
}
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c Mon Feb 4 20:48:05 2013
@@ -231,10 +231,8 @@ switch_internal(svn_revnum_t *result_rev
svn_boolean_t wc_root;
svn_boolean_t needs_iprop_cache = TRUE;
- SVN_ERR(svn_wc__strictly_is_wc_root(&wc_root,
- ctx->wc_ctx,
- local_abspath,
- pool));
+ SVN_ERR(svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath,
+ pool));
/* Switching the WC root to anything but the repos root means
we need an iprop cache. */
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/update.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/update.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/update.c Mon Feb 4 20:48:05 2013
@@ -376,23 +376,9 @@ update_internal(svn_revnum_t *result_rev
dfb.target_revision = revnum;
dfb.anchor_url = anchor_loc->url;
- err = svn_client__get_inheritable_props(&wcroot_iprops, local_abspath,
- revnum, depth, ra_session, ctx,
- pool, pool);
-
- /* We might be trying to update to a non-existant path-rev. */
- if (err)
- {
- if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
- {
- svn_error_clear(err);
- err = NULL;
- }
- else
- {
- return svn_error_trace(err);
- }
- }
+ SVN_ERR(svn_client__get_inheritable_props(&wcroot_iprops, local_abspath,
+ revnum, depth, ra_session,
+ ctx, pool, pool));
/* Fetch the update editor. If REVISION is invalid, that's okay;
the RA driver will call editor->set_target_revision later on. */
Modified: subversion/branches/fsfs-format7/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_delta/editor.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_delta/editor.c Mon Feb 4 20:48:05 2013
@@ -26,17 +26,27 @@
#include "svn_types.h"
#include "svn_error.h"
#include "svn_pools.h"
-#include "svn_editor.h"
#include "svn_dirent_uri.h"
+#include "private/svn_editor.h"
+
#ifdef SVN_DEBUG
/* This enables runtime checks of the editor API constraints. This may
introduce additional memory and runtime overhead, and should not be used
in production builds.
- ### Remove before release? */
+ ### Remove before release?
+
+ ### Disabled for now. If I call svn_editor_alter_directory(A) then
+ svn_editor_add_file(A/f) the latter fails on SHOULD_ALLOW_ADD.
+ If I modify svn_editor_alter_directory to MARK_ALLOW_ADD(child)
+ then if I call svn_editor_alter_directory(A) followed by
+ svn_editor_alter_directory(A/B/C) the latter fails on
+ VERIFY_PARENT_MAY_EXIST. */
+#if 0
#define ENABLE_ORDERING_CHECK
#endif
+#endif
struct svn_editor_t
@@ -665,6 +675,7 @@ svn_editor_alter_directory(svn_editor_t
apr_hash_set(editor->pending_incomplete_children, child,
APR_HASH_KEY_STRING, "");
+ /* Perhaps MARK_ALLOW_ADD(editor, child); ? */
}
}
#endif
Modified: subversion/branches/fsfs-format7/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_delta/svndiff.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_delta/svndiff.c Mon Feb 4 20:48:05 2013
@@ -203,7 +203,7 @@ send_simple_insertion_window(svn_txdelta
assert(window->ops[0].offset == 0);
/* write stream header if necessary */
- if (eb->header_done == FALSE)
+ if (!eb->header_done)
{
eb->header_done = TRUE;
headers[0] = 'S';
@@ -229,10 +229,11 @@ send_simple_insertion_window(svn_txdelta
ip_len = encode_int(ibuf + 1, window->tview_len) - ibuf;
}
- /* encode the window header. */
- header_current[0] = 0; /* source offset == 0 */
- header_current[1] = 0; /* source length == 0 */
- header_current = encode_int(header_current + 2, window->tview_len);
+ /* encode the window header. Please note that the source window may
+ * have content despite not being used for deltification. */
+ header_current = encode_int(header_current, window->sview_offset);
+ header_current = encode_int(header_current, window->sview_len);
+ header_current = encode_int(header_current, window->tview_len);
header_current[0] = (unsigned char)ip_len; /* 1 instruction */
header_current = encode_int(&header_current[1], len);
@@ -268,7 +269,7 @@ window_handler(svn_txdelta_window_t *win
return svn_error_trace(send_simple_insertion_window(window, eb));
/* Make sure we write the header. */
- if (eb->header_done == FALSE)
+ if (!eb->header_done)
{
char svnver[4] = {'S','V','N','\0'};
len = 4;