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 2015/01/21 17:22:22 UTC
svn commit: r1653578 [17/18] - in /subversion/branches/pin-externals: ./
notes/ subversion/bindings/swig/ subversion/bindings/swig/include/
subversion/bindings/swig/perl/native/ subversion/bindings/swig/perl/native/t/
subversion/bindings/swig/python/te...
Modified: subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c Wed Jan 21 16:22:19 2015
@@ -30,6 +30,7 @@
#include "svn_subst.h"
#include "svn_dirent_uri.h"
+#include "private/svn_repos_private.h"
#include "private/svn_subr_private.h"
#include "private/svn_dep_compat.h"
#include "private/svn_editor.h"
@@ -50,17 +51,10 @@
struct dir_baton
{
struct dump_edit_baton *eb;
- struct dir_baton *parent_dir_baton;
/* Pool for per-directory allocations */
apr_pool_t *pool;
- /* is this directory a new addition to this revision? */
- svn_boolean_t added;
-
- /* has this directory been written to the output stream? */
- svn_boolean_t written_out;
-
/* the path to this directory */
const char *repos_relpath; /* a relpath */
@@ -90,7 +84,6 @@ struct dir_baton
struct file_baton
{
struct dump_edit_baton *eb;
- struct dir_baton *parent_dir_baton;
/* Pool for per-file allocations */
apr_pool_t *pool;
@@ -164,53 +157,42 @@ struct dump_edit_baton {
* copy source.
*
* PB is the directory baton of this directory's parent, or NULL if
- * this is the top-level directory of the edit. ADDED indicates if
- * this directory is newly added in this revision. Perform all
- * allocations in POOL. */
+ * this is the top-level directory of the edit.
+ *
+ * Perform all allocations in POOL. */
static struct dir_baton *
make_dir_baton(const char *path,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
void *edit_baton,
struct dir_baton *pb,
- svn_boolean_t added,
apr_pool_t *pool)
{
struct dump_edit_baton *eb = edit_baton;
struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
const char *repos_relpath;
- apr_pool_t *dir_pool;
/* Construct the full path of this node. */
if (pb)
- {
- dir_pool = svn_pool_create(pb->pool);
- repos_relpath = svn_relpath_canonicalize(path, dir_pool);
- }
+ repos_relpath = svn_relpath_canonicalize(path, pool);
else
- {
- dir_pool = svn_pool_create(eb->pool);
- repos_relpath = "";
- }
+ repos_relpath = "";
/* Strip leading slash from copyfrom_path so that the path is
canonical and svn_relpath_join can be used */
if (copyfrom_path)
- copyfrom_path = svn_relpath_canonicalize(copyfrom_path, dir_pool);
+ copyfrom_path = svn_relpath_canonicalize(copyfrom_path, pool);
new_db->eb = eb;
- new_db->parent_dir_baton = pb;
- new_db->pool = dir_pool;
+ new_db->pool = pool;
new_db->repos_relpath = repos_relpath;
new_db->copyfrom_path = copyfrom_path
- ? svn_relpath_canonicalize(copyfrom_path, dir_pool)
+ ? svn_relpath_canonicalize(copyfrom_path, pool)
: NULL;
new_db->copyfrom_rev = copyfrom_rev;
- new_db->added = added;
- new_db->written_out = FALSE;
- new_db->props = apr_hash_make(dir_pool);
- new_db->deleted_props = apr_hash_make(dir_pool);
- new_db->deleted_entries = apr_hash_make(dir_pool);
+ new_db->props = apr_hash_make(pool);
+ new_db->deleted_props = apr_hash_make(pool);
+ new_db->deleted_entries = apr_hash_make(pool);
return new_db;
}
@@ -224,15 +206,13 @@ make_file_baton(const char *path,
struct dir_baton *pb,
apr_pool_t *pool)
{
- apr_pool_t *file_pool = svn_pool_create(pb->pool);
- struct file_baton *new_fb = apr_pcalloc(file_pool, sizeof(*new_fb));
+ struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb));
new_fb->eb = pb->eb;
- new_fb->parent_dir_baton = pb;
- new_fb->pool = file_pool;
- new_fb->repos_relpath = svn_relpath_canonicalize(path, file_pool);
- new_fb->props = apr_hash_make(file_pool);
- new_fb->deleted_props = apr_hash_make(file_pool);
+ new_fb->pool = pool;
+ new_fb->repos_relpath = svn_relpath_canonicalize(path, pool);
+ new_fb->props = apr_hash_make(pool);
+ new_fb->deleted_props = apr_hash_make(pool);
new_fb->is_copy = FALSE;
new_fb->copyfrom_path = NULL;
new_fb->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -241,9 +221,11 @@ make_file_baton(const char *path,
return new_fb;
}
-/* Return in *HEADER and *CONTENT the headers and content for PROPS. */
+/* Append to HEADERS the required headers, and set *CONTENT to the property
+ * content section, to represent the property delta of PROPS/DELETED_PROPS.
+ */
static svn_error_t *
-get_props_content(svn_stringbuf_t **header,
+get_props_content(apr_array_header_t *headers,
svn_stringbuf_t **content,
apr_hash_t *props,
apr_hash_t *deleted_props,
@@ -252,10 +234,8 @@ get_props_content(svn_stringbuf_t **head
{
svn_stream_t *content_stream;
apr_hash_t *normal_props;
- const char *buf;
*content = svn_stringbuf_create_empty(result_pool);
- *header = svn_stringbuf_create_empty(result_pool);
content_stream = svn_stream_from_stringbuf(*content, scratch_pool);
@@ -266,71 +246,13 @@ get_props_content(svn_stringbuf_t **head
SVN_ERR(svn_stream_close(content_stream));
/* Prop-delta: true */
- *header = svn_stringbuf_createf(result_pool, SVN_REPOS_DUMPFILE_PROP_DELTA
- ": true\n");
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_PROP_DELTA, "true");
/* Prop-content-length: 193 */
- buf = apr_psprintf(scratch_pool, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n", (*content)->len);
- svn_stringbuf_appendcstr(*header, buf);
-
- return SVN_NO_ERROR;
-}
-
-/* Extract and dump properties stored in PROPS and property deletions
- * stored in DELETED_PROPS. If TRIGGER_VAR is not NULL, it is set to
- * FALSE.
- *
- * If PROPSTRING is non-NULL, set *PROPSTRING to a string containing
- * the content block of the property changes; otherwise, dump that to
- * the stream, too.
- */
-static svn_error_t *
-do_dump_props(svn_stringbuf_t **propstring,
- svn_stream_t *stream,
- apr_hash_t *props,
- apr_hash_t *deleted_props,
- svn_boolean_t *trigger_var,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_stringbuf_t *header;
- svn_stringbuf_t *content;
- apr_size_t len;
-
- if (trigger_var && !*trigger_var)
- return SVN_NO_ERROR;
-
- SVN_ERR(get_props_content(&header, &content, props, deleted_props,
- result_pool, scratch_pool));
- len = header->len;
- SVN_ERR(svn_stream_write(stream, header->data, &len));
-
- if (propstring)
- {
- *propstring = content;
- }
- else
- {
- /* Content-length: 14 */
- SVN_ERR(svn_stream_printf(stream, scratch_pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n\n",
- content->len));
-
- len = content->len;
- SVN_ERR(svn_stream_write(stream, content->data, &len));
-
- /* No text is going to be dumped. Write a couple of newlines and
- wait for the next node/ revision. */
- SVN_ERR(svn_stream_puts(stream, "\n\n"));
-
- /* Cleanup so that data is never dumped twice. */
- apr_hash_clear(props);
- apr_hash_clear(deleted_props);
- if (trigger_var)
- *trigger_var = FALSE;
- }
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
+ "%" APR_SIZE_T_FMT, (*content)->len);
return SVN_NO_ERROR;
}
@@ -349,15 +271,17 @@ do_dump_newlines(struct dump_edit_baton
}
/*
- * Write out a node record for PATH of type KIND under EB->FS_ROOT.
+ * Write out a partial node record for PATH of type KIND.
* ACTION describes what is happening to the node (see enum
- * svn_node_action). Write record to writable EB->STREAM, using
- * EB->BUFFER to write in chunks.
+ * svn_node_action). Write record to writable EB->STREAM.
*
* If the node was itself copied, IS_COPY is TRUE and the
* path/revision of the copy source are in COPYFROM_PATH/COPYFROM_REV.
* If IS_COPY is FALSE, yet COPYFROM_PATH/COPYFROM_REV are valid, this
* node is part of a copied subtree.
+
+ * Note: only when ACTION=delete, write a complete dumpfile record
+ * terminated with blank lines.
*/
static svn_error_t *
dump_node(struct dump_edit_baton *eb,
@@ -371,6 +295,7 @@ dump_node(struct dump_edit_baton *eb,
apr_pool_t *pool)
{
const char *node_relpath = repos_relpath;
+ apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
assert(svn_relpath_is_canonical(repos_relpath));
assert(!copyfrom_path || svn_relpath_is_canonical(copyfrom_path));
@@ -382,17 +307,16 @@ dump_node(struct dump_edit_baton *eb,
node_relpath, pool);
/* Node-path: ... */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
- node_relpath));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath);
/* Node-kind: "file" | "dir" */
if (fb)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_KIND, "file");
else if (db)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_KIND, "dir");
/* Write the appropriate Node-action header */
@@ -404,26 +328,32 @@ dump_node(struct dump_edit_baton *eb,
do here but print node action information.
Node-action: change. */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "change");
break;
case svn_node_action_replace:
if (is_copy)
{
- /* Delete the original, and then re-add the replacement as a
- copy using recursive calls into this function. */
- SVN_ERR(dump_node(eb, repos_relpath, db, fb, svn_node_action_delete,
- FALSE, NULL, SVN_INVALID_REVNUM, pool));
+ /* More complex case: is_copy is true, and copyfrom_path/
+ copyfrom_rev are present: delete the original, and then re-add
+ it */
+
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
+
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
+
+ /* Recurse: Print an additional add-with-history record. */
SVN_ERR(dump_node(eb, repos_relpath, db, fb, svn_node_action_add,
is_copy, copyfrom_path, copyfrom_rev, pool));
+ return SVN_NO_ERROR;
}
else
{
/* Node-action: replace */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": replace\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "replace");
/* Wait for a change_*_prop to be called before dumping
anything */
@@ -436,30 +366,29 @@ dump_node(struct dump_edit_baton *eb,
case svn_node_action_delete:
/* Node-action: delete */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
/* We can leave this routine quietly now. Nothing more to do-
- print a couple of newlines because we're not dumping props or
- text. */
- SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+ print the headers terminated by one blank line, and an extra
+ blank line because we're not dumping props or text. */
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
+ SVN_ERR(svn_stream_puts(eb->stream, "\n"));
- break;
+ return SVN_NO_ERROR;
case svn_node_action_add:
/* Node-action: add */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "add");
if (is_copy)
{
/* Node-copyfrom-rev / Node-copyfrom-path */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
- ": %ld\n"
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
- ": %s\n",
- copyfrom_rev, copyfrom_path));
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV, "%ld", copyfrom_rev);
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH, copyfrom_path);
/* Ugly hack: If a directory was copied from a previous
revision, nothing like close_file() will be called to write two
@@ -497,6 +426,11 @@ dump_node(struct dump_edit_baton *eb,
break;
}
+
+ /* Write the headers so far. We don't necessarily have all the headers
+ yet -- there may be property-related and content length headers to
+ come -- so don't write a terminating blank line. */
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, FALSE, pool));
return SVN_NO_ERROR;
}
@@ -505,34 +439,30 @@ dump_mkdir(struct dump_edit_baton *eb,
const char *repos_relpath,
apr_pool_t *pool)
{
- svn_stringbuf_t *prop_header, *prop_content;
+ svn_stringbuf_t *prop_content;
apr_size_t len;
- const char *buf;
+ apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
/* Node-path: ... */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
- repos_relpath));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_PATH, repos_relpath);
/* Node-kind: dir */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_KIND, "dir");
/* Node-action: add */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "add");
/* Dump the (empty) property block. */
- SVN_ERR(get_props_content(&prop_header, &prop_content,
+ SVN_ERR(get_props_content(headers, &prop_content,
apr_hash_make(pool), apr_hash_make(pool),
pool, pool));
- len = prop_header->len;
- SVN_ERR(svn_stream_write(eb->stream, prop_header->data, &len));
len = prop_content->len;
- buf = apr_psprintf(pool, SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n", len);
- SVN_ERR(svn_stream_puts(eb->stream, buf));
- SVN_ERR(svn_stream_puts(eb->stream, "\n"));
+ svn_repos__dumpfile_header_pushf(headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ "%" APR_SIZE_T_FMT, len);
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
SVN_ERR(svn_stream_write(eb->stream, prop_content->data, &len));
/* Newlines to tie it all off. */
@@ -547,31 +477,79 @@ static svn_error_t *
dump_pending(struct dump_edit_baton *eb,
apr_pool_t *scratch_pool)
{
+ svn_boolean_t dump_props = FALSE;
+ apr_hash_t *props, *deleted_props;
+
if (! eb->pending_baton)
return SVN_NO_ERROR;
+ /* Some pending properties to dump? */
if (eb->pending_kind == svn_node_dir)
{
struct dir_baton *db = eb->pending_baton;
- /* Some pending properties to dump? */
- SVN_ERR(do_dump_props(NULL, eb->stream, db->props, db->deleted_props,
- &(db->dump_props), db->pool, scratch_pool));
+ if (db->dump_props)
+ {
+ dump_props = TRUE;
+ props = db->props;
+ deleted_props = db->deleted_props;
- /* Some pending newlines to dump? */
- SVN_ERR(do_dump_newlines(eb, &(db->dump_newlines), scratch_pool));
+ db->dump_props = FALSE;
+ }
}
else if (eb->pending_kind == svn_node_file)
{
struct file_baton *fb = eb->pending_baton;
- /* Some pending properties to dump? */
- SVN_ERR(do_dump_props(NULL, eb->stream, fb->props, fb->deleted_props,
- &(fb->dump_props), fb->pool, scratch_pool));
+ if (fb->dump_props)
+ {
+ dump_props = TRUE;
+ props = fb->props;
+ deleted_props = fb->deleted_props;
+ fb->dump_props = FALSE;
+ }
}
else
abort();
+ if (dump_props)
+ {
+ apr_array_header_t *headers
+ = svn_repos__dumpfile_headers_create(scratch_pool);
+ svn_stringbuf_t *content;
+ apr_size_t len;
+
+ SVN_ERR(get_props_content(headers, &content, props, deleted_props,
+ scratch_pool, scratch_pool));
+
+ /* Content-length: 14 */
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ "%" APR_SIZE_T_FMT, content->len);
+
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE,
+ scratch_pool));
+
+ len = content->len;
+ SVN_ERR(svn_stream_write(eb->stream, content->data, &len));
+
+ /* No text is going to be dumped. Write a couple of newlines and
+ wait for the next node/ revision. */
+ SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+
+ /* Cleanup so that data is never dumped twice. */
+ apr_hash_clear(props);
+ apr_hash_clear(deleted_props);
+ }
+
+ if (eb->pending_kind == svn_node_dir)
+ {
+ struct dir_baton *db = eb->pending_baton;
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(do_dump_newlines(eb, &(db->dump_newlines), scratch_pool));
+ }
+
/* Anything that was pending is pending no longer. */
eb->pending_baton = NULL;
eb->pending_kind = svn_node_none;
@@ -629,14 +607,13 @@ open_root(void *edit_baton,
/* ... but for the source directory itself, we'll defer
to letting the typical plumbing handle this task. */
new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, TRUE, pool);
+ edit_baton, NULL, pool);
SVN_ERR(dump_node(eb, new_db->repos_relpath, new_db,
NULL, svn_node_action_add, FALSE,
NULL, SVN_INVALID_REVNUM, pool));
/* Remember that we've started but not yet finished
handling this directory. */
- new_db->written_out = TRUE;
eb->pending_baton = new_db;
eb->pending_kind = svn_node_dir;
}
@@ -647,7 +624,7 @@ open_root(void *edit_baton,
if (! new_db)
{
new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, FALSE, pool);
+ edit_baton, NULL, pool);
}
*root_baton = new_db;
@@ -684,7 +661,7 @@ add_directory(const char *path,
void **child_baton)
{
struct dir_baton *pb = parent_baton;
- void *val;
+ void *was_deleted;
struct dir_baton *new_db;
svn_boolean_t is_copy;
@@ -693,29 +670,28 @@ add_directory(const char *path,
SVN_ERR(dump_pending(pb->eb, pool));
new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb,
- pb, TRUE, pb->pool);
+ pb, pb->pool);
/* This might be a replacement -- is the path already deleted? */
- val = svn_hash_gets(pb->deleted_entries, path);
+ was_deleted = svn_hash_gets(pb->deleted_entries, path);
/* Detect an add-with-history */
is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
/* Dump the node */
SVN_ERR(dump_node(pb->eb, new_db->repos_relpath, new_db, NULL,
- val ? svn_node_action_replace : svn_node_action_add,
+ was_deleted ? svn_node_action_replace : svn_node_action_add,
is_copy,
is_copy ? new_db->copyfrom_path : NULL,
is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
pool));
- if (val)
+ if (was_deleted)
/* Delete the path, it's now been dumped */
svn_hash_sets(pb->deleted_entries, path, NULL);
/* Remember that we've started, but not yet finished handling this
directory. */
- new_db->written_out = TRUE;
pb->eb->pending_baton = new_db;
pb->eb->pending_kind = svn_node_dir;
@@ -750,7 +726,7 @@ open_directory(const char *path,
}
new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb,
- FALSE, pb->pool);
+ pb->pool);
*child_baton = new_db;
return SVN_NO_ERROR;
@@ -801,7 +777,7 @@ close_directory(void *dir_baton,
}
/* ### should be unnecessary */
- svn_pool_destroy(db->pool);
+ apr_hash_clear(db->deleted_entries);
return SVN_NO_ERROR;
}
@@ -816,7 +792,7 @@ add_file(const char *path,
{
struct dir_baton *pb = parent_baton;
struct file_baton *fb;
- void *val;
+ void *was_deleted;
LDR_DBG(("add_file %s\n", path));
@@ -826,7 +802,7 @@ add_file(const char *path,
fb = make_file_baton(path, pb, pool);
/* This might be a replacement -- is the path already deleted? */
- val = svn_hash_gets(pb->deleted_entries, path);
+ was_deleted = svn_hash_gets(pb->deleted_entries, path);
/* Detect add-with-history. */
if (ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev))
@@ -835,10 +811,10 @@ add_file(const char *path,
fb->copyfrom_rev = copyfrom_rev;
fb->is_copy = TRUE;
}
- fb->action = val ? svn_node_action_replace : svn_node_action_add;
+ fb->action = was_deleted ? svn_node_action_replace : svn_node_action_add;
/* Delete the path, it's now been dumped. */
- if (val)
+ if (was_deleted)
svn_hash_sets(pb->deleted_entries, path, NULL);
*file_baton = fb;
@@ -975,6 +951,7 @@ close_file(void *file_baton,
struct dump_edit_baton *eb = fb->eb;
apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t));
svn_stringbuf_t *propstring;
+ apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
LDR_DBG(("close_file %p\n", file_baton));
@@ -988,8 +965,12 @@ close_file(void *file_baton,
/* Some pending properties to dump? We'll dump just the headers for
now, then dump the actual propchange content only after dumping
the text headers too (if present). */
- SVN_ERR(do_dump_props(&propstring, eb->stream, fb->props, fb->deleted_props,
- &(fb->dump_props), pool, pool));
+ if (fb->dump_props)
+ {
+ SVN_ERR(get_props_content(headers, &propstring,
+ fb->props, fb->deleted_props,
+ pool, pool));
+ }
/* Dump the text headers */
if (fb->dump_text)
@@ -997,9 +978,8 @@ close_file(void *file_baton,
apr_status_t err;
/* Text-delta: true */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_TEXT_DELTA
- ": true\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_DELTA, "true");
err = apr_file_info_get(info, APR_FINFO_SIZE, eb->delta_file);
if (err)
@@ -1007,36 +987,31 @@ close_file(void *file_baton,
if (fb->base_checksum)
/* Text-delta-base-md5: */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5
- ": %s\n",
- fb->base_checksum));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5, fb->base_checksum);
/* Text-content-length: 39 */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH
- ": %lu\n",
- (unsigned long)info->size));
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,
+ "%lu", (unsigned long)info->size);
/* Text-content-md5: 82705804337e04dcd0e586bfa2389a7f */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5
- ": %s\n",
- text_checksum));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5, text_checksum);
}
/* Content-length: 1549 */
/* If both text and props are absent, skip this header */
if (fb->dump_props)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %ld\n\n",
- (unsigned long)info->size + propstring->len));
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ "%lu", (unsigned long)(info->size + propstring->len));
else if (fb->dump_text)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %ld\n\n",
- (unsigned long)info->size));
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ "%lu", (unsigned long)info->size);
+
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
/* Dump the props now */
if (fb->dump_props)
@@ -1074,8 +1049,6 @@ close_file(void *file_baton,
dump` */
SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
- svn_pool_clear(fb->pool);
-
return SVN_NO_ERROR;
}
Modified: subversion/branches/pin-externals/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnrdump/load_editor.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/pin-externals/subversion/svnrdump/load_editor.c Wed Jan 21 16:22:19 2015
@@ -66,9 +66,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;
@@ -99,13 +96,12 @@ struct parse_baton
/**
* 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;
struct directory_baton *parent;
};
@@ -175,169 +171,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
- preceding 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_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;
-}
-
-
static svn_error_t *
commit_callback(const svn_commit_info_t *commit_info,
void *baton,
@@ -599,9 +432,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;
}
@@ -661,7 +491,6 @@ new_node_record(void **node_baton,
/* child_db corresponds to the root directory baton here */
child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
child_db->baton = child_baton;
- child_db->depth = 0;
child_db->relpath = "";
child_db->parent = NULL;
rb->db = child_db;
@@ -745,7 +574,6 @@ new_node_record(void **node_baton,
LDR_DBG(("Opened dir %p\n", child_baton));
child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
child_db->baton = child_baton;
- child_db->depth = rb->db->depth + 1;
child_db->relpath = relpath_compose;
child_db->parent = rb->db;
rb->db = child_db;
@@ -813,7 +641,6 @@ new_node_record(void **node_baton,
nb->path, rb->db->baton, child_baton));
child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
child_db->baton = child_baton;
- child_db->depth = rb->db->depth + 1;
child_db->relpath = apr_pstrdup(rb->pool, nb->path);
child_db->parent = rb->db;
rb->db = child_db;
@@ -836,7 +663,6 @@ new_node_record(void **node_baton,
rb->pool, &child_baton));
child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
child_db->baton = child_baton;
- child_db->depth = rb->db->depth + 1;
child_db->relpath = apr_pstrdup(rb->pool, nb->path);
child_db->parent = rb->db;
rb->db = child_db;
@@ -893,51 +719,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;
const struct svn_delta_editor_t *commit_editor = nb->rb->pb->commit_editor;
apr_pool_t *pool = nb->rb->pool;
if (value && strcmp(name, SVN_PROP_MERGEINFO) == 0)
{
- svn_string_t *renumbered_mergeinfo;
- svn_string_t prop_val;
+ svn_string_t *new_value;
+ svn_error_t *err;
- /* 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"))
+ 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));
Modified: subversion/branches/pin-externals/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnrdump/svnrdump.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/pin-externals/subversion/svnrdump/svnrdump.c Wed Jan 21 16:22:19 2015
@@ -39,6 +39,7 @@
#include "svnrdump.h"
+#include "private/svn_repos_private.h"
#include "private/svn_cmdline_private.h"
#include "private/svn_ra_private.h"
@@ -229,38 +230,13 @@ replay_revstart(svn_revnum_t revision,
{
struct replay_baton *rb = replay_baton;
apr_hash_t *normal_props;
- svn_stringbuf_t *propstring;
- svn_stream_t *stdout_stream;
- svn_stream_t *revprop_stream;
-
- SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
- /* Revision-number: 19 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_REVISION_NUMBER
- ": %ld\n", revision));
+ /* Normalize and dump the revprops */
SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool));
- propstring = svn_stringbuf_create_ensure(0, pool);
- revprop_stream = svn_stream_from_stringbuf(propstring, pool);
- SVN_ERR(svn_hash_write2(normal_props, revprop_stream, "PROPS-END", pool));
- SVN_ERR(svn_stream_close(revprop_stream));
-
- /* Prop-content-length: 13 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n", propstring->len));
-
- /* Content-length: 29 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n\n", propstring->len));
-
- /* Property data. */
- SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
- &(propstring->len)));
-
- SVN_ERR(svn_stream_puts(stdout_stream, "\n"));
- SVN_ERR(svn_stream_close(stdout_stream));
+ SVN_ERR(svn_repos__dump_revision_record(rb->stdout_stream, revision, NULL,
+ normal_props,
+ TRUE /*props_section_always*/,
+ pool));
SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
rb->stdout_stream, rb->extra_ra_session,
@@ -303,38 +279,13 @@ replay_revstart_v2(svn_revnum_t revision
{
struct replay_baton *rb = replay_baton;
apr_hash_t *normal_props;
- svn_stringbuf_t *propstring;
- svn_stream_t *stdout_stream;
- svn_stream_t *revprop_stream;
- SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
-
- /* Revision-number: 19 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_REVISION_NUMBER
- ": %ld\n", revision));
+ /* Normalize and dump the revprops */
SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool));
- propstring = svn_stringbuf_create_ensure(0, pool);
- revprop_stream = svn_stream_from_stringbuf(propstring, pool);
- SVN_ERR(svn_hash_write2(normal_props, revprop_stream, "PROPS-END", pool));
- SVN_ERR(svn_stream_close(revprop_stream));
-
- /* Prop-content-length: 13 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n", propstring->len));
-
- /* Content-length: 29 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n\n", propstring->len));
-
- /* Property data. */
- SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
- &(propstring->len)));
-
- SVN_ERR(svn_stream_puts(stdout_stream, "\n"));
- SVN_ERR(svn_stream_close(stdout_stream));
+ SVN_ERR(svn_repos__dump_revision_record(rb->stdout_stream, revision,
+ normal_props,
+ TRUE /*props_section_always*/,
+ pool));
SVN_ERR(svn_rdump__get_dump_editor_v2(editor, revision,
rb->stdout_stream,
@@ -471,35 +422,12 @@ dump_revision_header(svn_ra_session_t *s
apr_pool_t *pool)
{
apr_hash_t *prophash;
- svn_stringbuf_t *propstring;
- svn_stream_t *propstream;
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_REVISION_NUMBER
- ": %ld\n", revision));
-
- prophash = apr_hash_make(pool);
- propstring = svn_stringbuf_create_empty(pool);
SVN_ERR(svn_ra_rev_proplist(session, revision, &prophash, pool));
-
- propstream = svn_stream_from_stringbuf(propstring, pool);
- SVN_ERR(svn_hash_write2(prophash, propstream, "PROPS-END", pool));
- SVN_ERR(svn_stream_close(propstream));
-
- /* Property-content-length: 14; Content-length: 14 */
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n",
- propstring->len));
- SVN_ERR(svn_stream_printf(stdout_stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n\n",
- propstring->len));
- /* The properties */
- SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
- &(propstring->len)));
- SVN_ERR(svn_stream_puts(stdout_stream, "\n"));
-
+ SVN_ERR(svn_repos__dump_revision_record(stdout_stream, revision, NULL,
+ prophash,
+ TRUE /*props_section_always*/,
+ pool));
return SVN_NO_ERROR;
}
@@ -1176,7 +1104,7 @@ sub_main(int *exit_code, int argc, const
if (strcmp(subcommand->name, "load") == 0)
{
- /*
+ /*
* By default (no --*-interactive options given), the 'load' subcommand
* is interactive unless username and password were provided on the
* command line. This allows prompting for auth creds to work without
Modified: subversion/branches/pin-externals/subversion/svnserve/logger.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnserve/logger.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnserve/logger.c (original)
+++ subversion/branches/pin-externals/subversion/svnserve/logger.c Wed Jan 21 16:22:19 2015
@@ -134,7 +134,10 @@ logger__log_error(logger_t *logger,
if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) {
len = sizeof(errstr) - sizeof(APR_EOL_STR);
}
+
memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR));
+ len += sizeof(APR_EOL_STR) -1; /* add NL, ex terminating NUL */
+
svn_error_clear(svn_stream_write(logger->stream, errstr, &len));
continuation = "-";
Modified: subversion/branches/pin-externals/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnserve/svnserve.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/pin-externals/subversion/svnserve/svnserve.c Wed Jan 21 16:22:19 2015
@@ -271,6 +271,8 @@ static const apr_getopt_option_t svnserv
" "
"Default is 16.\n"
" "
+ "0 switches to dynamically sized caches.\n"
+ " "
"[used for FSFS and FSX repositories only]")},
{"cache-txdeltas", SVNSERVE_OPT_CACHE_TXDELTAS, 1,
N_("enable or disable caching of deltas between older\n"
Modified: subversion/branches/pin-externals/subversion/svnsync/sync.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnsync/sync.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnsync/sync.c (original)
+++ subversion/branches/pin-externals/subversion/svnsync/sync.c Wed Jan 21 16:22:19 2015
@@ -34,6 +34,8 @@
#include "svn_subst.h"
#include "svn_string.h"
+#include "private/svn_string_private.h"
+
#include "sync.h"
#include "svn_private_config.h"
@@ -83,6 +85,90 @@ normalize_string(const svn_string_t **st
return SVN_NO_ERROR;
}
+/* Remove r0 references from the mergeinfo string *STR.
+ *
+ * r0 was never a valid mergeinfo reference and cannot be committed with
+ * recent servers, but can be committed through a server older than 1.6.18
+ * for HTTP or older than 1.6.17 for the other protocols. See issue #4476
+ * "Mergeinfo containing r0 makes svnsync and dump and load fail".
+ *
+ * Set *WAS_CHANGED to TRUE if *STR was changed, otherwise to FALSE.
+ */
+static svn_error_t *
+remove_r0_mergeinfo(const svn_string_t **str,
+ svn_boolean_t *was_changed,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_stringbuf_t *new_str = svn_stringbuf_create_empty(result_pool);
+ apr_array_header_t *lines;
+ int i;
+
+ SVN_ERR_ASSERT(*str && (*str)->data);
+
+ *was_changed = FALSE;
+
+ /* for each line */
+ lines = svn_cstring_split((*str)->data, "\n", FALSE, scratch_pool);
+
+ for (i = 0; i < lines->nelts; i++)
+ {
+ char *line = APR_ARRAY_IDX(lines, i, char *);
+ char *colon;
+
+ /* split at the last colon */
+ colon = strrchr(line, ':');
+
+ if (! colon)
+ return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
+ _("Missing colon in svn:mergeinfo "
+ "property"));
+
+ /* remove r0 */
+ if (colon[1] == '0')
+ {
+ char *rangelist;
+
+ rangelist = colon + 1;
+
+ if (strncmp(rangelist, "0*,", 3) == 0)
+ {
+ rangelist += 3;
+ }
+ else if (strcmp(rangelist, "0*") == 0
+ || strncmp(rangelist, "0,", 2) == 0
+ || strncmp(rangelist, "0-1*", 4) == 0
+ || strncmp(rangelist, "0-1,", 4) == 0
+ || strcmp(rangelist, "0-1") == 0)
+ {
+ rangelist += 2;
+ }
+ else if (strcmp(rangelist, "0") == 0)
+ {
+ rangelist += 1;
+ }
+ else if (strncmp(rangelist, "0-", 2) == 0)
+ {
+ rangelist[0] = '1';
+ }
+
+ /* reassemble */
+ if (new_str->len)
+ svn_stringbuf_appendbyte(new_str, '\n');
+ svn_stringbuf_appendbytes(new_str, line, colon + 1 - line);
+ svn_stringbuf_appendcstr(new_str, rangelist);
+ }
+ }
+
+ if (strcmp((*str)->data, new_str->data) != 0)
+ {
+ *was_changed = TRUE;
+ }
+
+ *str = svn_stringbuf__morph_into_string(new_str);
+ return SVN_NO_ERROR;
+}
+
/* Normalize the encoding and line ending style of the values of properties
* in REV_PROPS that "need translation" (according to
@@ -153,6 +239,7 @@ typedef struct edit_baton_t {
svn_boolean_t got_textdeltas;
svn_revnum_t base_revision;
svn_boolean_t quiet;
+ svn_boolean_t mergeinfo_tweaked; /* Did we tweak svn:mergeinfo? */
svn_boolean_t strip_mergeinfo; /* Are we stripping svn:mergeinfo? */
svn_boolean_t migrate_svnmerge; /* Are we converting svnmerge.py data? */
svn_boolean_t mergeinfo_stripped; /* Did we strip svn:mergeinfo? */
@@ -414,8 +501,19 @@ change_file_prop(void *file_baton,
if (svn_prop_needs_translation(name))
{
svn_boolean_t was_normalized;
+ svn_boolean_t mergeinfo_tweaked = FALSE;
+
+ /* Normalize encoding to UTF-8, and EOL style to LF. */
SVN_ERR(normalize_string(&value, &was_normalized,
eb->source_prop_encoding, pool, pool));
+ /* Correct malformed mergeinfo. */
+ if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
+ {
+ SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked,
+ pool, pool));
+ if (mergeinfo_tweaked)
+ eb->mergeinfo_tweaked = TRUE;
+ }
if (was_normalized)
(*(eb->normalized_node_props_counter))++;
}
@@ -513,8 +611,19 @@ change_dir_prop(void *dir_baton,
if (svn_prop_needs_translation(name))
{
svn_boolean_t was_normalized;
+ svn_boolean_t mergeinfo_tweaked = FALSE;
+
+ /* Normalize encoding to UTF-8, and EOL style to LF. */
SVN_ERR(normalize_string(&value, &was_normalized, eb->source_prop_encoding,
pool, pool));
+ /* Maybe adjust svn:mergeinfo. */
+ if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
+ {
+ SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked,
+ pool, pool));
+ if (mergeinfo_tweaked)
+ eb->mergeinfo_tweaked = TRUE;
+ }
if (was_normalized)
(*(eb->normalized_node_props_counter))++;
}
@@ -548,6 +657,10 @@ close_edit(void *edit_baton,
{
if (eb->got_textdeltas)
SVN_ERR(svn_cmdline_printf(pool, "\n"));
+ if (eb->mergeinfo_tweaked)
+ SVN_ERR(svn_cmdline_printf(pool,
+ "NOTE: Adjusted Subversion mergeinfo in "
+ "this revision.\n"));
if (eb->mergeinfo_stripped)
SVN_ERR(svn_cmdline_printf(pool,
"NOTE: Dropped Subversion mergeinfo "
Modified: subversion/branches/pin-externals/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/tests/cmdline/basic_tests.py?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/pin-externals/subversion/tests/cmdline/basic_tests.py Wed Jan 21 16:22:19 2015
@@ -3146,6 +3146,31 @@ def basic_youngest(sbox):
'youngest', path)
+# With 'svn mkdir --parents' the target directory may already exist on disk.
+# In that case it was wrongly performing a recursive 'add' on its contents.
+def mkdir_parents_target_exists_on_disk(sbox):
+ "mkdir parents target exists on disk"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ Y_path = sbox.ospath('Y')
+ Y_Z_path = sbox.ospath('Y/Z')
+
+ os.mkdir(Y_path)
+ os.mkdir(Y_Z_path)
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', '--parents', Y_path)
+
+ # Y should be added, and Z should not. There was a regression in which Z
+ # was also added.
+ expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+ expected_status.add({
+ 'Y' : Item(status='A ', wc_rev=0),
+ })
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
########################################################################
# Run the tests
@@ -3215,6 +3240,7 @@ test_list = [ None,
delete_conflicts_one_of_many,
peg_rev_on_non_existent_wc_path,
basic_youngest,
+ mkdir_parents_target_exists_on_disk,
]
if __name__ == '__main__':
Modified: subversion/branches/pin-externals/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/tests/cmdline/copy_tests.py?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/pin-externals/subversion/tests/cmdline/copy_tests.py Wed Jan 21 16:22:19 2015
@@ -560,7 +560,7 @@ def no_copy_overwrites(sbox):
# Repeat the last command. It should *fail* because A/D/H/G already exists.
svntest.actions.run_and_verify_svn(
"Whoa, I was able to overwrite a directory!",
- None, svntest.verify.AnyOutput,
+ None, ".*'/A/D/H/G'.*",
'cp', dirURL1, dirURL2,
'-m', 'fooogle')
Modified: subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py Wed Jan 21 16:22:19 2015
@@ -3479,6 +3479,74 @@ def switch_relative_externals(sbox):
svntest.actions.run_and_verify_svn(None, None, [],
'up', wc)
+
+def copy_file_external_to_repo(sbox):
+ "explicitly copy file external to repo"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ change_external(sbox.ospath('A'), '^/A/mu ext')
+ sbox.simple_update()
+
+ svntest.actions.run_and_verify_svn(None, None, [], 'cp',
+ '--message', 'external copy',
+ sbox.ospath('A/ext'),
+ sbox.repo_url + '/ext_copy')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'ext_copy' : Item(status='A '),
+ })
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/ext' : Item('This is the file \'mu\'.\n'),
+ 'ext_copy' : Item('This is the file \'mu\'.\n'),
+ })
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output, expected_disk, None)
+
+@Issue(4550)
+def replace_tree_with_foreign_external(sbox):
+ "replace tree with foreign external"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ repo_dir = sbox.repo_dir
+
+ other_repo_dir, other_repo_url = sbox.add_repo_path('other')
+ svntest.main.copy_repos(repo_dir, other_repo_dir, 1)
+
+ sbox.simple_propset('svn:externals', other_repo_url + '/A/B X', 'A')
+ sbox.simple_commit()
+ sbox.simple_propdel('svn:externals', 'A')
+ sbox.simple_mkdir('A/X')
+ sbox.simple_mkdir('A/X/E')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/X' : Item(status='D '),
+ 'A' : Item(status=' U'),
+ 'A/X/lambda' : Item(status='A '),
+ 'A/X/E' : Item(status='A '),
+ 'A/X/E/alpha' : Item(status='A '),
+ 'A/X/E/beta' : Item(status='A '),
+ 'A/X/F' : Item(status='A '),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.add({
+ 'A/X' : Item(status=' ', wc_rev=1, prev_status='X '),
+ 'A/X/E' : Item(status=' ', wc_rev=1, prev_status=' '),
+ 'A/X/E/alpha' : Item(status=' ', wc_rev=1),
+ 'A/X/E/beta' : Item(status=' ', wc_rev=1),
+ 'A/X/F' : Item(status=' ', wc_rev=1),
+ 'A/X/lambda' : Item(status=' ', wc_rev=1),
+ })
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output, None, expected_status,
+ None, None, None, None, None, 1,
+ '-r', '2', wc_dir)
+
def pin_externals(sbox):
"test svn copy --pin-externals"
@@ -3564,6 +3632,8 @@ test_list = [ None,
update_external_peg_rev,
update_deletes_file_external,
switch_relative_externals,
+ copy_file_external_to_repo,
+ replace_tree_with_foreign_external,
pin_externals,
]