You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/08/16 12:18:03 UTC
svn commit: r1373783 [16/50] - in /subversion/branches/compressed-pristines:
./ build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/
contrib/client-side/svnmerge/ cont...
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/fs_fs.h?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/fs_fs.h Thu Aug 16 10:17:48 2012
@@ -131,8 +131,9 @@ svn_error_t *svn_fs_fs__rep_contents_dir
apr_pool_t *pool);
/* Set *DIRENT to the entry identified by NAME in the directory given
- by NODEREV in filesystem FS. The returned object is allocated in
- RESULT_POOL; SCRATCH_POOL used for temporary allocations. */
+ by NODEREV in filesystem FS. If no such entry exits, *DIRENT will
+ be NULL. The returned object is allocated in RESULT_POOL; SCRATCH_POOL
+ used for temporary allocations. */
svn_error_t *
svn_fs_fs__rep_contents_dir_entry(svn_fs_dirent_t **dirent,
svn_fs_t *fs,
@@ -355,12 +356,6 @@ svn_error_t *svn_fs_fs__create(svn_fs_t
const char *path,
apr_pool_t *pool);
-/* Store the uuid of the repository FS in *UUID. Allocate space in
- POOL. */
-svn_error_t *svn_fs_fs__get_uuid(svn_fs_t *fs,
- const char **uuid,
- apr_pool_t *pool);
-
/* Set the uuid of repository FS to UUID, if UUID is not NULL;
otherwise, set the uuid of FS to a newly generated UUID. Perform
temporary allocations in POOL. */
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/key-gen.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/key-gen.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/key-gen.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/key-gen.c Thu Aug 16 10:17:48 2012
@@ -60,7 +60,7 @@ svn_fs_fs__add_keys(const char *key1, co
carry = val / 36;
val = val % 36;
- buf[i3++] = (val <= 9) ? (val + '0') : (val - 10 + 'a');
+ buf[i3++] = (char)((val <= 9) ? (val + '0') : (val - 10 + 'a'));
if (i1>=0)
i1--;
@@ -115,7 +115,7 @@ svn_fs_fs__next_key(const char *this, ap
if (c == '9')
next[i] = 'a';
else
- next[i] = c + 1;
+ next[i] = ++c;
}
}
else
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/lock.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/lock.c Thu Aug 16 10:17:48 2012
@@ -477,23 +477,31 @@ delete_lock(svn_fs_t *fs,
/* Set *LOCK_P to the lock for PATH in FS. HAVE_WRITE_LOCK should be
TRUE if the caller (or one of its callers) has taken out the
- repository-wide write lock, FALSE otherwise. Use POOL for
- allocations. */
+ repository-wide write lock, FALSE otherwise. If MUST_EXIST is
+ not set, the function will simply return NULL in *LOCK_P instead
+ of creating an SVN_FS__ERR_NO_SUCH_LOCK error in case the lock
+ was not found (much faster). Use POOL for allocations. */
static svn_error_t *
get_lock(svn_lock_t **lock_p,
svn_fs_t *fs,
const char *path,
svn_boolean_t have_write_lock,
+ svn_boolean_t must_exist,
apr_pool_t *pool)
{
- svn_lock_t *lock;
+ svn_lock_t *lock = NULL;
const char *digest_path;
+ svn_node_kind_t kind;
SVN_ERR(digest_path_from_path(&digest_path, fs->path, path, pool));
+ SVN_ERR(svn_io_check_path(digest_path, &kind, pool));
+
+ *lock_p = NULL;
+ if (kind != svn_node_none)
+ SVN_ERR(read_digest_file(NULL, &lock, fs->path, digest_path, pool));
- SVN_ERR(read_digest_file(NULL, &lock, fs->path, digest_path, pool));
if (! lock)
- return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
+ return must_exist ? SVN_FS__ERR_NO_SUCH_LOCK(fs, path) : SVN_NO_ERROR;
/* Don't return an expired lock. */
if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
@@ -502,8 +510,7 @@ get_lock(svn_lock_t **lock_p,
Read operations shouldn't change the filesystem. */
if (have_write_lock)
SVN_ERR(delete_lock(fs, lock, pool));
- *lock_p = NULL;
- return SVN_FS__ERR_LOCK_EXPIRED(fs, lock->token, pool);
+ return SVN_FS__ERR_LOCK_EXPIRED(fs, lock->token);
}
*lock_p = lock;
@@ -525,7 +532,7 @@ get_lock_helper(svn_fs_t *fs,
svn_lock_t *lock;
svn_error_t *err;
- err = get_lock(&lock, fs, path, have_write_lock, pool);
+ err = get_lock(&lock, fs, path, have_write_lock, FALSE, pool);
/* We've deliberately decided that this function doesn't tell the
caller *why* the lock is unavailable. */
@@ -648,7 +655,11 @@ walk_locks(svn_fs_t *fs,
svn_boolean_t have_write_lock,
apr_pool_t *pool)
{
- struct walk_locks_baton wlb = { get_locks_func, get_locks_baton, fs };
+ struct walk_locks_baton wlb;
+
+ wlb.get_locks_func = get_locks_func;
+ wlb.get_locks_baton = get_locks_baton;
+ wlb.fs = fs;
SVN_ERR(walk_digest_files(fs->path, digest_path, locks_walker, &wlb,
have_write_lock, pool));
return SVN_NO_ERROR;
@@ -766,7 +777,7 @@ lock_body(void *baton, apr_pool_t *pool)
SVN_ERR(lb->fs->vtable->revision_root(&root, lb->fs, youngest, pool));
SVN_ERR(svn_fs_fs__check_path(&kind, root, lb->path, pool));
if (kind == svn_node_dir)
- return SVN_FS__ERR_NOT_FILE(lb->fs, lb->path, pool);
+ return SVN_FS__ERR_NOT_FILE(lb->fs, lb->path);
/* While our locking implementation easily supports the locking of
nonexistent paths, we deliberately choose not to allow such madness. */
@@ -786,7 +797,7 @@ lock_body(void *baton, apr_pool_t *pool)
/* We need to have a username attached to the fs. */
if (!lb->fs->access_ctx || !lb->fs->access_ctx->username)
- return SVN_FS__ERR_NO_USER(lb->fs, pool);
+ return SVN_FS__ERR_NO_USER(lb->fs);
/* Is the caller attempting to lock an out-of-date working file? */
if (SVN_IS_VALID_REVNUM(lb->current_rev))
@@ -832,7 +843,7 @@ lock_body(void *baton, apr_pool_t *pool)
if (! lb->steal_lock)
{
/* Sorry, the path is already locked. */
- return SVN_FS__ERR_PATH_ALREADY_LOCKED(lb->fs, existing_lock, pool);
+ return SVN_FS__ERR_PATH_ALREADY_LOCKED(lb->fs, existing_lock);
}
else
{
@@ -881,23 +892,23 @@ unlock_body(void *baton, apr_pool_t *poo
svn_lock_t *lock;
/* This could return SVN_ERR_FS_BAD_LOCK_TOKEN or SVN_ERR_FS_LOCK_EXPIRED. */
- SVN_ERR(get_lock(&lock, ub->fs, ub->path, TRUE, pool));
+ SVN_ERR(get_lock(&lock, ub->fs, ub->path, TRUE, TRUE, pool));
/* Unless breaking the lock, we do some checks. */
if (! ub->break_lock)
{
/* Sanity check: the incoming token should match lock->token. */
if (strcmp(ub->token, lock->token) != 0)
- return SVN_FS__ERR_NO_SUCH_LOCK(ub->fs, lock->path, pool);
+ return SVN_FS__ERR_NO_SUCH_LOCK(ub->fs, lock->path);
/* There better be a username attached to the fs. */
if (! (ub->fs->access_ctx && ub->fs->access_ctx->username))
- return SVN_FS__ERR_NO_USER(ub->fs, pool);
+ return SVN_FS__ERR_NO_USER(ub->fs);
/* And that username better be the same as the lock's owner. */
if (strcmp(ub->fs->access_ctx->username, lock->owner) != 0)
return SVN_FS__ERR_LOCK_OWNER_MISMATCH(
- ub->fs, ub->fs->access_ctx->username, lock->owner, pool);
+ ub->fs, ub->fs->access_ctx->username, lock->owner);
}
/* Remove lock and lock token files. */
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache-db.sql Thu Aug 16 10:17:48 2012
@@ -41,25 +41,19 @@ SELECT revision, offset, size, expanded_
FROM rep_cache
WHERE hash = ?1
-
-- STMT_SET_REP
INSERT OR FAIL INTO rep_cache (hash, revision, offset, size, expanded_size)
VALUES (?1, ?2, ?3, ?4, ?5)
-
-- STMT_GET_REPS_FOR_RANGE
SELECT hash, revision, offset, size, expanded_size
FROM rep_cache
WHERE revision >= ?1 AND revision <= ?2
-
-- STMT_GET_MAX_REV
SELECT MAX(revision)
FROM rep_cache
-
-- STMT_DEL_REPS_YOUNGER_THAN_REV
DELETE FROM rep_cache
WHERE revision > ?1
-
-
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/rep-cache.c Thu Aug 16 10:17:48 2012
@@ -158,11 +158,11 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
STMT_GET_MAX_REV));
SVN_ERR(svn_sqlite__step(&have_row, stmt2));
max = svn_sqlite__column_revnum(stmt2, 0);
- SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
+ if (SVN_IS_VALID_REVNUM(max)) /* The rep-cache could be empty. */
+ SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
SVN_ERR(svn_sqlite__reset(stmt2));
}
- /* Get the statement. (There are no arguments to bind.) */
SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
STMT_GET_REPS_FOR_RANGE));
SVN_ERR(svn_sqlite__bindf(stmt, "rr",
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/structure?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/structure Thu Aug 16 10:17:48 2012
@@ -40,6 +40,9 @@ repository) is:
revprops/ Subdirectory containing rev-props
<shard>/ Shard directory, if sharding is in use (see below)
<revnum> File containing rev-props for <revnum>
+ <shard>.pack/ Pack directory, if the repo has been packed (see below)
+ <rev>.<count> Pack file, if the repository has been packed (see below)
+ manifest Pack manifest file, if a pack file exists (see below)
revprops.db SQLite database of the packed revision properties
transactions/ Subdirectory containing transactions
<txnid>.txn/ Directory containing transaction <txnid>
@@ -134,6 +137,7 @@ The formats are:
Format 3, understood by Subversion 1.5+
Format 4, understood by Subversion 1.6+
Format 5, understood by Subversion 1.7-dev, never released
+ Format 6, understood by Subversion 1.8
The differences between the formats are:
@@ -173,6 +177,12 @@ Revision changed paths list:
Format 1-3: Does not contain the node's kind.
Format 4+: Contains the node's kind.
+Shard packing:
+ Format 4: Applied to revision data only.
+ Format 5: Revprops would be packed independently of revision data.
+ Format 6+: Applied equally to revision data and revprop data
+ (i.e. same min packed revision)
+
# Incomplete list. See SVN_FS_FS__MIN_*_FORMAT
@@ -232,6 +242,79 @@ See r1143829 of this file:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/structure?view=markup&pathrev=1143829
+Packing revision properties (format 6+)
+---------------------------
+
+Similarly to the revision data, packing will concatenate multiple
+revprops into a single file. Since they are mutable data, we put an
+upper limit to the size of these files: We will concatenate the data
+up to the limit and then use a new file for the following revisions.
+
+The limit can be set and changed at will in the configuration file.
+It is 64kB by default. Because a pack file must contain at least one
+complete property list, files containing just one revision may exceed
+that limit.
+
+Furthermore, pack files can be compressed which saves about 75% of
+disk space. A configuration file flag enables the compression; it is
+off by default and may be switched on and off at will. The pack size
+limit is always applied to the uncompressed data. For this reason,
+the default is 256kB while compression has been enabled.
+
+Files are named after their start revision as "<rev>.<counter>" where
+counter will be increased whenever we rewrite a pack file due to a
+revprop change. The manifest file contains the list of pack file
+names, one line for each revision.
+
+Many tools track repository global data in revision properties at
+revision 0. To minimize I/O overhead for those applications, we
+will never pack that revision, i.e. its data is always being kept
+in revprops/0/0.
+
+Pack file format
+
+ Top level: <length><packed container>
+
+ We always apply data compression to the pack file - using the
+ SVN_DELTA_COMPRESSION_LEVEL_NONE level if compression is disabled.
+ <length> is being encoded using the variable-length svndiff integer
+ format.
+
+ container := header '\n' (revprops)+
+ header := start_rev '\n' rev_count '\n' (size '\n')+
+
+ All numbers in the header are given as ASCII decimals. rev_count
+ is the number of revisions packed into this container. There must
+ be exactly as many "size" and serialized "revprops". The "size"
+ values in the list are the length in bytes of the serialized
+ revprops of the respective revision.
+
+Writing to packed revprops
+
+ The old pack file is being read and the new revprops serialized.
+ If they fit into the same pack file, a temp file with the new
+ content gets written and moved into place just like an non-packed
+ revprop file would. No name change or manifest update required.
+
+ If they don't fit into the same pack file, i.e. exceed the pack
+ size limit, the pack will be split into 2 or 3 new packs just
+ before and / or after the modified revision.
+
+ In the current implementation, they will never be merged again.
+ To minimize fragmentation, the initial packing process will only
+ use about 90% of the limit, i.e. leave some room for growth.
+
+ When a pack file gets split, its counter is being increased
+ creating a new file and leaving the old content in place and
+ available for concurrent readers. Only after the new manifest
+ file got moved into place, will the old pack files be deleted.
+
+ Write access to revprops is being serialized by the global
+ filesystem write lock. We only need to build a few retries into
+ the reader code to gracefully handle manifest changes and pack
+ file deletions.
+
+
Node-revision IDs
-----------------
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/temp_serializer.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/temp_serializer.c Thu Aug 16 10:17:48 2012
@@ -30,6 +30,7 @@
#include "private/svn_fs_util.h"
#include "private/svn_temp_serializer.h"
+#include "private/svn_subr_private.h"
#include "temp_serializer.h"
@@ -47,16 +48,16 @@ encode_number(apr_int64_t number, char *
if (number < 0)
{
number = -number;
- *key_buffer = (number & 63) + ' ' + 65;
+ *key_buffer = (char)((number & 63) + ' ' + 65);
}
else
- *key_buffer = (number & 63) + ' ' + 1;
+ *key_buffer = (char)((number & 63) + ' ' + 1);
number /= 64;
/* write 7 bits / byte until no significant bits are left */
while (number)
{
- *++key_buffer = (number & 127) + ' ' + 1;
+ *++key_buffer = (char)((number & 127) + ' ' + 1);
number /= 128;
}
@@ -359,7 +360,7 @@ serialize_dir(apr_hash_t *entries, apr_p
static apr_hash_t *
deserialize_dir(void *buffer, hash_data_t *hash_data, apr_pool_t *pool)
{
- apr_hash_t *result = apr_hash_make(pool);
+ apr_hash_t *result = svn_hash__make(pool);
apr_size_t i;
apr_size_t count;
svn_fs_dirent_t *entry;
@@ -594,7 +595,7 @@ serialize_cstring_array(svn_temp_seriali
{
apr_size_t i;
const char **entries = *strings;
-
+
/* serialize COUNT entries pointers (the array) */
svn_temp_serializer__push(context,
(const void * const *)strings,
@@ -615,7 +616,7 @@ serialize_svn_string_array(svn_temp_seri
{
apr_size_t i;
const svn_string_t **entries = *strings;
-
+
/* serialize COUNT entries pointers (the array) */
svn_temp_serializer__push(context,
(const void * const *)strings,
@@ -645,14 +646,14 @@ svn_fs_fs__serialize_properties(void **d
properties.count = apr_hash_count(hash);
properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
-
+
/* populate it with the hash entries */
for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
{
properties.keys[i] = svn__apr_hash_index_key(hi);
properties.values[i] = svn__apr_hash_index_val(hi);
}
-
+
/* serialize it */
context = svn_temp_serializer__init(&properties,
sizeof(properties),
@@ -678,26 +679,26 @@ svn_fs_fs__deserialize_properties(void *
apr_size_t data_len,
apr_pool_t *pool)
{
- apr_hash_t *hash = apr_hash_make(pool);
+ apr_hash_t *hash = svn_hash__make(pool);
properties_data_t *properties = (properties_data_t *)data;
size_t i;
/* de-serialize our auxilliary data structure */
svn_temp_deserializer__resolve(properties, (void**)&properties->keys);
svn_temp_deserializer__resolve(properties, (void**)&properties->values);
-
+
/* de-serialize each entry and put it into the hash */
for (i = 0; i < properties->count; ++i)
{
apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1;
- svn_temp_deserializer__resolve(properties->keys,
+ svn_temp_deserializer__resolve((void*)properties->keys,
(void**)&properties->keys[i]);
-
- deserialize_svn_string(properties->values,
+
+ deserialize_svn_string((void*)properties->values,
(svn_string_t **)&properties->values[i]);
-
- apr_hash_set(hash,
- properties->keys[i], len,
+
+ apr_hash_set(hash,
+ properties->keys[i], len,
properties->values[i]);
}
@@ -931,7 +932,7 @@ svn_fs_fs__extract_dir_entry(void **out,
svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]);
/* Entries have been serialized one-by-one, each time including all
- * nestes structures and strings. Therefore, they occupy a single
+ * nested structures and strings. Therefore, they occupy a single
* block of memory whose end-offset is either the beginning of the
* next entry or the end of the buffer
*/
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/tree.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_fs/tree.c Thu Aug 16 10:17:48 2012
@@ -155,7 +155,7 @@ locate_cache(svn_cache__t **cache,
{
fs_fs_data_t *ffd = root->fs->fsap_data;
if (cache) *cache = ffd->rev_node_cache;
- if (key && path) *key
+ if (key && path) *key
= svn_fs_fs__combine_number_and_string(root->rev, path, pool);
}
}
@@ -359,7 +359,7 @@ mutable_root_node(dag_node_t **node_p,
return svn_fs_fs__dag_clone_root(node_p, root->fs, root->txn, pool);
else
/* If it's not a transaction root, we can't change its contents. */
- return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path, pool);
+ return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path);
}
@@ -696,7 +696,7 @@ open_path(parent_path_t **parent_path_p,
/* The path isn't finished yet; we'd better be in a directory. */
if (svn_fs_fs__dag_node_kind(child) != svn_node_dir)
- SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far, iterpool),
+ SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far),
apr_psprintf(iterpool, _("Failure opening '%s'"), path));
rest = next;
@@ -1837,7 +1837,7 @@ fs_make_dir(svn_fs_root_t *root,
/* If there's already a sub-directory by that name, complain. This
also catches the case of trying to make a subdirectory named `/'. */
if (parent_path->node)
- return SVN_FS__ALREADY_EXISTS(root, path, pool);
+ return SVN_FS__ALREADY_EXISTS(root, path);
/* Create the subdirectory. */
SVN_ERR(make_path_mutable(root, parent_path->parent, path, pool));
@@ -1925,17 +1925,7 @@ fs_same_p(svn_boolean_t *same_p,
svn_fs_t *fs2,
apr_pool_t *pool)
{
- const char *uuid1;
- const char *uuid2;
-
- /* Random thought: if fetching UUIDs to compare filesystems is too
- expensive, one solution would be to cache the UUID in each fs
- object (copying the UUID into fs->pool, of course). */
-
- SVN_ERR(fs1->vtable->get_uuid(fs1, &uuid1, pool));
- SVN_ERR(fs2->vtable->get_uuid(fs2, &uuid2, pool));
-
- *same_p = ! strcmp(uuid1, uuid2);
+ *same_p = ! strcmp(fs1->uuid, fs2->uuid);
return SVN_NO_ERROR;
}
@@ -2182,7 +2172,7 @@ fs_make_file(svn_fs_root_t *root,
/* If there's already a file by that name, complain.
This also catches the case of trying to make a file named `/'. */
if (parent_path->node)
- return SVN_FS__ALREADY_EXISTS(root, path, pool);
+ return SVN_FS__ALREADY_EXISTS(root, path);
/* Check (non-recursively) to see if path is locked; if so, check
that we can use it. */
@@ -2468,17 +2458,8 @@ fs_apply_textdelta(svn_txdelta_window_ha
tb->root = root;
tb->path = path;
tb->pool = pool;
-
- if (base_checksum)
- tb->base_checksum = svn_checksum_dup(base_checksum, pool);
- else
- tb->base_checksum = NULL;
-
- if (result_checksum)
- tb->result_checksum = svn_checksum_dup(result_checksum, pool);
- else
- tb->result_checksum = NULL;
-
+ tb->base_checksum = svn_checksum_dup(base_checksum, pool);
+ tb->result_checksum = svn_checksum_dup(result_checksum, pool);
SVN_ERR(apply_textdelta(tb, pool));
@@ -2610,11 +2591,7 @@ fs_apply_text(svn_stream_t **contents_p,
tb->root = root;
tb->path = path;
tb->pool = pool;
-
- if (result_checksum)
- tb->result_checksum = svn_checksum_dup(result_checksum, pool);
- else
- tb->result_checksum = NULL;
+ tb->result_checksum = svn_checksum_dup(result_checksum, pool);
SVN_ERR(apply_text(tb, pool));
@@ -3749,7 +3726,8 @@ make_txn_root(svn_fs_root_t **root_p,
svn_fs_fs__dag_deserialize,
APR_HASH_KEY_STRING,
32, 20, FALSE,
- apr_pstrcat(pool, txn, ":TXN", (char *)NULL),
+ apr_pstrcat(pool, txn, ":TXN",
+ (char *)NULL),
root->pool));
/* Initialize transaction-local caches in FS.
@@ -3816,8 +3794,9 @@ verify_node(dag_node_t *node,
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
"Predecessor count mismatch: "
"%s has %d, but %s has %d",
- stringify_node(node, iterpool), pred_count,
- stringify_node(pred, iterpool), pred_pred_count);
+ stringify_node(node, iterpool), pred_count,
+ stringify_node(pred, iterpool),
+ pred_pred_count);
}
/* Kind-dependent verifications. */
@@ -3922,8 +3901,9 @@ svn_fs_fs__verify_root(svn_fs_root_t *ro
if (pred_rev+1 != root->rev)
/* Issue #4129. */
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- "r%ld's root node's predecessor is r%ld",
- root->rev, pred_rev);
+ "r%ld's root node's predecessor is r%ld"
+ " but should be r%ld",
+ root->rev, pred_rev, root->rev - 1);
}
}
Modified: subversion/branches/compressed-pristines/subversion/libsvn_fs_util/fs-util.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_fs_util/fs-util.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_fs_util/fs-util.c Thu Aug 16 10:17:48 2012
@@ -163,7 +163,7 @@ svn_fs__append_to_merged_froms(svn_merge
for (hi = apr_hash_first(pool, input); hi; hi = apr_hash_next(hi))
{
const char *path = svn__apr_hash_index_key(hi);
- apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
+ svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
apr_hash_set(*output, svn_fspath__join(path, rel_path, pool),
APR_HASH_KEY_STRING, svn_rangelist_dup(rangelist, pool));
Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra/compat.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra/compat.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra/compat.c Thu Aug 16 10:17:48 2012
@@ -757,8 +757,9 @@ svn_ra__file_revs_from_log(svn_ra_sessio
/* Compute and send delta if client asked for it. */
if (delta_handler)
{
- /* Get the content delta. */
- svn_txdelta(&delta_stream, last_stream, stream, lastpool);
+ /* Get the content delta. Don't calculate checksums as we don't
+ * use them. */
+ svn_txdelta2(&delta_stream, last_stream, stream, FALSE, lastpool);
/* And send. */
SVN_ERR(svn_txdelta_send_txstream(delta_stream, delta_handler,
Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra/debug_reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra/debug_reporter.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra/debug_reporter.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra/debug_reporter.c Thu Aug 16 10:17:48 2012
@@ -95,7 +95,7 @@ finish_report(void *report_baton,
apr_pool_t *pool)
{
struct report_baton *rb = report_baton;
- SVN_ERR(svn_stream_printf(rb->out, pool, "finish_report()\n"));
+ SVN_ERR(svn_stream_puts(rb->out, "finish_report()\n"));
SVN_ERR(rb->wrapped_reporter->finish_report(rb->wrapped_report_baton, pool));
return SVN_NO_ERROR;
}
@@ -105,7 +105,7 @@ abort_report(void *report_baton,
apr_pool_t *pool)
{
struct report_baton *rb = report_baton;
- SVN_ERR(svn_stream_printf(rb->out, pool, "abort_report()\n"));
+ SVN_ERR(svn_stream_puts(rb->out, "abort_report()\n"));
SVN_ERR(rb->wrapped_reporter->abort_report(rb->wrapped_report_baton, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.c Thu Aug 16 10:17:48 2012
@@ -50,20 +50,6 @@
#include "svn_private_config.h"
-/* ### This file maps URL schemes to particular RA libraries.
- ### Currently, the only pair of RA libraries which support the same
- ### protocols are neon and serf. svn_ra_open3 makes the assumption
- ### that this is the case; that their 'schemes' fields are both
- ### dav_schemes; and that "neon" is listed first.
-
- ### Users can choose which dav library to use with the http-library
- ### preference in .subversion/servers; however, it is ignored by
- ### any code which uses the pre-1.2 API svn_ra_get_ra_library
- ### instead of svn_ra_open. */
-
-#if defined(SVN_HAVE_NEON) && defined(SVN_HAVE_SERF)
-#define CHOOSABLE_DAV_MODULE
-#endif
/* These are the URI schemes that the respective libraries *may* support.
@@ -85,15 +71,6 @@ static const struct ra_lib_defn {
svn_ra_init_func_t compat_initfunc;
} ra_libraries[] = {
{
- "neon",
- dav_schemes,
-#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_NEON
- svn_ra_neon__init,
- svn_ra_dav_init
-#endif
- },
-
- {
"svn",
svn_schemes,
#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SVN
@@ -413,8 +390,7 @@ svn_error_t *svn_ra_open4(svn_ra_session
SVN_CONFIG_OPTION_HTTP_LIBRARY,
DEFAULT_HTTP_LIBRARY);
- if (strcmp(http_library, "neon") != 0 &&
- strcmp(http_library, "serf") != 0)
+ if (strcmp(http_library, "serf") != 0)
return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
_("Invalid config: unknown HTTP library "
"'%s'"),
@@ -706,6 +682,39 @@ commit_callback_wrapper(const svn_commit
return ccwb->original_callback(ci, ccwb->original_baton, pool);
}
+
+/* Some RA layers do not correctly fill in REPOS_ROOT in commit_info, or
+ they are third-party layers conforming to an older commit_info structure.
+ Interpose a utility function to ensure the field is valid. */
+static void
+remap_commit_callback(svn_commit_callback2_t *callback,
+ void **callback_baton,
+ svn_ra_session_t *session,
+ svn_commit_callback2_t original_callback,
+ void *original_baton,
+ apr_pool_t *result_pool)
+{
+ if (original_callback == NULL)
+ {
+ *callback = NULL;
+ *callback_baton = NULL;
+ }
+ else
+ {
+ /* Allocate this in RESULT_POOL, since the callback will be called
+ long after this function has returned. */
+ struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb));
+
+ ccwb->session = session;
+ ccwb->original_callback = original_callback;
+ ccwb->original_baton = original_baton;
+
+ *callback = commit_callback_wrapper;
+ *callback_baton = ccwb;
+ }
+}
+
+
svn_error_t *svn_ra_get_commit_editor3(svn_ra_session_t *session,
const svn_delta_editor_t **editor,
void **edit_baton,
@@ -716,20 +725,13 @@ svn_error_t *svn_ra_get_commit_editor3(s
svn_boolean_t keep_locks,
apr_pool_t *pool)
{
- /* Allocate this in a pool, since the callback will be called long after
- this function as returned. */
- struct ccw_baton *ccwb = apr_palloc(pool, sizeof(*ccwb));
-
- ccwb->original_callback = callback;
- ccwb->original_baton = callback_baton;
- ccwb->session = session;
+ remap_commit_callback(&callback, &callback_baton,
+ session, callback, callback_baton,
+ pool);
return session->vtable->get_commit_editor(session, editor, edit_baton,
revprop_table,
- callback
- ? commit_callback_wrapper
- : NULL,
- callback ? ccwb : NULL,
+ callback, callback_baton,
lock_tokens, keep_locks, pool);
}
@@ -876,6 +878,8 @@ svn_error_t *svn_ra_do_diff3(svn_ra_sess
void *diff_baton,
apr_pool_t *pool)
{
+ SVN_ERR_ASSERT(svn_path_is_empty(diff_target)
+ || svn_path_is_single_path_component(diff_target));
return session->vtable->do_diff(session,
reporter, report_baton,
revision, diff_target,
@@ -1141,6 +1145,17 @@ svn_error_t *svn_ra_replay(svn_ra_sessio
}
svn_error_t *
+svn_ra__replay_ev2(svn_ra_session_t *session,
+ svn_revnum_t revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_editor_t *editor,
+ apr_pool_t *scratch_pool)
+{
+ SVN__NOT_IMPLEMENTED();
+}
+
+svn_error_t *
svn_ra_replay_range(svn_ra_session_t *session,
svn_revnum_t start_revision,
svn_revnum_t end_revision,
@@ -1193,6 +1208,20 @@ svn_ra_replay_range(svn_ra_session_t *se
return err;
}
+svn_error_t *
+svn_ra__replay_range_ev2(svn_ra_session_t *session,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_ra__replay_revstart_ev2_callback_t revstart_func,
+ svn_ra__replay_revfinish_ev2_callback_t revfinish_func,
+ void *replay_baton,
+ apr_pool_t *scratch_pool)
+{
+ SVN__NOT_IMPLEMENTED();
+}
+
svn_error_t *svn_ra_has_capability(svn_ra_session_t *session,
svn_boolean_t *has,
const char *capability,
@@ -1228,8 +1257,7 @@ svn_ra_get_deleted_rev(svn_ra_session_t
end_revision,
revision_deleted,
pool);
- if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE /* serf */
- || err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)) /* neon */
+ if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
{
svn_error_clear(err);
@@ -1241,6 +1269,67 @@ svn_ra_get_deleted_rev(svn_ra_session_t
return err;
}
+
+svn_error_t *
+svn_ra__get_commit_ev2(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (session->vtable->get_commit_ev2 == NULL)
+ {
+ /* The specific RA layer does not have an implementation. Use our
+ default shim over the normal commit editor. */
+
+ /* Remap for RA layers exposing Ev1. */
+ remap_commit_callback(&callback, &callback_baton,
+ session, callback, callback_baton,
+ result_pool);
+
+ return svn_error_trace(svn_ra__use_commit_shim(
+ editor,
+ session,
+ revprop_table,
+ callback, callback_baton,
+ lock_tokens,
+ keep_locks,
+ provide_base_cb,
+ provide_props_cb,
+ get_copysrc_kind_cb,
+ cb_baton,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+ }
+
+ /* Note: no need to remap the callback for Ev2. RA layers providing this
+ vtable entry should completely fill in commit_info. */
+
+ return svn_error_trace(session->vtable->get_commit_ev2(
+ editor,
+ session,
+ revprop_table,
+ callback, callback_baton,
+ lock_tokens,
+ keep_locks,
+ provide_base_cb,
+ provide_props_cb,
+ get_copysrc_kind_cb,
+ cb_baton,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+}
+
svn_error_t *
Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.h?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra/ra_loader.h Thu Aug 16 10:17:48 2012
@@ -32,6 +32,8 @@
#include "svn_ra.h"
+#include "private/svn_ra_private.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -56,7 +58,7 @@ typedef struct svn_ra__vtable_t {
time this is called. SESSION->priv may be set by this function. */
svn_error_t *(*open_session)(svn_ra_session_t *session,
const char **corrected_url,
- const char *repos_URL,
+ const char *session_URL,
const svn_ra_callbacks2_t *callbacks,
void *callback_baton,
apr_hash_t *config,
@@ -293,9 +295,29 @@ typedef struct svn_ra__vtable_t {
svn_revnum_t end_revision,
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+
+ /* See svn_ra__register_editor_shim_callbacks() */
svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
svn_delta_shim_callbacks_t *callbacks);
+ /* See svn_ra__get_commit_ev2() */
+ svn_error_t *(*get_commit_ev2)(
+ svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
} svn_ra__vtable_t;
/* The RA session object. */
@@ -331,9 +353,6 @@ svn_error_t *svn_ra_local__init(const sv
svn_error_t *svn_ra_svn__init(const svn_version_t *loader_version,
const svn_ra__vtable_t **vtable,
apr_pool_t *pool);
-svn_error_t *svn_ra_neon__init(const svn_version_t *loader_version,
- const svn_ra__vtable_t **vtable,
- apr_pool_t *pool);
svn_error_t *svn_ra_serf__init(const svn_version_t *loader_version,
const svn_ra__vtable_t **vtable,
apr_pool_t *pool);
@@ -453,6 +472,29 @@ svn_ra__get_deleted_rev_from_log(svn_ra_
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+
+/* Utility function to provide a shim between a returned Ev2 and an RA
+ provider's Ev1-based commit editor.
+
+ See svn_ra__get_commit_ev2() for parameter semantics. */
+svn_error_t *
+svn_ra__use_commit_shim(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
#ifdef __cplusplus
}
#endif
Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_local/ra_plugin.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_local/ra_plugin.c Thu Aug 16 10:17:48 2012
@@ -76,8 +76,6 @@ get_username(svn_ra_session_t *session,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
- svn_auth_iterstate_t *iterstate;
- svn_fs_access_t *access_ctx;
/* If we've already found the username don't ask for it again. */
if (! sess->username)
@@ -88,6 +86,8 @@ get_username(svn_ra_session_t *session,
{
void *creds;
svn_auth_cred_username_t *username_creds;
+ svn_auth_iterstate_t *iterstate;
+
SVN_ERR(svn_auth_first_credentials(&creds, &iterstate,
SVN_AUTH_CRED_USERNAME,
sess->uuid, /* realmstring */
@@ -118,6 +118,8 @@ get_username(svn_ra_session_t *session,
*/
if (*sess->username)
{
+ svn_fs_access_t *access_ctx;
+
SVN_ERR(svn_fs_create_access(&access_ctx, sess->username,
session->pool));
SVN_ERR(svn_fs_set_access(sess->fs, access_ctx));
@@ -367,11 +369,12 @@ struct deltify_etc_baton
{
svn_fs_t *fs; /* the fs to deltify in */
svn_repos_t *repos; /* repos for unlocking */
- const char *fs_path; /* fs-path part of split session URL */
+ const char *fspath_base; /* fs-path part of split session URL */
+
apr_hash_t *lock_tokens; /* tokens to unlock, if any */
- apr_pool_t *pool; /* pool for scratch work */
- svn_commit_callback2_t callback; /* the original callback */
- void *callback_baton; /* the original callback's baton */
+
+ svn_commit_callback2_t commit_cb; /* the original callback */
+ void *commit_baton; /* the original callback's baton */
};
/* This implements 'svn_commit_callback_t'. Its invokes the original
@@ -380,60 +383,107 @@ struct deltify_etc_baton
BATON is 'struct deltify_etc_baton *'. */
static svn_error_t *
deltify_etc(const svn_commit_info_t *commit_info,
- void *baton, apr_pool_t *pool)
+ void *baton,
+ apr_pool_t *scratch_pool)
{
- struct deltify_etc_baton *db = baton;
+ struct deltify_etc_baton *deb = baton;
svn_error_t *err1 = SVN_NO_ERROR;
svn_error_t *err2;
- apr_hash_index_t *hi;
- apr_pool_t *iterpool;
/* Invoke the original callback first, in case someone's waiting to
know the revision number so they can go off and annotate an
issue or something. */
- if (db->callback)
- err1 = db->callback(commit_info, db->callback_baton, pool);
+ if (deb->commit_cb)
+ err1 = deb->commit_cb(commit_info, deb->commit_baton, scratch_pool);
/* Maybe unlock the paths. */
- if (db->lock_tokens)
+ if (deb->lock_tokens)
{
- iterpool = svn_pool_create(db->pool);
- for (hi = apr_hash_first(db->pool, db->lock_tokens); hi;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, deb->lock_tokens); hi;
hi = apr_hash_next(hi))
{
- const void *rel_path;
- void *val;
- const char *abs_path, *token;
+ const void *relpath = svn__apr_hash_index_key(hi);
+ const char *token = svn__apr_hash_index_val(hi);
+ const char *fspath;
svn_pool_clear(iterpool);
- apr_hash_this(hi, &rel_path, NULL, &val);
- token = val;
- abs_path = svn_fspath__join(db->fs_path, rel_path, iterpool);
+
+ fspath = svn_fspath__join(deb->fspath_base, relpath, iterpool);
+
/* We may get errors here if the lock was broken or stolen
after the commit succeeded. This is fine and should be
ignored. */
- svn_error_clear(svn_repos_fs_unlock(db->repos, abs_path, token,
+ svn_error_clear(svn_repos_fs_unlock(deb->repos, fspath, token,
FALSE, iterpool));
}
+
svn_pool_destroy(iterpool);
}
/* But, deltification shouldn't be stopped just because someone's
random callback failed, so proceed unconditionally on to
deltification. */
- err2 = svn_fs_deltify_revision(db->fs, commit_info->revision, db->pool);
+ err2 = svn_fs_deltify_revision(deb->fs, commit_info->revision, scratch_pool);
+
+ return svn_error_compose_create(err1, err2);
+}
+
- /* It's more interesting if the original callback failed, so let
- that one dominate. */
- if (err1)
+/* If LOCK_TOKENS is not NULL, then copy all tokens into the access context
+ of FS. The tokens' paths will be prepended with FSPATH_BASE.
+
+ ACCESS_POOL must match (or exceed) the lifetime of the access context
+ that was associated with FS. Typically, this is the session pool.
+
+ Temporary allocations are made in SCRATCH_POOL. */
+static svn_error_t *
+apply_lock_tokens(svn_fs_t *fs,
+ const char *fspath_base,
+ apr_hash_t *lock_tokens,
+ apr_pool_t *access_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (lock_tokens)
{
- svn_error_clear(err2);
- return err1;
+ svn_fs_access_t *access_ctx;
+
+ SVN_ERR(svn_fs_get_access(&access_ctx, fs));
+
+ /* If there is no access context, the filesystem will scream if a
+ lock is needed. */
+ if (access_ctx)
+ {
+ apr_hash_index_t *hi;
+
+ /* Note: we have no use for an iterpool here since the data
+ within the loop is copied into ACCESS_POOL. */
+
+ for (hi = apr_hash_first(scratch_pool, lock_tokens); hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *relpath = svn__apr_hash_index_key(hi);
+ const char *token = svn__apr_hash_index_val(hi);
+ const char *fspath;
+
+ /* The path needs to live as long as ACCESS_CTX. */
+ fspath = svn_fspath__join(fspath_base, relpath, access_pool);
+
+ /* The token must live as long as ACCESS_CTX. */
+ token = apr_pstrdup(access_pool, token);
+
+ SVN_ERR(svn_fs_access_add_lock_token2(access_ctx, fspath,
+ token));
+ }
+ }
}
- return err2;
+ return SVN_NO_ERROR;
}
+
/*----------------------------------------------------------------*/
/*** The RA vtable routines ***/
@@ -679,47 +729,24 @@ svn_ra_local__get_commit_editor(svn_ra_s
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
- struct deltify_etc_baton *db = apr_palloc(pool, sizeof(*db));
- apr_hash_index_t *hi;
- svn_fs_access_t *fs_access;
+ struct deltify_etc_baton *deb = apr_palloc(pool, sizeof(*deb));
- db->fs = sess->fs;
- db->repos = sess->repos;
- db->fs_path = sess->fs_path->data;
+ /* Prepare the baton for deltify_etc() */
+ deb->fs = sess->fs;
+ deb->repos = sess->repos;
+ deb->fspath_base = sess->fs_path->data;
if (! keep_locks)
- db->lock_tokens = lock_tokens;
+ deb->lock_tokens = lock_tokens;
else
- db->lock_tokens = NULL;
- db->pool = pool;
- db->callback = callback;
- db->callback_baton = callback_baton;
+ deb->lock_tokens = NULL;
+ deb->commit_cb = callback;
+ deb->commit_baton = callback_baton;
SVN_ERR(get_username(session, pool));
/* If there are lock tokens to add, do so. */
- if (lock_tokens)
- {
- SVN_ERR(svn_fs_get_access(&fs_access, sess->fs));
-
- /* If there is no access context, the filesystem will scream if a
- lock is needed. */
- if (fs_access)
- {
- for (hi = apr_hash_first(pool, lock_tokens); hi;
- hi = apr_hash_next(hi))
- {
- void *val;
- const char *abs_path, *token;
- const void *key;
-
- apr_hash_this(hi, &key, NULL, &val);
- abs_path = svn_fspath__join(sess->fs_path->data, key, pool);
- token = val;
- SVN_ERR(svn_fs_access_add_lock_token2(fs_access,
- abs_path, token));
- }
- }
- }
+ SVN_ERR(apply_lock_tokens(sess->fs, sess->fs_path->data, lock_tokens,
+ session->pool, pool));
/* Copy the revprops table so we can add the username. */
revprop_table = apr_hash_copy(pool, revprop_table);
@@ -730,7 +757,7 @@ svn_ra_local__get_commit_editor(svn_ra_s
return svn_repos_get_commit_editor5
(editor, edit_baton, sess->repos, NULL,
svn_path_uri_decode(sess->repos_url, pool), sess->fs_path->data,
- revprop_table, deltify_etc, db, NULL, NULL, pool);
+ revprop_table, deltify_etc, deb, NULL, NULL, pool);
}
@@ -1514,6 +1541,62 @@ svn_ra_local__register_editor_shim_callb
return SVN_NO_ERROR;
}
+
+static svn_error_t *
+svn_ra_local__get_commit_ev2(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprops,
+ svn_commit_callback2_t commit_cb,
+ void *commit_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_local__session_baton_t *sess = session->priv;
+ struct deltify_etc_baton *deb = apr_palloc(result_pool, sizeof(*deb));
+
+ /* NOTE: the RA callbacks are ignored. We pass everything directly to
+ the REPOS editor. */
+
+ /* Prepare the baton for deltify_etc() */
+ deb->fs = sess->fs;
+ deb->repos = sess->repos;
+ deb->fspath_base = sess->fs_path->data;
+ if (! keep_locks)
+ deb->lock_tokens = lock_tokens;
+ else
+ deb->lock_tokens = NULL;
+ deb->commit_cb = commit_cb;
+ deb->commit_baton = commit_baton;
+
+ /* Ensure there is a username (and an FS access context) associated with
+ the session and its FS handle. */
+ SVN_ERR(get_username(session, scratch_pool));
+
+ /* If there are lock tokens to add, do so. */
+ SVN_ERR(apply_lock_tokens(sess->fs, sess->fs_path->data, lock_tokens,
+ session->pool, scratch_pool));
+
+ /* Copy the REVPROPS and insert the author/username. */
+ revprops = apr_hash_copy(scratch_pool, revprops);
+ apr_hash_set(revprops, SVN_PROP_REVISION_AUTHOR, APR_HASH_KEY_STRING,
+ svn_string_create(sess->username, scratch_pool));
+
+ return svn_error_trace(svn_repos__get_commit_ev2(
+ editor, sess->repos, NULL /* authz */,
+ NULL /* authz_repos_name */, NULL /* authz_user */,
+ revprops,
+ deltify_etc, deb, cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+}
+
/*----------------------------------------------------------------*/
static const svn_version_t *
@@ -1561,7 +1644,8 @@ static const svn_ra__vtable_t ra_local_v
svn_ra_local__has_capability,
svn_ra_local__replay_range,
svn_ra_local__get_deleted_rev,
- svn_ra_local__register_editor_shim_callbacks
+ svn_ra_local__register_editor_shim_callbacks,
+ svn_ra_local__get_commit_ev2
};
Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/blame.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/blame.c Thu Aug 16 10:17:48 2012
@@ -22,9 +22,6 @@
*/
#include <apr_uri.h>
-
-#include <expat.h>
-
#include <serf.h>
#include "svn_pools.h"
@@ -49,7 +46,7 @@
* This enum represents the current state of our XML parsing for a REPORT.
*/
typedef enum blame_state_e {
- NONE = 0,
+ INITIAL = 0,
FILE_REVS_REPORT,
FILE_REV,
REV_PROP,
@@ -59,40 +56,6 @@ typedef enum blame_state_e {
TXDELTA
} blame_state_e;
-typedef struct blame_info_t {
- /* Current pool. */
- apr_pool_t *pool;
-
- /* our suspicious file */
- const char *path;
-
- /* the intended suspect */
- svn_revnum_t rev;
-
- /* Hashtable of revision properties */
- apr_hash_t *rev_props;
-
- /* Added and removed properties (svn_prop_t*'s) */
- apr_array_header_t *prop_diffs;
-
- /* txdelta */
- svn_txdelta_window_handler_t txdelta;
- void *txdelta_baton;
-
- /* returned txdelta stream */
- svn_stream_t *stream;
-
- /* Is this property base64-encoded? */
- svn_boolean_t prop_base64;
-
- /* The currently collected value as we build it up */
- const char *prop_name;
- svn_stringbuf_t *prop_value;
-
- /* Merged revision flag */
- svn_boolean_t merged_revision;
-
-} blame_info_t;
typedef struct blame_context_t {
/* pool passed to get_file_revs */
@@ -104,272 +67,213 @@ typedef struct blame_context_t {
svn_revnum_t end;
svn_boolean_t include_merged_revisions;
- /* are we done? */
- svn_boolean_t done;
-
/* blame handler and baton */
svn_file_rev_handler_t file_rev;
void *file_rev_baton;
+
+ /* As we parse each FILE_REV, we collect data in these variables:
+ property changes and new content. STREAM is valid when we're
+ in the TXDELTA state, processing the incoming cdata. */
+ apr_hash_t *rev_props;
+ apr_array_header_t *prop_diffs;
+ apr_pool_t *state_pool; /* put property stuff in here */
+
+ svn_stream_t *stream;
+
} blame_context_t;
-
-static blame_info_t *
-push_state(svn_ra_serf__xml_parser_t *parser,
- blame_context_t *blame_ctx,
- blame_state_e state)
-{
- svn_ra_serf__xml_push_state(parser, state);
- if (state == FILE_REV)
- {
- blame_info_t *info;
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t blame_ttable[] = {
+ { INITIAL, S_, "file-revs-report", FILE_REVS_REPORT,
+ FALSE, { NULL }, FALSE },
- info = apr_pcalloc(parser->state->pool, sizeof(*info));
+ { FILE_REVS_REPORT, S_, "file-rev", FILE_REV,
+ FALSE, { "path", "rev", NULL }, TRUE },
- info->pool = parser->state->pool;
+ { FILE_REV, S_, "rev-prop", REV_PROP,
+ TRUE, { "name", "?encoding", NULL }, TRUE },
- info->rev = SVN_INVALID_REVNUM;
+ { FILE_REV, S_, "set-prop", SET_PROP,
+ TRUE, { "name", "?encoding", NULL }, TRUE },
- info->rev_props = apr_hash_make(info->pool);
- info->prop_diffs = apr_array_make(info->pool, 0, sizeof(svn_prop_t));
+ { FILE_REV, S_, "remove-prop", REMOVE_PROP,
+ FALSE, { "name", NULL }, TRUE },
- info->prop_value = svn_stringbuf_create_empty(info->pool);
+ { FILE_REV, S_, "merged-revision", MERGED_REVISION,
+ FALSE, { NULL }, TRUE },
- parser->state->private = info;
- }
+ { FILE_REV, S_, "txdelta", TXDELTA,
+ FALSE, { NULL }, TRUE },
- return parser->state->private;
-}
+ { 0 }
+};
-static const svn_string_t *
-create_propval(blame_info_t *info)
+/* Conforms to svn_ra_serf__xml_opened_t */
+static svn_error_t *
+blame_opened(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int entered_state,
+ const svn_ra_serf__dav_props_t *tag,
+ apr_pool_t *scratch_pool)
{
- if (info->prop_base64)
+ blame_context_t *blame_ctx = baton;
+
+ if (entered_state == FILE_REV)
{
- const svn_string_t *morph;
+ apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes);
- morph = svn_stringbuf__morph_into_string(info->prop_value);
-#ifdef SVN_DEBUG
- info->prop_value = NULL; /* morph killed the stringbuf. */
-#endif
- return svn_base64_decode_string(morph, info->pool);
+ /* Child elements will store properties in these structures. */
+ blame_ctx->rev_props = apr_hash_make(state_pool);
+ blame_ctx->prop_diffs = apr_array_make(state_pool,
+ 5, sizeof(svn_prop_t));
+ blame_ctx->state_pool = state_pool;
+
+ /* Clear this, so we can detect the absence of a TXDELTA. */
+ blame_ctx->stream = NULL;
+ }
+ else if (entered_state == TXDELTA)
+ {
+ apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes);
+ apr_hash_t *gathered = svn_ra_serf__xml_gather_since(xes, FILE_REV);
+ const char *path;
+ const char *rev;
+ const char *merged_revision;
+ svn_txdelta_window_handler_t txdelta;
+ void *txdelta_baton;
+
+ path = apr_hash_get(gathered, "path", APR_HASH_KEY_STRING);
+ rev = apr_hash_get(gathered, "rev", APR_HASH_KEY_STRING);
+ merged_revision = apr_hash_get(gathered,
+ "merged-revision", APR_HASH_KEY_STRING);
+
+ SVN_ERR(blame_ctx->file_rev(blame_ctx->file_rev_baton,
+ path, SVN_STR_TO_REV(rev),
+ blame_ctx->rev_props,
+ merged_revision != NULL,
+ &txdelta, &txdelta_baton,
+ blame_ctx->prop_diffs,
+ state_pool));
+
+ blame_ctx->stream = svn_base64_decode(svn_txdelta_parse_svndiff(
+ txdelta, txdelta_baton,
+ TRUE /* error_on_early_close */,
+ state_pool),
+ state_pool);
}
- return svn_string_create_from_buf(info->prop_value, info->pool);
+ return SVN_NO_ERROR;
}
+
+/* Conforms to svn_ra_serf__xml_closed_t */
static svn_error_t *
-start_blame(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- const char **attrs,
- apr_pool_t *scratch_pool)
+blame_closed(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int leaving_state,
+ const svn_string_t *cdata,
+ apr_hash_t *attrs,
+ apr_pool_t *scratch_pool)
{
- blame_context_t *blame_ctx = parser->user_data;
- blame_state_e state;
+ blame_context_t *blame_ctx = baton;
- state = parser->state->current_state;
+ if (leaving_state == FILE_REV)
+ {
+ /* Note that we test STREAM, but any pointer is currently invalid.
+ It was closed when left the TXDELTA state. */
+ if (blame_ctx->stream == NULL)
+ {
+ const char *path;
+ const char *rev;
+
+ path = apr_hash_get(attrs, "path", APR_HASH_KEY_STRING);
+ rev = apr_hash_get(attrs, "rev", APR_HASH_KEY_STRING);
- if (state == NONE && strcmp(name.name, "file-revs-report") == 0)
+ /* Send a "no content" notification. */
+ SVN_ERR(blame_ctx->file_rev(blame_ctx->file_rev_baton,
+ path, SVN_STR_TO_REV(rev),
+ blame_ctx->rev_props,
+ FALSE /* result_of_merge */,
+ NULL, NULL, /* txdelta / baton */
+ blame_ctx->prop_diffs,
+ scratch_pool));
+ }
+ }
+ else if (leaving_state == MERGED_REVISION)
{
- push_state(parser, blame_ctx, FILE_REVS_REPORT);
+ svn_ra_serf__xml_note(xes, FILE_REV, "merged-revision", "*");
}
- else if (state == FILE_REVS_REPORT &&
- strcmp(name.name, "file-rev") == 0)
+ else if (leaving_state == TXDELTA)
{
- blame_info_t *info;
-
- info = push_state(parser, blame_ctx, FILE_REV);
-
- info->path = apr_pstrdup(info->pool,
- svn_xml_get_attr_value("path", attrs));
- info->rev = SVN_STR_TO_REV(svn_xml_get_attr_value("rev", attrs));
+ SVN_ERR(svn_stream_close(blame_ctx->stream));
}
- else if (state == FILE_REV)
+ else
{
- blame_info_t *info;
- const char *enc;
+ const char *name;
+ const svn_string_t *value;
- info = parser->state->private;
+ SVN_ERR_ASSERT(leaving_state == REV_PROP
+ || leaving_state == SET_PROP
+ || leaving_state == REMOVE_PROP);
- if (strcmp(name.name, "rev-prop") == 0)
- {
- push_state(parser, blame_ctx, REV_PROP);
- }
- else if (strcmp(name.name, "set-prop") == 0)
- {
- push_state(parser, blame_ctx, SET_PROP);
- }
- if (strcmp(name.name, "remove-prop") == 0)
- {
- push_state(parser, blame_ctx, REMOVE_PROP);
- }
- else if (strcmp(name.name, "merged-revision") == 0)
+ name = apr_pstrdup(blame_ctx->state_pool,
+ apr_hash_get(attrs, "name", APR_HASH_KEY_STRING));
+
+ if (leaving_state == REMOVE_PROP)
{
- push_state(parser, blame_ctx, MERGED_REVISION);
+ value = NULL;
}
- else if (strcmp(name.name, "txdelta") == 0)
+ else
{
- SVN_ERR(blame_ctx->file_rev(blame_ctx->file_rev_baton,
- info->path, info->rev,
- info->rev_props, info->merged_revision,
- &info->txdelta, &info->txdelta_baton,
- info->prop_diffs, info->pool));
-
- info->stream = svn_base64_decode
- (svn_txdelta_parse_svndiff(info->txdelta, info->txdelta_baton,
- TRUE, info->pool), info->pool);
-
- push_state(parser, blame_ctx, TXDELTA);
- }
+ const char *encoding = apr_hash_get(attrs,
+ "encoding", APR_HASH_KEY_STRING);
- state = parser->state->current_state;
-
- switch (state)
- {
- case REV_PROP:
- case SET_PROP:
- case REMOVE_PROP:
- info->prop_name = apr_pstrdup(info->pool,
- svn_xml_get_attr_value("name", attrs));
- svn_stringbuf_setempty(info->prop_value);
-
- enc = svn_xml_get_attr_value("encoding", attrs);
- if (enc && strcmp(enc, "base64") == 0)
- {
- info->prop_base64 = TRUE;
- }
+ if (encoding && strcmp(encoding, "base64") == 0)
+ value = svn_base64_decode_string(cdata, blame_ctx->state_pool);
else
- {
- info->prop_base64 = FALSE;
- }
- break;
- case MERGED_REVISION:
- info->merged_revision = TRUE;
- break;
- default:
- break;
+ value = svn_string_dup(cdata, blame_ctx->state_pool);
}
- }
-
- return SVN_NO_ERROR;
-}
-static svn_error_t *
-end_blame(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- apr_pool_t *scratch_pool)
-{
- blame_context_t *blame_ctx = parser->user_data;
- blame_state_e state;
- blame_info_t *info;
-
- state = parser->state->current_state;
- info = parser->state->private;
-
- if (state == NONE)
- {
- return SVN_NO_ERROR;
- }
-
- if (state == FILE_REVS_REPORT &&
- strcmp(name.name, "file-revs-report") == 0)
- {
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == FILE_REV &&
- strcmp(name.name, "file-rev") == 0)
- {
- /* no file changes. */
- if (!info->stream)
+ if (leaving_state == REV_PROP)
{
- SVN_ERR(blame_ctx->file_rev(blame_ctx->file_rev_baton,
- info->path, info->rev,
- info->rev_props, FALSE,
- NULL, NULL,
- info->prop_diffs, info->pool));
+ apr_hash_set(blame_ctx->rev_props, name, APR_HASH_KEY_STRING, value);
}
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == REV_PROP &&
- strcmp(name.name, "rev-prop") == 0)
- {
- apr_hash_set(info->rev_props,
- info->prop_name, APR_HASH_KEY_STRING,
- create_propval(info));
-
- svn_ra_serf__xml_pop_state(parser);
- }
- else if ((state == SET_PROP &&
- strcmp(name.name, "set-prop") == 0) ||
- (state == REMOVE_PROP &&
- strcmp(name.name, "remove-prop") == 0))
- {
- svn_prop_t *prop = apr_array_push(info->prop_diffs);
- prop->name = info->prop_name;
- prop->value = create_propval(info);
-
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == MERGED_REVISION &&
- strcmp(name.name, "merged-revision") == 0)
- {
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == TXDELTA &&
- strcmp(name.name, "txdelta") == 0)
- {
- SVN_ERR(svn_stream_close(info->stream));
+ else
+ {
+ svn_prop_t *prop = apr_array_push(blame_ctx->prop_diffs);
- svn_ra_serf__xml_pop_state(parser);
+ prop->name = name;
+ prop->value = value;
+ }
}
return SVN_NO_ERROR;
}
+
+/* Conforms to svn_ra_serf__xml_cdata_t */
static svn_error_t *
-cdata_blame(svn_ra_serf__xml_parser_t *parser,
+blame_cdata(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int current_state,
const char *data,
apr_size_t len,
apr_pool_t *scratch_pool)
{
- blame_context_t *blame_ctx = parser->user_data;
- blame_state_e state;
- blame_info_t *info;
-
- UNUSED_CTX(blame_ctx);
-
- state = parser->state->current_state;
- info = parser->state->private;
-
- if (state == NONE)
- {
- return SVN_NO_ERROR;
- }
+ blame_context_t *blame_ctx = baton;
- switch (state)
+ if (current_state == TXDELTA)
{
- case REV_PROP:
- case SET_PROP:
- svn_stringbuf_appendbytes(info->prop_value, data, len);
- break;
- case TXDELTA:
- if (info->stream)
- {
- apr_size_t ret_len;
-
- ret_len = len;
-
- SVN_ERR(svn_stream_write(info->stream, data, &ret_len));
- }
- break;
- default:
- break;
+ SVN_ERR(svn_stream_write(blame_ctx->stream, data, &len));
+ /* Ignore the returned LEN value. */
}
return SVN_NO_ERROR;
}
+
/* Implements svn_ra_serf__request_body_delegate_t */
static svn_error_t *
create_file_revs_body(serf_bucket_t **body_bkt,
@@ -426,9 +330,8 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
blame_context_t *blame_ctx;
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
- svn_ra_serf__xml_parser_t *parser_ctx;
- const char *relative_url, *basecoll_url, *req_url;
- int status_code;
+ svn_ra_serf__xml_context_t *xmlctx;
+ const char *req_url;
svn_error_t *err;
blame_ctx = apr_pcalloc(pool, sizeof(*blame_ctx));
@@ -439,14 +342,19 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
blame_ctx->start = start;
blame_ctx->end = end;
blame_ctx->include_merged_revisions = include_merged_revisions;
- blame_ctx->done = FALSE;
-
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
- NULL, session->session_url.path,
- end, NULL, pool));
- req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
- handler = apr_pcalloc(pool, sizeof(*handler));
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ NULL /* url */, end,
+ pool, pool));
+
+ xmlctx = svn_ra_serf__xml_context_create(blame_ttable,
+ blame_opened,
+ blame_closed,
+ blame_cdata,
+ blame_ctx,
+ pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
handler->method = "REPORT";
handler->path = req_url;
@@ -456,27 +364,12 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
handler->conn = session->conns[0];
handler->session = session;
- parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
- parser_ctx->pool = pool;
- parser_ctx->user_data = blame_ctx;
- parser_ctx->start = start_blame;
- parser_ctx->end = end_blame;
- parser_ctx->cdata = cdata_blame;
- parser_ctx->done = &blame_ctx->done;
- parser_ctx->status_code = &status_code;
-
- handler->response_handler = svn_ra_serf__handle_xml_parser;
- handler->response_baton = parser_ctx;
-
- svn_ra_serf__request_create(handler);
-
- err = svn_ra_serf__context_run_wait(&blame_ctx->done, session, pool);
+ err = svn_ra_serf__context_run_one(handler, pool);
err = svn_error_compose_create(
- svn_ra_serf__error_on_status(status_code,
+ svn_ra_serf__error_on_status(handler->sline.code,
handler->path,
- parser_ctx->location),
+ handler->location),
err);
return svn_error_trace(err);