summaryrefslogtreecommitdiff
path: root/subversion/svnrdump/load_editor.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-08-05 16:22:51 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-08-05 16:22:51 +0000
commitcf46733632c7279a9fd0fe6ce26f9185a4ae82a9 (patch)
treeda27775a2161723ef342e91af41a8b51fedef405 /subversion/svnrdump/load_editor.c
parentbb0ef45f7c46b0ae221b26265ef98a768c33f820 (diff)
downloadsubversion-tarball-master.tar.gz
Diffstat (limited to 'subversion/svnrdump/load_editor.c')
-rw-r--r--subversion/svnrdump/load_editor.c309
1 files changed, 57 insertions, 252 deletions
diff --git a/subversion/svnrdump/load_editor.c b/subversion/svnrdump/load_editor.c
index c35a289..15dac6e 100644
--- a/subversion/svnrdump/load_editor.c
+++ b/subversion/svnrdump/load_editor.c
@@ -43,14 +43,7 @@
#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
-#if 0
-#define LDR_DBG(x) SVN_DBG(x)
-#else
-#define LDR_DBG(x) while(0)
-#endif
-
-
/**
* General baton used by the parser functions.
*/
@@ -68,9 +61,6 @@ struct parse_baton
/* To bleep, or not to bleep? (What kind of question is that?) */
svn_boolean_t quiet;
- /* UUID found in the dumpstream, if any; NULL otherwise. */
- const char *uuid;
-
/* Root URL of the target repository. */
const char *root_url;
@@ -93,17 +83,20 @@ struct parse_baton
/* The oldest revision loaded from the dump stream, or
SVN_INVALID_REVNUM if none have been loaded. */
svn_revnum_t oldest_dumpstream_rev;
+
+ /* An hash containing specific revision properties to skip while
+ loading. */
+ apr_hash_t *skip_revprops;
};
/**
* Use to wrap the dir_context_t in commit.c so we can keep track of
- * depth, relpath and parent for open_directory and close_directory.
+ * relpath and parent for open_directory and close_directory.
*/
struct directory_baton
{
void *baton;
const char *relpath;
- int depth;
/* The copy-from source of this directory, no matter whether it is
copied explicitly (the root node of a copy) or implicitly (being an
@@ -190,160 +183,6 @@ get_revision_mapping(apr_hash_t *rev_map,
}
-/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with
- PARENT_DIR, and return it in *MERGEINFO_VAL. */
-/* ### FIXME: Consider somehow sharing code with
- ### libsvn_repos/load-fs-vtable.c:prefix_mergeinfo_paths() */
-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 = svn_relpath_canonicalize(key, pool);
-
- /* The svn:mergeinfo property syntax demands a repos abspath */
- path = svn_fspath__canonicalize(svn_relpath_join(parent_dir,
- merge_source, pool),
- pool);
- svn_hash_sets(prefixed_mergeinfo, path, 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). */
-/* ### FIXME: Consider somehow sharing code with
- ### libsvn_repos/load-fs-vtable.c:renumber_mergeinfo_revs() */
-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_dumpstream_rev > 1)
- {
- SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
- &predates_stream_mergeinfo, mergeinfo,
- rb->pb->oldest_dumpstream_rev - 1, 0,
- TRUE, subpool, subpool));
- SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
- &mergeinfo, mergeinfo,
- rb->pb->oldest_dumpstream_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))
- {
- svn_rangelist_t *rangelist;
- struct parse_baton *pb = rb->pb;
- int i;
- const void *path;
- apr_ssize_t pathlen;
- void *val;
-
- apr_hash_this(hi, &path, &pathlen, &val);
- 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 = get_revision_mapping(pb->rev_map, range->start);
- if (SVN_IS_VALID_REVNUM(rev_from_map))
- {
- range->start = rev_from_map;
- }
- else if (range->start == pb->oldest_dumpstream_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 = get_revision_mapping(pb->rev_map,
- pb->oldest_dumpstream_rev);
- if (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 = get_revision_mapping(pb->rev_map, range->end);
- if (SVN_IS_VALID_REVNUM(rev_from_map))
- range->end = rev_from_map;
- }
- apr_hash_set(final_mergeinfo, path, pathlen, rangelist);
- }
-
- if (predates_stream_mergeinfo)
- {
- SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
- subpool, subpool));
- }
-
- SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
-
- SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
- svn_pool_destroy(subpool);
-
- return SVN_NO_ERROR;
-}
-
-
static svn_error_t *
commit_callback(const svn_commit_info_t *commit_info,
void *baton,
@@ -564,8 +403,8 @@ new_revision_record(void **revision_baton,
for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
{
- const char *hname = svn__apr_hash_index_key(hi);
- const char *hval = svn__apr_hash_index_val(hi);
+ const char *hname = apr_hash_this_key(hi);
+ const char *hval = apr_hash_this_val(hi);
if (strcmp(hname, SVN_REPOS_DUMPFILE_REVISION_NUMBER) == 0)
rb->rev = atoi(hval);
@@ -606,9 +445,6 @@ uuid_record(const char *uuid,
void *parse_baton,
apr_pool_t *pool)
{
- struct parse_baton *pb;
- pb = parse_baton;
- pb->uuid = apr_pstrdup(pool, uuid);
return SVN_NO_ERROR;
}
@@ -704,8 +540,6 @@ new_node_record(void **node_baton,
rb->rev - rb->rev_offset - 1,
rb->pool, &child_baton));
- LDR_DBG(("Opened root %p\n", child_baton));
-
/* child_baton corresponds to the root directory baton here */
push_directory(rb, child_baton, "", TRUE /*is_added*/,
NULL, SVN_INVALID_REVNUM);
@@ -713,8 +547,8 @@ new_node_record(void **node_baton,
for (hi = apr_hash_first(rb->pool, headers); hi; hi = apr_hash_next(hi))
{
- const char *hname = svn__apr_hash_index_key(hi);
- const char *hval = svn__apr_hash_index_val(hi);
+ const char *hname = apr_hash_this_key(hi);
+ const char *hval = apr_hash_this_val(hi);
/* Parse the different kinds of headers we can encounter and
stuff them into the node_baton for writing later */
@@ -741,6 +575,9 @@ new_node_record(void **node_baton,
nb->copyfrom_path = apr_pstrdup(rb->pool, hval);
}
+ /* Before handling the new node, ensure depth-first editing order by
+ traversing the directory hierarchy from the old node's to the new
+ node's parent directory. */
nb_dirname = svn_relpath_dirname(nb->path, pool);
if (svn_path_compare_paths(nb_dirname,
rb->db->relpath) != 0)
@@ -751,9 +588,6 @@ new_node_record(void **node_baton,
int i;
apr_size_t n;
- /* Before attempting to handle the action, call open_directory
- for all the path components and set the directory baton
- accordingly */
ancestor_path =
svn_relpath_get_longest_ancestor(nb_dirname,
rb->db->relpath, pool);
@@ -771,7 +605,6 @@ new_node_record(void **node_baton,
/* Don't worry about destroying the actual rb->db object,
since the pool we're using has the lifetime of one
revision anyway */
- LDR_DBG(("Closing dir %p\n", rb->db->baton));
SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
rb->db = rb->db->parent;
}
@@ -786,7 +619,6 @@ new_node_record(void **node_baton,
rb->db->baton,
rb->rev - rb->rev_offset - 1,
rb->pool, &child_baton));
- LDR_DBG(("Opened dir %p\n", child_baton));
push_directory(rb, child_baton, relpath_compose, TRUE /*is_added*/,
NULL, SVN_INVALID_REVNUM);
}
@@ -816,6 +648,7 @@ new_node_record(void **node_baton,
if (rb->pb->parent_dir)
nb->copyfrom_path = svn_relpath_join(rb->pb->parent_dir,
nb->copyfrom_path, rb->pool);
+ /* Convert to a URL, as the commit editor requires. */
nb->copyfrom_url = svn_path_url_add_component2(rb->pb->root_url,
nb->copyfrom_path,
rb->pool);
@@ -826,7 +659,6 @@ new_node_record(void **node_baton,
{
case svn_node_action_delete:
case svn_node_action_replace:
- LDR_DBG(("Deleting entry %s in %p\n", nb->path, rb->db->baton));
SVN_ERR(commit_editor->delete_entry(nb->path,
rb->rev - rb->rev_offset - 1,
rb->db->baton, rb->pool));
@@ -843,16 +675,12 @@ new_node_record(void **node_baton,
nb->copyfrom_url,
nb->copyfrom_rev,
rb->pool, &(nb->file_baton)));
- LDR_DBG(("Added file %s to dir %p as %p\n",
- nb->path, rb->db->baton, nb->file_baton));
break;
case svn_node_dir:
SVN_ERR(commit_editor->add_directory(nb->path, rb->db->baton,
nb->copyfrom_url,
nb->copyfrom_rev,
rb->pool, &child_baton));
- LDR_DBG(("Added dir %s to dir %p as %p\n",
- nb->path, rb->db->baton, child_baton));
push_directory(rb, child_baton, nb->path, TRUE /*is_added*/,
nb->copyfrom_path, nb->copyfrom_rev);
break;
@@ -896,11 +724,13 @@ set_revision_property(void *baton,
if (rb->rev > 0)
{
- svn_hash_sets(rb->revprop_table,
- apr_pstrdup(rb->pool, name),
- svn_string_dup(value, rb->pool));
+ if (! svn_hash_gets(rb->pb->skip_revprops, name))
+ svn_hash_sets(rb->revprop_table,
+ apr_pstrdup(rb->pool, name),
+ svn_string_dup(value, rb->pool));
}
- else if (rb->rev_offset == -1)
+ else if (rb->rev_offset == -1
+ && ! svn_hash_gets(rb->pb->skip_revprops, name))
{
/* Special case: set revision 0 properties directly (which is
safe because the commit_editor hasn't been created yet), but
@@ -925,51 +755,30 @@ set_node_property(void *baton,
const svn_string_t *value)
{
struct node_baton *nb = baton;
+ struct revision_baton *rb = nb->rb;
+ struct parse_baton *pb = rb->pb;
apr_pool_t *pool = nb->rb->pool;
svn_prop_t *prop;
if (value && strcmp(name, SVN_PROP_MERGEINFO) == 0)
{
- svn_string_t *renumbered_mergeinfo;
- svn_string_t prop_val;
-
- /* Tolerate mergeinfo with "\r\n" line endings because some
- dumpstream sources might contain as much. If so normalize
- the line endings to '\n' and make a notification to
- PARSE_BATON->FEEDBACK_STREAM that we have made this
- correction. */
- if (strstr(value->data, "\r"))
+ svn_string_t *new_value;
+ svn_error_t *err;
+
+ err = svn_repos__adjust_mergeinfo_property(&new_value, value,
+ pb->parent_dir,
+ pb->rev_map,
+ pb->oldest_dumpstream_rev,
+ rb->rev_offset,
+ NULL, NULL, /*notify*/
+ pool, pool);
+ if (err)
{
- const char *prop_eol_normalized;
-
- SVN_ERR(svn_subst_translate_cstring2(value->data,
- &prop_eol_normalized,
- "\n", /* translate to LF */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- pool));
- prop_val.data = prop_eol_normalized;
- prop_val.len = strlen(prop_eol_normalized);
- value = &prop_val;
-
- /* ### TODO: notify? */
+ return svn_error_quick_wrap(err,
+ _("Invalid svn:mergeinfo value"));
}
- /* Renumber mergeinfo as appropriate. */
- SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, value,
- nb->rb, pool));
- value = renumbered_mergeinfo;
-
- if (nb->rb->pb->parent_dir)
- {
- /* Prefix the merge source paths with PB->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,
- nb->rb->pb->parent_dir, pool));
- value = mergeinfo_val;
- }
+ value = new_value;
}
SVN_ERR(svn_rdump__normalize_prop(name, &value, pool));
@@ -978,7 +787,7 @@ set_node_property(void *baton,
prop = apr_palloc(nb->rb->pool, sizeof (*prop));
prop->name = apr_pstrdup(pool, name);
- prop->value = value ? svn_string_dup(value, pool) : NULL;
+ prop->value = svn_string_dup(value, pool);
svn_hash_sets(nb->prop_changes, prop->name, prop);
return SVN_NO_ERROR;
@@ -1024,7 +833,6 @@ remove_node_props(void *baton)
/* Find the path and revision that has the node's original properties */
if (ARE_VALID_COPY_ARGS(nb->copyfrom_path, nb->copyfrom_rev))
{
- LDR_DBG(("using nb->copyfrom %s@%ld", nb->copyfrom_path, nb->copyfrom_rev));
orig_path = nb->copyfrom_path;
orig_rev = nb->copyfrom_rev;
}
@@ -1033,8 +841,6 @@ remove_node_props(void *baton)
{
/* If this is a dir, then it's described by rb->db;
if this is a file, then it's a child of the dir in rb->db. */
- LDR_DBG(("using rb->db->copyfrom (k=%d) %s@%ld",
- nb->kind, rb->db->copyfrom_path, rb->db->copyfrom_rev));
orig_path = (nb->kind == svn_node_dir)
? rb->db->copyfrom_path
: svn_relpath_join(rb->db->copyfrom_path,
@@ -1044,13 +850,11 @@ remove_node_props(void *baton)
}
else
{
- LDR_DBG(("using self.path@head %s@%ld", nb->path, SVN_INVALID_REVNUM));
/* ### Should we query at a known, fixed, "head" revision number
instead of passing SVN_INVALID_REVNUM and getting a moving target? */
orig_path = nb->path;
orig_rev = SVN_INVALID_REVNUM;
}
- LDR_DBG(("Trying %s@%ld", orig_path, orig_rev));
if ((nb->action == svn_node_action_add
|| nb->action == svn_node_action_replace)
@@ -1071,7 +875,7 @@ remove_node_props(void *baton)
for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
{
- const char *name = svn__apr_hash_index_key(hi);
+ const char *name = apr_hash_this_key(hi);
svn_prop_kind_t kind = svn_property_kind2(name);
if (kind == svn_prop_regular_kind)
@@ -1091,7 +895,6 @@ set_fulltext(svn_stream_t **stream,
void *handler_baton;
apr_pool_t *pool = nb->rb->pool;
- LDR_DBG(("Setting fulltext for %p\n", nb->file_baton));
SVN_ERR(commit_editor->apply_textdelta(nb->file_baton, nb->base_checksum,
pool, &handler, &handler_baton));
*stream = svn_txdelta_target_push(handler, handler_baton,
@@ -1108,7 +911,6 @@ apply_textdelta(svn_txdelta_window_handler_t *handler,
const struct svn_delta_editor_t *commit_editor = nb->rb->pb->commit_editor;
apr_pool_t *pool = nb->rb->pool;
- LDR_DBG(("Applying textdelta to %p\n", nb->file_baton));
SVN_ERR(commit_editor->apply_textdelta(nb->file_baton, nb->base_checksum,
pool, handler, handler_baton));
@@ -1126,8 +928,8 @@ close_node(void *baton)
for (hi = apr_hash_first(pool, nb->prop_changes);
hi; hi = apr_hash_next(hi))
{
- const char *name = svn__apr_hash_index_key(hi);
- svn_prop_t *prop = svn__apr_hash_index_val(hi);
+ const char *name = apr_hash_this_key(hi);
+ svn_prop_t *prop = apr_hash_this_val(hi);
switch (nb->kind)
{
@@ -1148,7 +950,6 @@ close_node(void *baton)
deleted the file (which doesn't require us to open it). */
if ((nb->kind == svn_node_file) && (nb->file_baton))
{
- LDR_DBG(("Closing file %p\n", nb->file_baton));
SVN_ERR(commit_editor->close_file(nb->file_baton, NULL, nb->rb->pool));
}
@@ -1178,12 +979,10 @@ close_revision(void *baton)
session itself */
while (rb->db && rb->db->parent)
{
- LDR_DBG(("Closing dir %p\n", rb->db->baton));
SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
rb->db = rb->db->parent;
}
/* root dir's baton */
- LDR_DBG(("Closing edit on %p\n", commit_edit_baton));
SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pool));
}
@@ -1201,8 +1000,6 @@ close_revision(void *baton)
rb->rev - rb->rev_offset - 1,
rb->pool, &child_baton));
- LDR_DBG(("Opened root %p\n", child_baton));
- LDR_DBG(("Closing edit on %p\n", commit_edit_baton));
SVN_ERR(commit_editor->close_directory(child_baton, rb->pool));
SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pool));
}
@@ -1222,16 +1019,22 @@ close_revision(void *baton)
if (SVN_IS_VALID_REVNUM(committed_rev))
{
- SVN_ERR(svn_repos__validate_prop(SVN_PROP_REVISION_DATE,
- rb->datestamp, rb->pool));
- SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, committed_rev,
- SVN_PROP_REVISION_DATE,
- NULL, rb->datestamp, rb->pool));
- SVN_ERR(svn_repos__validate_prop(SVN_PROP_REVISION_AUTHOR,
- rb->author, rb->pool));
- SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, committed_rev,
- SVN_PROP_REVISION_AUTHOR,
- NULL, rb->author, rb->pool));
+ if (!svn_hash_gets(rb->pb->skip_revprops, SVN_PROP_REVISION_DATE))
+ {
+ SVN_ERR(svn_repos__validate_prop(SVN_PROP_REVISION_DATE,
+ rb->datestamp, rb->pool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, committed_rev,
+ SVN_PROP_REVISION_DATE,
+ NULL, rb->datestamp, rb->pool));
+ }
+ if (!svn_hash_gets(rb->pb->skip_revprops, SVN_PROP_REVISION_AUTHOR))
+ {
+ SVN_ERR(svn_repos__validate_prop(SVN_PROP_REVISION_AUTHOR,
+ rb->author, rb->pool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, committed_rev,
+ SVN_PROP_REVISION_AUTHOR,
+ NULL, rb->author, rb->pool));
+ }
}
svn_pool_destroy(rb->pool);
@@ -1244,6 +1047,7 @@ svn_rdump__load_dumpstream(svn_stream_t *stream,
svn_ra_session_t *session,
svn_ra_session_t *aux_session,
svn_boolean_t quiet,
+ apr_hash_t *skip_revprops,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -1287,6 +1091,7 @@ svn_rdump__load_dumpstream(svn_stream_t *stream,
parse_baton->rev_map = apr_hash_make(pool);
parse_baton->last_rev_mapped = SVN_INVALID_REVNUM;
parse_baton->oldest_dumpstream_rev = SVN_INVALID_REVNUM;
+ parse_baton->skip_revprops = skip_revprops;
err = svn_repos_parse_dumpstream3(stream, parser, parse_baton, FALSE,
cancel_func, cancel_baton, pool);