You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/04/30 23:04:38 UTC
svn commit: r1332392 [1/4] - in /subversion/branches/ev2-export: ./
notes/api-errata/1.8/ subversion/include/ subversion/include/private/
subversion/libsvn_client/ subversion/libsvn_delta/ subversion/libsvn_diff/
subversion/libsvn_fs/ subversion/libsvn...
Author: hwright
Date: Mon Apr 30 21:04:36 2012
New Revision: 1332392
URL: http://svn.apache.org/viewvc?rev=1332392&view=rev
Log:
On the ev2-export branch:
Bring up-to-date with trunk.
Added:
subversion/branches/ev2-export/notes/api-errata/1.8/
- copied from r1332387, subversion/trunk/notes/api-errata/1.8/
Modified:
subversion/branches/ev2-export/ (props changed)
subversion/branches/ev2-export/CHANGES
subversion/branches/ev2-export/subversion/include/private/svn_fs_util.h
subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h
subversion/branches/ev2-export/subversion/include/private/svn_ra_private.h
subversion/branches/ev2-export/subversion/include/private/svn_sqlite.h
subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h
subversion/branches/ev2-export/subversion/include/svn_error.h
subversion/branches/ev2-export/subversion/include/svn_fs.h
subversion/branches/ev2-export/subversion/include/svn_io.h
subversion/branches/ev2-export/subversion/libsvn_client/diff.c
subversion/branches/ev2-export/subversion/libsvn_client/merge.c
subversion/branches/ev2-export/subversion/libsvn_client/ra.c
subversion/branches/ev2-export/subversion/libsvn_client/revisions.c
subversion/branches/ev2-export/subversion/libsvn_delta/compat.c
subversion/branches/ev2-export/subversion/libsvn_delta/debug_editor.c
subversion/branches/ev2-export/subversion/libsvn_delta/editor.c
subversion/branches/ev2-export/subversion/libsvn_diff/diff_file.c
subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c
subversion/branches/ev2-export/subversion/libsvn_fs/editor.c
subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c
subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/lock-tokens-table.c
subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c
subversion/branches/ev2-export/subversion/libsvn_fs_base/err.c
subversion/branches/ev2-export/subversion/libsvn_fs_base/lock.c
subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c
subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h
subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
subversion/branches/ev2-export/subversion/libsvn_fs_fs/lock.c
subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c
subversion/branches/ev2-export/subversion/libsvn_ra/debug_reporter.c
subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c
subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h
subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c
subversion/branches/ev2-export/subversion/libsvn_repos/dump.c
subversion/branches/ev2-export/subversion/libsvn_repos/repos.c
subversion/branches/ev2-export/subversion/libsvn_subr/error.c
subversion/branches/ev2-export/subversion/libsvn_subr/hash.c
subversion/branches/ev2-export/subversion/libsvn_subr/io.c
subversion/branches/ev2-export/subversion/libsvn_subr/named_atomic.c
subversion/branches/ev2-export/subversion/libsvn_subr/sqlite.c
subversion/branches/ev2-export/subversion/libsvn_subr/stream.c
subversion/branches/ev2-export/subversion/libsvn_subr/win32_crashrpt.c
subversion/branches/ev2-export/subversion/libsvn_wc/entries.c
subversion/branches/ev2-export/subversion/libsvn_wc/node.c
subversion/branches/ev2-export/subversion/libsvn_wc/props.c
subversion/branches/ev2-export/subversion/libsvn_wc/wc.h
subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h
subversion/branches/ev2-export/subversion/po/de.po
subversion/branches/ev2-export/subversion/svn/blame-cmd.c
subversion/branches/ev2-export/subversion/svn/log-cmd.c
subversion/branches/ev2-export/subversion/svn/props.c
subversion/branches/ev2-export/subversion/svnadmin/main.c
subversion/branches/ev2-export/subversion/svnlook/main.c
subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c
subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c
subversion/branches/ev2-export/subversion/tests/cmdline/davautocheck.sh
subversion/branches/ev2-export/subversion/tests/cmdline/merge_symmetric_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/stat_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py
subversion/branches/ev2-export/subversion/tests/libsvn_subr/named_atomic-test.c
subversion/branches/ev2-export/subversion/tests/libsvn_wc/op-depth-test.c
subversion/branches/ev2-export/tools/buildbot/slaves/bb-openbsd/svnbuild.sh
subversion/branches/ev2-export/tools/dev/unix-build/Makefile.svn
Propchange: subversion/branches/ev2-export/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1331061-1332387
Modified: subversion/branches/ev2-export/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/CHANGES?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/CHANGES (original)
+++ subversion/branches/ev2-export/CHANGES Mon Apr 30 21:04:36 2012
@@ -62,7 +62,7 @@ http://svn.apache.org/repos/asf/subversi
* fix regression from 1.6 in update with --depth option (issue #4136)
* propset: avoid undefined behaviour in error path (r1325361)
* reset sqlite statements, partly for sqlite-3.7.11 compat (r1328846, et al)
- * [reverted/renominated] fix assertion during 'svn diff -r BASE:HEAD ^/trunk' (issue #4161)
+ * fix assertion during 'svn diff -r BASE:HEAD ^/trunk' (issue #4161)
* notify upon 'update' just removing locks on files (r1329876)
* neon: fix potential use of freed memory during commits (r1329388)
* 'status --xml' doesn't show repository deletes correctly (issue #4167)
Modified: subversion/branches/ev2-export/subversion/include/private/svn_fs_util.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_fs_util.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_fs_util.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_fs_util.h Mon Apr 30 21:04:36 2012
@@ -59,8 +59,12 @@ svn_fs__canonicalize_abspath(const char
svn_error_t *
svn_fs__check_fs(svn_fs_t *fs, svn_boolean_t expect_open);
-/** Temporary, to be removed in the next revision. */
-#define svn_fs__identifier(fs, unused) ((fs)->uuid)
+/* An identifier for FS to be used in the text of error messages.
+ (Not used anywhere but in this header.)
+
+ Note: we log the UUID, rather than (fs)->path, since some of these
+ errors are marshalled to the client. */
+#define svn_fs__identifier(fs) ((fs)->uuid)
/* Constructing nice error messages for roots. */
@@ -82,17 +86,17 @@ svn_fs__check_fs(svn_fs_t *fs, svn_boole
/* Build a detailed `file already exists' message for PATH in ROOT.
ROOT is of type svn_fs_root_t *. */
-#define SVN_FS__ALREADY_EXISTS(root, path_str, pool) ( \
+#define SVN_FS__ALREADY_EXISTS(root, path_str) ( \
root->is_txn_root ? \
svn_error_createf \
(SVN_ERR_FS_ALREADY_EXISTS, 0, \
_("File already exists: filesystem '%s', transaction '%s', path '%s'"), \
- svn_fs__identifier(root->fs, pool), root->txn, path_str) \
+ svn_fs__identifier(root->fs), root->txn, path_str) \
: \
svn_error_createf \
(SVN_ERR_FS_ALREADY_EXISTS, 0, \
_("File already exists: filesystem '%s', revision %ld, path '%s'"), \
- svn_fs__identifier(root->fs, pool), root->rev, path_str) \
+ svn_fs__identifier(root->fs), root->rev, path_str) \
)
/* ROOT is of type svn_fs_root_t *. */
@@ -103,64 +107,64 @@ svn_fs__check_fs(svn_fs_t *fs, svn_boole
/* SVN_FS__ERR_NOT_MUTABLE: the caller attempted to change a node
outside of a transaction. FS is of type "svn_fs_t *". */
-#define SVN_FS__ERR_NOT_MUTABLE(fs, rev, path_in_repo, scratch_pool) \
+#define SVN_FS__ERR_NOT_MUTABLE(fs, rev, path_in_repo) \
svn_error_createf( \
SVN_ERR_FS_NOT_MUTABLE, 0, \
_("File is not mutable: filesystem '%s', revision %ld, path '%s'"), \
- svn_fs__identifier(fs, scratch_pool), rev, path_in_repo)
+ svn_fs__identifier(fs), rev, path_in_repo)
/* FS is of type "svn_fs_t *".*/
-#define SVN_FS__ERR_NOT_DIRECTORY(fs, path_in_repo, scratch_pool) \
+#define SVN_FS__ERR_NOT_DIRECTORY(fs, path_in_repo) \
svn_error_createf( \
SVN_ERR_FS_NOT_DIRECTORY, 0, \
_("'%s' is not a directory in filesystem '%s'"), \
- path_in_repo, svn_fs__identifier(fs, scratch_pool))
+ path_in_repo, svn_fs__identifier(fs))
/* FS is of type "svn_fs_t *". */
-#define SVN_FS__ERR_NOT_FILE(fs, path_in_repo, scratch_pool) \
+#define SVN_FS__ERR_NOT_FILE(fs, path_in_repo) \
svn_error_createf( \
SVN_ERR_FS_NOT_FILE, 0, \
_("'%s' is not a file in filesystem '%s'"), \
- path_in_repo, svn_fs__identifier(fs, scratch_pool))
+ path_in_repo, svn_fs__identifier(fs))
/* FS is of type "svn_fs_t *", LOCK is of type "svn_lock_t *". */
-#define SVN_FS__ERR_PATH_ALREADY_LOCKED(fs, lock, scratch_pool) \
+#define SVN_FS__ERR_PATH_ALREADY_LOCKED(fs, lock) \
svn_error_createf( \
SVN_ERR_FS_PATH_ALREADY_LOCKED, 0, \
_("Path '%s' is already locked by user '%s' in filesystem '%s'"), \
- lock->path, lock->owner, svn_fs__identifier(fs, scratch_pool))
+ (lock)->path, (lock)->owner, svn_fs__identifier(fs))
/* FS is of type "svn_fs_t *". */
-#define SVN_FS__ERR_NO_SUCH_LOCK(fs, path_in_repo, scratch_pool) \
+#define SVN_FS__ERR_NO_SUCH_LOCK(fs, path_in_repo) \
svn_error_createf( \
SVN_ERR_FS_NO_SUCH_LOCK, 0, \
_("No lock on path '%s' in filesystem '%s'"), \
- path_in_repo, svn_fs__identifier(fs, scratch_pool))
+ path_in_repo, svn_fs__identifier(fs))
/* FS is of type "svn_fs_t *". */
-#define SVN_FS__ERR_LOCK_EXPIRED(fs, token, scratch_pool) \
+#define SVN_FS__ERR_LOCK_EXPIRED(fs, token) \
svn_error_createf( \
SVN_ERR_FS_LOCK_EXPIRED, 0, \
_("Lock has expired: lock-token '%s' in filesystem '%s'"), \
- token, svn_fs__identifier(fs, scratch_pool))
+ token, svn_fs__identifier(fs))
/* FS is of type "svn_fs_t *". */
-#define SVN_FS__ERR_NO_USER(fs, scratch_pool) \
+#define SVN_FS__ERR_NO_USER(fs) \
svn_error_createf( \
SVN_ERR_FS_NO_USER, 0, \
_("No username is currently associated with filesystem '%s'"), \
- svn_fs__identifier(fs, scratch_pool))
+ svn_fs__identifier(fs))
/* SVN_FS__ERR_LOCK_OWNER_MISMATCH: trying to use a lock whose
LOCK_OWNER doesn't match the USERNAME associated with FS.
FS is of type "svn_fs_t *". */
-#define SVN_FS__ERR_LOCK_OWNER_MISMATCH(fs, username, lock_owner, pool) \
+#define SVN_FS__ERR_LOCK_OWNER_MISMATCH(fs, username, lock_owner) \
svn_error_createf( \
SVN_ERR_FS_LOCK_OWNER_MISMATCH, 0, \
_("User '%s' is trying to use a lock owned by '%s' in " \
"filesystem '%s'"), \
- username, lock_owner, svn_fs__identifier(fs, pool))
+ username, lock_owner, svn_fs__identifier(fs))
/* Return a NULL-terminated copy of the first component of PATH,
allocated in POOL. If path is empty, or consists entirely of
Modified: subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h Mon Apr 30 21:04:36 2012
@@ -51,6 +51,16 @@ typedef struct svn_named_atomic__t svn_n
*/
#define SVN_NAMED_ATOMIC__MAX_NAME_LENGTH 30
+/** Returns #FALSE when named atomics are not available to our process
+ * and svn_atomic_namespace__create is likely to fail.
+ *
+ * Please note that the actual check will be performed only once and later
+ * changes in process privileges will not reflect in the outcome of future
+ * calls to this function.
+ */
+svn_boolean_t
+svn_named_atomic__is_supported(void);
+
/** Returns #TRUE on platforms that don't need expensive synchronization
* objects to serialize access to named atomics. If this returns #FALSE,
* reading from or modifying a #svn_named_atomic__t may be as expensive
Modified: subversion/branches/ev2-export/subversion/include/private/svn_ra_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_ra_private.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_ra_private.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_ra_private.h Mon Apr 30 21:04:36 2012
@@ -214,6 +214,7 @@ typedef svn_error_t *(*svn_ra__get_copys
in order to determine whether to use delta->add_directory() or the
delta->add_file() vtable entry to perform the copy.
### unclear on impact if this is NULL.
+ ### this callback will disappear when "everything" is running Ev2
CB_BATON is the baton used/shared by the above three callbacks.
Modified: subversion/branches/ev2-export/subversion/include/private/svn_sqlite.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_sqlite.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_sqlite.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_sqlite.h Mon Apr 30 21:04:36 2012
@@ -151,7 +151,9 @@ svn_sqlite__get_statement(svn_sqlite__st
Spec Argument type Item type
---- ----------------- ---------
n <none, absent> Column assignment skip
- i apr_int64_t Number
+ d int Number
+ L apr_int64_t Number
+ i apr_int64_t Number (deprecated format spec)
s const char * String
b const void * Blob data
apr_size_t Blob length
Modified: subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h Mon Apr 30 21:04:36 2012
@@ -689,34 +689,33 @@ svn_wc__node_get_pre_ng_status_data(svn_
apr_pool_t *scratch_pool);
-/** This whole function is for legacy, and it sucks. It does not really
- * make sense to get the copy-from revision number without the copy-from
- * URL, but higher level code currently wants that. This should go away.
- * (This function serves to get away from entry_t->revision without having to
- * change the public API.)
+/**
+ * Return the location of the base for this node's next commit,
+ * reflecting any local tree modifications affecting this node.
*
- * Get the base revision of @a local_abspath using @a wc_ctx. If @a
+ * Get the base location of @a local_abspath using @a wc_ctx. If @a
* local_abspath is not in the working copy, return @c
* SVN_ERR_WC_PATH_NOT_FOUND.
*
- * Return the revision number of the base for this node's next commit,
- * reflecting any local tree modifications affecting this node.
- *
- * If this node has no uncommitted changes, return the same revision as
+ * If this node has no uncommitted changes, return the same location as
* svn_wc__node_get_base().
*
* If this node is moved-here or copied-here (possibly as part of a replace),
- * return the revision of the copy/move source. Do the same even when the node
+ * return the location of the copy/move source. Do the same even when the node
* has been removed from a recursive copy (subpath excluded from the copy).
*
- * Else, if this node is locally added, return SVN_INVALID_REVNUM, or if this
- * node is locally deleted or replaced, return the revert-base revision.
+ * Else, if this node is locally added, return SVN_INVALID_REVNUM/NULL, or
+ * if locally deleted or replaced, return the revert-base location.
*/
svn_error_t *
-svn_wc__node_get_commit_base_rev(svn_revnum_t *base_revision,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
+svn_wc__node_get_commit_base(svn_revnum_t *revision,
+ const char **repos_relpath,
+ const char **repos_root_url,
+ const char **repos_uuid,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/**
* Fetch lock information (if any) for @a local_abspath using @a wc_ctx:
Modified: subversion/branches/ev2-export/subversion/include/svn_error.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_error.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_error.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_error.h Mon Apr 30 21:04:36 2012
@@ -317,7 +317,10 @@ svn_handle_warning(FILE *stream,
#ifdef SVN_ERR__TRACING
#define SVN_ERR__TRACED "traced call"
-#define svn_error_trace(expr) svn_error_quick_wrap((expr), SVN_ERR__TRACED)
+svn_error_t *
+svn_error__trace(const char *file, long line, svn_error_t *err);
+
+#define svn_error_trace(expr) svn_error__trace(__FILE__, __LINE__, (expr))
#else
#define svn_error_trace(expr) (expr)
#endif
Modified: subversion/branches/ev2-export/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_fs.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_fs.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_fs.h Mon Apr 30 21:04:36 2012
@@ -865,7 +865,7 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p,
* If @a conflict_p is non-zero, use it to provide details on any
* conflicts encountered merging @a txn with the most recent committed
* revisions. If a conflict occurs, set @a *conflict_p to the path of
- * the conflict in @a txn, with the same lifetime as @a txn;
+ * the conflict in @a txn, allocated within @a pool;
* otherwise, set @a *conflict_p to NULL.
*
* If the commit succeeds, @a txn is invalid.
@@ -881,6 +881,9 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p,
* even though a non-@c NULL function return value may indicate that
* something else went wrong in post commit FS processing.
*
+ * @note See api-errata/1.8/fs001.txt for information on how this
+ * function was documented in versions prior to 1.8.
+ *
* ### need to document this better. there are four combinations of
* ### return values:
* ### 1) err=NULL. conflict=NULL. new_rev is valid
Modified: subversion/branches/ev2-export/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_io.h?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_io.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_io.h Mon Apr 30 21:04:36 2012
@@ -1179,6 +1179,14 @@ svn_stream_tee(svn_stream_t *out1,
svn_stream_t *out2,
apr_pool_t *pool);
+/** Write NULL-terminated string @a str to @a stream.
+ *
+ * @since New in 1.8.
+ *
+ */
+svn_error_t *
+svn_stream_puts(svn_stream_t *stream,
+ const char *str);
/** Write to @a stream using a printf-style @a fmt specifier, passed through
* apr_psprintf() using memory from @a pool.
Modified: subversion/branches/ev2-export/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/diff.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/diff.c Mon Apr 30 21:04:36 2012
@@ -708,8 +708,7 @@ display_prop_diffs(const apr_array_heade
if (!val_has_eol)
{
const char *s = "\\ No newline at end of property" APR_EOL_STR;
- apr_size_t len = strlen(s);
- SVN_ERR(svn_stream_write(outstream, s, &len));
+ SVN_ERR(svn_stream_puts(outstream, s));
}
}
}
Modified: subversion/branches/ev2-export/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/merge.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/merge.c Mon Apr 30 21:04:36 2012
@@ -2841,9 +2841,9 @@ update_the_list_of_added_subtrees(const
}
else
{
- const char *added_path_parent =
- svn_dirent_dirname(added_abspath, scratch_pool);
apr_pool_t *subpool = svn_pool_create(scratch_pool);
+ const char *added_path_parent =
+ svn_dirent_dirname(added_abspath, subpool);
/* Is NOTIFY->PATH the root of an added subtree? */
while (strcmp(target_abspath, added_path_parent))
Modified: subversion/branches/ev2-export/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/ra.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/ra.c Mon Apr 30 21:04:36 2012
@@ -1012,8 +1012,9 @@ svn_client__ra_provide_base(svn_stream_t
{
/* The pristine contents refer to the BASE, or to the pristine of
a copy/move to this location. Fetch the correct revision. */
- SVN_ERR(svn_wc__node_get_commit_base_rev(revision, reb->wc_ctx,
- local_abspath, scratch_pool));
+ SVN_ERR(svn_wc__node_get_commit_base(revision, NULL, NULL, NULL,
+ reb->wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
}
return SVN_NO_ERROR;
@@ -1056,8 +1057,9 @@ svn_client__ra_provide_props(apr_hash_t
{
/* The pristine props refer to the BASE, or to the pristine props of
a copy/move to this location. Fetch the correct revision. */
- SVN_ERR(svn_wc__node_get_commit_base_rev(revision, reb->wc_ctx,
- local_abspath, scratch_pool));
+ SVN_ERR(svn_wc__node_get_commit_base(revision, NULL, NULL, NULL,
+ reb->wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
}
return SVN_NO_ERROR;
@@ -1100,6 +1102,9 @@ svn_client__ra_make_cb_baton(svn_wc_cont
{
struct ra_ev2_baton *reb = apr_palloc(result_pool, sizeof(*reb));
+ SVN_ERR_ASSERT_NO_RETURN(wc_ctx != NULL);
+ SVN_ERR_ASSERT_NO_RETURN(relpath_map != NULL);
+
reb->wc_ctx = wc_ctx;
reb->relpath_map = relpath_map;
Modified: subversion/branches/ev2-export/subversion/libsvn_client/revisions.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/revisions.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/revisions.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/revisions.c Mon Apr 30 21:04:36 2012
@@ -91,9 +91,9 @@ svn_client__get_revision_number(svn_revn
if (svn_path_is_url(local_abspath))
goto invalid_rev_arg;
- err = svn_wc__node_get_commit_base_rev(revnum, wc_ctx,
- local_abspath,
- scratch_pool);
+ err = svn_wc__node_get_commit_base(revnum, NULL, NULL, NULL,
+ wc_ctx, local_abspath,
+ scratch_pool, scratch_pool);
/* Return the same error as older code did (before and at r935091).
At least svn_client_proplist3 promises SVN_ERR_ENTRY_NOT_FOUND. */
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/compat.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/compat.c Mon Apr 30 21:04:36 2012
@@ -112,9 +112,8 @@ struct ev2_edit_baton
{
svn_editor_t *editor;
- /* ### need to ensure we understand the proper root for these relpaths */
- apr_hash_t *changes; /* RELPATH -> struct change_node */
- apr_hash_t *paths;
+ apr_hash_t *changes; /* REPOS_RELPATH -> struct change_node */
+
apr_array_header_t *path_order;
int paths_processed;
@@ -157,28 +156,6 @@ struct ev2_file_baton
const char *delta_base;
};
-enum action_code_t
-{
- ACTION_MKDIR,
- ACTION_COPY,
- ACTION_PROPSET,
- ACTION_PUT,
- ACTION_DELETE,
- ACTION_ADD_ABSENT
-};
-
-struct path_action
-{
- enum action_code_t action;
- void *args;
-};
-
-struct copy_args
-{
- const char *copyfrom_path;
- svn_revnum_t copyfrom_rev;
-};
-
enum restructure_action_t
{
RESTRUCTURE_NONE = 0,
@@ -222,61 +199,19 @@ struct change_node
};
-static svn_error_t *
-add_action(struct ev2_edit_baton *eb,
- const char *path,
- enum action_code_t action,
- void *args)
-{
- struct path_action *p_action;
- apr_array_header_t *action_list = apr_hash_get(eb->paths, path,
- APR_HASH_KEY_STRING);
-
- p_action = apr_palloc(eb->edit_pool, sizeof(*p_action));
- p_action->action = action;
- p_action->args = args;
-
- if (action_list == NULL)
- {
- const char *path_dup = apr_pstrdup(eb->edit_pool, path);
-
- action_list = apr_array_make(eb->edit_pool, 1,
- sizeof(struct path_action *));
- apr_hash_set(eb->paths, path_dup, APR_HASH_KEY_STRING, action_list);
- APR_ARRAY_PUSH(eb->path_order, const char *) = path_dup;
- }
-
- APR_ARRAY_PUSH(action_list, struct path_action *) = p_action;
-
- return SVN_NO_ERROR;
-}
-
-
static struct change_node *
locate_change(struct ev2_edit_baton *eb,
const char *relpath)
{
struct change_node *change = apr_hash_get(eb->changes, relpath,
APR_HASH_KEY_STRING);
- apr_array_header_t *action_list;
if (change != NULL)
return change;
- /* Shift RELPATH into the proper pool. */
+ /* Shift RELPATH into the proper pool, and record the observed order. */
relpath = apr_pstrdup(eb->edit_pool, relpath);
-
- /* Investigate whether there is an action in PATHS. Any presence there
- will determine whether we need to update PATH_ORDER. */
- action_list = apr_hash_get(eb->paths, relpath, APR_HASH_KEY_STRING);
- if (action_list == NULL)
- {
- /* Store an empty ACTION_LIST into PATHS. */
- action_list = apr_array_make(eb->edit_pool, 1,
- sizeof(struct path_action *));
- apr_hash_set(eb->paths, relpath, APR_HASH_KEY_STRING, action_list);
- APR_ARRAY_PUSH(eb->path_order, const char *) = relpath;
- }
+ APR_ARRAY_PUSH(eb->path_order, const char *) = relpath;
/* Return an empty change. Callers will tweak as needed. */
change = apr_pcalloc(eb->edit_pool, sizeof(*change));
@@ -353,17 +288,13 @@ get_children(struct ev2_edit_baton *eb,
apr_array_header_t *children = apr_array_make(pool, 1, sizeof(const char *));
apr_hash_index_t *hi;
- for (hi = apr_hash_first(pool, eb->paths); hi; hi = apr_hash_next(hi))
+ for (hi = apr_hash_first(pool, eb->changes); hi; hi = apr_hash_next(hi))
{
- const char *p = svn__apr_hash_index_key(hi);
+ const char *repos_relpath = svn__apr_hash_index_key(hi);
const char *child;
- /* Sanitize our paths. */
- if (*p == '/')
- p++;
-
/* Find potential children. */
- child = svn_relpath_skip_ancestor(path, p);
+ child = svn_relpath_skip_ancestor(path, repos_relpath);
if (!child || !*child)
continue;
@@ -381,173 +312,131 @@ get_children(struct ev2_edit_baton *eb,
static svn_error_t *
process_actions(struct ev2_edit_baton *eb,
- const char *path,
- apr_array_header_t *actions,
+ const char *repos_relpath,
const struct change_node *change,
apr_pool_t *scratch_pool)
{
apr_hash_t *props = NULL;
- svn_boolean_t need_add = FALSE;
- svn_boolean_t need_copy = FALSE;
- const char *copyfrom_path;
- svn_revnum_t copyfrom_rev;
- apr_array_header_t *children = NULL;
svn_stream_t *contents = NULL;
svn_checksum_t *checksum = NULL;
- svn_revnum_t delete_revnum = SVN_INVALID_REVNUM;
- svn_revnum_t props_base_revision = SVN_INVALID_REVNUM;
- svn_revnum_t text_base_revision = SVN_INVALID_REVNUM;
svn_kind_t kind = svn_kind_unknown;
- if (*path == '/')
+ SVN_ERR_ASSERT(change != NULL);
+
+ if (change->unlock)
+ SVN_ERR(eb->do_unlock(eb->unlock_baton, repos_relpath, scratch_pool));
+
+ if (change->action == RESTRUCTURE_DELETE)
{
- path++;
- *eb->found_abs_paths = TRUE;
+ /* If the action was left as RESTRUCTURE_DELETE, then a
+ replacement is not occurring. Just do the delete and bail. */
+ SVN_ERR(svn_editor_delete(eb->editor, repos_relpath,
+ change->deleting));
+
+ /* No further work possible on this node. */
+ return SVN_NO_ERROR;
}
+ if (change->action == RESTRUCTURE_ADD_ABSENT)
+ {
+ SVN_ERR(svn_editor_add_absent(eb->editor, repos_relpath,
+ change->kind, change->deleting));
- SVN_ERR_ASSERT(change != NULL);
- if (change != NULL)
+ /* No further work possible on this node. */
+ return SVN_NO_ERROR;
+ }
+
+ if (change->contents_abspath != NULL)
{
- if (change->unlock)
- SVN_ERR(eb->do_unlock(eb->unlock_baton, path, scratch_pool));
+ /* We can only set text on files. */
+ /* ### validate we aren't overwriting KIND? */
+ kind = svn_kind_file;
+
+ /* ### the checksum might be in CHANGE->CHECKSUM */
+ SVN_ERR(svn_io_file_checksum2(&checksum, change->contents_abspath,
+ svn_checksum_sha1, scratch_pool));
+ SVN_ERR(svn_stream_open_readonly(&contents, change->contents_abspath,
+ scratch_pool, scratch_pool));
+ }
- if (change->action == RESTRUCTURE_DELETE)
- {
- /* If the action was left as RESTRUCTURE_DELETE, then a
- replacement is not occurring. Just do the delete and bail. */
- SVN_ERR(svn_editor_delete(eb->editor, path, change->deleting));
+ if (change->props != NULL)
+ {
+ /* ### validate we aren't overwriting KIND? */
+ kind = change->kind;
+ props = change->props;
+ }
- /* No further work possible on this node. */
- return SVN_NO_ERROR;
- }
- if (change->action == RESTRUCTURE_ADD_ABSENT)
- {
- SVN_ERR(svn_editor_add_absent(eb->editor, path, change->kind,
- change->deleting));
+ if (change->action == RESTRUCTURE_ADD)
+ {
+ /* An add might be a replace. Grab the revnum we're replacing. */
+ svn_revnum_t replaces_rev = change->deleting;
- /* No further work possible on this node. */
- return SVN_NO_ERROR;
- }
+ kind = change->kind;
- if (change->action == RESTRUCTURE_ADD)
+ if (change->copyfrom_path != NULL)
{
- kind = change->kind;
-
- /* An add might be a replace. Grab the revnum we're replacing. */
- delete_revnum = change->deleting;
+ SVN_ERR(svn_editor_copy(eb->editor, change->copyfrom_path,
+ change->copyfrom_rev,
+ repos_relpath, replaces_rev));
+ /* Fall through to possibly make changes post-copy. */
+ }
+ else
+ {
+ /* If no properties were defined, then use an empty set. */
+ if (props == NULL)
+ props = apr_hash_make(scratch_pool);
if (kind == svn_kind_dir)
{
- children = get_children(eb, path, scratch_pool);
+ const apr_array_header_t *children;
+
+ children = get_children(eb, repos_relpath, scratch_pool);
+ SVN_ERR(svn_editor_add_directory(eb->editor, repos_relpath,
+ children, props,
+ replaces_rev));
}
else
{
- /* If this file is copied here, then we don't need CONTENTS.
- Otherwise, the contents comes from apply_txdelta() and has
- been saved at CONTENTS_ABSPATH. If apply_txdelta() was not
- called, then we're adding an empty file. */
- if (change->copyfrom_path == NULL
- && change->contents_abspath == NULL)
+ /* If this file was added, but apply_txdelta() was not
+ called (ie. no CONTENTS_ABSPATH), then we're adding
+ an empty file. */
+ if (change->contents_abspath == NULL)
{
contents = svn_stream_empty(scratch_pool);
checksum = svn_checksum_empty_checksum(svn_checksum_sha1,
scratch_pool);
}
- }
- if (change->copyfrom_path != NULL)
- {
- need_copy = TRUE;
- copyfrom_path = change->copyfrom_path;
- copyfrom_rev = change->copyfrom_rev;
+ SVN_ERR(svn_editor_add_file(eb->editor, repos_relpath,
+ checksum, contents, props,
+ replaces_rev));
}
- else
- {
- need_add = TRUE;
- }
- }
-
- if (change->contents_abspath != NULL)
- {
- /* We can only set text on files. */
- /* ### validate we aren't overwriting KIND? */
- kind = svn_kind_file;
-
- /* ### the checksum might be in CHANGE->CHECKSUM */
- SVN_ERR(svn_io_file_checksum2(&checksum, change->contents_abspath,
- svn_checksum_sha1, scratch_pool));
- SVN_ERR(svn_stream_open_readonly(&contents, change->contents_abspath,
- scratch_pool, scratch_pool));
-
- text_base_revision = change->changing;
- }
- if (change->props != NULL)
- {
- /* ### validate we aren't overwriting KIND? */
- kind = change->kind;
- props = change->props;
- props_base_revision = change->changing;
- }
- }
-
- /* We've now got a wholistic view of what has happened to this node,
- * so we can call our own editor APIs on it. */
-
- if (need_add)
- {
- if (props == NULL)
- props = apr_hash_make(scratch_pool);
-
- if (kind == svn_kind_dir)
- {
- SVN_ERR(svn_editor_add_directory(eb->editor, path, children,
- props, delete_revnum));
- }
- else
- {
- SVN_ERR(svn_editor_add_file(eb->editor, path, checksum, contents,
- props, delete_revnum));
+ /* No further work possible on this node. */
+ return SVN_NO_ERROR;
}
-
- /* No further work possible on this node. */
- return SVN_NO_ERROR;
- }
-
- if (need_copy)
- {
- SVN_ERR(svn_editor_copy(eb->editor, copyfrom_path, copyfrom_rev, path,
- delete_revnum));
- /* Fall through to possibly make changes post-copy. */
}
#if 0
/* There *should* be work for this node. But it seems that isn't true
in some cases. Future investigation... */
- SVN_ERR_ASSERT(need_copy || props || contents);
+ SVN_ERR_ASSERT(props || contents);
#endif
if (props || contents)
{
- /* We fetched and modified the props or content in some way. Apply 'em
- now. */
- svn_revnum_t base_revision;
-
- if (SVN_IS_VALID_REVNUM(props_base_revision)
- && SVN_IS_VALID_REVNUM(text_base_revision))
- SVN_ERR_ASSERT(props_base_revision == text_base_revision);
-
- if (SVN_IS_VALID_REVNUM(props_base_revision))
- base_revision = props_base_revision;
- else if (SVN_IS_VALID_REVNUM(text_base_revision))
- base_revision = text_base_revision;
- else
- base_revision = SVN_INVALID_REVNUM;
+ /* Changes to properties or content should have indicated the revision
+ it was intending to change.
+
+ Oop. Not true. The node may be locally-added. */
+#if 0
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(change->changing));
+#endif
if (kind == svn_kind_dir)
- SVN_ERR(svn_editor_alter_directory(eb->editor, path, base_revision,
- props));
+ SVN_ERR(svn_editor_alter_directory(eb->editor, repos_relpath,
+ change->changing, props));
else
- SVN_ERR(svn_editor_alter_file(eb->editor, path, base_revision, props,
+ SVN_ERR(svn_editor_alter_file(eb->editor, repos_relpath,
+ change->changing, props,
checksum, contents));
}
@@ -566,16 +455,16 @@ run_ev2_actions(struct ev2_edit_baton *e
as part of close_edit() and then some more as part of abort_edit() */
for (; eb->paths_processed < eb->path_order->nelts; ++eb->paths_processed)
{
- const char *path = APR_ARRAY_IDX(eb->path_order, eb->paths_processed,
- const char *);
- apr_array_header_t *actions = apr_hash_get(eb->paths, path,
- APR_HASH_KEY_STRING);
- struct change_node *change = apr_hash_get(eb->changes, path,
- APR_HASH_KEY_STRING);
+ const char *repos_relpath = APR_ARRAY_IDX(eb->path_order,
+ eb->paths_processed,
+ const char *);
+ const struct change_node *change = apr_hash_get(eb->changes,
+ repos_relpath,
+ APR_HASH_KEY_STRING);
svn_pool_clear(iterpool);
- SVN_ERR(process_actions(eb, path, actions, change, iterpool));
+ SVN_ERR(process_actions(eb, repos_relpath, change, iterpool));
}
svn_pool_destroy(iterpool);
@@ -700,7 +589,6 @@ ev2_add_directory(const char *path,
else
{
/* A copy */
- struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
change->copyfrom_path = map_to_repos_relpath(pb->eb, copyfrom_path,
pb->eb->edit_pool);
@@ -813,7 +701,6 @@ ev2_add_file(const char *path,
else
{
/* A copy */
- struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
change->copyfrom_path = map_to_repos_relpath(fb->eb, copyfrom_path,
fb->eb->edit_pool);
@@ -1081,7 +968,6 @@ svn_delta__delta_from_editor(const svn_d
eb->editor = editor;
eb->changes = apr_hash_make(pool);
- eb->paths = apr_hash_make(pool);
eb->path_order = apr_array_make(pool, 1, sizeof(const char *));
eb->edit_pool = pool;
eb->found_abs_paths = found_abs_paths;
@@ -1109,29 +995,9 @@ svn_delta__delta_from_editor(const svn_d
/* ### note the similarity to struct change_node. these structures will
### be combined in the future. */
struct operation {
- enum {
- OP_OPEN,
- OP_DELETE,
- OP_ADD,
- OP_REPLACE,
- OP_ADD_ABSENT,
- OP_PROPSET /* only for files for which no other operation is
- occuring; directories are OP_OPEN with non-empty
- props */
- } operation;
-
- const char *path;
- svn_kind_t kind; /* to copy, mkdir, put or set revprops */
- svn_revnum_t base_revision; /* When committing, the base revision */
- svn_revnum_t copyfrom_revision; /* to copy, valid for add and replace */
- svn_checksum_t *new_checksum; /* An MD5 hash of the new contents, if any */
- const char *copyfrom_url; /* to copy, valid for add and replace */
- const char *src_file; /* for put, the source file for contents */
- apr_hash_t *children; /* const char *path -> struct operation * */
- apr_hash_t *prop_mods; /* const char *prop_name ->
- const svn_string_t *prop_value */
- apr_array_header_t *prop_dels; /* const char *prop_name deletions */
- void *baton; /* as returned by the commit editor */
+ /* ### leave these two here for now. still used. */
+ svn_revnum_t base_revision;
+ void *baton;
};
struct editor_baton
@@ -1150,228 +1016,38 @@ struct editor_baton
const char *repos_root;
const char *base_relpath;
- apr_hash_t *paths;
+ /* REPOS_RELPATH -> struct change_node * */
+ apr_hash_t *changes;
+
apr_pool_t *edit_pool;
};
-/* Find the operation associated with PATH, which is a single-path
- component representing a child of the path represented by
- OPERATION. If no such child operation exists, create a new one of
- type OP_OPEN. */
-static struct operation *
-get_operation(const char *path,
- struct operation *operation,
- svn_revnum_t base_revision,
- apr_pool_t *result_pool)
+/* Insert a new change for RELPATH, or return an existing one. */
+static struct change_node *
+insert_change(const char *relpath,
+ apr_hash_t *changes)
{
- struct operation *child = apr_hash_get(operation->children, path,
- APR_HASH_KEY_STRING);
- if (! child)
- {
- child = apr_pcalloc(result_pool, sizeof(*child));
- child->children = apr_hash_make(result_pool);
- child->path = apr_pstrdup(result_pool, path);
- child->operation = OP_OPEN;
- child->copyfrom_revision = SVN_INVALID_REVNUM;
- child->kind = svn_kind_dir;
- child->base_revision = base_revision;
- child->prop_mods = apr_hash_make(result_pool);
- child->prop_dels = apr_array_make(result_pool, 1, sizeof(const char *));
- apr_hash_set(operation->children, apr_pstrdup(result_pool, path),
- APR_HASH_KEY_STRING, child);
- }
-
- /* If an operation has a child, it must of necessity be a directory,
- so ensure this fact. */
- operation->kind = svn_kind_dir;
-
- return child;
-}
-
-/* Add PATH to the operations tree rooted at OPERATION, creating any
- intermediate nodes that are required. Here's what's expected for
- each action type:
-
- ACTION URL REV SRC-FILE PROPNAME
- ------------ ----- ------- -------- --------
- ACTION_MKDIR NULL invalid NULL NULL
- ACTION_COPY valid valid NULL NULL
- ACTION_PUT NULL invalid valid NULL
- ACTION_DELETE NULL invalid NULL NULL
- ACTION_PROPSET valid invalid NULL valid
-
- Node type information is obtained for any copy source (to determine
- whether to create a file or directory) and for any deleted path (to
- ensure it exists since svn_delta_editor_t->delete_entry doesn't
- return an error on non-existent nodes). */
-static svn_error_t *
-build(struct editor_baton *eb,
- enum action_code_t action,
- const char *relpath,
- svn_kind_t kind,
- const char *url,
- svn_revnum_t rev,
- apr_hash_t *props,
- const char *src_file,
- svn_checksum_t *checksum,
- svn_revnum_t head,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *path_bits;
- const char *path_so_far = "";
- struct operation *operation = &eb->root;
- int i;
-
- /* We should only see PROPS when action is ACTION_PROPSET. */
- SVN_ERR_ASSERT((props && action == ACTION_PROPSET)
- || (!props && action != ACTION_PROPSET) );
-
- relpath = svn_relpath_skip_ancestor(eb->base_relpath, relpath);
-
- /* Look for any previous operations we've recognized for PATH. If
- any of PATH's ancestors have not yet been traversed, we'll be
- creating OP_OPEN operations for them as we walk down PATH's path
- components. */
- path_bits = svn_path_decompose(relpath, scratch_pool);
- for (i = 0; i < path_bits->nelts; ++i)
- {
- const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
- path_so_far = svn_relpath_join(path_so_far, path_bit, scratch_pool);
- operation = get_operation(path_so_far, operation, head, eb->edit_pool);
- }
-
- /* Handle property changes. */
- if (props)
- {
- apr_hash_t *current_props;
- apr_array_header_t *propdiffs;
-
- operation->kind = kind;
-
- if (operation->operation == OP_REPLACE)
- current_props = apr_hash_make(scratch_pool);
- else if (operation->copyfrom_url)
- {
- const char *copyfrom_relpath;
-
- if (eb->repos_root)
- copyfrom_relpath = svn_uri_skip_ancestor(eb->repos_root,
- operation->copyfrom_url,
- scratch_pool);
- else
- copyfrom_relpath = operation->copyfrom_url;
-
- SVN_ERR(eb->fetch_props_func(¤t_props, eb->fetch_props_baton,
- copyfrom_relpath,
- operation->copyfrom_revision,
- scratch_pool, scratch_pool));
- }
- else
- SVN_ERR(eb->fetch_props_func(¤t_props, eb->fetch_props_baton,
- svn_relpath_join(eb->base_relpath,
- relpath,
- scratch_pool),
- rev, scratch_pool,
- scratch_pool));
-
- SVN_ERR(svn_prop_diffs(&propdiffs, props, current_props, scratch_pool));
-
- for (i = 0; i < propdiffs->nelts; i++)
- {
- /* Note: the array returned by svn_prop_diffs() is an array of
- actual structures, not pointers to them. */
- svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
- if (!prop->value)
- APR_ARRAY_PUSH(operation->prop_dels, const char *) =
- apr_pstrdup(eb->edit_pool, prop->name);
- else
- apr_hash_set(operation->prop_mods,
- apr_pstrdup(eb->edit_pool, prop->name),
- APR_HASH_KEY_STRING,
- svn_string_dup(prop->value, eb->edit_pool));
- }
-
- /* If we're not adding this thing ourselves, check for existence. */
- if (! ((operation->operation == OP_ADD) ||
- (operation->operation == OP_REPLACE)))
- {
- if ((operation->kind == svn_kind_file)
- && (operation->operation == OP_OPEN))
- operation->operation = OP_PROPSET;
- }
- if (!SVN_IS_VALID_REVNUM(operation->copyfrom_revision))
- operation->copyfrom_revision = rev;
- return SVN_NO_ERROR;
- }
-
- if (action == ACTION_DELETE)
- {
- operation->operation = OP_DELETE;
- operation->base_revision = rev;
- }
-
- else if (action == ACTION_ADD_ABSENT)
- operation->operation = OP_ADD_ABSENT;
+ apr_pool_t *result_pool;
+ struct change_node *change;
- /* Handle copy operations (which can be adds or replacements). */
- else if (action == ACTION_COPY)
- {
- operation->operation =
- operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
+ change = apr_hash_get(changes, relpath, APR_HASH_KEY_STRING);
+ if (change != NULL)
+ return change;
- if (kind == svn_kind_none || kind == svn_kind_unknown)
- SVN_ERR(eb->fetch_kind_func(&operation->kind, eb->fetch_kind_baton,
- url, rev, scratch_pool));
- else
- operation->kind = kind;
+ result_pool = apr_hash_pool_get(changes);
- operation->copyfrom_revision = rev;
+ /* Return an empty change. Callers will tweak as needed. */
+ change = apr_pcalloc(result_pool, sizeof(*change));
+ change->changing = SVN_INVALID_REVNUM;
+ change->deleting = SVN_INVALID_REVNUM;
- if (eb->repos_root)
- operation->copyfrom_url = svn_path_url_add_component2(eb->repos_root,
- url,
- eb->edit_pool);
- else
- operation->copyfrom_url = apr_pstrcat(eb->edit_pool, "/", url, NULL);
- }
- /* Handle mkdir operations (which can be adds or replacements). */
- else if (action == ACTION_MKDIR)
- {
- operation->operation =
- operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
- operation->kind = svn_kind_dir;
- }
- /* Handle put operations (which can be adds, replacements, or opens). */
- else if (action == ACTION_PUT)
- {
- if (operation->operation == OP_DELETE)
- {
- operation->operation = OP_REPLACE;
- }
- else if (operation->operation == OP_OPEN)
- {
- if (kind == svn_kind_file)
- operation->operation = OP_OPEN;
- else if (kind == svn_kind_none)
- operation->operation = OP_ADD;
- else
- return svn_error_createf(SVN_ERR_BAD_URL, NULL,
- "'%s' is not a file", relpath);
- }
- operation->kind = svn_kind_file;
- operation->src_file = apr_pstrdup(eb->edit_pool, src_file);
- operation->new_checksum = svn_checksum_dup(checksum, eb->edit_pool);
- }
- else
- {
- /* We shouldn't get here. */
- SVN_ERR_MALFUNCTION();
- }
+ apr_hash_set(changes, relpath, APR_HASH_KEY_STRING, change);
- return SVN_NO_ERROR;
+ return change;
}
+
/* This implements svn_editor_cb_add_directory_t */
static svn_error_t *
add_directory_cb(void *baton,
@@ -1382,24 +1058,12 @@ add_directory_cb(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
+ struct change_node *change = insert_change(relpath, eb->changes);
- if (SVN_IS_VALID_REVNUM(replaces_rev))
- {
- /* We need to add the delete action. */
-
- SVN_ERR(build(eb, ACTION_DELETE, relpath, svn_kind_unknown,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
- }
-
- SVN_ERR(build(eb, ACTION_MKDIR, relpath, svn_kind_dir,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
-
- if (props && apr_hash_count(props) > 0)
- SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_dir,
- NULL, SVN_INVALID_REVNUM, props,
- NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
+ change->action = RESTRUCTURE_ADD;
+ change->kind = svn_kind_dir;
+ change->deleting = replaces_rev;
+ change->props = apr_hash_copy(eb->edit_pool, props);
return SVN_NO_ERROR;
}
@@ -1418,6 +1082,7 @@ add_file_cb(void *baton,
const char *tmp_filename;
svn_stream_t *tmp_stream;
svn_checksum_t *md5_checksum;
+ struct change_node *change = insert_change(relpath, eb->changes);
/* We may need to re-checksum these contents */
if (!(checksum && checksum->kind == svn_checksum_md5))
@@ -1426,30 +1091,18 @@ add_file_cb(void *baton,
else
md5_checksum = (svn_checksum_t *)checksum;
- if (SVN_IS_VALID_REVNUM(replaces_rev))
- {
- /* We need to add the delete action. */
-
- SVN_ERR(build(eb, ACTION_DELETE, relpath, svn_kind_unknown,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
- }
-
/* Spool the contents to a tempfile, and provide that to the driver. */
SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_filename, NULL,
svn_io_file_del_on_pool_cleanup,
eb->edit_pool, scratch_pool));
SVN_ERR(svn_stream_copy3(contents, tmp_stream, NULL, NULL, scratch_pool));
- SVN_ERR(build(eb, ACTION_PUT, relpath, svn_kind_none,
- NULL, SVN_INVALID_REVNUM,
- NULL, tmp_filename, md5_checksum, SVN_INVALID_REVNUM,
- scratch_pool));
-
- if (props && apr_hash_count(props) > 0)
- SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_file,
- NULL, SVN_INVALID_REVNUM, props,
- NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
+ change->action = RESTRUCTURE_ADD;
+ change->kind = svn_kind_file;
+ change->deleting = replaces_rev;
+ change->props = apr_hash_copy(eb->edit_pool, props);
+ change->contents_abspath = tmp_filename;
+ change->checksum = svn_checksum_dup(md5_checksum, eb->edit_pool);
return SVN_NO_ERROR;
}
@@ -1463,17 +1116,18 @@ add_symlink_cb(void *baton,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool)
{
+#if 0
struct editor_baton *eb = baton;
+ struct change_node *change = insert_change(relpath, eb->changes);
- if (SVN_IS_VALID_REVNUM(replaces_rev))
- {
- /* We need to add the delete action. */
-
- SVN_ERR(build(eb, ACTION_DELETE, relpath, svn_kind_unknown,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
- }
+ change->action = RESTRUCTURE_ADD;
+ change->kind = svn_kind_symlink;
+ change->deleting = replaces_rev;
+ change->props = apr_hash_copy(eb->edit_pool, props);
+ /* ### target */
+#endif
+ SVN__NOT_IMPLEMENTED();
return SVN_NO_ERROR;
}
@@ -1486,10 +1140,11 @@ add_absent_cb(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
+ struct change_node *change = insert_change(relpath, eb->changes);
- SVN_ERR(build(eb, ACTION_ADD_ABSENT, relpath, kind,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
+ change->action = RESTRUCTURE_ADD_ABSENT;
+ change->kind = kind;
+ change->deleting = replaces_rev;
return SVN_NO_ERROR;
}
@@ -1503,12 +1158,15 @@ alter_directory_cb(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
+ struct change_node *change = insert_change(relpath, eb->changes);
/* ### should we verify the kind is truly a directory? */
- SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_dir,
- NULL, SVN_INVALID_REVNUM,
- props, NULL, NULL, revision, scratch_pool));
+ /* Note: this node may already have information in CHANGE as a result
+ of an earlier copy/move operation. */
+ change->kind = svn_kind_dir;
+ change->changing = revision;
+ change->props = apr_hash_copy(eb->edit_pool, props);
return SVN_NO_ERROR;
}
@@ -1527,6 +1185,7 @@ alter_file_cb(void *baton,
const char *tmp_filename;
svn_stream_t *tmp_stream;
svn_checksum_t *md5_checksum;
+ struct change_node *change = insert_change(relpath, eb->changes);
/* ### should we verify the kind is truly a file? */
@@ -1546,17 +1205,19 @@ alter_file_cb(void *baton,
eb->edit_pool, scratch_pool));
SVN_ERR(svn_stream_copy3(contents, tmp_stream, NULL, NULL,
scratch_pool));
-
- SVN_ERR(build(eb, ACTION_PUT, relpath, svn_kind_file,
- NULL, SVN_INVALID_REVNUM,
- NULL, tmp_filename, md5_checksum, revision, scratch_pool));
}
- if (props)
+ /* Note: this node may already have information in CHANGE as a result
+ of an earlier copy/move operation. */
+
+ change->kind = svn_kind_file;
+ change->changing = revision;
+ if (props != NULL)
+ change->props = apr_hash_copy(eb->edit_pool, props);
+ if (contents != NULL)
{
- SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_file,
- NULL, SVN_INVALID_REVNUM,
- props, NULL, NULL, revision, scratch_pool));
+ change->contents_abspath = tmp_filename;
+ change->checksum = svn_checksum_dup(md5_checksum, eb->edit_pool);
}
return SVN_NO_ERROR;
@@ -1587,10 +1248,11 @@ delete_cb(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
+ struct change_node *change = insert_change(relpath, eb->changes);
- SVN_ERR(build(eb, ACTION_DELETE, relpath, svn_kind_unknown,
- NULL, revision, NULL, NULL, NULL, SVN_INVALID_REVNUM,
- scratch_pool));
+ change->action = RESTRUCTURE_DELETE;
+ /* change->kind = svn_kind_unknown; */
+ change->deleting = revision;
return SVN_NO_ERROR;
}
@@ -1605,19 +1267,22 @@ copy_cb(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
+ struct change_node *change = insert_change(dst_relpath, eb->changes);
- if (SVN_IS_VALID_REVNUM(replaces_rev))
- {
- /* We need to add the delete action. */
-
- SVN_ERR(build(eb, ACTION_DELETE, dst_relpath, svn_kind_unknown,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
- }
+ change->action = RESTRUCTURE_ADD;
+ /* change->kind = svn_kind_unknown; */
+ change->deleting = replaces_rev;
+ change->copyfrom_path = apr_pstrdup(eb->edit_pool, src_relpath);
+ change->copyfrom_rev = src_revision;
+
+ /* We need the source's kind to know whether to call add_directory()
+ or add_file() later on. */
+ SVN_ERR(eb->fetch_kind_func(&change->kind, eb->fetch_kind_baton,
+ change->copyfrom_path,
+ change->copyfrom_rev,
+ scratch_pool));
- SVN_ERR(build(eb, ACTION_COPY, dst_relpath, svn_kind_unknown,
- src_relpath, src_revision, NULL, NULL, NULL,
- SVN_INVALID_REVNUM, scratch_pool));
+ /* Note: this node may later have alter_*() called on it. */
return SVN_NO_ERROR;
}
@@ -1632,23 +1297,30 @@ move_cb(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
+ struct change_node *change;
- /* Delete the move source. */
- SVN_ERR(build(eb, ACTION_DELETE, src_relpath, svn_kind_unknown,
- NULL, src_revision, NULL, NULL, NULL, SVN_INVALID_REVNUM,
- scratch_pool));
-
- if (SVN_IS_VALID_REVNUM(replaces_rev))
- {
- /* We need to add the delete action for the replaced target. */
- SVN_ERR(build(eb, ACTION_DELETE, dst_relpath, svn_kind_unknown,
- NULL, SVN_INVALID_REVNUM,
- NULL, NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
- }
-
- SVN_ERR(build(eb, ACTION_COPY, dst_relpath, svn_kind_unknown,
- src_relpath, src_revision, NULL, NULL, NULL,
- SVN_INVALID_REVNUM, scratch_pool));
+ /* Remap a move into a DELETE + COPY. */
+
+ change = insert_change(src_relpath, eb->changes);
+ change->action = RESTRUCTURE_DELETE;
+ /* change->kind = svn_kind_unknown; */
+ change->deleting = src_revision;
+
+ change = insert_change(dst_relpath, eb->changes);
+ change->action = RESTRUCTURE_ADD;
+ /* change->kind = svn_kind_unknown; */
+ change->deleting = replaces_rev;
+ change->copyfrom_path = apr_pstrdup(eb->edit_pool, src_relpath);
+ change->copyfrom_rev = src_revision;
+
+ /* We need the source's kind to know whether to call add_directory()
+ or add_file() later on. */
+ SVN_ERR(eb->fetch_kind_func(&change->kind, eb->fetch_kind_baton,
+ change->copyfrom_path,
+ change->copyfrom_rev,
+ scratch_pool));
+
+ /* Note: this node may later have alter_*() called on it. */
return SVN_NO_ERROR;
}
@@ -1664,200 +1336,287 @@ rotate_cb(void *baton,
return SVN_NO_ERROR;
}
+
static svn_error_t *
-change_props(const svn_delta_editor_t *editor,
- void *baton,
- const struct operation *child,
- apr_pool_t *scratch_pool)
+drive_ev1_props(const struct editor_baton *eb,
+ const char *repos_relpath,
+ const struct change_node *change,
+ void *node_baton,
+ apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_hash_t *old_props;
+ apr_array_header_t *propdiffs;
+ const char *ev1_relpath;
+ int i;
- if (child->prop_dels)
+ /* If there are no properties to install, then just exit. */
+ if (change->props == NULL)
+ return SVN_NO_ERROR;
+
+ if (change->copyfrom_path)
{
- int i;
- for (i = 0; i < child->prop_dels->nelts; i++)
- {
- const char *prop_name;
+ /* The pristine properties are from the copy/move source. */
+ SVN_ERR(eb->fetch_props_func(&old_props, eb->fetch_props_baton,
+ change->copyfrom_path,
+ change->copyfrom_rev,
+ scratch_pool, iterpool));
+ }
+ else if (change->action == RESTRUCTURE_ADD)
+ {
+ /* Locally-added nodes have no pristine properties.
- svn_pool_clear(iterpool);
- prop_name = APR_ARRAY_IDX(child->prop_dels, i, const char *);
- if (child->kind == svn_kind_dir)
- SVN_ERR(editor->change_dir_prop(baton, prop_name,
- NULL, iterpool));
- else
- SVN_ERR(editor->change_file_prop(baton, prop_name,
- NULL, iterpool));
- }
+ Note: we can use iterpool; this hash only needs to survive to
+ the propdiffs call, and there are no contents to preserve. */
+ old_props = apr_hash_make(iterpool);
}
+ else
+ {
+ /* Fetch the pristine properties for whatever we're editing. */
+ SVN_ERR(eb->fetch_props_func(&old_props, eb->fetch_props_baton,
+ repos_relpath, change->changing,
+ scratch_pool, iterpool));
+ }
+
+ SVN_ERR(svn_prop_diffs(&propdiffs, change->props, old_props, scratch_pool));
- if (apr_hash_count(child->prop_mods))
+ ev1_relpath = svn_relpath_skip_ancestor(eb->base_relpath, repos_relpath);
+
+ for (i = 0; i < propdiffs->nelts; i++)
{
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(scratch_pool, child->prop_mods);
- hi; hi = apr_hash_next(hi))
- {
- const char *name = svn__apr_hash_index_key(hi);
- svn_string_t *val = svn__apr_hash_index_val(hi);
+ /* Note: the array returned by svn_prop_diffs() is an array of
+ actual structures, not pointers to them. */
+ const svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
- svn_pool_clear(iterpool);
- if (child->kind == svn_kind_dir)
- SVN_ERR(editor->change_dir_prop(baton, name, val, iterpool));
- else
- SVN_ERR(editor->change_file_prop(baton, name, val, iterpool));
- }
+ svn_pool_clear(iterpool);
+
+ if (change->kind == svn_kind_dir)
+ SVN_ERR(eb->deditor->change_dir_prop(node_baton,
+ prop->name, prop->value,
+ iterpool));
+ else
+ SVN_ERR(eb->deditor->change_file_prop(node_baton,
+ prop->name, prop->value,
+ iterpool));
+ }
+
+ /* Handle the funky unlock protocol. Note: only possibly on files. */
+ if (change->unlock)
+ {
+ SVN_ERR_ASSERT(change->kind == svn_kind_file);
+ SVN_ERR(eb->deditor->change_file_prop(node_baton,
+ SVN_PROP_ENTRY_LOCK_TOKEN, NULL,
+ iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
+
+/* Conforms to svn_delta_path_driver_cb_func_t */
static svn_error_t *
-drive_tree(struct operation *op,
- const struct operation *parent_op,
- const svn_delta_editor_t *editor,
- svn_boolean_t make_abs_paths,
- apr_pool_t *scratch_pool)
+apply_change(void **dir_baton,
+ void *parent_baton,
+ void *callback_baton,
+ const char *ev1_relpath,
+ apr_pool_t *result_pool)
{
- const char *path = op->path;
+ /* ### fix this? */
+ apr_pool_t *scratch_pool = result_pool;
+ const struct editor_baton *eb = callback_baton;
+ const struct change_node *change;
+ const char *relpath;
+ void *file_baton = NULL;
+
+ /* Typically, we are not creating new directory batons. */
+ *dir_baton = NULL;
- if (path[0] != '/' && make_abs_paths)
- path = apr_pstrcat(scratch_pool, "/", path, NULL);
+ relpath = svn_relpath_join(eb->base_relpath, ev1_relpath, scratch_pool);
+ change = apr_hash_get(eb->changes, relpath, APR_HASH_KEY_STRING);
- /* Deletes and replacements are simple -- just delete the thing. */
- if (op->operation == OP_DELETE || op->operation == OP_REPLACE)
+ /* The callback should only be called for paths in CHANGES. */
+ SVN_ERR_ASSERT(change != NULL);
+
+ /* Are we editing the root of the tree? */
+ if (parent_baton == NULL)
{
- SVN_ERR(editor->delete_entry(path, op->base_revision,
- parent_op->baton, scratch_pool));
+ /* The root was opened in start_edit_func() */
+ *dir_baton = eb->root.baton;
+
+ /* Only property edits are allowed on the root. */
+ SVN_ERR_ASSERT(change->action == RESTRUCTURE_NONE);
+ SVN_ERR(drive_ev1_props(eb, relpath, change, *dir_baton, scratch_pool));
+
+ /* No further action possible for the root. */
+ return SVN_NO_ERROR;
}
- if (op->kind == svn_kind_dir)
+ if (change->action == RESTRUCTURE_DELETE)
{
- /* Open or create our baton. */
- if (op->operation == OP_OPEN || op->operation == OP_PROPSET)
- SVN_ERR(editor->open_directory(path, parent_op->baton,
- op->base_revision,
- scratch_pool, &op->baton));
+ SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting,
+ parent_baton, scratch_pool));
- else if (op->operation == OP_ADD || op->operation == OP_REPLACE)
- SVN_ERR(editor->add_directory(path, parent_op->baton,
- op->copyfrom_url, op->copyfrom_revision,
- scratch_pool, &op->baton));
+ /* No futher action possible for this node. */
+ return SVN_NO_ERROR;
+ }
- else if (op->operation == OP_ADD_ABSENT)
- SVN_ERR(editor->absent_directory(path, parent_op->baton,
+ /* If we're not deleting this node, then we should know its kind. */
+ SVN_ERR_ASSERT(change->kind != svn_kind_unknown);
+
+ if (change->action == RESTRUCTURE_ADD_ABSENT)
+ {
+ if (change->kind == svn_kind_dir)
+ SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton,
+ scratch_pool));
+ else
+ SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton,
scratch_pool));
- if (op->baton)
- {
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- apr_hash_index_t *hi;
+ /* No further action possible for this node. */
+ return SVN_NO_ERROR;
+ }
+ /* RESTRUCTURE_NONE or RESTRUCTURE_ADD */
- /* Do any prop mods we may have. */
- SVN_ERR(change_props(editor, op->baton, op, scratch_pool));
+ if (change->action == RESTRUCTURE_ADD)
+ {
+ const char *copyfrom_url = NULL;
+ svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
- for (hi = apr_hash_first(scratch_pool, op->children);
- hi; hi = apr_hash_next(hi))
- {
- struct operation *child = svn__apr_hash_index_val(hi);
+ /* Do we have an old node to delete first? */
+ if (SVN_IS_VALID_REVNUM(change->deleting))
+ SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting,
+ parent_baton, scratch_pool));
- svn_pool_clear(iterpool);
- SVN_ERR(drive_tree(child, op, editor, make_abs_paths, iterpool));
- }
- svn_pool_destroy(iterpool);
+ /* Are we copying the node from somewhere? */
+ if (change->copyfrom_path)
+ {
+ if (eb->repos_root)
+ copyfrom_url = svn_path_url_add_component2(eb->repos_root,
+ change->copyfrom_path,
+ scratch_pool);
+ else
+ /* ### prefix with "/" ? */
+ copyfrom_url = change->copyfrom_path;
- /* We're done, close the directory. */
- SVN_ERR(editor->close_directory(op->baton, scratch_pool));
+ copyfrom_rev = change->copyfrom_rev;
}
+
+ if (change->kind == svn_kind_dir)
+ SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton,
+ copyfrom_url, copyfrom_rev,
+ result_pool, dir_baton));
+ else
+ SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton,
+ copyfrom_url, copyfrom_rev,
+ result_pool, &file_baton));
}
else
{
- /* This currently treats anything that isn't a directory as a file.
- I don't know that that's a valid assumption... */
-
- void *file_baton = NULL;
-
- /* Open or create our baton. */
- if (op->operation == OP_OPEN || op->operation == OP_PROPSET)
- SVN_ERR(editor->open_file(path, parent_op->baton, op->base_revision,
- scratch_pool, &file_baton));
-
- else if (op->operation == OP_ADD || op->operation == OP_REPLACE)
- SVN_ERR(editor->add_file(path, parent_op->baton, op->copyfrom_url,
- op->copyfrom_revision, scratch_pool,
- &file_baton));
-
- else if (op->operation == OP_ADD_ABSENT)
- SVN_ERR(editor->absent_file(path, parent_op->baton, scratch_pool));
+ if (change->kind == svn_kind_dir)
+ SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton,
+ change->changing,
+ result_pool, dir_baton));
+ else
+ SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton,
+ change->changing,
+ result_pool, &file_baton));
+ }
- if (file_baton)
- {
- /* Do we need to change text contents? */
- if (op->src_file)
- {
- svn_txdelta_window_handler_t handler;
- void *handler_baton;
- svn_stream_t *contents;
-
- SVN_ERR(editor->apply_textdelta(file_baton, NULL, scratch_pool,
- &handler, &handler_baton));
- SVN_ERR(svn_stream_open_readonly(&contents, op->src_file,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_txdelta_send_stream(contents, handler, handler_baton,
- NULL, scratch_pool));
- SVN_ERR(svn_stream_close(contents));
- }
+ /* Apply any properties in CHANGE to the node. */
+ if (change->kind == svn_kind_dir)
+ SVN_ERR(drive_ev1_props(eb, relpath, change, *dir_baton, scratch_pool));
+ else
+ SVN_ERR(drive_ev1_props(eb, relpath, change, file_baton, scratch_pool));
- /* Do any prop mods we may have. */
- SVN_ERR(change_props(editor, file_baton, op, scratch_pool));
+ if (change->contents_abspath)
+ {
+ svn_txdelta_window_handler_t handler;
+ void *handler_baton;
+ svn_stream_t *contents;
+
+ /* ### would be nice to have a BASE_CHECKSUM, but hey: this is the
+ ### shim code... */
+ SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool,
+ &handler, &handler_baton));
+ SVN_ERR(svn_stream_open_readonly(&contents, change->contents_abspath,
+ scratch_pool, scratch_pool));
+ /* ### it would be nice to send a true txdelta here, but whatever. */
+ SVN_ERR(svn_txdelta_send_stream(contents, handler, handler_baton,
+ NULL, scratch_pool));
+ SVN_ERR(svn_stream_close(contents));
+ }
- /* Close the file. */
- SVN_ERR(editor->close_file(file_baton,
- svn_checksum_to_cstring(op->new_checksum,
- scratch_pool),
- scratch_pool));
- }
+ if (file_baton)
+ {
+ const char *digest = svn_checksum_to_cstring(change->checksum,
+ scratch_pool);
+ SVN_ERR(eb->deditor->close_file(file_baton, digest, scratch_pool));
}
return SVN_NO_ERROR;
}
-/* This is a special case of drive_tree(), meant to handle the root, which
- doesn't have a parent and should already be open. */
+
static svn_error_t *
-drive_root(struct operation *root,
- const svn_delta_editor_t *editor,
- svn_boolean_t make_abs_paths,
- apr_pool_t *scratch_pool)
+drive_changes(const struct editor_baton *eb,
+ apr_pool_t *scratch_pool)
{
+ struct change_node *change;
+ apr_array_header_t *paths = apr_array_make(scratch_pool, 10,
+ sizeof(const char *));
apr_hash_index_t *hi;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- /* Early out: if we haven't opened the root yet (which would usually only
- be the case in an abort), there isn't much we can do here. */
- if (!root->baton)
+ /* If we never opened a root baton, then the caller aborted the editor
+ before it even began. There is nothing to do. Bail. */
+ if (eb->root.baton == NULL)
return SVN_NO_ERROR;
- /* Do any prop mods we may have. */
- SVN_ERR(change_props(editor, root->baton, root, scratch_pool));
+ /* We need to make the path driver believe we want to make changes to
+ the root. Otherwise, it will attempt an open_root(), which we already
+ did in start_edit_func(). We can forge up a change record, if one
+ does not already exist. */
+ change = insert_change(eb->base_relpath, eb->changes);
+ change->kind = svn_kind_dir;
+ /* No property changes (tho they might exist from a real change). */
- /* Now iterate over our children. */
- for (hi = apr_hash_first(scratch_pool, root->children);
- hi; hi = apr_hash_next(hi))
+ for (hi = apr_hash_first(scratch_pool, eb->changes); hi;
+ hi = apr_hash_next(hi))
{
- struct operation *child = svn__apr_hash_index_val(hi);
-
- svn_pool_clear(iterpool);
- SVN_ERR(drive_tree(child, root, editor, make_abs_paths, iterpool));
+ const char *relpath = svn__apr_hash_index_key(hi);
+ const char *ev1_relpath = svn_relpath_skip_ancestor(eb->base_relpath,
+ relpath);
+ APR_ARRAY_PUSH(paths, const char *) = ev1_relpath;
}
- /* We need to close the root directory, but leave it to our caller to call
- close_ or abort_edit(). */
- SVN_ERR(editor->close_directory(root->baton, scratch_pool));
+ /* We need to pass SVN_INVALID_REVNUM to the path_driver. It uses this
+ revision whenever it opens directory batons. If we specified a "real"
+ value, such as eb->root.base_revision, then it might use that for a
+ subdirectory *incorrectly*.
+
+ Specifically, log_tests 38 demonstrates that erroneous behavior when
+ it attempts to open "/A" at revision 0 (not there, of course).
+
+ All this said: passing SVN_INVALID_REVNUM to all of those
+ open_directory() calls is not the best behavior either, but it does
+ happen to magically work. (ugh)
+
+ Thankfully, we're moving away from this skitchy behavior to Ev2.
+
+ Final note: every other caller of svn_delta_path_driver() passes
+ SVN_INVALID_REVNUM, so we can't be the only goofball.
+
+ Note: dropping const on the callback_baton. */
+ SVN_ERR(svn_delta_path_driver(eb->deditor, eb->dedit_baton,
+ SVN_INVALID_REVNUM, paths,
+ apply_change, (void *)eb,
+ scratch_pool));
return SVN_NO_ERROR;
}
+
/* This implements svn_editor_cb_complete_t */
static svn_error_t *
complete_cb(void *baton,
@@ -1867,7 +1626,7 @@ complete_cb(void *baton,
svn_error_t *err;
/* Drive the tree we've created. */
- err = drive_root(&eb->root, eb->deditor, *eb->make_abs_paths, scratch_pool);
+ err = drive_changes(eb, scratch_pool);
if (!err)
{
err = svn_error_compose_create(err, eb->deditor->close_edit(
@@ -1894,7 +1653,7 @@ abort_cb(void *baton,
point. */
/* Drive the tree we've created. */
- err = drive_root(&eb->root, eb->deditor, *eb->make_abs_paths, scratch_pool);
+ err = drive_changes(eb, scratch_pool);
err2 = eb->deditor->abort_edit(eb->dedit_baton, scratch_pool);
@@ -1916,6 +1675,10 @@ start_edit_func(void *baton,
struct editor_baton *eb = baton;
eb->root.base_revision = base_revision;
+
+ /* For some Ev1 editors (such as the repos commit editor), the root must
+ be open before can invoke any callbacks. The open_root() call sets up
+ stuff (eg. open an FS txn) which will be needed. */
SVN_ERR(eb->deditor->open_root(eb->dedit_baton, eb->root.base_revision,
eb->edit_pool, &eb->root.baton));
@@ -1941,25 +1704,14 @@ do_unlock(void *baton,
apr_pool_t *scratch_pool)
{
struct editor_baton *eb = baton;
- apr_array_header_t *path_bits = svn_path_decompose(path, scratch_pool);
- const char *path_so_far = "";
- struct operation *operation = &eb->root;
- int i;
-
- /* Look for any previous operations we've recognized for PATH. If
- any of PATH's ancestors have not yet been traversed, we'll be
- creating OP_OPEN operations for them as we walk down PATH's path
- components. */
- for (i = 0; i < path_bits->nelts; ++i)
- {
- const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
- path_so_far = svn_relpath_join(path_so_far, path_bit, scratch_pool);
- operation = get_operation(path_so_far, operation, SVN_INVALID_REVNUM,
- eb->edit_pool);
- }
- APR_ARRAY_PUSH(operation->prop_dels, const char *) =
- SVN_PROP_ENTRY_LOCK_TOKEN;
+ {
+ /* PATH is REPOS_RELPATH */
+ struct change_node *change = insert_change(path, eb->changes);
+
+ /* We will need to propagate a deletion of SVN_PROP_ENTRY_LOCK_TOKEN */
+ change->unlock = TRUE;
+ }
return SVN_NO_ERROR;
}
@@ -2037,22 +1789,17 @@ svn_delta__editor_from_delta(svn_editor_
eb->deditor = deditor;
eb->dedit_baton = dedit_baton;
eb->edit_pool = result_pool;
- eb->paths = apr_hash_make(result_pool);
eb->repos_root = apr_pstrdup(result_pool, repos_root);
eb->base_relpath = apr_pstrdup(result_pool, base_relpath);
+ eb->changes = apr_hash_make(result_pool);
+
eb->fetch_kind_func = fetch_kind_func;
eb->fetch_kind_baton = fetch_kind_baton;
eb->fetch_props_func = fetch_props_func;
eb->fetch_props_baton = fetch_props_baton;
- eb->root.path = NULL;
- eb->root.children = apr_hash_make(result_pool);
- eb->root.kind = svn_kind_dir;
- eb->root.operation = OP_OPEN;
- eb->root.prop_mods = apr_hash_make(result_pool);
- eb->root.prop_dels = apr_array_make(result_pool, 1, sizeof(const char *));
- eb->root.copyfrom_revision = SVN_INVALID_REVNUM;
+ eb->root.base_revision = SVN_INVALID_REVNUM;
eb->make_abs_paths = send_abs_paths;
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/debug_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/debug_editor.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/debug_editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/debug_editor.c Mon Apr 30 21:04:36 2012
@@ -51,7 +51,7 @@ write_indent(struct edit_baton *eb, apr_
int i;
for (i = 0; i < eb->indent_level; ++i)
- SVN_ERR(svn_stream_printf(eb->out, pool, " "));
+ SVN_ERR(svn_stream_puts(eb->out, " "));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/editor.c?rev=1332392&r1=1332391&r2=1332392&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/editor.c Mon Apr 30 21:04:36 2012
@@ -397,7 +397,7 @@ check_cancel(svn_editor_t *editor)
END_CALLBACK(editor);
}
- return err;
+ return svn_error_trace(err);
}
@@ -448,7 +448,7 @@ svn_editor_add_directory(svn_editor_t *e
#endif
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -486,7 +486,7 @@ svn_editor_add_file(svn_editor_t *editor
CLEAR_INCOMPLETE(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -519,7 +519,7 @@ svn_editor_add_symlink(svn_editor_t *edi
CLEAR_INCOMPLETE(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -550,7 +550,7 @@ svn_editor_add_absent(svn_editor_t *edit
CLEAR_INCOMPLETE(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -581,7 +581,7 @@ svn_editor_alter_directory(svn_editor_t
MARK_COMPLETED(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -619,7 +619,7 @@ svn_editor_alter_file(svn_editor_t *edit
MARK_COMPLETED(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -652,7 +652,7 @@ svn_editor_alter_symlink(svn_editor_t *e
MARK_COMPLETED(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -680,7 +680,7 @@ svn_editor_delete(svn_editor_t *editor,
MARK_COMPLETED(editor, relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -713,7 +713,7 @@ svn_editor_copy(svn_editor_t *editor,
CLEAR_INCOMPLETE(editor, dst_relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -748,7 +748,7 @@ svn_editor_move(svn_editor_t *editor,
CLEAR_INCOMPLETE(editor, dst_relpath);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -795,7 +795,7 @@ svn_editor_rotate(svn_editor_t *editor,
#endif
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -819,7 +819,7 @@ svn_editor_complete(svn_editor_t *editor
MARK_FINISHED(editor);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}
@@ -840,5 +840,5 @@ svn_editor_abort(svn_editor_t *editor)
MARK_FINISHED(editor);
svn_pool_clear(editor->scratch_pool);
- return err;
+ return svn_error_trace(err);
}