You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/10/20 19:57:43 UTC
svn commit: r1025655 [2/6] - in /subversion/branches/object-model: ./
build/win32/ notes/http-and-webdav/ notes/wc-ng/
subversion/bindings/ctypes-python/csvn/ subversion/include/
subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs_fs...
Modified: subversion/branches/object-model/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_repos/load.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/object-model/subversion/libsvn_repos/load.c Wed Oct 20 17:57:41 2010
@@ -43,73 +43,6 @@
/*----------------------------------------------------------------------*/
-/** Batons used herein **/
-
-struct parse_baton
-{
- svn_repos_t *repos;
- svn_fs_t *fs;
-
- svn_boolean_t use_history;
- svn_boolean_t use_pre_commit_hook;
- svn_boolean_t use_post_commit_hook;
- enum svn_repos_load_uuid uuid_action;
- const char *parent_dir;
- svn_repos_notify_func_t notify_func;
- void *notify_baton;
- svn_repos_notify_t *notify;
- apr_pool_t *pool;
-
- /* A hash mapping copy-from revisions and mergeinfo range revisions
- (svn_revnum_t *) in the dump stream to their corresponding revisions
- (svn_revnum_t *) in the loaded repository. The hash and its
- contents are allocated in POOL. */
- apr_hash_t *rev_map;
-
- /* The most recent (youngest) revision from the dump stream mapped in
- REV_MAP. If no revisions have been mapped yet, this is set to
- SVN_INVALID_REVNUM. */
- svn_revnum_t last_rev_mapped;
-
- /* The oldest old revision loaded from the dump stream. If no revisions
- have been loaded yet, this is set to SVN_INVALID_REVNUM. */
- svn_revnum_t oldest_old_rev;
-};
-
-struct revision_baton
-{
- svn_revnum_t rev;
-
- svn_fs_txn_t *txn;
- svn_fs_root_t *txn_root;
-
- const svn_string_t *datestamp;
-
- apr_int32_t rev_offset;
-
- struct parse_baton *pb;
- apr_pool_t *pool;
-};
-
-struct node_baton
-{
- const char *path;
- svn_node_kind_t kind;
- enum svn_node_action action;
- svn_checksum_t *base_checksum; /* null, if not available */
- svn_checksum_t *result_checksum; /* null, if not available */
- svn_checksum_t *copy_source_checksum; /* null, if not available */
-
- svn_revnum_t copyfrom_rev;
- const char *copyfrom_path;
-
- struct revision_baton *rb;
- apr_pool_t *pool;
-};
-
-
-/*----------------------------------------------------------------------*/
-
/** The parser and related helper funcs **/
@@ -236,170 +169,6 @@ read_key_or_val(char **pbuf,
}
-/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with PARENT_DIR, and
- return it in *MERGEINFO_VAL. */
-static svn_error_t *
-prefix_mergeinfo_paths(svn_string_t **mergeinfo_val,
- const svn_string_t *mergeinfo_orig,
- const char *parent_dir,
- apr_pool_t *pool)
-{
- apr_hash_t *prefixed_mergeinfo, *mergeinfo;
- apr_hash_index_t *hi;
- void *rangelist;
-
- SVN_ERR(svn_mergeinfo_parse(&mergeinfo, mergeinfo_orig->data, pool));
- prefixed_mergeinfo = apr_hash_make(pool);
- for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
- {
- const void *key;
- const char *path, *merge_source;
-
- apr_hash_this(hi, &key, NULL, &rangelist);
- merge_source = key;
-
- /* The svn:mergeinfo property syntax demands absolute repository
- paths, so prepend a leading slash if PARENT_DIR lacks one. */
- if (*parent_dir != '/')
- path = svn_path_join_many(pool, "/", parent_dir,
- merge_source + 1, NULL);
- else
- path = svn_path_join(parent_dir, merge_source + 1, pool);
-
- apr_hash_set(prefixed_mergeinfo, path, APR_HASH_KEY_STRING, rangelist);
- }
- return svn_mergeinfo_to_string(mergeinfo_val, prefixed_mergeinfo, pool);
-}
-
-
-/* Examine the mergeinfo in INITIAL_VAL, renumber revisions in rangelists
- as appropriate, and return the (possibly new) mergeinfo in *FINAL_VAL
- (allocated from POOL). */
-static svn_error_t *
-renumber_mergeinfo_revs(svn_string_t **final_val,
- const svn_string_t *initial_val,
- struct revision_baton *rb,
- apr_pool_t *pool)
-{
- apr_pool_t *subpool = svn_pool_create(pool);
- svn_mergeinfo_t mergeinfo, predates_stream_mergeinfo;
- svn_mergeinfo_t final_mergeinfo = apr_hash_make(subpool);
- apr_hash_index_t *hi;
-
- SVN_ERR(svn_mergeinfo_parse(&mergeinfo, initial_val->data, subpool));
-
- /* Issue #3020
- http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16
- Remove mergeinfo older than the oldest revision in the dump stream
- and adjust its revisions by the difference between the head rev of
- the target repository and the current dump stream rev. */
- if (rb->pb->oldest_old_rev > 1)
- {
- SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
- &predates_stream_mergeinfo, mergeinfo,
- rb->pb->oldest_old_rev - 1, 0,
- TRUE, subpool, subpool));
- SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
- &mergeinfo, mergeinfo,
- rb->pb->oldest_old_rev - 1, 0,
- FALSE, subpool, subpool));
- SVN_ERR(svn_mergeinfo__adjust_mergeinfo_rangelists(
- &predates_stream_mergeinfo, predates_stream_mergeinfo,
- -rb->rev_offset, subpool, subpool));
- }
- else
- {
- predates_stream_mergeinfo = NULL;
- }
-
- for (hi = apr_hash_first(subpool, mergeinfo); hi; hi = apr_hash_next(hi))
- {
- const char *merge_source;
- apr_array_header_t *rangelist;
- struct parse_baton *pb = rb->pb;
- int i;
- const void *key;
- void *val;
-
- apr_hash_this(hi, &key, NULL, &val);
- merge_source = key;
- rangelist = val;
-
- /* Possibly renumber revisions in merge source's rangelist. */
- for (i = 0; i < rangelist->nelts; i++)
- {
- svn_revnum_t *rev_from_map;
- svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i,
- svn_merge_range_t *);
- rev_from_map = apr_hash_get(pb->rev_map, &range->start,
- sizeof(svn_revnum_t));
- if (rev_from_map && SVN_IS_VALID_REVNUM(*rev_from_map))
- {
- range->start = *rev_from_map;
- }
- else if (range->start == pb->oldest_old_rev - 1)
- {
- /* Since the start revision of svn_merge_range_t are not
- inclusive there is one possible valid start revision that
- won't be found in the PB->REV_MAP mapping of load stream
- revsions to loaded revisions: The revision immediately
- preceeding the oldest revision from the load stream.
- This is a valid revision for mergeinfo, but not a valid
- copy from revision (which PB->REV_MAP also maps for) so it
- will never be in the mapping.
-
- If that is what we have here, then find the mapping for the
- oldest rev from the load stream and subtract 1 to get the
- renumbered, non-inclusive, start revision. */
- rev_from_map = apr_hash_get(pb->rev_map, &pb->oldest_old_rev,
- sizeof(svn_revnum_t));
- if (rev_from_map && SVN_IS_VALID_REVNUM(*rev_from_map))
- range->start = *rev_from_map - 1;
- }
- else
- {
- /* If we can't remap the start revision then don't even bother
- trying to remap the end revision. It's possible we might
- actually succeed at the latter, which can result in invalid
- mergeinfo with a start rev > end rev. If that gets into the
- repository then a world of bustage breaks loose anytime that
- bogus mergeinfo is parsed. See
- http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16.
- */
- continue;
- }
-
- rev_from_map = apr_hash_get(pb->rev_map, &range->end,
- sizeof(svn_revnum_t));
- if (rev_from_map && SVN_IS_VALID_REVNUM(*rev_from_map))
- range->end = *rev_from_map;
- }
- apr_hash_set(final_mergeinfo, merge_source,
- APR_HASH_KEY_STRING, rangelist);
- }
-
- if (predates_stream_mergeinfo)
- SVN_ERR(svn_mergeinfo_merge(final_mergeinfo, predates_stream_mergeinfo,
- subpool));
-
- SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
-
- /* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0
- or r1. However, svndumpfilter can be abused to produce r1 merge source
- revs. So if we encounter any, then strip them out, no need to put them
- into the load target. */
- SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo,
- final_mergeinfo,
- 1, 0, FALSE,
- subpool, subpool));
-
- SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
- svn_pool_destroy(subpool);
-
- return SVN_NO_ERROR;
-}
-
-
/* Read CONTENT_LENGTH bytes from STREAM, parsing the bytes as an
encoded Subversion properties hash, and making multiple calls to
PARSE_FNS->set_*_property on RECORD_BATON (depending on the value
@@ -480,38 +249,6 @@ parse_property_block(svn_stream_t *strea
/* Now, send the property pair to the vtable! */
if (is_node)
{
- /* svn_mergeinfo_parse() in parse_fns->set_node_property()
- will choke on mergeinfo with "\r\n" line endings, but we
- might legitimately encounter these in a dump stream. If
- so normalize the line endings to '\n' and make a
- notification to PARSE_BATON->FEEDBACK_STREAM that we
- have made this correction. */
- if (strcmp(keybuf, SVN_PROP_MERGEINFO) == 0
- && strstr(propstring.data, "\r"))
- {
- const char *prop_eol_normalized;
- struct parse_baton *pb = parse_baton;
-
- SVN_ERR(svn_subst_translate_cstring2(
- propstring.data,
- &prop_eol_normalized,
- "\n", /* translate to LF */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- proppool));
- propstring.data = prop_eol_normalized;
- propstring.len = strlen(prop_eol_normalized);
-
- if (pb->notify_func)
- {
- pb->notify->action =
- svn_repos_notify_load_normalized_mergeinfo;
- pb->notify_func(pb->notify_baton, pb->notify,
- proppool);
- }
- }
-
SVN_ERR(parse_fns->set_node_property(record_baton,
keybuf,
&propstring));
@@ -663,7 +400,10 @@ parse_format_version(const char *version
-/* The Main Parser Logic */
+/*----------------------------------------------------------------------*/
+
+/** The public routines **/
+
svn_error_t *
svn_repos_parse_dumpstream2(svn_stream_t *stream,
const svn_repos_parse_fns2_t *parse_fns,
@@ -952,662 +692,3 @@ svn_repos_parse_dumpstream2(svn_stream_t
svn_pool_destroy(nodepool);
return SVN_NO_ERROR;
}
-
-
-/*----------------------------------------------------------------------*/
-
-/** vtable for doing commits to a fs **/
-
-
-static struct node_baton *
-make_node_baton(apr_hash_t *headers,
- struct revision_baton *rb,
- apr_pool_t *pool)
-{
- struct node_baton *nb = apr_pcalloc(pool, sizeof(*nb));
- const char *val;
-
- /* Start with sensible defaults. */
- nb->rb = rb;
- nb->pool = pool;
- nb->kind = svn_node_unknown;
-
- /* Then add info from the headers. */
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_PATH,
- APR_HASH_KEY_STRING)))
- {
- if (rb->pb->parent_dir)
- nb->path = svn_path_join(rb->pb->parent_dir, val, pool);
- else
- nb->path = apr_pstrdup(pool, val);
- }
-
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_KIND,
- APR_HASH_KEY_STRING)))
- {
- if (! strcmp(val, "file"))
- nb->kind = svn_node_file;
- else if (! strcmp(val, "dir"))
- nb->kind = svn_node_dir;
- }
-
- nb->action = (enum svn_node_action)(-1); /* an invalid action code */
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_ACTION,
- APR_HASH_KEY_STRING)))
- {
- if (! strcmp(val, "change"))
- nb->action = svn_node_action_change;
- else if (! strcmp(val, "add"))
- nb->action = svn_node_action_add;
- else if (! strcmp(val, "delete"))
- nb->action = svn_node_action_delete;
- else if (! strcmp(val, "replace"))
- nb->action = svn_node_action_replace;
- }
-
- nb->copyfrom_rev = SVN_INVALID_REVNUM;
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV,
- APR_HASH_KEY_STRING)))
- {
- nb->copyfrom_rev = SVN_STR_TO_REV(val);
- }
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH,
- APR_HASH_KEY_STRING)))
- {
- if (rb->pb->parent_dir)
- nb->copyfrom_path = svn_path_join(rb->pb->parent_dir,
- (*val == '/' ? val + 1 : val), pool);
- else
- nb->copyfrom_path = apr_pstrdup(pool, val);
- }
-
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_CHECKSUM,
- APR_HASH_KEY_STRING)))
- {
- svn_checksum_parse_hex(&nb->result_checksum, svn_checksum_md5, val, pool);
- }
-
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_CHECKSUM,
- APR_HASH_KEY_STRING)))
- {
- svn_checksum_parse_hex(&nb->base_checksum, svn_checksum_md5, val, pool);
- }
-
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_CHECKSUM,
- APR_HASH_KEY_STRING)))
- {
- svn_checksum_parse_hex(&nb->copy_source_checksum, svn_checksum_md5, val,
- pool);
- }
-
- /* What's cool about this dump format is that the parser just
- ignores any unrecognized headers. :-) */
-
- return nb;
-}
-
-static struct revision_baton *
-make_revision_baton(apr_hash_t *headers,
- struct parse_baton *pb,
- apr_pool_t *pool)
-{
- struct revision_baton *rb = apr_pcalloc(pool, sizeof(*rb));
- const char *val;
-
- rb->pb = pb;
- rb->pool = pool;
- rb->rev = SVN_INVALID_REVNUM;
-
- if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,
- APR_HASH_KEY_STRING)))
- rb->rev = SVN_STR_TO_REV(val);
-
- return rb;
-}
-
-
-static svn_error_t *
-new_revision_record(void **revision_baton,
- apr_hash_t *headers,
- void *parse_baton,
- apr_pool_t *pool)
-{
- struct parse_baton *pb = parse_baton;
- struct revision_baton *rb;
- svn_revnum_t head_rev;
-
- rb = make_revision_baton(headers, pb, pool);
- SVN_ERR(svn_fs_youngest_rev(&head_rev, pb->fs, pool));
-
- /* FIXME: This is a lame fallback loading multiple segments of dump in
- several separate operations. It is highly susceptible to race conditions.
- Calculate the revision 'offset' for finding copyfrom sources.
- It might be positive or negative. */
- rb->rev_offset = (apr_int32_t) (rb->rev) - (head_rev + 1);
-
- if (rb->rev > 0)
- {
- /* Create a new fs txn. */
- SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));
- SVN_ERR(svn_fs_txn_root(&(rb->txn_root), rb->txn, pool));
-
- if (pb->notify_func)
- {
- pb->notify->action = svn_repos_notify_load_txn_start;
- pb->notify->old_revision = rb->rev;
- pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
- }
-
- /* Stash the oldest "old" revision committed from the load stream. */
- if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
- pb->oldest_old_rev = rb->rev;
- }
-
- /* If we're parsing revision 0, only the revision are (possibly)
- interesting to us: when loading the stream into an empty
- filesystem, then we want new filesystem's revision 0 to have the
- same props. Otherwise, we just ignore revision 0 in the stream. */
-
- *revision_baton = rb;
- return SVN_NO_ERROR;
-}
-
-
-
-/* Factorized helper func for new_node_record() */
-static svn_error_t *
-maybe_add_with_history(struct node_baton *nb,
- struct revision_baton *rb,
- apr_pool_t *pool)
-{
- struct parse_baton *pb = rb->pb;
-
- if ((nb->copyfrom_path == NULL) || (! pb->use_history))
- {
- /* Add empty file or dir, without history. */
- if (nb->kind == svn_node_file)
- SVN_ERR(svn_fs_make_file(rb->txn_root, nb->path, pool));
-
- else if (nb->kind == svn_node_dir)
- SVN_ERR(svn_fs_make_dir(rb->txn_root, nb->path, pool));
- }
- else
- {
- /* Hunt down the source revision in this fs. */
- svn_fs_root_t *copy_root;
- svn_revnum_t src_rev = nb->copyfrom_rev - rb->rev_offset;
- svn_revnum_t *src_rev_from_map;
- if ((src_rev_from_map = apr_hash_get(pb->rev_map, &nb->copyfrom_rev,
- sizeof(nb->copyfrom_rev))))
- src_rev = *src_rev_from_map;
-
- if (! SVN_IS_VALID_REVNUM(src_rev))
- return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
- _("Relative source revision %ld is not"
- " available in current repository"),
- src_rev);
-
- SVN_ERR(svn_fs_revision_root(©_root, pb->fs, src_rev, pool));
-
- if (nb->copy_source_checksum)
- {
- svn_checksum_t *checksum;
- SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, copy_root,
- nb->copyfrom_path, TRUE, pool));
- if (!svn_checksum_match(nb->copy_source_checksum, checksum))
- return svn_error_createf
- (SVN_ERR_CHECKSUM_MISMATCH,
- NULL,
- apr_psprintf(pool, "%s:\n%s\n%s\n",
- _("Copy source checksum mismatch on copy from '%s'@%ld\n"
- "to '%s' in rev based on r%ld"),
- _(" expected: %s"),
- _(" actual: %s")),
- nb->copyfrom_path, src_rev,
- nb->path, rb->rev,
- svn_checksum_to_cstring_display(nb->copy_source_checksum, pool),
- svn_checksum_to_cstring_display(checksum, pool));
- }
-
- SVN_ERR(svn_fs_copy(copy_root, nb->copyfrom_path,
- rb->txn_root, nb->path, pool));
-
- if (pb->notify_func)
- {
- pb->notify->action = svn_repos_notify_load_copied_node;
- pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-uuid_record(const char *uuid,
- void *parse_baton,
- apr_pool_t *pool)
-{
- struct parse_baton *pb = parse_baton;
- svn_revnum_t youngest_rev;
-
- if (pb->uuid_action == svn_repos_load_uuid_ignore)
- return SVN_NO_ERROR;
-
- if (pb->uuid_action != svn_repos_load_uuid_force)
- {
- SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, pool));
- if (youngest_rev != 0)
- return SVN_NO_ERROR;
- }
-
- return svn_fs_set_uuid(pb->fs, uuid, pool);
-}
-
-static svn_error_t *
-new_node_record(void **node_baton,
- apr_hash_t *headers,
- void *revision_baton,
- apr_pool_t *pool)
-{
- struct revision_baton *rb = revision_baton;
- struct parse_baton *pb = rb->pb;
- struct node_baton *nb;
-
- if (rb->rev == 0)
- return svn_error_create(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
- _("Malformed dumpstream: "
- "Revision 0 must not contain node records"));
-
- nb = make_node_baton(headers, rb, pool);
-
- /* Make sure we have an action we recognize. */
- if (nb->action < svn_node_action_change
- || nb->action > svn_node_action_replace)
- return svn_error_createf(SVN_ERR_STREAM_UNRECOGNIZED_DATA, NULL,
- _("Unrecognized node-action on node '%s'"),
- nb->path);
-
- if (pb->notify_func)
- {
- pb->notify->action = svn_repos_notify_load_node_start;
- pb->notify->node_action = nb->action;
- pb->notify->path = nb->path;
- pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
- }
-
- switch (nb->action)
- {
- case svn_node_action_change:
- break;
-
- case svn_node_action_delete:
- SVN_ERR(svn_fs_delete(rb->txn_root, nb->path, pool));
- break;
-
- case svn_node_action_add:
- SVN_ERR(maybe_add_with_history(nb, rb, pool));
- break;
-
- case svn_node_action_replace:
- SVN_ERR(svn_fs_delete(rb->txn_root, nb->path, pool));
- SVN_ERR(maybe_add_with_history(nb, rb, pool));
- break;
- }
-
- *node_baton = nb;
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-set_revision_property(void *baton,
- const char *name,
- const svn_string_t *value)
-{
- struct revision_baton *rb = baton;
-
- if (rb->rev > 0)
- {
- SVN_ERR(svn_fs_change_txn_prop(rb->txn, name, value, rb->pool));
-
- /* Remember any datestamp that passes through! (See comment in
- close_revision() below.) */
- if (! strcmp(name, SVN_PROP_REVISION_DATE))
- rb->datestamp = svn_string_dup(value, rb->pool);
- }
- else if (rb->rev == 0)
- {
- /* Special case: set revision 0 properties when loading into an
- 'empty' filesystem. */
- struct parse_baton *pb = rb->pb;
- svn_revnum_t youngest_rev;
-
- SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool));
-
- if (youngest_rev == 0)
- SVN_ERR(svn_fs_change_rev_prop2(pb->fs, 0, name, NULL, value,
- rb->pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-set_node_property(void *baton,
- const char *name,
- const svn_string_t *value)
-{
- struct node_baton *nb = baton;
- struct revision_baton *rb = nb->rb;
- const char *parent_dir = rb->pb->parent_dir;
-
- if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
- {
- /* Renumber mergeinfo as appropriate. */
- svn_string_t *renumbered_mergeinfo;
- SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, value, rb,
- nb->pool));
- value = renumbered_mergeinfo;
- if (parent_dir)
- {
- /* Prefix the merge source paths with PARENT_DIR. */
- /* ASSUMPTION: All source paths are included in the dump stream. */
- svn_string_t *mergeinfo_val;
- SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value, parent_dir,
- nb->pool));
- value = mergeinfo_val;
- }
- }
-
- return svn_fs_change_node_prop(rb->txn_root, nb->path,
- name, value, nb->pool);
-}
-
-
-static svn_error_t *
-delete_node_property(void *baton,
- const char *name)
-{
- struct node_baton *nb = baton;
- struct revision_baton *rb = nb->rb;
-
- return svn_fs_change_node_prop(rb->txn_root, nb->path,
- name, NULL, nb->pool);
-}
-
-
-static svn_error_t *
-remove_node_props(void *baton)
-{
- struct node_baton *nb = baton;
- struct revision_baton *rb = nb->rb;
- apr_hash_t *proplist;
- apr_hash_index_t *hi;
-
- SVN_ERR(svn_fs_node_proplist(&proplist,
- rb->txn_root, nb->path, nb->pool));
-
- for (hi = apr_hash_first(nb->pool, proplist); hi; hi = apr_hash_next(hi))
- {
- const void *key;
-
- apr_hash_this(hi, &key, NULL, NULL);
-
- SVN_ERR(svn_fs_change_node_prop(rb->txn_root, nb->path,
- (const char *) key, NULL,
- nb->pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-apply_textdelta(svn_txdelta_window_handler_t *handler,
- void **handler_baton,
- void *node_baton)
-{
- struct node_baton *nb = node_baton;
- struct revision_baton *rb = nb->rb;
-
- return svn_fs_apply_textdelta(handler, handler_baton,
- rb->txn_root, nb->path,
- nb->base_checksum ?
- svn_checksum_to_cstring(nb->base_checksum,
- nb->pool) : NULL,
- nb->result_checksum ?
- svn_checksum_to_cstring(nb->result_checksum,
- nb->pool) : NULL,
- nb->pool);
-}
-
-
-static svn_error_t *
-set_fulltext(svn_stream_t **stream,
- void *node_baton)
-{
- struct node_baton *nb = node_baton;
- struct revision_baton *rb = nb->rb;
-
- return svn_fs_apply_text(stream,
- rb->txn_root, nb->path,
- nb->result_checksum ?
- svn_checksum_to_cstring(nb->result_checksum,
- nb->pool) : NULL,
- nb->pool);
-}
-
-
-static svn_error_t *
-close_node(void *baton)
-{
- struct node_baton *nb = baton;
- struct revision_baton *rb = nb->rb;
- struct parse_baton *pb = rb->pb;
-
- if (pb->notify_func)
- {
- pb->notify->action = svn_repos_notify_load_node_done;
- pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-close_revision(void *baton)
-{
- struct revision_baton *rb = baton;
- struct parse_baton *pb = rb->pb;
- const char *conflict_msg = NULL;
- svn_revnum_t *old_rev, *new_rev;
- svn_error_t *err;
-
- if (rb->rev <= 0)
- return SVN_NO_ERROR;
-
- /* Prepare memory for saving dump-rev -> in-repos-rev mapping. */
- old_rev = apr_palloc(pb->pool, sizeof(*old_rev) * 2);
- new_rev = old_rev + 1;
- *old_rev = rb->rev;
-
- /* Run the pre-commit hook, if so commanded. */
- if (pb->use_pre_commit_hook)
- {
- const char *txn_name;
- err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool);
- if (! err)
- err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool);
- if (err)
- {
- svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
- return svn_error_return(err);
- }
- }
-
- /* Commit. */
- if ((err = svn_fs_commit_txn(&conflict_msg, new_rev, rb->txn, rb->pool)))
- {
- svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
- if (conflict_msg)
- return svn_error_quick_wrap(err, conflict_msg);
- else
- return svn_error_return(err);
- }
-
- /* Run post-commit hook, if so commanded. */
- if (pb->use_post_commit_hook)
- {
- if ((err = svn_repos__hooks_post_commit(pb->repos, *new_rev, rb->pool)))
- return svn_error_create
- (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
- _("Commit succeeded, but post-commit hook failed"));
- }
-
- /* After a successful commit, must record the dump-rev -> in-repos-rev
- mapping, so that copyfrom instructions in the dump file can look up the
- correct repository revision to copy from. */
- apr_hash_set(pb->rev_map, old_rev, sizeof(svn_revnum_t), new_rev);
-
- /* If the incoming dump stream has non-contiguous revisions (e.g. from
- using svndumpfilter --drop-empty-revs without --renumber-revs) then
- we must account for the missing gaps in PB->REV_MAP. Otherwise we
- might not be able to map all mergeinfo source revisions to the correct
- revisions in the target repos. */
- if (pb->last_rev_mapped != SVN_INVALID_REVNUM
- && *old_rev != pb->last_rev_mapped + 1)
- {
- svn_revnum_t i;
-
- /* Map all dropped revisions between PB->LAST_REV_MAPPED and OLD_REV. */
- for (i = pb->last_rev_mapped + 1; i < *old_rev; i++)
- {
- svn_revnum_t *gap_rev_old = apr_palloc(pb->pool,
- sizeof(*gap_rev_old));
- svn_revnum_t *gap_rev_new = apr_palloc(pb->pool,
- sizeof(*gap_rev_new));
- *gap_rev_old = i;
- *gap_rev_new = pb->last_rev_mapped;
- apr_hash_set(pb->rev_map, gap_rev_old, sizeof(svn_revnum_t),
- gap_rev_new);
- }
- }
- pb->last_rev_mapped = *old_rev;
-
- /* Deltify the predecessors of paths changed in this revision. */
- SVN_ERR(svn_fs_deltify_revision(pb->fs, *new_rev, rb->pool));
-
- /* Grrr, svn_fs_commit_txn rewrites the datestamp property to the
- current clock-time. We don't want that, we want to preserve
- history exactly. Good thing revision props aren't versioned!
- Note that if rb->datestamp is NULL, that's fine -- if the dump
- data doesn't carry a datestamp, we want to preserve that fact in
- the load. */
- SVN_ERR(svn_fs_change_rev_prop(pb->fs, *new_rev,
- SVN_PROP_REVISION_DATE, rb->datestamp,
- rb->pool));
-
- if (pb->notify_func)
- {
- pb->notify->action = svn_repos_notify_load_txn_committed;
- pb->notify->new_revision = *new_rev;
- pb->notify->old_revision = ((*new_rev == rb->rev)
- ? SVN_INVALID_REVNUM
- : rb->rev);
- pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-
-/*----------------------------------------------------------------------*/
-
-/** The public routines **/
-
-
-svn_error_t *
-svn_repos_get_fs_build_parser3(const svn_repos_parse_fns2_t **callbacks,
- void **parse_baton,
- svn_repos_t *repos,
- svn_boolean_t use_history,
- enum svn_repos_load_uuid uuid_action,
- const char *parent_dir,
- svn_repos_notify_func_t notify_func,
- void *notify_baton,
- apr_pool_t *pool)
-{
- svn_repos_parse_fns2_t *parser = apr_pcalloc(pool, sizeof(*parser));
- struct parse_baton *pb = apr_pcalloc(pool, sizeof(*pb));
-
- parser->new_revision_record = new_revision_record;
- parser->new_node_record = new_node_record;
- parser->uuid_record = uuid_record;
- parser->set_revision_property = set_revision_property;
- parser->set_node_property = set_node_property;
- parser->remove_node_props = remove_node_props;
- parser->set_fulltext = set_fulltext;
- parser->close_node = close_node;
- parser->close_revision = close_revision;
- parser->delete_node_property = delete_node_property;
- parser->apply_textdelta = apply_textdelta;
-
- pb->repos = repos;
- pb->fs = svn_repos_fs(repos);
- pb->use_history = use_history;
- pb->notify_func = notify_func;
- pb->notify_baton = notify_baton;
- pb->notify = svn_repos_notify_create(svn_repos_notify_load_txn_start, pool);
- pb->uuid_action = uuid_action;
- pb->parent_dir = parent_dir;
- pb->pool = pool;
- pb->rev_map = apr_hash_make(pool);
- pb->oldest_old_rev = SVN_INVALID_REVNUM;
- pb->last_rev_mapped = SVN_INVALID_REVNUM;
-
- *callbacks = parser;
- *parse_baton = pb;
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_repos_load_fs3(svn_repos_t *repos,
- svn_stream_t *dumpstream,
- enum svn_repos_load_uuid uuid_action,
- const char *parent_dir,
- svn_boolean_t use_pre_commit_hook,
- svn_boolean_t use_post_commit_hook,
- svn_repos_notify_func_t notify_func,
- void *notify_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-{
- const svn_repos_parse_fns2_t *parser;
- void *parse_baton;
- struct parse_baton *pb;
-
- /* This is really simple. */
-
- SVN_ERR(svn_repos_get_fs_build_parser3(&parser, &parse_baton,
- repos,
- TRUE, /* look for copyfrom revs */
- uuid_action,
- parent_dir,
- notify_func,
- notify_baton,
- pool));
-
- /* Heh. We know this is a parse_baton. This file made it. So
- cast away, and set our hook booleans. */
- pb = parse_baton;
- pb->use_pre_commit_hook = use_pre_commit_hook;
- pb->use_post_commit_hook = use_post_commit_hook;
-
- return svn_repos_parse_dumpstream2(dumpstream, parser, parse_baton,
- cancel_func, cancel_baton, pool);
-}
Modified: subversion/branches/object-model/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_repos/repos.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/object-model/subversion/libsvn_repos/repos.c Wed Oct 20 17:57:41 2010
@@ -1141,6 +1141,13 @@ create_conf(svn_repos_t *repos, apr_pool
"### have the same password database, and vice versa. The default realm" NL
"### is repository's uuid." NL
"# realm = My First Repository" NL
+"### The force-username-case option causes svnserve to case-normalize" NL
+"### usernames before comparing them against the authorization rules in the" NL
+"### authz-db file configured above. Valid values are \"upper\" (to upper-" NL
+"### case the usernames), \"lower\" (to lowercase the usernames), and" NL
+"### \"none\" (to compare usernames as-is without case conversion, which" NL
+"### is the default behavior)." NL
+"# force-username-case = none" NL
"" NL
"[sasl]" NL
"### This option specifies whether you want to use the Cyrus SASL" NL
Modified: subversion/branches/object-model/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_subr/config_file.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/object-model/subversion/libsvn_subr/config_file.c Wed Oct 20 17:57:41 2010
@@ -38,6 +38,11 @@
#include "svn_private_config.h"
+#ifdef __HAIKU__
+# include <FindDirectory.h>
+# include <StorageDefs.h>
+#endif
+
/* Used to terminate lines in large multi-line string literals. */
#define NL APR_EOL_STR
@@ -331,7 +336,19 @@ svn_config__sys_config_path(const char *
SVN_CONFIG__SUBDIRECTORY, fname, NULL);
}
-#else /* ! WIN32 */
+#elif defined(__HAIKU__)
+ {
+ char folder[B_PATH_NAME_LENGTH];
+
+ status_t error = find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false,
+ folder, sizeof(folder));
+ if (error)
+ return SVN_NO_ERROR;
+
+ *path_p = svn_dirent_join_many(pool, folder,
+ SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
+ }
+#else /* ! WIN32 && !__HAIKU__ */
*path_p = svn_dirent_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
@@ -1117,7 +1134,20 @@ svn_config_get_user_config_path(const ch
SVN_CONFIG__SUBDIRECTORY, fname, NULL);
}
-#else /* ! WIN32 */
+#elif defined(__HAIKU__)
+ {
+ char folder[B_PATH_NAME_LENGTH];
+
+ status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false,
+ folder, sizeof(folder));
+ if (error)
+ return SVN_NO_ERROR;
+
+ *path = svn_dirent_join_many(pool, folder,
+ SVN_CONFIG__USR_DIRECTORY, fname, NULL);
+ }
+#else /* ! WIN32 && !__HAIKU__ */
+
{
const char *homedir = svn_user_get_homedir(pool);
if (! homedir)
Modified: subversion/branches/object-model/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_subr/config_impl.h?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/object-model/subversion/libsvn_subr/config_impl.h Wed Oct 20 17:57:41 2010
@@ -114,7 +114,10 @@ svn_error_t *svn_config__parse_registry(
or svn_config_get_user_config_path() instead. */
#ifdef WIN32
# define SVN_CONFIG__SUBDIRECTORY "Subversion"
-#else /* ! WIN32 */
+#elif defined __HAIKU__ /* HAIKU */
+# define SVN_CONFIG__SYS_DIRECTORY "subversion"
+# define SVN_CONFIG__USR_DIRECTORY "subversion"
+#else /* ! WIN32 && ! __HAIKU__ */
# define SVN_CONFIG__SYS_DIRECTORY "/etc/subversion"
# define SVN_CONFIG__USR_DIRECTORY ".subversion"
#endif /* WIN32 */
Modified: subversion/branches/object-model/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_subr/io.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/object-model/subversion/libsvn_subr/io.c Wed Oct 20 17:57:41 2010
@@ -334,6 +334,10 @@ svn_io_open_uniquely_named(apr_file_t **
unsigned int i;
struct temp_file_cleanup_s *baton = NULL;
+ /* At the beginning, we don't know whether unique_path will need
+ UTF8 conversion */
+ svn_boolean_t needs_utf8_conversion = TRUE;
+
SVN_ERR_ASSERT(file || unique_path);
if (dirpath == NULL)
@@ -374,6 +378,11 @@ svn_io_open_uniquely_named(apr_file_t **
if (delete_when == svn_io_file_del_on_close)
flag |= APR_DELONCLOSE;
+ /* Increase the chance that rand() will return something truely
+ independent from what others get or do. */
+ if (i == 2)
+ srand(apr_time_now());
+
/* Special case the first attempt -- if we can avoid having a
generated numeric portion at all, that's best. So first we
try with just the suffix; then future tries add a number
@@ -384,17 +393,35 @@ svn_io_open_uniquely_named(apr_file_t **
This is good, since "1" would misleadingly imply that
the second attempt was actually the first... and if someone's
got conflicts on their conflicts, we probably don't want to
- add to their confusion :-). */
+ add to their confusion :-).
+
+ Also, the randomization used to minimize the number of re-try
+ cycles will interfere with certain tests that compare working
+ copies etc.
+ */
if (i == 1)
unique_name = apr_psprintf(scratch_pool, "%s%s", path, suffix);
else
- unique_name = apr_psprintf(scratch_pool, "%s.%u%s", path, i, suffix);
+ unique_name = apr_psprintf(scratch_pool, "%s.%u_%x%s", path, i, rand(), suffix);
/* Hmmm. Ideally, we would append to a native-encoding buf
before starting iteration, then convert back to UTF-8 for
return. But I suppose that would make the appending code
sensitive to i18n in a way it shouldn't be... Oh well. */
- SVN_ERR(cstring_from_utf8(&unique_name_apr, unique_name, scratch_pool));
+ if (needs_utf8_conversion)
+ {
+ SVN_ERR(cstring_from_utf8(&unique_name_apr, unique_name, scratch_pool));
+ if (i == 1)
+ {
+ /* The variable parts of unique_name will not require UTF8
+ conversion. Therefore, if UTF8 conversion had no effect
+ on it in the first iteration, it won't require conversion
+ in any future interation. */
+ needs_utf8_conversion = strcmp(unique_name_apr, unique_name);
+ }
+ }
+ else
+ unique_name_apr = unique_name;
apr_err = file_open(&try_file, unique_name_apr, flag,
APR_OS_DEFAULT, FALSE, result_pool);
Modified: subversion/branches/object-model/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/adm_ops.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/adm_ops.c Wed Oct 20 17:57:41 2010
@@ -735,28 +735,128 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_wc_add4(svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- svn_depth_t depth,
- const char *copyfrom_url,
- svn_revnum_t copyfrom_rev,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
+/* Schedule the single node at LOCAL_ABSPATH, of kind KIND, for addition in
+ * its parent directory in the WC. It will have no properties. */
+static svn_error_t *
+add_from_disk(svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ svn_node_kind_t kind,
+ apr_pool_t *scratch_pool)
{
- const char *parent_abspath;
- const char *base_name;
- const char *parent_repos_relpath;
- const char *repos_root_url, *repos_uuid;
- svn_boolean_t is_wc_root = FALSE;
- svn_node_kind_t kind;
svn_wc__db_t *db = wc_ctx->db;
+
+ if (kind == svn_node_file)
+ {
+ SVN_ERR(svn_wc__db_op_add_file(db, local_abspath, NULL, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_wc__db_op_add_directory(db, local_abspath, NULL,
+ scratch_pool));
+ }
+ return SVN_NO_ERROR;
+}
+
+/* Set *REPOS_ROOT_URL and *REPOS_UUID to the repository of the parent of
+ LOCAL_ABSPATH. REPOS_ROOT_URL and/or REPOS_UUID may be NULL if not
+ wanted. Check that the parent of LOCAL_ABSPATH is a versioned directory
+ in a state in which a new child node can be scheduled for addition;
+ return an error if not. */
+static svn_error_t *
+check_can_add_to_parent(svn_wc__db_t *db,
+ const char **repos_root_url,
+ const char **repos_uuid,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+ svn_wc__db_status_t parent_status;
+ svn_wc__db_kind_t parent_kind;
svn_error_t *err;
- svn_wc__db_status_t status;
- svn_wc__db_kind_t db_kind;
+
+ SVN_ERR(svn_wc__write_check(db, parent_abspath, scratch_pool));
+
+ err = svn_wc__db_read_info(&parent_status, &parent_kind, NULL,
+ NULL, repos_root_url,
+ repos_uuid, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ db, parent_abspath, scratch_pool, scratch_pool);
+
+ if (err
+ || parent_status == svn_wc__db_status_not_present
+ || parent_status == svn_wc__db_status_excluded
+ || parent_status == svn_wc__db_status_absent)
+ {
+ return
+ svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, err,
+ _("Can't find parent directory's node while"
+ " trying to add '%s'"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+ else if (parent_status == svn_wc__db_status_deleted)
+ {
+ return
+ svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
+ _("Can't add '%s' to a parent directory"
+ " scheduled for deletion"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+ else if (parent_kind != svn_wc__db_kind_dir)
+ /* Can't happen until single db; but then it causes serious
+ trouble if we allow this. */
+ return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+ _("Can't schedule an addition of '%s'"
+ " below a not-directory node"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
+ /* If we haven't found the repository info yet, find it now. */
+ if ((repos_root_url && ! *repos_root_url)
+ || (repos_uuid && ! *repos_uuid))
+ {
+ if (parent_status == svn_wc__db_status_added)
+ SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
+ repos_root_url, repos_uuid, NULL,
+ NULL, NULL, NULL,
+ db, parent_abspath,
+ scratch_pool, scratch_pool));
+ else
+ SVN_ERR(svn_wc__db_scan_base_repos(NULL,
+ repos_root_url, repos_uuid,
+ db, parent_abspath,
+ scratch_pool, scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Check that the on-disk item at LOCAL_ABSPATH can be scheduled for
+ * addition to its WC parent directory.
+ *
+ * Set *KIND_P to the kind of node to be added, *DB_ROW_EXISTS_P to whether
+ * it is already a versioned path, and if so, *IS_WC_ROOT_P to whether it's
+ * a WC root.
+ *
+ * ### The checks here, and the outputs, are geared towards svn_wc_add4().
+ */
+static svn_error_t *
+check_can_add_node(svn_node_kind_t *kind_p,
+ svn_boolean_t *db_row_exists_p,
+ svn_boolean_t *is_wc_root_p,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ const char *copyfrom_url,
+ svn_revnum_t copyfrom_rev,
+ apr_pool_t *scratch_pool)
+{
+ const char *base_name = svn_dirent_basename(local_abspath, scratch_pool);
+ svn_boolean_t is_wc_root;
+ svn_node_kind_t kind;
+ svn_wc__db_t *db = wc_ctx->db;
svn_boolean_t exists;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -764,7 +864,7 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
scratch_pool)
&& SVN_IS_VALID_REVNUM(copyfrom_rev)));
- svn_dirent_split(&parent_abspath, &base_name, local_abspath, scratch_pool);
+ /* Check that the proposed node has an acceptable name. */
if (svn_wc_is_adm_dir(base_name, scratch_pool))
return svn_error_createf
(SVN_ERR_ENTRY_FORBIDDEN, NULL,
@@ -773,7 +873,7 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
SVN_ERR(svn_path_check_valid(local_abspath, scratch_pool));
- /* Make sure something's there. */
+ /* Make sure something's there; set KIND and *KIND_P. */
SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
if (kind == svn_node_none)
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
@@ -785,122 +885,106 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
_("Unsupported node kind for path '%s'"),
svn_dirent_local_style(local_abspath,
scratch_pool));
+ if (kind_p)
+ *kind_p = kind;
- /* Get the node information for this path if one exists (perhaps
- this is actually a replacement of a previously deleted thing). */
- err = svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL, NULL,
+ /* Determine whether a DB row for this node EXISTS, and whether it
+ IS_WC_ROOT. If it exists, check that it is in an acceptable state for
+ adding the new node; if not, return an error. */
+ {
+ svn_wc__db_status_t status;
+ svn_error_t *err
+ = svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool);
- if (err)
- {
- if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_return(err);
-
- svn_error_clear(err);
- exists = FALSE;
- is_wc_root = FALSE;
- }
- else
- {
- is_wc_root = FALSE;
- exists = TRUE;
- switch (status)
- {
- case svn_wc__db_status_not_present:
- break;
- case svn_wc__db_status_deleted:
- /* A working copy root should never have a WORKING_NODE */
- SVN_ERR_ASSERT(!is_wc_root);
- break;
- case svn_wc__db_status_normal:
- if (copyfrom_url)
- {
- SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
- db, local_abspath,
- scratch_pool));
-
- if (is_wc_root)
- break;
- }
- /* else: Fall through in default error */
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_return(err);
- default:
- return svn_error_createf(
- SVN_ERR_ENTRY_EXISTS, NULL,
- _("'%s' is already under version control"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
- }
- } /* err */
+ svn_error_clear(err);
+ exists = FALSE;
+ is_wc_root = FALSE;
+ }
+ else
+ {
+ is_wc_root = FALSE;
+ exists = TRUE;
+ switch (status)
+ {
+ case svn_wc__db_status_not_present:
+ break;
+ case svn_wc__db_status_deleted:
+ /* A working copy root should never have a WORKING_NODE */
+ SVN_ERR_ASSERT(!is_wc_root);
+ break;
+ case svn_wc__db_status_normal:
+ if (copyfrom_url)
+ {
+ SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
+ db, local_abspath,
+ scratch_pool));
- SVN_ERR(svn_wc__write_check(db, parent_abspath, scratch_pool));
+ if (is_wc_root)
+ break;
+ }
+ /* else: Fall through in default error */
- {
- svn_wc__db_status_t parent_status;
- svn_wc__db_kind_t parent_kind;
+ default:
+ return svn_error_createf(
+ SVN_ERR_ENTRY_EXISTS, NULL,
+ _("'%s' is already under version control"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+ } /* err */
- err = svn_wc__db_read_info(&parent_status, &parent_kind, NULL,
- &parent_repos_relpath, &repos_root_url,
- &repos_uuid, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- db, parent_abspath, scratch_pool, scratch_pool);
+ if (db_row_exists_p)
+ *db_row_exists_p = exists;
+ if (is_wc_root_p)
+ *is_wc_root_p = is_wc_root;
+ }
- if (err
- || parent_status == svn_wc__db_status_not_present
- || parent_status == svn_wc__db_status_excluded
- || parent_status == svn_wc__db_status_absent)
- {
- return
- svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, err,
- _("Can't find parent directory's node while"
- " trying to add '%s'"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
- }
- else if (parent_status == svn_wc__db_status_deleted)
- {
- return
- svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
- _("Can't add '%s' to a parent directory"
- " scheduled for deletion"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
- }
- else if (parent_kind != svn_wc__db_kind_dir)
- /* Can't happen until single db; but then it causes serious
- trouble if we allow this. */
- return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
- _("Can't schedule an addition of '%s'"
- " below a not-directory node"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
+ return SVN_NO_ERROR;
+}
- if (!repos_root_url)
- {
- if (parent_status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &parent_repos_relpath,
- &repos_root_url, &repos_uuid, NULL,
- NULL, NULL, NULL,
- db, parent_abspath,
- scratch_pool, scratch_pool));
- else
- SVN_ERR(svn_wc__db_scan_base_repos(&parent_repos_relpath,
- &repos_root_url, &repos_uuid,
- db, parent_abspath,
- scratch_pool, scratch_pool));
- }
+svn_error_t *
+svn_wc_add4(svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ svn_depth_t depth,
+ const char *copyfrom_url,
+ svn_revnum_t copyfrom_rev,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_t *db = wc_ctx->db;
+ svn_node_kind_t kind;
+ svn_boolean_t db_row_exists, is_wc_root;
+ const char *repos_root_url, *repos_uuid;
- if (copyfrom_url
- && !svn_uri_is_ancestor(repos_root_url, copyfrom_url))
- return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("The URL '%s' has a different repository "
- "root than its parent"), copyfrom_url);
- }
+ SVN_ERR(check_can_add_node(&kind, &db_row_exists, &is_wc_root,
+ wc_ctx, local_abspath, copyfrom_url, copyfrom_rev,
+ scratch_pool));
+
+ /* Get REPOS_ROOT_URL and REPOS_UUID. Check that the
+ parent is a versioned directory in an acceptable state. */
+ SVN_ERR(check_can_add_to_parent(db, &repos_root_url, &repos_uuid,
+ local_abspath, scratch_pool, scratch_pool));
+
+ /* If we're performing a repos-to-WC copy, check that the copyfrom
+ repository is the same as the parent dir's repository. */
+ if (copyfrom_url
+ && !svn_uri_is_ancestor(repos_root_url, copyfrom_url))
+ return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("The URL '%s' has a different repository "
+ "root than its parent"), copyfrom_url);
/* Verify that we can actually integrate the inner working copy */
if (is_wc_root)
@@ -943,11 +1027,27 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
copyfrom_url, inner_url);
}
- if (kind == svn_node_file)
+ if (!copyfrom_url) /* Case 2a: It's a simple add */
{
- if (!copyfrom_url)
- SVN_ERR(svn_wc__db_op_add_file(db, local_abspath, NULL, scratch_pool));
- else
+ SVN_ERR(add_from_disk(wc_ctx, local_abspath, kind, scratch_pool));
+ if (kind == svn_node_dir && !db_row_exists)
+ {
+ /* If using the legacy 1.6 interface the parent lock may not
+ be recursive and add is expected to lock the new dir.
+
+ ### Perhaps the lock should be created in the same
+ transaction that adds the node? */
+ svn_boolean_t owns_lock;
+ SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, local_abspath,
+ FALSE, scratch_pool));
+ if (!owns_lock)
+ SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
+ scratch_pool));
+ }
+ }
+ else if (!is_wc_root) /* Case 2b: It's a copy from the repository */
+ {
+ if (kind == svn_node_file)
{
/* This code should never be used, as it doesn't install proper
pristine and/or properties. But it was not an error in the old
@@ -964,46 +1064,27 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
NULL, NULL,
scratch_pool));
}
+ else
+ SVN_ERR(svn_wc__db_op_copy_dir(db,
+ local_abspath,
+ apr_hash_make(scratch_pool),
+ copyfrom_rev,
+ 0,
+ NULL,
+ svn_path_uri_decode(
+ svn_uri_skip_ancestor(repos_root_url,
+ copyfrom_url),
+ scratch_pool),
+ repos_root_url,
+ repos_uuid,
+ copyfrom_rev,
+ NULL,
+ depth,
+ NULL,
+ NULL,
+ scratch_pool));
}
- else if (!copyfrom_url)
- {
- SVN_ERR(svn_wc__db_op_add_directory(db, local_abspath, NULL,
- scratch_pool));
- if (!exists)
- {
- /* If using the legacy 1.6 interface the parent lock may not
- be recursive and add is expected to lock the new dir.
-
- ### Perhaps the lock should be created in the same
- transaction that adds the node? */
- svn_boolean_t owns_lock;
- SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, local_abspath,
- FALSE, scratch_pool));
- if (!owns_lock)
- SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
- scratch_pool));
- }
- }
- else if (!is_wc_root)
- SVN_ERR(svn_wc__db_op_copy_dir(db,
- local_abspath,
- apr_hash_make(scratch_pool),
- copyfrom_rev,
- 0,
- NULL,
- svn_path_uri_decode(
- svn_uri_skip_ancestor(repos_root_url,
- copyfrom_url),
- scratch_pool),
- repos_root_url,
- repos_uuid,
- copyfrom_rev,
- NULL,
- depth,
- NULL,
- NULL,
- scratch_pool));
- else
+ else /* Case 1: Integrating a separate WC into this one, in place */
{
svn_boolean_t owns_lock;
const char *tmpdir_abspath, *moved_abspath, *moved_adm_abspath;
@@ -1015,7 +1096,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
/* Move the admin dir from the wc to a temporary location */
SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, db,
- parent_abspath,
+ svn_dirent_dirname(local_abspath,
+ scratch_pool),
scratch_pool, scratch_pool));
SVN_ERR(svn_io_open_unique_file3(NULL, &moved_abspath, tmpdir_abspath,
svn_io_file_del_on_close,
@@ -1058,6 +1140,37 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
}
svn_error_t *
+svn_wc_add_from_disk(svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_node_kind_t kind;
+
+ SVN_ERR(check_can_add_node(&kind, NULL, NULL, wc_ctx, local_abspath,
+ NULL, SVN_INVALID_REVNUM, scratch_pool));
+ SVN_ERR(check_can_add_to_parent(wc_ctx->db, NULL, NULL,
+ local_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(add_from_disk(wc_ctx, local_abspath, kind, scratch_pool));
+
+ /* Report the addition to the caller. */
+ if (notify_func != NULL)
+ {
+ svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath,
+ svn_wc_notify_add,
+ scratch_pool);
+ notify->kind = kind;
+ (*notify_func)(notify_baton, notify, scratch_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_wc__register_file_external(svn_wc_context_t *wc_ctx,
const char *local_abspath,
const char *external_url,
@@ -1133,183 +1246,6 @@ svn_wc__register_file_external(svn_wc_co
*/
-/* */
-static svn_error_t *
-revert_admin_things(svn_boolean_t *reverted,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_boolean_t use_commit_times,
- apr_pool_t *pool)
-{
- SVN_ERR(svn_wc__wq_add_revert(reverted, db, local_abspath, use_commit_times,
- pool));
- SVN_ERR(svn_wc__wq_run(db, local_abspath, NULL, NULL, pool));
-
- return SVN_NO_ERROR;
-}
-
-
-/* Revert LOCAL_ABSPATH in DB, where the on-disk node kind is DISK_KIND.
- *DEPTH is the depth of the reversion crawl the caller is
- using; this function may choose to override that value as needed.
-
- See svn_wc_revert4() for the interpretations of
- USE_COMMIT_TIMES, CANCEL_FUNC and CANCEL_BATON.
-
- Set *DID_REVERT to true if actually reverting anything, else do not
- touch *DID_REVERT.
-
- Use POOL for allocations.
- */
-static svn_error_t *
-revert_entry(svn_depth_t *depth,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_node_kind_t disk_kind,
- svn_boolean_t use_commit_times,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_boolean_t *did_revert,
- apr_pool_t *pool)
-{
- svn_wc__db_status_t status, base_status;
- svn_wc__db_kind_t kind, base_kind;
- svn_boolean_t replaced;
- svn_boolean_t have_base;
- svn_revnum_t base_revision;
- svn_boolean_t is_add_root;
-
- /* Initialize this even though revert_admin_things() is guaranteed
- to set it, because we don't know that revert_admin_things() will
- be called. */
- svn_boolean_t reverted = FALSE;
-
- SVN_ERR(svn_wc__db_read_info(&status, &kind,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &have_base, NULL,
- NULL, NULL,
- db, local_abspath, pool, pool));
-
- if (have_base)
- SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, &base_revision,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, local_abspath, pool, pool));
-
- replaced = (status == svn_wc__db_status_added
- && have_base
- && base_status != svn_wc__db_status_not_present);
-
- if (status == svn_wc__db_status_added)
- {
- const char *op_root_abspath;
- SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, local_abspath, pool, pool));
-
- is_add_root = (strcmp(op_root_abspath, local_abspath) == 0);
- }
- else
- is_add_root = FALSE;
-
- /* Additions. */
- if (!replaced
- && is_add_root)
- {
- const char *repos_relpath;
- const char *repos_root_url;
- const char *repos_uuid;
- /* Before removing item from revision control, notice if the
- BASE_NODE is in a 'not-present' state. */
- svn_boolean_t was_not_present = FALSE;
-
- /* NOTE: if WAS_NOT_PRESENT gets set, then we have BASE nodes.
- The code below will then figure out the repository information, so
- that we can later insert a node for the same repository. */
-
- if (have_base
- && base_status == svn_wc__db_status_not_present)
- {
- /* Remember the BASE revision. (already handled) */
- /* Remember the repository this node is associated with. */
-
- was_not_present = TRUE;
-
- SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
- &repos_root_url,
- &repos_uuid,
- db, local_abspath,
- pool, pool));
- }
-
- /* ### much of this is probably bullshit. we should be able to just
- ### remove the WORKING and ACTUAL rows, and be done. but we're
- ### not quite there yet, so nodes get fully removed and then
- ### shoved back into the database. this is why we need to record
- ### the repository information, and the BASE revision. */
-
- if (kind == svn_wc__db_kind_file
- || kind == svn_wc__db_kind_dir)
- {
- SVN_ERR(svn_wc__internal_remove_from_revision_control(db,
- local_abspath,
- FALSE, FALSE,
- cancel_func,
- cancel_baton,
- pool));
- }
- else /* Else it's `none', or something exotic like a symlink... */
- {
- return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
- _("Unknown or unexpected kind for path "
- "'%s'"),
- svn_dirent_local_style(local_abspath,
- pool));
-
- }
-
- /* Recursivity is taken care of by svn_wc_remove_from_revision_control,
- and we've definitely reverted PATH at this point. */
- *depth = svn_depth_empty;
- reverted = TRUE;
-
- /* If the removed item was *also* in a 'not-present' state, make
- sure we leave a not-present node behind */
- if (was_not_present)
- {
- SVN_ERR(svn_wc__db_base_add_not_present_node(
- db, local_abspath,
- repos_relpath, repos_root_url, repos_uuid,
- base_revision,
- base_kind,
- NULL, NULL,
- pool));
- }
- }
- /* Regular prop and text edit. */
- /* Deletions and replacements. */
- else if (status == svn_wc__db_status_normal
- || status == svn_wc__db_status_deleted
- || replaced
- || (status == svn_wc__db_status_added && !is_add_root))
- {
- /* Revert the prop and text mods (if any). */
- SVN_ERR(revert_admin_things(&reverted, db, local_abspath,
- use_commit_times, pool));
-
- /* Force recursion on replaced directories. */
- if (kind == svn_wc__db_kind_dir && replaced)
- *depth = svn_depth_infinity;
- }
-
- /* If PATH was reverted, tell our client that. */
- if (reverted)
- *did_revert = TRUE;
-
- return SVN_NO_ERROR;
-}
-
/* Verifies if an add (or copy) to LOCAL_ABSPATH can be reverted with depth
* DEPTH, without touching nodes that are filtered by DEPTH.
*
@@ -1383,6 +1319,7 @@ verify_revert_depth(svn_wc__db_t *db,
documentation. */
static svn_error_t *
revert_internal(svn_wc__db_t *db,
+ const char *revert_root,
const char *local_abspath,
svn_depth_t depth,
svn_boolean_t use_commit_times,
@@ -1394,10 +1331,13 @@ revert_internal(svn_wc__db_t *db,
apr_pool_t *pool)
{
svn_node_kind_t disk_kind;
- svn_wc__db_status_t status;
+ svn_wc__db_status_t status, base_status;
svn_wc__db_kind_t db_kind;
svn_boolean_t unversioned;
+ svn_boolean_t have_base;
+ svn_boolean_t replaced;
const svn_wc_conflict_description2_t *tree_conflict;
+ const char *op_root_abspath = NULL;
svn_error_t *err;
/* Check cancellation here, so recursive calls get checked early. */
@@ -1410,7 +1350,7 @@ revert_internal(svn_wc__db_t *db,
err = svn_wc__db_read_info(&status, &db_kind,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, &have_base, NULL, NULL,
NULL,
db, local_abspath, pool, pool);
@@ -1429,11 +1369,30 @@ revert_internal(svn_wc__db_t *db,
case svn_wc__db_status_excluded:
unversioned = TRUE;
break;
+ case svn_wc__db_status_incomplete:
+ /* Remove NAME from PATH's entries file
+
+ Not being able to revert incomplete entries breaks working
+ copies flat out, but the usual revert process can't be
+ applied. Most preconditions aren't met. */
+ SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath, pool));
+ return SVN_NO_ERROR;
+ break;
default:
unversioned = FALSE;
break;
}
+ if (! unversioned && have_base)
+ SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath, pool, pool));
+
+ replaced = ! unversioned && (status == svn_wc__db_status_added
+ && have_base
+ && base_status != svn_wc__db_status_not_present);
+
SVN_ERR(svn_wc__db_op_read_tree_conflict(&tree_conflict, db, local_abspath,
pool, pool));
if (unversioned && tree_conflict == NULL)
@@ -1482,17 +1441,17 @@ revert_internal(svn_wc__db_t *db,
_("Cannot revert '%s': unsupported node kind in working copy"),
svn_dirent_local_style(local_abspath, pool));
+ if (status == svn_wc__db_status_added)
+ SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath, pool, pool));
+
/* Safeguard 4: Make sure we don't revert deeper then asked */
if (status == svn_wc__db_status_added
&& db_kind == svn_wc__db_kind_dir
&& depth >= svn_depth_empty
&& depth < svn_depth_infinity)
{
- const char *op_root_abspath;
- SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, local_abspath, pool, pool));
-
/* If this node is an operation root for a copy/add, then reverting
it will change its descendants, if it has any. */
if (strcmp(local_abspath, op_root_abspath) == 0)
@@ -1521,10 +1480,19 @@ revert_internal(svn_wc__db_t *db,
/* Actually revert this entry. If this is a working copy root,
we provide a base_name from the parent path. */
if (!unversioned)
- SVN_ERR(revert_entry(&depth, db, local_abspath, disk_kind,
- use_commit_times,
- cancel_func, cancel_baton,
- &reverted, pool));
+ {
+ /* Revert the prop, text and tree mods (if any). */
+ SVN_ERR(svn_wc__wq_add_revert(&reverted, db, revert_root,
+ local_abspath, use_commit_times,
+ pool));
+ SVN_ERR(svn_wc__wq_run(db, local_abspath,
+ cancel_func, cancel_baton, pool));
+
+ /* Force recursion on replaced directories. */
+ if (db_kind == svn_wc__db_kind_dir && replaced)
+ depth = svn_depth_infinity;
+
+ }
/* Notify */
if (notify_func && reverted)
@@ -1534,6 +1502,15 @@ revert_internal(svn_wc__db_t *db,
pool);
}
+
+ if (op_root_abspath && strcmp(local_abspath, op_root_abspath) == 0)
+ /* If this is a copy or add root, disable notifications for the children,
+ because wc-1.0 used to behave like that. */
+ {
+ notify_func = NULL;
+ notify_baton = NULL;
+ }
+
/* Finally, recurse if requested. */
if (!unversioned && db_kind == svn_wc__db_kind_dir && depth > svn_depth_empty)
{
@@ -1577,7 +1554,7 @@ revert_internal(svn_wc__db_t *db,
continue;
/* Revert the entry. */
- SVN_ERR(revert_internal(db, node_abspath,
+ SVN_ERR(revert_internal(db, revert_root, node_abspath,
depth_under_here, use_commit_times,
changelist_hash, cancel_func, cancel_baton,
notify_func, notify_baton, iterpool));
@@ -1621,7 +1598,8 @@ revert_internal(svn_wc__db_t *db,
const svn_wc_conflict_description2_t *);
if (conflict->kind == svn_wc_conflict_kind_tree)
- SVN_ERR(revert_internal(db, conflict->local_abspath,
+ SVN_ERR(revert_internal(db, revert_root,
+ conflict->local_abspath,
svn_depth_empty,
use_commit_times, changelist_hash,
cancel_func, cancel_baton,
@@ -1634,6 +1612,14 @@ revert_internal(svn_wc__db_t *db,
svn_pool_destroy(iterpool);
}
+ if (! replaced && status == svn_wc__db_status_added
+ && db_kind == svn_wc__db_kind_dir)
+ {
+ /* Non-replacements have their admin area deleted. wc-1.0 */
+ SVN_ERR(svn_wc__adm_destroy(db, local_abspath,
+ cancel_func, cancel_baton, pool));
+ }
+
return SVN_NO_ERROR;
}
@@ -1656,7 +1642,7 @@ svn_wc_revert4(svn_wc_context_t *wc_ctx,
SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelists, pool));
return svn_error_return(revert_internal(wc_ctx->db,
- local_abspath, depth,
+ local_abspath, local_abspath, depth,
use_commit_times, changelist_hash,
cancel_func, cancel_baton,
notify_func, notify_baton,
Modified: subversion/branches/object-model/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/copy.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/copy.c Wed Oct 20 17:57:41 2010
@@ -238,10 +238,22 @@ copy_versioned_file(svn_wc__db_t *db,
tmpdir_abspath,
TRUE, /* recursive */
cancel_func, cancel_baton, scratch_pool));
+
if (tmp_dst_abspath)
{
svn_skel_t *work_item;
+ /* Remove 'read-only' from the destination file; it's a local add. */
+ {
+ const svn_string_t *needs_lock;
+ SVN_ERR(svn_wc__internal_propget(&needs_lock, db, src_abspath,
+ SVN_PROP_NEEDS_LOCK,
+ scratch_pool, scratch_pool));
+ if (needs_lock)
+ SVN_ERR(svn_io_set_file_read_write(tmp_dst_abspath,
+ FALSE, scratch_pool));
+ }
+
SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
tmp_dst_abspath, dst_abspath,
scratch_pool, scratch_pool));
Modified: subversion/branches/object-model/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/props.c?rev=1025655&r1=1025654&r2=1025655&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/props.c Wed Oct 20 17:57:41 2010
@@ -139,30 +139,9 @@ svn_wc__get_prejfile_abspath(const char
static svn_error_t *
immediate_install_props(svn_wc__db_t *db,
const char *local_abspath,
- svn_wc__db_kind_t kind,
apr_hash_t *working_props,
apr_pool_t *scratch_pool)
{
- apr_hash_t *base_props;
-
- /* ### no pristines should be okay. */
- SVN_ERR_W(svn_wc__db_read_pristine_props(&base_props, db, local_abspath,
- scratch_pool, scratch_pool),
- _("Failed to load pristine properties"));
-
- /* Check if the props are modified. If no changes, then wipe out
- the ACTUAL props. No pristines defined means that any ACTUAL
- props are okay, so go ahead and set them. */
- if (base_props != NULL)
- {
- apr_array_header_t *prop_diffs;
-
- SVN_ERR(svn_prop_diffs(&prop_diffs, working_props, base_props,
- scratch_pool));
- if (prop_diffs->nelts == 0)
- working_props = NULL;
- }
-
SVN_ERR(svn_wc__db_op_set_props(db, local_abspath,
working_props,
NULL /* conflict */,
@@ -350,7 +329,6 @@ svn_wc__perform_props_merge(svn_wc_notif
{
svn_wc__db_status_t status;
svn_boolean_t have_base;
- apr_array_header_t *prop_diffs;
SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -365,41 +343,18 @@ svn_wc__perform_props_merge(svn_wc_notif
SVN_ERR(svn_wc__db_temp_base_set_props(db, local_abspath,
new_base_props, pool));
- /* Check if the props are modified. */
- SVN_ERR(svn_prop_diffs(&prop_diffs, actual_props, new_base_props, pool));
-
- /* Save the actual properties file if it differs from base. */
- if (prop_diffs->nelts == 0)
- SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, NULL, NULL, NULL,
- pool));
- else
- SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
- NULL, NULL, pool));
+ SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
+ NULL, NULL, pool));
}
#else
if (base_merge)
return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
U_("base_merge=TRUE is no longer supported"));
- {
- apr_array_header_t *prop_diffs;
-
- SVN_ERR(svn_prop_diffs(&prop_diffs, new_actual_props, new_base_props,
- pool));
-
- /* Save the actual properties file if it differs from base. */
- if (prop_diffs->nelts == 0)
- new_actual_props = NULL; /* Remove actual properties*/
-
- /* For the old school: write the properties into the "working"
- (aka ACTUAL) location. Note that PROPS may be NULL, indicating
- a removal of the props file. */
-
- SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props,
- NULL /* conflict */,
- NULL /* work_item */,
- pool));
- }
+ SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props,
+ NULL /* conflict */,
+ NULL /* work_item */,
+ pool));
#endif
SVN_ERR(svn_wc__wq_run(db, local_abspath,
@@ -2185,7 +2140,7 @@ svn_wc__internal_propset(svn_wc__db_t *d
/* Drop it right onto the disk. We don't need loggy since we aren't
coordinating this change with anything else. */
- SVN_ERR(immediate_install_props(db, local_abspath, kind, prophash,
+ SVN_ERR(immediate_install_props(db, local_abspath, prophash,
scratch_pool));
if (notify_func)