You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/12/02 21:55:18 UTC
svn commit: r1041580 [7/35] - in
/subversion/branches/gpg-agent-password-store: ./ build/ build/ac-macros/
build/generator/ build/generator/templates/ build/win32/
contrib/hook-scripts/ contrib/server-side/ notes/http-and-webdav/
notes/wc-ng/ subversio...
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.c Thu Dec 2 20:55:08 2010
@@ -486,7 +486,7 @@ parent_path_path(parent_path_t *parent_p
if (parent_path->parent)
path_so_far = parent_path_path(parent_path->parent, pool);
return parent_path->entry
- ? svn_uri_join(path_so_far, parent_path->entry, pool)
+ ? svn_fspath__join(path_so_far, parent_path->entry, pool)
: path_so_far;
}
@@ -693,7 +693,7 @@ open_path(parent_path_t **parent_path_p,
entry = svn_fs__next_entry_name(&next, rest, pool);
/* Calculate the path traversed thus far. */
- path_so_far = svn_uri_join(path_so_far, entry, pool);
+ path_so_far = svn_fspath__join(path_so_far, entry, pool);
if (*entry == '\0')
{
@@ -1727,7 +1727,7 @@ deltify_mutable(svn_fs_t *fs,
apr_hash_this(hi, &key, NULL, &val);
entry = val;
SVN_ERR(deltify_mutable(fs, root,
- svn_uri_join(path, key, subpool),
+ svn_fspath__join(path, key, subpool),
entry->id, entry->kind, txn_id, subpool));
}
@@ -2271,7 +2271,7 @@ merge(svn_stringbuf_t *conflict_p,
a modification. In any of these cases, flag a conflict. */
if (s_entry == NULL || t_entry == NULL)
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
a_entry->name,
iterpool));
@@ -2286,7 +2286,7 @@ merge(svn_stringbuf_t *conflict_p,
|| strcmp(svn_fs_base__id_copy_id(t_entry->id),
svn_fs_base__id_copy_id(a_entry->id)) != 0)
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
a_entry->name,
iterpool));
@@ -2303,14 +2303,14 @@ merge(svn_stringbuf_t *conflict_p,
|| (svn_fs_base__dag_node_kind(t_ent_node) == svn_node_file)
|| (svn_fs_base__dag_node_kind(a_ent_node) == svn_node_file))
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
a_entry->name,
iterpool));
/* Direct modifications were made to the directory
ANCESTOR-ENTRY in both SOURCE and TARGET. Recursively
merge these modifications. */
- new_tpath = svn_uri_join(target_path, t_entry->name, iterpool);
+ new_tpath = svn_fspath__join(target_path, t_entry->name, iterpool);
SVN_ERR(merge(conflict_p, new_tpath,
t_ent_node, s_ent_node, a_ent_node,
txn_id, &sub_mergeinfo_increment, trail, iterpool));
@@ -2346,7 +2346,7 @@ merge(svn_stringbuf_t *conflict_p,
/* If NAME exists in TARGET, declare a conflict. */
if (t_entry)
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
t_entry->name,
iterpool));
@@ -2522,7 +2522,7 @@ verify_locks(const char *txn_name,
/* If this path has already been verified as part of a recursive
check of one of its parents, no need to do it again. */
if (last_recursed
- && svn_uri_is_child(last_recursed->data, path, subpool))
+ && svn_fspath__is_child(last_recursed->data, path, subpool))
continue;
/* Fetch the change associated with our path. */
@@ -4488,7 +4488,7 @@ txn_body_history_prev(void *baton, trail
if (strcmp(path, copy_dst) == 0)
remainder = "";
else
- remainder = svn_uri_is_child(copy_dst, path, trail->pool);
+ remainder = svn_fspath__is_child(copy_dst, path, trail->pool);
if (remainder)
{
@@ -4501,7 +4501,7 @@ txn_body_history_prev(void *baton, trail
(&dst_rev, fs,
svn_fs_base__id_txn_id(copy->dst_noderev_id),
trail, trail->pool));
- src_path = svn_uri_join(copy->src_path, remainder,
+ src_path = svn_fspath__join(copy->src_path, remainder,
trail->pool);
if (copy->kind == copy_kind_soft)
retry = TRUE;
@@ -4911,8 +4911,8 @@ prev_location(const char **prev_path,
SVN_ERR(base_copied_from(©_src_rev, ©_src_path,
copy_root, copy_path, pool));
if (! strcmp(copy_path, path) == 0)
- remainder = svn_uri_is_child(copy_path, path, pool);
- *prev_path = svn_uri_join(copy_src_path, remainder, pool);
+ remainder = svn_fspath__is_child(copy_path, path, pool);
+ *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
*prev_rev = copy_src_rev;
return SVN_NO_ERROR;
}
@@ -5090,6 +5090,129 @@ base_node_origin_rev(svn_revnum_t *revis
/* Mergeinfo Queries */
+
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_base__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_mergeinfo_t filtered_mergeinfo;
+ apr_hash_t *rev_to_sources;
+ apr_hash_index_t *hi;
+ apr_pool_t *iterpool;
+
+ /* A couple easy outs. */
+ if (mergeinfo == NULL)
+ {
+ *validated_mergeinfo = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (apr_hash_count(mergeinfo) == 0)
+ {
+ *validated_mergeinfo = apr_hash_make(result_pool);
+ return SVN_NO_ERROR;
+ }
+
+ filtered_mergeinfo = apr_hash_make(scratch_pool);
+ rev_to_sources = apr_hash_make(scratch_pool);
+
+ /* Since svn_fs_check_path needs an svn_fs_root_t based on a revision,
+ we convert MERGEINFO into a mapping of revisions to a hash of source
+ paths for efficiency. */
+ for (hi = apr_hash_first(scratch_pool, mergeinfo);
+ 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);
+ int i;
+
+ for (i = 0; i < rangelist->nelts; i++)
+ {
+ svn_merge_range_t *range =
+ APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+ svn_revnum_t j;
+
+ for (j = range->start + 1; j <= range->end; j++)
+ {
+ apr_hash_t *paths_for_rev =
+ apr_hash_get(rev_to_sources, &j, sizeof(svn_revnum_t));
+
+ /* No hash associated with this rev yet? */
+ if (!paths_for_rev)
+ {
+ svn_revnum_t *rev = apr_palloc(scratch_pool, sizeof(*rev));
+
+ *rev = j;
+ paths_for_rev = apr_hash_make(scratch_pool);
+ apr_hash_set(rev_to_sources, rev,
+ sizeof(svn_revnum_t), paths_for_rev);
+ }
+
+ apr_hash_set(paths_for_rev, path, APR_HASH_KEY_STRING, path);
+ }
+ }
+ }
+
+ iterpool = svn_pool_create(scratch_pool);
+
+ /* Validate the rev->source MERGEINFO equivalent hash, building the
+ validated mergeinfo as we go. */
+ for (hi = apr_hash_first(scratch_pool, rev_to_sources);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
+ apr_hash_t *paths = svn__apr_hash_index_val(hi);
+ apr_pool_t *inner_iterpool;
+ apr_hash_index_t *hi2;
+ svn_node_kind_t kind;
+ svn_fs_root_t *mergeinfo_rev_root;
+
+ svn_pool_clear(iterpool);
+ inner_iterpool = svn_pool_create(iterpool);
+
+ SVN_ERR(svn_fs_base__revision_root(&mergeinfo_rev_root, fs,
+ *rev, iterpool));
+
+ for (hi2 = apr_hash_first(iterpool, paths);
+ hi2;
+ hi2 = apr_hash_next(hi2))
+ {
+ const char *path = svn__apr_hash_index_key(hi2);
+
+ svn_pool_clear(inner_iterpool);
+ SVN_ERR(base_check_path(&kind, mergeinfo_rev_root,
+ path, inner_iterpool));
+ if (kind == svn_node_none)
+ {
+ apr_hash_set(paths, path, APR_HASH_KEY_STRING, NULL);
+ }
+ else
+ {
+ svn_mergeinfo_t good_mergeinfo_fragment;
+ const char *mergeinfo_str =
+ apr_psprintf(inner_iterpool, "%s:%ld", path, *rev);
+
+ SVN_ERR(svn_mergeinfo_parse(&good_mergeinfo_fragment,
+ mergeinfo_str, scratch_pool));
+ SVN_ERR(svn_mergeinfo_merge(filtered_mergeinfo,
+ good_mergeinfo_fragment,
+ scratch_pool));
+ }
+ }
+ svn_pool_destroy(inner_iterpool);
+ }
+
+ svn_pool_destroy(iterpool);
+ *validated_mergeinfo = svn_mergeinfo_dup(filtered_mergeinfo, result_pool);
+ return SVN_NO_ERROR;
+}
+
+
/* Examine directory NODE's immediately children for mergeinfo.
For those which have explicit mergeinfo, add their mergeinfo to
@@ -5173,7 +5296,7 @@ txn_body_get_mergeinfo_data_and_entries(
SVN_ERR(svn_mergeinfo_parse(&child_mergeinfo, pval->data,
result_pool));
apr_hash_set(args->result_catalog,
- svn_uri_join(args->node_path, dirent->name,
+ svn_fspath__join(args->node_path, dirent->name,
result_pool),
APR_HASH_KEY_STRING,
child_mergeinfo);
@@ -5243,7 +5366,7 @@ crawl_directory_for_mergeinfo(svn_fs_t *
svn_pool_clear(iterpool);
apr_hash_this(hi, &key, NULL, &val);
crawl_directory_for_mergeinfo(fs, val,
- svn_uri_join(node_path, key, iterpool),
+ svn_fspath__join(node_path, key, iterpool),
result_catalog, iterpool);
}
svn_pool_destroy(iterpool);
@@ -5269,7 +5392,7 @@ append_to_merged_froms(svn_mergeinfo_t *
const void *key;
void *val;
apr_hash_this(hi, &key, NULL, &val);
- apr_hash_set(*output, svn_uri_join(key, rel_path, pool),
+ apr_hash_set(*output, svn_fspath__join(key, rel_path, pool),
APR_HASH_KEY_STRING, svn_rangelist_dup(val, pool));
}
return SVN_NO_ERROR;
@@ -5278,12 +5401,14 @@ append_to_merged_froms(svn_mergeinfo_t *
/* Calculate the mergeinfo for PATH under revision ROOT using
inheritance type INHERIT. Set *MERGEINFO to the mergeinfo, or to
- NULL if there is none. Results are allocated in POOL; TRAIL->pool
+ NULL if there is none. If *MERGEINFO is inherited set *INHERITED
+ to true, false otherwise. Results are allocated in POOL; TRAIL->POOL
is used for temporary allocations. */
struct get_mergeinfo_for_path_baton
{
svn_mergeinfo_t *mergeinfo;
+ svn_boolean_t *inherited;
svn_fs_root_t *root;
const char *path;
svn_mergeinfo_inheritance_t inherit;
@@ -5301,6 +5426,7 @@ txn_body_get_mergeinfo_for_path(void *ba
dag_node_t *node = NULL;
*(args->mergeinfo) = NULL;
+ *(args->inherited) = FALSE;
SVN_ERR(open_path(&parent_path, args->root, args->path, 0,
NULL, trail, trail->pool));
@@ -5382,6 +5508,7 @@ txn_body_get_mergeinfo_for_path(void *ba
nearest_ancestor,
trail->pool),
args->pool));
+ *(args->inherited) = TRUE;
}
return SVN_NO_ERROR;
}
@@ -5413,14 +5540,17 @@ txn_body_get_node_mergeinfo_stats(void *
}
-/* Get the mergeinfo for a set of paths, returned in
- *MERGEINFO_CATALOG. Returned values are allocated in POOL, while
- temporary values are allocated in a sub-pool. */
+/* Get the mergeinfo for a set of paths, returned in *MERGEINFO_CATALOG.
+ If the mergeinfo for any path is inherited and VALIDATE_INHERITED_MERGEINFO
+ is true, then the mergeinfo for that path in *MERGEINFO_CATALOG will only
+ contain path-revs that actually exist in repository. Returned values are
+ allocated in POOL, while temporary values are allocated in a sub-pool. */
static svn_error_t *
get_mergeinfos_for_paths(svn_fs_root_t *root,
svn_mergeinfo_catalog_t *mergeinfo_catalog,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -5431,6 +5561,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *
for (i = 0; i < paths->nelts; i++)
{
svn_mergeinfo_t path_mergeinfo;
+ svn_boolean_t inherited;
struct get_mergeinfo_for_path_baton gmfp_args;
const char *path = APR_ARRAY_IDX(paths, i, const char *);
@@ -5440,6 +5571,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *
/* Get the mergeinfo for PATH itself. */
gmfp_args.mergeinfo = &path_mergeinfo;
+ gmfp_args.inherited = &inherited;
gmfp_args.root = root;
gmfp_args.path = path;
gmfp_args.inherit = inherit;
@@ -5448,9 +5580,16 @@ get_mergeinfos_for_paths(svn_fs_root_t *
txn_body_get_mergeinfo_for_path,
&gmfp_args, FALSE, iterpool));
if (path_mergeinfo)
- apr_hash_set(result_catalog, apr_pstrdup(pool, path),
- APR_HASH_KEY_STRING,
- path_mergeinfo);
+ {
+ if (inherited && validate_inherited_mergeinfo)
+ SVN_ERR(svn_fs_base__validate_mergeinfo(&path_mergeinfo, root->fs,
+ path_mergeinfo, pool,
+ iterpool));
+
+ apr_hash_set(result_catalog, apr_pstrdup(pool, path),
+ APR_HASH_KEY_STRING,
+ path_mergeinfo);
+ }
/* If we're including descendants, do so. */
if (include_descendants)
@@ -5493,6 +5632,7 @@ base_get_mergeinfo(svn_mergeinfo_catalog
svn_fs_root_t *root,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -5506,10 +5646,11 @@ base_get_mergeinfo(svn_mergeinfo_catalog
/* Retrieve a path -> mergeinfo mapping. */
return get_mergeinfos_for_paths(root, catalog, paths,
- inherit, include_descendants,
- pool);
+ inherit, validate_inherited_mergeinfo,
+ include_descendants, pool);
}
+
/* Creating root objects. */
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/tree.h Thu Dec 2 20:55:08 2010
@@ -95,6 +95,14 @@ svn_error_t *svn_fs_base__get_path_creat
trail_t *trail,
apr_pool_t *pool);
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_base__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* ### Experimental obliterate-like-deltify - see implementation. */
svn_error_t *
svn_fs_base__obliterate_rep(svn_fs_t *fs,
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/caching.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/caching.c Thu Dec 2 20:55:08 2010
@@ -119,7 +119,7 @@ manifest_serialize(char **data,
{
apr_array_header_t *manifest = in;
- *data_len = sizeof(apr_off_t) *manifest->nelts;
+ *data_len = sizeof(apr_off_t) * manifest->nelts;
*data = apr_palloc(pool, *data_len);
memcpy(*data, manifest->elts, *data_len);
@@ -134,10 +134,10 @@ manifest_deserialize(void **out,
apr_pool_t *pool)
{
apr_array_header_t *manifest = apr_array_make(pool,
- data_len / sizeof(apr_off_t),
- sizeof(apr_off_t));
+ (int) (data_len / sizeof(apr_off_t)),
+ sizeof(apr_off_t));
memcpy(manifest->elts, data, data_len);
- manifest->nelts = data_len / sizeof(apr_off_t);
+ manifest->nelts = (int) (data_len / sizeof(apr_off_t));
*out = manifest;
return SVN_NO_ERROR;
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/dag.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/dag.c Thu Dec 2 20:55:08 2010
@@ -29,7 +29,6 @@
#include "svn_pools.h"
#include "dag.h"
-#include "err.h"
#include "fs.h"
#include "key-gen.h"
#include "fs_fs.h"
@@ -395,7 +394,7 @@ make_entry(dag_node_t **child_p,
/* Create the new node's NODE-REVISION */
memset(&new_noderev, 0, sizeof(new_noderev));
new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
- new_noderev.created_path = svn_uri_join(parent_path, name, pool);
+ new_noderev.created_path = svn_fspath__join(parent_path, name, pool);
SVN_ERR(get_node_revision(&parent_noderev, parent, pool));
new_noderev.copyroot_path = apr_pstrdup(pool,
@@ -688,7 +687,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **
noderev->predecessor_id = svn_fs_fs__id_copy(cur_entry->id, pool);
if (noderev->predecessor_count != -1)
noderev->predecessor_count++;
- noderev->created_path = svn_uri_join(parent_path, name, pool);
+ noderev->created_path = svn_fspath__join(parent_path, name, pool);
SVN_ERR(svn_fs_fs__create_successor(&new_node_id, fs, cur_entry->id,
noderev, copy_id, txn_id, pool));
@@ -1257,7 +1256,7 @@ svn_fs_fs__dag_copy(dag_node_t *to_node,
if (to_noderev->predecessor_count != -1)
to_noderev->predecessor_count++;
to_noderev->created_path =
- svn_uri_join(svn_fs_fs__dag_get_created_path(to_node), entry,
+ svn_fspath__join(svn_fs_fs__dag_get_created_path(to_node), entry,
pool);
to_noderev->copyfrom_path = apr_pstrdup(pool, from_path);
to_noderev->copyfrom_rev = from_rev;
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.c Thu Dec 2 20:55:08 2010
@@ -34,7 +34,6 @@
#include "svn_version.h"
#include "svn_pools.h"
#include "fs.h"
-#include "err.h"
#include "fs_fs.h"
#include "tree.h"
#include "lock.h"
@@ -160,7 +159,8 @@ static fs_vtable_t fs_vtable = {
svn_fs_fs__unlock,
svn_fs_fs__get_lock,
svn_fs_fs__get_locks,
- fs_set_errcall
+ fs_set_errcall,
+ svn_fs_fs__validate_mergeinfo,
};
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs.h Thu Dec 2 20:55:08 2010
@@ -132,7 +132,6 @@ extern "C" {
relate to a particular transaction in a filesystem (as identified
by transaction id and filesystem UUID). Objects of this type are
allocated in their own subpool of the common pool. */
-struct fs_fs_shared_txn_data_t;
typedef struct fs_fs_shared_txn_data_t
{
/* The next transaction in the list, or NULL if there is no following
@@ -171,7 +170,7 @@ typedef struct fs_fs_shared_txn_data_t
/* Private FSFS-specific data shared between all svn_fs_t objects that
relate to a particular filesystem, as identified by filesystem UUID.
Objects of this type are allocated in the common pool. */
-typedef struct
+typedef struct fs_fs_shared_data_t
{
/* A list of shared transaction objects for each transaction that is
currently active, or NULL if none are. All access to this list,
@@ -203,7 +202,7 @@ typedef struct
} fs_fs_shared_data_t;
/* Private (non-shared) FSFS-specific data for each svn_fs_t object. */
-typedef struct
+typedef struct fs_fs_data_t
{
/* The format number of this FS. */
int format;
@@ -268,7 +267,7 @@ typedef struct
/*** Filesystem Transaction ***/
-typedef struct
+typedef struct transaction_t
{
/* property list (const char * name, svn_string_t * value).
may be NULL if there are no properties. */
@@ -291,7 +290,7 @@ typedef struct
/*** Representation ***/
/* If you add fields to this, check to see if you need to change
* svn_fs_fs__rep_copy. */
-typedef struct
+typedef struct representation_t
{
/* Checksums for the contents produced by this representation.
This checksum is for the contents the rep shows to consumers,
@@ -338,7 +337,7 @@ typedef struct
/*** Node-Revision ***/
/* If you add fields to this, check to see if you need to change
* copy_node_revision in dag.c. */
-typedef struct
+typedef struct node_revision_t
{
/* node kind */
svn_node_kind_t kind;
@@ -388,7 +387,7 @@ typedef struct
/*** Change ***/
-typedef struct
+typedef struct change_t
{
/* Path of the change. */
const char *path;
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c Thu Dec 2 20:55:08 2010
@@ -51,7 +51,6 @@
#include "svn_ctype.h"
#include "fs.h"
-#include "err.h"
#include "tree.h"
#include "lock.h"
#include "key-gen.h"
@@ -1214,6 +1213,28 @@ update_min_unpacked_revprop(svn_fs_t *fs
pool);
}
+/* Create a new SQLite database for storing the revprops in filesystem FS.
+ * Leave the DB open and set *SDB to its handle. Also create the "min
+ * unpacked revprop" file. */
+static svn_error_t *
+create_packed_revprops_db(svn_sqlite__db_t **sdb,
+ svn_fs_t *fs,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(svn_io_file_create(path_min_unpacked_revprop(fs, scratch_pool),
+ "0\n", scratch_pool));
+ SVN_ERR(svn_sqlite__open(sdb,
+ svn_dirent_join_many(scratch_pool, fs->path,
+ PATH_REVPROPS_DIR,
+ PATH_REVPROPS_DB,
+ NULL),
+ svn_sqlite__mode_rwcreate, statements,
+ 0, NULL, result_pool, scratch_pool));
+ SVN_ERR(svn_sqlite__exec_statements(*sdb, STMT_CREATE_SCHEMA));
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
get_youngest(svn_revnum_t *youngest_p, const char *fs_path, apr_pool_t *pool);
@@ -1310,13 +1331,11 @@ upgrade_body(void *baton, apr_pool_t *po
case svn_node_file:
break;
default:
- return svn_error_return(svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
- _("'%s' is not a regular file."
- " Please move it out of "
- "the way and try again"),
- svn_dirent_join(fs->path,
- PATH_CONFIG,
- pool)));
+ return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
+ _("'%s' is not a regular file."
+ " Please move it out of "
+ "the way and try again"),
+ svn_dirent_join(fs->path, PATH_CONFIG, pool));
}
/* If we're already up-to-date, there's nothing else to be done here. */
@@ -1351,19 +1370,7 @@ upgrade_body(void *baton, apr_pool_t *po
and create the database. */
if (format < SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
{
- SVN_ERR(svn_io_file_create(path_min_unpacked_revprop(fs, pool), "0\n",
- pool));
-
- SVN_ERR(svn_sqlite__open(&ffd->revprop_db, svn_dirent_join_many(
- pool, fs->path,
- PATH_REVPROPS_DIR,
- PATH_REVPROPS_DB,
- NULL),
- svn_sqlite__mode_rwcreate, statements,
- 0, NULL,
- fs->pool, pool));
- SVN_ERR(svn_sqlite__exec_statements(ffd->revprop_db,
- STMT_CREATE_SCHEMA));
+ SVN_ERR(create_packed_revprops_db(&ffd->revprop_db, fs, fs->pool, pool));
}
/* Bump the format file. */
@@ -1894,23 +1901,46 @@ open_pack_or_rev_file(apr_file_t **file,
svn_revnum_t rev,
apr_pool_t *pool)
{
+ fs_fs_data_t *ffd = fs->fsap_data;
svn_error_t *err;
const char *path;
+ svn_boolean_t retry = FALSE;
- err = svn_fs_fs__path_rev_absolute(&path, fs, rev, pool);
+ do
+ {
+ err = svn_fs_fs__path_rev_absolute(&path, fs, rev, pool);
- if (! err)
- err = svn_io_file_open(file, path,
- APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
+ /* open the revision file in buffered r/o mode */
+ if (! err)
+ err = svn_io_file_open(file, path,
+ APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- svn_error_clear(err);
- return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
- _("No such revision %ld"), rev);
+ if (err && APR_STATUS_IS_ENOENT(err->apr_err)
+ && ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
+ {
+ /* Could not open the file. This may happen if the
+ * file once existed but got packed later. */
+ svn_error_clear(err);
+
+ /* if that was our 2nd attempt, leave it at that. */
+ if (retry)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), rev);
+
+ /* We failed for the first time. Refresh cache & retry. */
+ SVN_ERR(update_min_unpacked_rev(fs, pool));
+
+ retry = TRUE;
+ }
+ else
+ {
+ /* the file exists but something prevented us from opnening it */
+ return svn_error_return(err);
+ }
}
+ while (err);
- return svn_error_return(err);
+ return SVN_NO_ERROR;
}
/* Given REV in FS, set *REV_OFFSET to REV's offset in the packed file.
@@ -2142,6 +2172,16 @@ read_rep_offsets(representation_t **rep_
return SVN_NO_ERROR;
}
+static svn_error_t *
+err_dangling_id(svn_fs_t *fs, const svn_fs_id_t *id)
+{
+ svn_string_t *id_str = svn_fs_fs__id_unparse(id, fs->pool);
+ return svn_error_createf
+ (SVN_ERR_FS_ID_NOT_FOUND, 0,
+ _("Reference to non-existent node '%s' in filesystem '%s'"),
+ id_str->data, fs->path);
+}
+
/* Get the node-revision for the node ID in FS.
Set *NODEREV_P to the new node-revision structure, allocated in POOL.
See svn_fs_fs__get_node_revision, which wraps this and adds another
@@ -2175,7 +2215,7 @@ get_node_revision_body(node_revision_t *
if (APR_STATUS_IS_ENOENT(err->apr_err))
{
svn_error_clear(err);
- return svn_fs_fs__err_dangling_id(fs, id);
+ return svn_error_return(err_dangling_id(fs, id));
}
return svn_error_return(err);
@@ -6496,6 +6536,7 @@ svn_fs_fs__create(svn_fs_t *fs,
pool),
pool));
+ /* Create the revprops directory. */
if (ffd->max_files_per_dir)
SVN_ERR(svn_io_make_dir_recursively(path_revprops_shard(fs, 0, pool),
pool));
@@ -6505,21 +6546,10 @@ svn_fs_fs__create(svn_fs_t *fs,
pool),
pool));
- /* Create the revprops directory. */
+ /* Write the min unpacked revprop file, and create the database. */
if (format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
{
- SVN_ERR(svn_io_file_create(path_min_unpacked_revprop(fs, pool), "0\n",
- pool));
- SVN_ERR(svn_sqlite__open(&ffd->revprop_db, svn_dirent_join_many(
- pool, path,
- PATH_REVPROPS_DIR,
- PATH_REVPROPS_DB,
- NULL),
- svn_sqlite__mode_rwcreate, statements,
- 0, NULL,
- fs->pool, pool));
- SVN_ERR(svn_sqlite__exec_statements(ffd->revprop_db,
- STMT_CREATE_SCHEMA));
+ SVN_ERR(create_packed_revprops_db(&ffd->revprop_db, fs, fs->pool, pool));
}
/* Create the transaction directory. */
@@ -6924,15 +6954,41 @@ recover_body(void *baton, apr_pool_t *po
SVN_ERR(svn_io_check_path(path_revprops(fs, max_rev, pool),
&youngest_revprops_kind, pool));
if (youngest_revprops_kind == svn_node_none)
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Revision %ld has a revs file but no "
- "revprops file"),
- max_rev);
+ {
+ svn_boolean_t uhohs = TRUE;
+
+ /* No file? Hrm... maybe that's because this repository is
+ packed and the youngest revision is in the revprops.db
+ file? We can at least see if that's a possibility.
+
+ ### TODO: Could we check for revprops in the revprops.db?
+ ### What if rNNN legitimately has no revprops? */
+ if (ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
+ {
+ svn_revnum_t min_unpacked_revprop;
+ const char *min_unpacked_revprop_path =
+ svn_dirent_join(fs->path, PATH_MIN_UNPACKED_REVPROP, pool);
+
+ SVN_ERR(read_min_unpacked_rev(&min_unpacked_revprop,
+ min_unpacked_revprop_path, pool));
+ if (min_unpacked_revprop == (max_rev + 1))
+ uhohs = FALSE;
+ }
+ if (uhohs)
+ {
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("Revision %ld has a revs file but no "
+ "revprops file"),
+ max_rev);
+ }
+ }
else if (youngest_revprops_kind != svn_node_file)
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Revision %ld has a non-file where its "
- "revprops file should be"),
- max_rev);
+ {
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("Revision %ld has a non-file where its "
+ "revprops file should be"),
+ max_rev);
+ }
/* Now store the discovered youngest revision, and the next IDs if
relevant, in a new 'current' file. */
@@ -7009,7 +7065,7 @@ svn_fs_fs__set_uuid(svn_fs_t *fs,
permissions as FS->path.*/
svn_error_t *
svn_fs_fs__ensure_dir_exists(const char *path,
- svn_fs_t *fs,
+ const char *fs_path,
apr_pool_t *pool)
{
svn_error_t *err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
@@ -7022,7 +7078,7 @@ svn_fs_fs__ensure_dir_exists(const char
/* We successfully created a new directory. Dup the permissions
from FS->path. */
- return svn_io_copy_perms(path, fs->path, pool);
+ return svn_io_copy_perms(path, fs_path, pool);
}
/* Set *NODE_ORIGINS to a hash mapping 'const char *' node IDs to
@@ -7094,7 +7150,7 @@ set_node_origins_for_file(svn_fs_t *fs,
SVN_ERR(svn_fs_fs__ensure_dir_exists(svn_dirent_join(fs->path,
PATH_NODE_ORIGINS_DIR,
pool),
- fs, pool));
+ fs->path, pool));
/* Read the previously existing origins (if any), and merge our
update with it. */
@@ -7550,8 +7606,8 @@ pack_shard(const char *revs_dir,
SVN_ERR(svn_io_set_file_read_only(manifest_file_path, FALSE, pool));
/* Update the min-unpacked-rev file to reflect our newly packed shard.
- * (ffd->min_unpacked_rev will be updated by open_pack_or_rev_file().)
- */
+ * (This doesn't update ffd->min_unpacked_rev. That will be updated by
+ * update_min_unpacked_rev() when necessary.) */
final_path = svn_dirent_join(fs_path, PATH_MIN_UNPACKED_REV, iterpool);
SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path, fs_path,
svn_io_file_del_none, iterpool, iterpool));
@@ -7618,9 +7674,8 @@ pack_revprop_shard(svn_fs_t *fs,
SVN_ERR(svn_sqlite__insert(NULL, stmt));
}
- /* Update the min-unpacked-rev file to reflect our newly packed shard.
- * (ffd->min_unpacked_rev will be updated by open_pack_or_rev_file().)
- */
+ /* Update the min-unpacked-revprop file to reflect our newly packed shard.
+ * (This doesn't update ffd->min_unpacked_revprop.) */
final_path = svn_dirent_join(fs_path, PATH_MIN_UNPACKED_REVPROP, iterpool);
SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path, fs_path,
svn_io_file_del_none, iterpool, iterpool));
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.h Thu Dec 2 20:55:08 2010
@@ -26,7 +26,10 @@
#include "fs.h"
/* Open the fsfs filesystem pointed to by PATH and associate it with
- filesystem object FS. Use POOL for temporary allocations. */
+ filesystem object FS. Use POOL for temporary allocations.
+
+ ### Some parts of *FS must have been initialized beforehand; some parts
+ (including FS->path) are initialized by this function. */
svn_error_t *svn_fs_fs__open(svn_fs_t *fs,
const char *path,
apr_pool_t *pool);
@@ -336,7 +339,10 @@ svn_error_t *svn_fs_fs__reserve_copy_id(
apr_pool_t *pool);
/* Create a fs_fs fileysystem referenced by FS at path PATH. Get any
- temporary allocations from POOL. */
+ temporary allocations from POOL.
+
+ ### Some parts of *FS must have been initialized beforehand; some parts
+ (including FS->path) are initialized by this function. */
svn_error_t *svn_fs_fs__create(svn_fs_t *fs,
const char *path,
apr_pool_t *pool);
@@ -401,8 +407,12 @@ svn_error_t *svn_fs_fs__move_into_place(
const char *perms_reference,
apr_pool_t *pool);
-/* Sets *PATH to the path of REV in FS, whether in a pack file or not.
- Allocate in POOL. */
+/* Set *PATH to the path of REV in FS, whether in a pack file or not.
+ Allocate *PATH in POOL.
+
+ Note: If the caller does not have the write lock on FS, then the path is
+ not guaranteed to remain correct after the function returns, because the
+ revision might become packed just after this call. */
svn_error_t *
svn_fs_fs__path_rev_absolute(const char **path,
svn_fs_t *fs,
@@ -486,9 +496,9 @@ svn_error_t *svn_fs_fs__txn_prop(svn_str
const char *propname, apr_pool_t *pool);
/* If directory PATH does not exist, create it and give it the same
- permissions as FS->path.*/
+ permissions as FS_PATH.*/
svn_error_t *svn_fs_fs__ensure_dir_exists(const char *path,
- svn_fs_t *fs,
+ const char *fs_path,
apr_pool_t *pool);
/* Update the node origin index for FS, recording the mapping from
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/lock.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/lock.c Thu Dec 2 20:55:08 2010
@@ -36,7 +36,6 @@
#include "lock.h"
#include "tree.h"
-#include "err.h"
#include "fs_fs.h"
#include "../libsvn_fs/fs-loader.h"
@@ -108,17 +107,28 @@ hash_fetch(apr_hash_t *hash,
}
+/* SVN_ERR_FS_CORRUPT: the lockfile for PATH in FS is corrupt. */
+static svn_error_t *
+err_corrupt_lockfile(const char *fs_path, const char *path)
+{
+ return
+ svn_error_createf(
+ SVN_ERR_FS_CORRUPT, 0,
+ _("Corrupt lockfile for path '%s' in filesystem '%s'"),
+ path, fs_path);
+}
+
/*** Digest file handling functions. ***/
/* Return the path of the lock/entries file for which DIGEST is the
hashed repository relative path. */
static const char *
-digest_path_from_digest(svn_fs_t *fs,
+digest_path_from_digest(const char *fs_path,
const char *digest,
apr_pool_t *pool)
{
- return svn_dirent_join_many(pool, fs->path, PATH_LOCKS_DIR,
+ return svn_dirent_join_many(pool, fs_path, PATH_LOCKS_DIR,
apr_pstrmemdup(pool, digest, DIGEST_SUBDIR_LEN),
digest, NULL);
}
@@ -128,12 +138,12 @@ digest_path_from_digest(svn_fs_t *fs,
PATH, where PATH is the path to the lock file or lock entries file
in FS. */
static const char *
-digest_path_from_path(svn_fs_t *fs,
+digest_path_from_path(const char *fs_path,
const char *path,
apr_pool_t *pool)
{
const char *digest = make_digest(path, pool);
- return svn_dirent_join_many(pool, fs->path, PATH_LOCKS_DIR,
+ return svn_dirent_join_many(pool, fs_path, PATH_LOCKS_DIR,
apr_pstrmemdup(pool, digest, DIGEST_SUBDIR_LEN),
digest, NULL);
}
@@ -142,12 +152,15 @@ digest_path_from_path(svn_fs_t *fs,
/* Write to DIGEST_PATH a representation of CHILDREN (which may be
empty, if the versioned path in FS represented by DIGEST_PATH has
no children) and LOCK (which may be NULL if that versioned path is
- lock itself locked). Use POOL for all allocations. */
+ lock itself locked). Set the permissions of DIGEST_PATH to those of
+ PERMS_REFERENCE. Use POOL for all allocations.
+ */
static svn_error_t *
write_digest_file(apr_hash_t *children,
svn_lock_t *lock,
- svn_fs_t *fs,
+ const char *fs_path,
const char *digest_path,
+ const char *perms_reference,
apr_pool_t *pool)
{
svn_error_t *err = SVN_NO_ERROR;
@@ -155,12 +168,11 @@ write_digest_file(apr_hash_t *children,
apr_hash_index_t *hi;
apr_hash_t *hash = apr_hash_make(pool);
const char *tmp_path;
- const char *rev_0_path;
- SVN_ERR(svn_fs_fs__ensure_dir_exists(svn_dirent_join(fs->path, PATH_LOCKS_DIR,
- pool), fs, pool));
+ SVN_ERR(svn_fs_fs__ensure_dir_exists(svn_dirent_join(fs_path, PATH_LOCKS_DIR,
+ pool), fs_path, pool));
SVN_ERR(svn_fs_fs__ensure_dir_exists(svn_dirent_dirname(digest_path, pool),
- fs, pool));
+ fs_path, pool));
if (lock)
{
@@ -212,8 +224,8 @@ write_digest_file(apr_hash_t *children,
SVN_ERR(svn_stream_close(stream));
SVN_ERR(svn_io_file_rename(tmp_path, digest_path, pool));
- SVN_ERR(svn_fs_fs__path_rev_absolute(&rev_0_path, fs, 0, pool));
- return svn_io_copy_perms(rev_0_path, digest_path, pool);
+ SVN_ERR(svn_io_copy_perms(perms_reference, digest_path, pool));
+ return SVN_NO_ERROR;
}
@@ -224,7 +236,7 @@ write_digest_file(apr_hash_t *children,
static svn_error_t *
read_digest_file(apr_hash_t **children_p,
svn_lock_t **lock_p,
- svn_fs_t *fs,
+ const char *fs_path,
const char *digest_path,
apr_pool_t *pool)
{
@@ -275,17 +287,17 @@ read_digest_file(apr_hash_t **children_p
lock->path = path;
if (! ((lock->token = hash_fetch(hash, TOKEN_KEY, pool))))
- return svn_fs_fs__err_corrupt_lockfile(fs, path);
+ return svn_error_return(err_corrupt_lockfile(fs_path, path));
if (! ((lock->owner = hash_fetch(hash, OWNER_KEY, pool))))
- return svn_fs_fs__err_corrupt_lockfile(fs, path);
+ return svn_error_return(err_corrupt_lockfile(fs_path, path));
if (! ((val = hash_fetch(hash, IS_DAV_COMMENT_KEY, pool))))
- return svn_fs_fs__err_corrupt_lockfile(fs, path);
+ return svn_error_return(err_corrupt_lockfile(fs_path, path));
lock->is_dav_comment = (val[0] == '1');
if (! ((val = hash_fetch(hash, CREATION_DATE_KEY, pool))))
- return svn_fs_fs__err_corrupt_lockfile(fs, path);
+ return svn_error_return(err_corrupt_lockfile(fs_path, path));
SVN_ERR(svn_time_from_cstring(&(lock->creation_date), val, pool));
if ((val = hash_fetch(hash, EXPIRATION_DATE_KEY, pool)))
@@ -318,10 +330,16 @@ read_digest_file(apr_hash_t **children_p
schema-supporting paths) ***/
-/* Write LOCK in FS to the actual OS filesystem. */
+/* Write LOCK in FS to the actual OS filesystem.
+
+ Use PERMS_REFERENCE for the permissions of any digest files.
+
+ Note: this takes an FS_PATH because it's called from the hotcopy logic.
+ */
static svn_error_t *
-set_lock(svn_fs_t *fs,
+set_lock(const char *fs_path,
svn_lock_t *lock,
+ const char *perms_reference,
apr_pool_t *pool)
{
svn_stringbuf_t *this_path = svn_stringbuf_create(lock->path, pool);
@@ -344,10 +362,10 @@ set_lock(svn_fs_t *fs,
/* Calculate the DIGEST_PATH for the currently FS path, and then
get its DIGEST_FILE basename. */
- digest_path = digest_path_from_path(fs, this_path->data, subpool);
+ digest_path = digest_path_from_path(fs_path, this_path->data, subpool);
digest_file = svn_dirent_basename(digest_path, subpool);
- SVN_ERR(read_digest_file(&this_children, &this_lock, fs,
+ SVN_ERR(read_digest_file(&this_children, &this_lock, fs_path,
digest_path, subpool));
/* We're either writing a new lock (first time through only) or
@@ -367,8 +385,8 @@ set_lock(svn_fs_t *fs,
apr_hash_set(this_children, lock_digest_path,
APR_HASH_KEY_STRING, (void *)1);
}
- SVN_ERR(write_digest_file(this_children, this_lock, fs,
- digest_path, subpool));
+ SVN_ERR(write_digest_file(this_children, this_lock, fs_path,
+ digest_path, perms_reference, subpool));
/* Prep for next iteration, or bail if we're done. */
if (svn_dirent_is_root(this_path->data, this_path->len))
@@ -406,10 +424,10 @@ delete_lock(svn_fs_t *fs,
/* Calculate the DIGEST_PATH for the currently FS path, and then
get its DIGEST_FILE basename. */
- digest_path = digest_path_from_path(fs, this_path->data, subpool);
+ digest_path = digest_path_from_path(fs->path, this_path->data, subpool);
digest_file = svn_dirent_basename(digest_path, subpool);
- SVN_ERR(read_digest_file(&this_children, &this_lock, fs,
+ SVN_ERR(read_digest_file(&this_children, &this_lock, fs->path,
digest_path, subpool));
/* Delete the lock (first time through only). */
@@ -431,8 +449,10 @@ delete_lock(svn_fs_t *fs,
}
else
{
- SVN_ERR(write_digest_file(this_children, this_lock, fs,
- digest_path, subpool));
+ const char *rev_0_path;
+ SVN_ERR(svn_fs_fs__path_rev_absolute(&rev_0_path, fs, 0, pool));
+ SVN_ERR(write_digest_file(this_children, this_lock, fs->path,
+ digest_path, rev_0_path, subpool));
}
/* Prep for next iteration, or bail if we're done. */
@@ -458,9 +478,9 @@ get_lock(svn_lock_t **lock_p,
apr_pool_t *pool)
{
svn_lock_t *lock;
- const char *digest_path = digest_path_from_path(fs, path, pool);
+ const char *digest_path = digest_path_from_path(fs->path, path, pool);
- SVN_ERR(read_digest_file(NULL, &lock, fs, 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);
@@ -513,43 +533,82 @@ get_lock_helper(svn_fs_t *fs,
}
-/* A recursive function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for
- all locks in and under PATH in FS.
- HAVE_WRITE_LOCK should be true if the caller (directly or indirectly)
- has the FS write lock. */
+/* Baton for locks_walker(). */
+struct walk_locks_baton {
+ svn_fs_get_locks_callback_t get_locks_func;
+ void *get_locks_baton;
+ svn_fs_t *fs;
+};
+
+/* Implements walk_digests_callback_t. */
static svn_error_t *
-walk_digest_files(svn_fs_t *fs,
- const char *digest_path,
- svn_fs_get_locks_callback_t get_locks_func,
- void *get_locks_baton,
- svn_boolean_t have_write_lock,
- apr_pool_t *pool)
+locks_walker(void *baton,
+ const char *fs_path,
+ const char *digest_path,
+ apr_hash_t *children,
+ svn_lock_t *lock,
+ svn_boolean_t have_write_lock,
+ apr_pool_t *pool)
{
- apr_hash_t *children;
- svn_lock_t *lock;
- apr_hash_index_t *hi;
- apr_pool_t *subpool;
+ struct walk_locks_baton *wlb = baton;
- /* First, send up any locks in the current digest file. */
- SVN_ERR(read_digest_file(&children, &lock, fs, digest_path, pool));
if (lock)
{
/* Don't report an expired lock. */
if (lock->expiration_date == 0
|| (apr_time_now() <= lock->expiration_date))
{
- if (get_locks_func)
- SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
+ if (wlb->get_locks_func)
+ SVN_ERR(wlb->get_locks_func(wlb->get_locks_baton, lock, pool));
}
else
{
/* Only remove the lock if we have the write lock.
Read operations shouldn't change the filesystem. */
if (have_write_lock)
- SVN_ERR(delete_lock(fs, lock, pool));
+ SVN_ERR(delete_lock(wlb->fs, lock, pool));
}
}
+ return SVN_NO_ERROR;
+}
+
+/* Callback type for walk_digest_files().
+ *
+ * CHILDREN and LOCK come from a read_digest_file(digest_path) call.
+ */
+typedef svn_error_t *(*walk_digests_callback_t)(void *baton,
+ const char *fs_path,
+ const char *digest_path,
+ apr_hash_t *children,
+ svn_lock_t *lock,
+ svn_boolean_t have_write_lock,
+ apr_pool_t *pool);
+
+/* A recursive function that calls WALK_DIGESTS_FUNC/WALK_DIGESTS_BATON for
+ all lock digest files in and under PATH in FS.
+ HAVE_WRITE_LOCK should be true if the caller (directly or indirectly)
+ has the FS write lock. */
+static svn_error_t *
+walk_digest_files(const char *fs_path,
+ const char *digest_path,
+ walk_digests_callback_t walk_digests_func,
+ void *walk_digests_baton,
+ svn_boolean_t have_write_lock,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+ apr_hash_t *children;
+ apr_pool_t *subpool;
+ svn_lock_t *lock;
+
+ /* First, send up any locks in the current digest file. */
+ SVN_ERR(read_digest_file(&children, &lock, fs_path, digest_path, pool));
+
+ SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path,
+ children, lock,
+ have_write_lock, pool));
+
/* Now, recurse on this thing's child entries (if any; bail otherwise). */
if (! apr_hash_count(children))
return SVN_NO_ERROR;
@@ -559,13 +618,31 @@ walk_digest_files(svn_fs_t *fs,
const char *digest = svn__apr_hash_index_key(hi);
svn_pool_clear(subpool);
SVN_ERR(walk_digest_files
- (fs, digest_path_from_digest(fs, digest, subpool),
- get_locks_func, get_locks_baton, have_write_lock, subpool));
+ (fs_path, digest_path_from_digest(fs_path, digest, subpool),
+ walk_digests_func, walk_digests_baton, have_write_lock, subpool));
}
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
+/* A recursive function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for
+ all locks in and under PATH in FS.
+ HAVE_WRITE_LOCK should be true if the caller (directly or indirectly)
+ has the FS write lock. */
+static svn_error_t *
+walk_locks(svn_fs_t *fs,
+ const char *digest_path,
+ svn_fs_get_locks_callback_t get_locks_func,
+ void *get_locks_baton,
+ svn_boolean_t have_write_lock,
+ apr_pool_t *pool)
+{
+ struct walk_locks_baton wlb = { get_locks_func, get_locks_baton, fs };
+ SVN_ERR(walk_digest_files(fs->path, digest_path, locks_walker, &wlb,
+ have_write_lock, pool));
+ return SVN_NO_ERROR;
+}
+
/* Utility function: verify that a lock can be used. Interesting
errors returned from this function:
@@ -625,9 +702,9 @@ svn_fs_fs__allow_locked_operation(const
if (recurse)
{
/* Discover all locks at or below the path. */
- const char *digest_path = digest_path_from_path(fs, path, pool);
- SVN_ERR(walk_digest_files(fs, digest_path, get_locks_callback,
- fs, have_write_lock, pool));
+ const char *digest_path = digest_path_from_path(fs->path, path, pool);
+ SVN_ERR(walk_locks(fs, digest_path, get_locks_callback,
+ fs, have_write_lock, pool));
}
else
{
@@ -667,6 +744,7 @@ lock_body(void *baton, apr_pool_t *pool)
svn_lock_t *lock;
svn_fs_root_t *root;
svn_revnum_t youngest;
+ const char *rev_0_path;
/* Until we implement directory locks someday, we only allow locks
on files or non-existent paths. */
@@ -766,7 +844,8 @@ lock_body(void *baton, apr_pool_t *pool)
lock->is_dav_comment = lb->is_dav_comment;
lock->creation_date = apr_time_now();
lock->expiration_date = lb->expiration_date;
- SVN_ERR(set_lock(lb->fs, lock, pool));
+ SVN_ERR(svn_fs_fs__path_rev_absolute(&rev_0_path, lb->fs, 0, pool));
+ SVN_ERR(set_lock(lb->fs->path, lock, rev_0_path, pool));
*lb->lock_p = lock;
return SVN_NO_ERROR;
@@ -945,7 +1024,7 @@ get_locks_filter_func(void *baton,
else if ((b->requested_depth == svn_depth_files) ||
(b->requested_depth == svn_depth_immediates))
{
- const char *rel_uri = svn_uri_is_child(b->path, lock->path, pool);
+ const char *rel_uri = svn_fspath__is_child(b->path, lock->path, pool);
if (rel_uri && (svn_path_component_count(rel_uri) == 1))
SVN_ERR(b->get_locks_func(b->get_locks_baton, lock, pool));
}
@@ -973,7 +1052,8 @@ svn_fs_fs__get_locks(svn_fs_t *fs,
glfb.get_locks_baton = get_locks_baton;
/* Get the top digest path in our tree of interest, and then walk it. */
- digest_path = digest_path_from_path(fs, path, pool);
- return walk_digest_files(fs, digest_path, get_locks_filter_func, &glfb,
- FALSE, pool);
+ digest_path = digest_path_from_path(fs->path, path, pool);
+ SVN_ERR(walk_locks(fs, digest_path, get_locks_filter_func, &glfb,
+ FALSE, pool));
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.c Thu Dec 2 20:55:08 2010
@@ -51,7 +51,6 @@
#include "svn_props.h"
#include "fs.h"
-#include "err.h"
#include "key-gen.h"
#include "dag.h"
#include "lock.h"
@@ -413,7 +412,7 @@ parent_path_path(parent_path_t *parent_p
if (parent_path->parent)
path_so_far = parent_path_path(parent_path->parent, pool);
return parent_path->entry
- ? svn_uri_join(path_so_far, parent_path->entry, pool)
+ ? svn_fspath__join(path_so_far, parent_path->entry, pool)
: path_so_far;
}
@@ -618,7 +617,7 @@ open_path(parent_path_t **parent_path_p,
entry = svn_fs__next_entry_name(&next, rest, pool);
/* Calculate the path traversed thus far. */
- path_so_far = svn_uri_join(path_so_far, entry, pool);
+ path_so_far = svn_fspath__join(path_so_far, entry, pool);
if (*entry == '\0')
{
@@ -802,8 +801,8 @@ make_path_mutable(svn_fs_root_t *root,
/* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the
- *node we find, allocated in POOL. Return the error
- *SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
+ node we find, allocated in POOL. Return the error
+ SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
static svn_error_t *
get_dag(dag_node_t **dag_node_p,
svn_fs_root_t *root,
@@ -1134,7 +1133,7 @@ fs_props_changed(svn_boolean_t *changed_
/* Merges and commits. */
-/* Set ARGS->node to the root node of ARGS->root. */
+/* Set *NODE to the root node of ROOT. */
static svn_error_t *
get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool)
{
@@ -1556,13 +1555,16 @@ merge(svn_stringbuf_t *conflict_p,
return SVN_NO_ERROR;
}
-/* Merge changes between an ancestor and BATON->source_node into
- BATON->txn. The ancestor is either BATON->ancestor_node, or if
- that is null, BATON->txn's base node.
-
- If the merge is successful, BATON->txn's base will become
- BATON->source_node, and its root node will have a new ID, a
- successor of BATON->source_node. */
+/* Merge changes between an ancestor and SOURCE_NODE into
+ TXN. The ancestor is either ANCESTOR_NODE, or if
+ that is null, TXN's base node.
+
+ If the merge is successful, TXN's base will become
+ SOURCE_NODE, and its root node will have a new ID, a
+ successor of SOURCE_NODE.
+
+ If a conflict results, update *CONFLICT to the path in the txn that
+ conflicted; see the CONFLICT_P parameter of merge() for details. */
static svn_error_t *
merge_changes(dag_node_t *ancestor_node,
dag_node_t *source_node,
@@ -1586,13 +1588,8 @@ merge_changes(dag_node_t *ancestor_node,
svn_fs_fs__dag_get_id(txn_root_node)))
{
/* If no changes have been made in TXN since its current base,
- then it can't conflict with any changes since that base. So
- we just set *both* its base and root to source, making TXN
- in effect a repeat of source. */
-
- /* ### kff todo: this would, of course, be a mighty silly thing
- for the caller to do, and we might want to consider whether
- this response is really appropriate. */
+ then it can't conflict with any changes since that base.
+ The caller isn't supposed to call us in that case. */
SVN_ERR_MALFUNCTION();
}
else
@@ -2981,7 +2978,7 @@ prev_location(const char **prev_path,
copy_root, copy_path, pool));
if (strcmp(copy_path, path) != 0)
remainder = svn_relpath_is_child(copy_path, path, pool);
- *prev_path = svn_uri_join(copy_src_path, remainder, pool);
+ *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
*prev_rev = copy_src_rev;
return SVN_NO_ERROR;
}
@@ -3241,7 +3238,7 @@ history_prev(void *baton, apr_pool_t *po
SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©_src, node, pool));
dst_rev = copyroot_rev;
- src_path = svn_uri_join(copy_src, remainder, pool);
+ src_path = svn_fspath__join(copy_src, remainder, pool);
}
}
@@ -3375,6 +3372,128 @@ assemble_history(svn_fs_t *fs,
/* mergeinfo queries */
+
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_fs__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_mergeinfo_t filtered_mergeinfo;
+ apr_hash_t *rev_to_sources;
+ apr_hash_index_t *hi;
+ apr_pool_t *iterpool;
+
+ /* A couple easy outs. */
+ if (mergeinfo == NULL)
+ {
+ *validated_mergeinfo = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (apr_hash_count(mergeinfo) == 0)
+ {
+ *validated_mergeinfo = apr_hash_make(result_pool);
+ return SVN_NO_ERROR;
+ }
+
+ filtered_mergeinfo = apr_hash_make(scratch_pool);
+ rev_to_sources = apr_hash_make(scratch_pool);
+
+ /* Since svn_fs_check_path needs an svn_fs_root_t based on a revision,
+ we convert MERGEINFO into a mapping of revisions to a hash of source
+ paths for efficiency. */
+ for (hi = apr_hash_first(scratch_pool, mergeinfo);
+ 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);
+ int i;
+
+ for (i = 0; i < rangelist->nelts; i++)
+ {
+ svn_merge_range_t *range =
+ APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+ svn_revnum_t j;
+
+ for (j = range->start + 1; j <= range->end; j++)
+ {
+ apr_hash_t *paths_for_rev =
+ apr_hash_get(rev_to_sources, &j, sizeof(svn_revnum_t));
+
+ /* No hash associated with this rev yet? */
+ if (!paths_for_rev)
+ {
+ svn_revnum_t *rev = apr_palloc(scratch_pool, sizeof(*rev));
+
+ *rev = j;
+ paths_for_rev = apr_hash_make(scratch_pool);
+ apr_hash_set(rev_to_sources, rev,
+ sizeof(svn_revnum_t), paths_for_rev);
+ }
+
+ apr_hash_set(paths_for_rev, path, APR_HASH_KEY_STRING, path);
+ }
+ }
+ }
+
+ iterpool = svn_pool_create(scratch_pool);
+
+ /* Validate the rev->source MERGEINFO equivalent hash, building the
+ validated mergeinfo as we go. */
+ for (hi = apr_hash_first(scratch_pool, rev_to_sources);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
+ apr_hash_t *paths = svn__apr_hash_index_val(hi);
+ apr_pool_t *inner_iterpool;
+ apr_hash_index_t *hi2;
+ svn_node_kind_t kind;
+ svn_fs_root_t *mergeinfo_rev_root;
+
+ svn_pool_clear(iterpool);
+ inner_iterpool = svn_pool_create(iterpool);
+
+ SVN_ERR(svn_fs_fs__revision_root(&mergeinfo_rev_root, fs,
+ *rev, iterpool));
+
+ for (hi2 = apr_hash_first(iterpool, paths);
+ hi2;
+ hi2 = apr_hash_next(hi2))
+ {
+ const char *path = svn__apr_hash_index_key(hi2);
+
+ svn_pool_clear(inner_iterpool);
+ SVN_ERR(svn_fs_fs__check_path(&kind, mergeinfo_rev_root,
+ path, inner_iterpool));
+ if (kind == svn_node_none)
+ {
+ apr_hash_set(paths, path, APR_HASH_KEY_STRING, NULL);
+ }
+ else
+ {
+ svn_mergeinfo_t good_mergeinfo_fragment;
+ const char *mergeinfo_str =
+ apr_psprintf(inner_iterpool, "%s:%ld", path, *rev);
+
+ SVN_ERR(svn_mergeinfo_parse(&good_mergeinfo_fragment,
+ mergeinfo_str, scratch_pool));
+ SVN_ERR(svn_mergeinfo_merge(filtered_mergeinfo,
+ good_mergeinfo_fragment,
+ scratch_pool));
+ }
+ }
+ svn_pool_destroy(inner_iterpool);
+ }
+
+ svn_pool_destroy(iterpool);
+ *validated_mergeinfo = svn_mergeinfo_dup(filtered_mergeinfo, result_pool);
+ return SVN_NO_ERROR;
+}
+
/* DIR_DAG is a directory DAG node which has mergeinfo in its
descendants. This function iterates over its children. For each
child with immediate mergeinfo, it adds its mergeinfo to
@@ -3411,7 +3530,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs
svn_pool_clear(iterpool);
- kid_path = svn_uri_join(this_path, dirent->name, iterpool);
+ kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag, iterpool));
@@ -3480,7 +3599,7 @@ append_to_merged_froms(svn_mergeinfo_t *
apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
char *newpath;
- newpath = svn_uri_join(path, path_piece, pool);
+ newpath = svn_fspath__join(path, path_piece, pool);
apr_hash_set(*output, newpath, APR_HASH_KEY_STRING,
svn_rangelist_dup(rangelist, pool));
}
@@ -3490,14 +3609,17 @@ append_to_merged_froms(svn_mergeinfo_t *
/* Calculates the mergeinfo for PATH under REV_ROOT using inheritance
type INHERIT. Returns it in *MERGEINFO, or NULL if there is none.
- The result is allocated in RESULT_POOL; POOL is used for temporary
- allocations.
+ If *MERGEINFO is inherited and VALIDATE_INHERITED_MERGEINFO is true,
+ then *MERGEINFO will only contain path-revs that actually exist in
+ repository. The result is allocated in RESULT_POOL; POOL is used for
+ temporary allocations.
*/
static svn_error_t *
get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
svn_fs_root_t *rev_root,
const char *path,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
apr_pool_t *pool,
apr_pool_t *result_pool)
{
@@ -3547,7 +3669,6 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
return SVN_NO_ERROR;
}
}
- svn_pool_destroy(iterpool);
SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, nearest_ancestor->node, pool));
mergeinfo_string = apr_hash_get(proplist, SVN_PROP_MERGEINFO,
@@ -3561,6 +3682,7 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
if (nearest_ancestor == parent_path)
{
/* We can return this directly. */
+ svn_pool_destroy(iterpool);
return svn_mergeinfo_parse(mergeinfo,
mergeinfo_string->data,
result_pool);
@@ -3582,12 +3704,18 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
NULL, SVN_INVALID_REVNUM,
SVN_INVALID_REVNUM, pool));
- return append_to_merged_froms(mergeinfo,
- temp_mergeinfo,
- parent_path_relpath(parent_path,
- nearest_ancestor,
- pool),
- result_pool);
+ SVN_ERR(append_to_merged_froms(mergeinfo,
+ temp_mergeinfo,
+ parent_path_relpath(parent_path,
+ nearest_ancestor,
+ pool),
+ result_pool));
+
+ if (validate_inherited_mergeinfo)
+ SVN_ERR(svn_fs_fs__validate_mergeinfo(mergeinfo, rev_root->fs,
+ *mergeinfo, pool, iterpool));
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
}
}
@@ -3620,13 +3748,17 @@ add_descendant_mergeinfo(svn_mergeinfo_c
/* Get the mergeinfo for a set of paths, returned in
- *MERGEINFO_CATALOG. Returned values are allocated in POOL, while
- temporary values are allocated in a sub-pool. */
+ *MERGEINFO_CATALOG. If the mergeinfo for any path is inherited
+ and VALIDATE_INHERITED_MERGEINFO is true, then the mergeinfo for
+ that path in *MERGEINFO_CATALOG will only contain path-revs that
+ actually exist in repository. Returned values are allocated in
+ POOL, while temporary values are allocated in a sub-pool. */
static svn_error_t *
get_mergeinfos_for_paths(svn_fs_root_t *root,
svn_mergeinfo_catalog_t *mergeinfo_catalog,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -3642,7 +3774,8 @@ get_mergeinfos_for_paths(svn_fs_root_t *
svn_pool_clear(iterpool);
SVN_ERR(get_mergeinfo_for_path(&path_mergeinfo, root, path,
- inherit, iterpool, pool));
+ inherit, validate_inherited_mergeinfo,
+ iterpool, pool));
if (path_mergeinfo)
apr_hash_set(result_catalog, path, APR_HASH_KEY_STRING,
path_mergeinfo);
@@ -3663,6 +3796,7 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t
svn_fs_root_t *root,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -3682,10 +3816,11 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t
/* Retrieve a path -> mergeinfo hash mapping. */
return get_mergeinfos_for_paths(root, catalog, paths,
- inherit, include_descendants,
- pool);
+ inherit, validate_inherited_mergeinfo,
+ include_descendants, pool);
}
+
/* The vtable associated with root objects. */
static root_vtable_t root_vtable = {
fs_paths_changed,
@@ -3715,7 +3850,7 @@ static root_vtable_t root_vtable = {
fs_contents_changed,
fs_get_file_delta_stream,
fs_merge,
- fs_get_mergeinfo
+ fs_get_mergeinfo,
};
/* Construct a new root object in FS, allocated from POOL. */
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/tree.h Thu Dec 2 20:55:08 2010
@@ -58,6 +58,7 @@ svn_error_t *svn_fs_fs__commit_obliterat
svn_error_t *svn_fs_fs__txn_root(svn_fs_root_t **root_p, svn_fs_txn_t *txn,
apr_pool_t *pool);
+
/* Set KIND_P to the node kind of the node at PATH in ROOT.
Allocate the structure in POOL. */
svn_error_t *
@@ -76,6 +77,14 @@ svn_fs_fs__node_created_rev(svn_revnum_t
const char *path,
apr_pool_t *pool);
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_fs__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/deprecated.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/deprecated.c Thu Dec 2 20:55:08 2010
@@ -418,3 +418,18 @@ svn_error_t *svn_ra_do_status(svn_ra_ses
status_editor, status_baton, pool);
}
+svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session,
+ svn_mergeinfo_catalog_t *catalog,
+ const apr_array_header_t *paths,
+ svn_revnum_t revision,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool)
+{
+ svn_boolean_t validate_inherited_mergeinfo = FALSE;
+
+ return svn_error_return(svn_ra_get_mergeinfo2(session, catalog, paths,
+ revision, inherit, &validate_inherited_mergeinfo,
+ include_descendants, pool));
+}
+
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.c Thu Dec 2 20:55:08 2010
@@ -753,13 +753,14 @@ svn_error_t *svn_ra_get_dir2(svn_ra_sess
path, revision, dirent_fields, pool);
}
-svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session,
- svn_mergeinfo_catalog_t *catalog,
- const apr_array_header_t *paths,
- svn_revnum_t revision,
- svn_mergeinfo_inheritance_t inherit,
- svn_boolean_t include_descendants,
- apr_pool_t *pool)
+svn_error_t *svn_ra_get_mergeinfo2(svn_ra_session_t *session,
+ svn_mergeinfo_catalog_t *catalog,
+ const apr_array_header_t *paths,
+ svn_revnum_t revision,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t *validate_inherited_mergeinfo,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool)
{
svn_error_t *err;
int i;
@@ -781,6 +782,7 @@ svn_error_t *svn_ra_get_mergeinfo(svn_ra
return session->vtable->get_mergeinfo(session, catalog, paths,
revision, inherit,
+ validate_inherited_mergeinfo,
include_descendants, pool);
}
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra/ra_loader.h Thu Dec 2 20:55:08 2010
@@ -119,6 +119,7 @@ typedef struct svn_ra__vtable_t {
const apr_array_header_t *paths,
svn_revnum_t revision,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t *validate_inherited_mergeinfo,
svn_boolean_t include_merged_revisions,
apr_pool_t *pool);
svn_error_t *(*do_update)(svn_ra_session_t *session,
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c Thu Dec 2 20:55:08 2010
@@ -693,6 +693,7 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
const apr_array_header_t *paths,
svn_revnum_t revision,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t *validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -709,9 +710,11 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
svn_dirent_join(sess->fs_path->data, relative_path, pool);
}
- SVN_ERR(svn_repos_fs_get_mergeinfo(&tmp_catalog, sess->repos, abs_paths,
- revision, inherit, include_descendants,
- NULL, NULL, pool));
+ SVN_ERR(svn_repos_fs_get_mergeinfo2(&tmp_catalog, sess->repos, abs_paths,
+ revision, inherit,
+ *validate_inherited_mergeinfo,
+ include_descendants,
+ NULL, NULL, pool));
if (apr_hash_count(tmp_catalog) > 0)
SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(catalog,
tmp_catalog,
@@ -925,7 +928,7 @@ svn_ra_local__do_check_path(svn_ra_sessi
{
svn_ra_local__session_baton_t *sess = session->priv;
svn_fs_root_t *root;
- const char *abs_path = svn_uri_join(sess->fs_path->data, path, pool);
+ const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
if (! SVN_IS_VALID_REVNUM(revision))
SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/mergeinfo.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/mergeinfo.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/mergeinfo.c Thu Dec 2 20:55:08 2010
@@ -51,6 +51,7 @@ struct mergeinfo_baton
svn_stringbuf_t *curr_path;
svn_stringbuf_t *curr_info;
svn_mergeinfo_catalog_t catalog;
+ svn_boolean_t validated_inherited_mergeinfo;
svn_error_t *err;
};
@@ -62,6 +63,8 @@ static const svn_ra_neon__xml_elm_t merg
SVN_RA_NEON__XML_CDATA },
{ SVN_XML_NAMESPACE, SVN_DAV__MERGEINFO_INFO, ELEM_mergeinfo_info,
SVN_RA_NEON__XML_CDATA },
+ { SVN_XML_NAMESPACE, SVN_DAV__VALIDATE_INHERITED,
+ ELEM_validate_inherited_mergeinfo, SVN_RA_NEON__XML_CDATA },
{ NULL }
};
@@ -93,6 +96,10 @@ start_element(int *elem, void *baton, in
svn_stringbuf_setempty(mb->curr_info);
svn_stringbuf_setempty(mb->curr_path);
}
+ else if (elm->id == ELEM_validate_inherited_mergeinfo)
+ {
+ mb->validated_inherited_mergeinfo = TRUE;
+ }
SVN_ERR(mb->err);
@@ -163,6 +170,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
const apr_array_header_t *paths,
svn_revnum_t revision,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t *validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -194,6 +202,14 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
"</S:inherit>",
svn_inheritance_to_word(inherit)));
+ if (*validate_inherited_mergeinfo)
+ {
+ /* Send it only if true; server will default to "no". */
+ svn_stringbuf_appendcstr(request_body,
+ "<S:" SVN_DAV__VALIDATE_INHERITED ">yes"
+ "</S:" SVN_DAV__VALIDATE_INHERITED ">");
+ }
+
if (include_descendants)
{
/* Send it only if true; server will default to "no". */
@@ -224,6 +240,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
mb.curr_path = svn_stringbuf_create("", pool);
mb.curr_info = svn_stringbuf_create("", pool);
mb.catalog = apr_hash_make(pool);
+ mb.validated_inherited_mergeinfo = FALSE;
mb.err = SVN_NO_ERROR;
/* ras's URL may not exist in HEAD, and thus it's not safe to send
@@ -253,5 +270,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
if (mb.err == SVN_NO_ERROR && apr_hash_count(mb.catalog))
*catalog = mb.catalog;
+ *validate_inherited_mergeinfo = mb.validated_inherited_mergeinfo;
+
return mb.err;
}
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/options.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/options.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/options.c Thu Dec 2 20:55:08 2010
@@ -395,12 +395,15 @@ svn_ra_neon__has_capability(svn_ra_sessi
support mergeinfo. */
svn_mergeinfo_catalog_t ignored;
svn_error_t *err;
+ svn_boolean_t validate_inherited_mergeinfo = FALSE;
apr_array_header_t *paths = apr_array_make(pool, 1,
sizeof(char *));
APR_ARRAY_PUSH(paths, const char *) = "";
err = svn_ra_neon__get_mergeinfo(session, &ignored, paths, 0,
- FALSE, FALSE, pool);
+ FALSE,
+ &validate_inherited_mergeinfo,
+ FALSE, pool);
if (err)
{
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/ra_neon.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/ra_neon.h Thu Dec 2 20:55:08 2010
@@ -299,13 +299,15 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
svn_error_t * svn_ra_neon__abort_commit(void *session_baton,
void *edit_baton);
-svn_error_t * svn_ra_neon__get_mergeinfo(svn_ra_session_t *session,
- apr_hash_t **mergeinfo,
- const apr_array_header_t *paths,
- svn_revnum_t revision,
- svn_mergeinfo_inheritance_t inherit,
- svn_boolean_t include_descendants,
- apr_pool_t *pool);
+svn_error_t * svn_ra_neon__get_mergeinfo(
+ svn_ra_session_t *session,
+ apr_hash_t **mergeinfo,
+ const apr_array_header_t *paths,
+ svn_revnum_t revision,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t *validate_inherited_mergeinfo,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool);
svn_error_t * svn_ra_neon__do_update(svn_ra_session_t *session,
const svn_ra_reporter3_t **reporter,
@@ -859,7 +861,8 @@ enum {
ELEM_mergeinfo_info,
ELEM_has_children,
ELEM_merged_revision,
- ELEM_deleted_rev_report
+ ELEM_deleted_rev_report,
+ ELEM_validate_inherited_mergeinfo
};
/* ### docco */
Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/mergeinfo.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/mergeinfo.c Thu Dec 2 20:55:08 2010
@@ -45,7 +45,8 @@ typedef enum {
MERGEINFO_REPORT,
MERGEINFO_ITEM,
MERGEINFO_PATH,
- MERGEINFO_INFO
+ MERGEINFO_INFO,
+ MERGEINFO_VALIDATED
} mergeinfo_state_e;
/* Baton for accumulating mergeinfo. RESULT_CATALOG stores the final
@@ -62,6 +63,8 @@ typedef struct {
const apr_array_header_t *paths;
svn_revnum_t revision;
svn_mergeinfo_inheritance_t inherit;
+ svn_boolean_t validate_inherited_mergeinfo;
+ svn_boolean_t validated_inherited_mergeinfo;
svn_boolean_t include_descendants;
} mergeinfo_context_t;
@@ -80,6 +83,11 @@ start_element(svn_ra_serf__xml_parser_t
svn_ra_serf__xml_push_state(parser, MERGEINFO_REPORT);
}
else if (state == MERGEINFO_REPORT &&
+ strcmp(name.name, SVN_DAV__VALIDATE_INHERITED) == 0)
+ {
+ svn_ra_serf__xml_push_state(parser, MERGEINFO_VALIDATED);
+ }
+ else if (state == MERGEINFO_REPORT &&
strcmp(name.name, SVN_DAV__MERGEINFO_ITEM) == 0)
{
svn_ra_serf__xml_push_state(parser, MERGEINFO_ITEM);
@@ -169,6 +177,11 @@ cdata_handler(svn_ra_serf__xml_parser_t
svn_stringbuf_appendbytes(mergeinfo_ctx->curr_info, data, len);
break;
+ case MERGEINFO_VALIDATED:
+ if (strncmp(data, "yes", 3) == 0)
+ mergeinfo_ctx->validated_inherited_mergeinfo = TRUE;
+ break;
+
default:
break;
}
@@ -206,6 +219,13 @@ create_mergeinfo_body(serf_bucket_t **bk
"yes", alloc);
}
+ if (mergeinfo_ctx->validate_inherited_mergeinfo)
+ {
+ svn_ra_serf__add_tag_buckets(body_bkt, "S:"
+ SVN_DAV__VALIDATE_INHERITED,
+ "yes", alloc);
+ }
+
if (mergeinfo_ctx->paths)
{
int i;
@@ -235,6 +255,7 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
const apr_array_header_t *paths,
svn_revnum_t revision,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t *validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -264,6 +285,8 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
mergeinfo_ctx->paths = paths;
mergeinfo_ctx->revision = revision;
mergeinfo_ctx->inherit = inherit;
+ mergeinfo_ctx->validate_inherited_mergeinfo = *validate_inherited_mergeinfo;
+ mergeinfo_ctx->validated_inherited_mergeinfo = FALSE;
mergeinfo_ctx->include_descendants = include_descendants;
handler = apr_pcalloc(pool, sizeof(*handler));
@@ -303,6 +326,9 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
SVN_ERR(err);
+ *validate_inherited_mergeinfo =
+ mergeinfo_ctx->validated_inherited_mergeinfo;
+
if (mergeinfo_ctx->done && apr_hash_count(mergeinfo_ctx->result_catalog))
*catalog = mergeinfo_ctx->result_catalog;