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 2013/02/04 21:48:13 UTC
svn commit: r1442344 [29/39] - in /subversion/branches/fsfs-format7: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/
contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ doc/...
Modified: subversion/branches/fsfs-format7/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnrdump/dump_editor.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/fsfs-format7/subversion/svnrdump/dump_editor.c Mon Feb 4 20:48:05 2013
@@ -31,6 +31,7 @@
#include "svn_dirent_uri.h"
#include "private/svn_subr_private.h"
+#include "private/svn_editor.h"
#include "svnrdump.h"
#include <assert.h>
@@ -50,7 +51,8 @@ struct dir_baton
struct dump_edit_baton *eb;
struct dir_baton *parent_dir_baton;
- apr_pool_t *pool; /* Directory pool */
+ /* Pool for per-directory allocations */
+ apr_pool_t *pool;
/* is this directory a new addition to this revision? */
svn_boolean_t added;
@@ -65,11 +67,21 @@ struct dir_baton
const char *copyfrom_path; /* a relpath */
svn_revnum_t copyfrom_rev;
+ /* Properties which were modified during change_dir_prop. */
+ apr_hash_t *props;
+
+ /* Properties which were deleted during change_dir_prop. */
+ apr_hash_t *deleted_props;
+
/* Hash of paths that need to be deleted, though some -might- be
replaced. Maps const char * paths to this dir_baton. Note that
they're full paths, because that's what the editor driver gives
us, although they're all really within this directory. */
apr_hash_t *deleted_entries;
+
+ /* Flags to trigger dumping props and record termination newlines. */
+ svn_boolean_t dump_props;
+ svn_boolean_t dump_newlines;
};
/* A file baton used by all file-related callback functions in the dump
@@ -79,11 +91,32 @@ struct file_baton
struct dump_edit_baton *eb;
struct dir_baton *parent_dir_baton;
+ /* Pool for per-file allocations */
+ apr_pool_t *pool;
+
/* the path to this file */
const char *repos_relpath; /* a relpath */
+ /* Properties which were modified during change_file_prop. */
+ apr_hash_t *props;
+
+ /* Properties which were deleted during change_file_prop. */
+ apr_hash_t *deleted_props;
+
/* The checksum of the file the delta is being applied to */
const char *base_checksum;
+
+ /* Copy state and source information (if any). */
+ svn_boolean_t is_copy;
+ const char *copyfrom_path;
+ svn_revnum_t copyfrom_rev;
+
+ /* The action associate with this node. */
+ enum svn_node_action action;
+
+ /* Flags to trigger dumping props and text. */
+ svn_boolean_t dump_text;
+ svn_boolean_t dump_props;
};
/* A handler baton to be used in window_handler(). */
@@ -101,34 +134,31 @@ struct dump_edit_baton {
/* A backdoor ra session to fetch additional information during the edit. */
svn_ra_session_t *ra_session;
+ /* The repository relpath of the anchor of the editor when driven
+ via the RA update mechanism; NULL otherwise. (When the editor is
+ driven via the RA "replay" mechanism instead, the editor is
+ always anchored at the repository, we don't need to prepend an
+ anchor path to the dumped node paths, and open_root() doesn't
+ need to manufacture directory additions.) */
+ const char *update_anchor_relpath;
+
/* Pool for per-revision allocations */
apr_pool_t *pool;
- /* Properties which were modified during change_file_prop
- * or change_dir_prop. */
- apr_hash_t *props;
-
- /* Properties which were deleted during change_file_prop
- * or change_dir_prop. */
- apr_hash_t *deleted_props;
-
- /* Temporary buffer to write property hashes to in human-readable
- * form. ### Is this really needed? */
- svn_stringbuf_t *propstring;
-
/* Temporary file used for textdelta application along with its
absolute path; these two variables should be allocated in the
per-edit-session pool */
const char *delta_abspath;
apr_file_t *delta_file;
- /* Flags to trigger dumping props and text */
- svn_boolean_t dump_text;
- svn_boolean_t dump_props;
- svn_boolean_t dump_newlines;
-
/* The revision we're currently dumping. */
svn_revnum_t current_revision;
+
+ /* The kind (file or directory) and baton of the item whose block of
+ dump stream data has not been fully completed; NULL if there's no
+ such item. */
+ svn_node_kind_t pending_kind;
+ void *pending_baton;
};
/* Make a directory baton to represent the directory at PATH (relative
@@ -139,21 +169,20 @@ struct dump_edit_baton {
* information is valid, the directory will be compared against its
* copy source.
*
- * PARENT_DIR_BATON 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. */
+ * 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. */
static struct dir_baton *
make_dir_baton(const char *path,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
void *edit_baton,
- void *parent_dir_baton,
+ struct dir_baton *pb,
svn_boolean_t added,
apr_pool_t *pool)
{
struct dump_edit_baton *eb = edit_baton;
- struct dir_baton *pb = parent_dir_baton;
struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
const char *repos_relpath;
@@ -178,11 +207,38 @@ make_dir_baton(const char *path,
new_db->copyfrom_rev = copyfrom_rev;
new_db->added = added;
new_db->written_out = FALSE;
+ 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;
}
+/* Make a file baton to represent the directory at PATH (relative to
+ * PB->eb). PB is the directory baton of this directory's parent, or
+ * NULL if this is the top-level directory of the edit. Perform all
+ * allocations in POOL. */
+static struct file_baton *
+make_file_baton(const char *path,
+ struct dir_baton *pb,
+ apr_pool_t *pool)
+{
+ 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 = 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;
+ new_fb->action = svn_node_action_change;
+
+ return new_fb;
+}
+
/* Return in *HEADER and *CONTENT the headers and content for PROPS. */
static svn_error_t *
get_props_content(svn_stringbuf_t **header,
@@ -219,9 +275,13 @@ get_props_content(svn_stringbuf_t **head
return SVN_NO_ERROR;
}
-/* Extract and dump properties stored in edit baton EB, using POOL for
- * any temporary allocations. If TRIGGER_VAR is not NULL, it is set to FALSE.
- * Unless DUMP_DATA_TOO is set, only property headers are dumped.
+/* 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,
@@ -229,7 +289,6 @@ do_dump_props(svn_stringbuf_t **propstri
apr_hash_t *props,
apr_hash_t *deleted_props,
svn_boolean_t *trigger_var,
- svn_boolean_t dump_data_too,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -242,14 +301,14 @@ do_dump_props(svn_stringbuf_t **propstri
SVN_ERR(get_props_content(&header, &content, props, deleted_props,
result_pool, scratch_pool));
-
- /* This is a wacky side-effect of this function. */
- *propstring = content;
-
len = header->len;
SVN_ERR(svn_stream_write(stream, header->data, &len));
- if (dump_data_too)
+ if (propstring)
+ {
+ *propstring = content;
+ }
+ else
{
/* Content-length: 14 */
SVN_ERR(svn_stream_printf(stream, scratch_pool,
@@ -301,25 +360,35 @@ do_dump_newlines(struct dump_edit_baton
static svn_error_t *
dump_node(struct dump_edit_baton *eb,
const char *repos_relpath,
- svn_node_kind_t kind,
+ struct dir_baton *db,
+ struct file_baton *fb,
enum svn_node_action action,
svn_boolean_t is_copy,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
apr_pool_t *pool)
{
+ const char *node_relpath = repos_relpath;
+
assert(svn_relpath_is_canonical(repos_relpath));
assert(!copyfrom_path || svn_relpath_is_canonical(copyfrom_path));
+ assert(! (db && fb));
+
+ /* Add the edit root relpath prefix if necessary. */
+ if (eb->update_anchor_relpath)
+ node_relpath = svn_relpath_join(eb->update_anchor_relpath,
+ node_relpath, pool);
- /* Node-path: commons/STATUS */
+ /* Node-path: ... */
SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n", repos_relpath));
+ SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+ node_relpath));
- /* Node-kind: file */
- if (kind == svn_node_file)
+ /* Node-kind: "file" | "dir" */
+ if (fb)
SVN_ERR(svn_stream_printf(eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
- else if (kind == svn_node_dir)
+ else if (db)
SVN_ERR(svn_stream_printf(eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
@@ -330,13 +399,24 @@ dump_node(struct dump_edit_baton *eb,
case svn_node_action_change:
/* We are here after a change_file_prop or change_dir_prop. They
set up whatever dump_props they needed to- nothing to
- do here but print node action information */
+ do here but print node action information.
+
+ Node-action: change. */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
break;
case svn_node_action_replace:
- if (!is_copy)
+ 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));
+ SVN_ERR(dump_node(eb, repos_relpath, db, fb, svn_node_action_add,
+ is_copy, copyfrom_path, copyfrom_rev, pool));
+ }
+ else
{
/* Node-action: replace */
SVN_ERR(svn_stream_puts(eb->stream,
@@ -345,25 +425,15 @@ dump_node(struct dump_edit_baton *eb,
/* Wait for a change_*_prop to be called before dumping
anything */
- eb->dump_props = TRUE;
- break;
+ if (fb)
+ fb->dump_props = TRUE;
+ else if (db)
+ db->dump_props = TRUE;
}
- /* More complex case: is_copy is true, and copyfrom_path/
- copyfrom_rev are present: delete the original, and then re-add
- it */
-
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n\n"));
-
- /* Recurse: Print an additional add-with-history record. */
- SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_add,
- is_copy, copyfrom_path, copyfrom_rev, pool));
-
- /* We can leave this routine quietly now, don't need to dump any
- content; that was already done in the second record. */
break;
case svn_node_action_delete:
+ /* Node-action: delete */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
@@ -371,44 +441,57 @@ dump_node(struct dump_edit_baton *eb,
print a couple of newlines because we're not dumping props or
text. */
SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+
break;
case svn_node_action_add:
+ /* Node-action: add */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
- if (!is_copy)
+ if (is_copy)
{
- /* eb->dump_props for files is handled in close_file
- which is called immediately. However, directories are not
- closed until all the work inside them has been done;
- eb->dump_props for directories is handled in all the
- functions that can possibly be called after add_directory:
- add_directory, open_directory, delete_entry, close_directory,
- add_file, open_file. change_dir_prop is a special case. */
-
- /* Wait for a change_*_prop to be called before dumping
- anything */
- eb->dump_props = TRUE;
- break;
+ /* 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));
+
+ /* Ugly hack: If a directory was copied from a previous
+ revision, nothing like close_file() will be called to write two
+ blank lines. If change_dir_prop() is called, props are dumped
+ (along with the necessary PROPS-END\n\n and we're good. So
+ set DUMP_NEWLINES here to print the newlines unless
+ change_dir_prop() is called next otherwise the `svnadmin load`
+ parser will fail. */
+ if (db)
+ db->dump_newlines = TRUE;
}
+ else
+ {
+ /* fb->dump_props (for files) is handled in close_file()
+ which is called immediately.
- 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));
-
- /* Ugly hack: If a directory was copied from a previous
- revision, nothing like close_file() will be called to write two
- blank lines. If change_dir_prop() is called, props are dumped
- (along with the necessary PROPS-END\n\n and we're good. So
- set DUMP_NEWLINES here to print the newlines unless
- change_dir_prop() is called next otherwise the `svnadmin load`
- parser will fail. */
- if (kind == svn_node_dir)
- eb->dump_newlines = TRUE;
+ However, directories are not closed until all the work
+ inside them has been done; db->dump_props (for directories)
+ is handled (via dump_pending()) in all the functions that
+ can possibly be called after add_directory():
+
+ - add_directory()
+ - open_directory()
+ - delete_entry()
+ - close_directory()
+ - add_file()
+ - open_file()
+
+ change_dir_prop() is a special case. */
+ if (fb)
+ fb->dump_props = TRUE;
+ else if (db)
+ db->dump_props = TRUE;
+ }
break;
}
@@ -416,23 +499,42 @@ dump_node(struct dump_edit_baton *eb,
}
static svn_error_t *
-open_root(void *edit_baton,
- svn_revnum_t base_revision,
- apr_pool_t *pool,
- void **root_baton)
+dump_mkdir(struct dump_edit_baton *eb,
+ const char *repos_relpath,
+ apr_pool_t *pool)
{
- struct dump_edit_baton *eb = edit_baton;
+ svn_stringbuf_t *prop_header, *prop_content;
+ apr_size_t len;
+ const char *buf;
- /* Clear the per-revision pool after each revision */
- svn_pool_clear(eb->pool);
+ /* Node-path: ... */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+ repos_relpath));
- eb->props = apr_hash_make(eb->pool);
- eb->deleted_props = apr_hash_make(eb->pool);
- eb->propstring = svn_stringbuf_create_empty(eb->pool);
+ /* Node-kind: dir */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
- *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, FALSE, eb->pool);
- LDR_DBG(("open_root %p\n", *root_baton));
+ /* Node-action: add */
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+
+ /* Dump the (empty) property block. */
+ SVN_ERR(get_props_content(&prop_header, &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_ERR(svn_stream_write(eb->stream, prop_content->data, &len));
+
+ /* Newlines to tie it all off. */
+ SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
return SVN_NO_ERROR;
}
@@ -440,18 +542,113 @@ open_root(void *edit_baton,
/* Dump pending items from the specified node, to allow starting the dump
of a child node */
static svn_error_t *
-dump_pending(struct dir_baton *pb,
+dump_pending(struct dump_edit_baton *eb,
apr_pool_t *scratch_pool)
{
- /* Some pending properties to dump? */
- SVN_ERR(do_dump_props(&pb->eb->propstring, pb->eb->stream,
- pb->eb->props, pb->eb->deleted_props,
- &(pb->eb->dump_props), TRUE,
- pb->pool, scratch_pool));
+ if (! eb->pending_baton)
+ return SVN_NO_ERROR;
- /* Some pending newlines to dump? */
- SVN_ERR(do_dump_newlines(pb->eb, &(pb->eb->dump_newlines), scratch_pool));
+ 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));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(do_dump_newlines(eb, &(db->dump_newlines), scratch_pool));
+ }
+ 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));
+ }
+ else
+ abort();
+
+ /* Anything that was pending is pending no longer. */
+ eb->pending_baton = NULL;
+ eb->pending_kind = svn_node_none;
+
+ return SVN_NO_ERROR;
+}
+
+
+
+/*** Editor Function Implementations ***/
+
+static svn_error_t *
+open_root(void *edit_baton,
+ svn_revnum_t base_revision,
+ apr_pool_t *pool,
+ void **root_baton)
+{
+ struct dump_edit_baton *eb = edit_baton;
+ struct dir_baton *new_db = NULL;
+
+ /* Clear the per-revision pool after each revision */
+ svn_pool_clear(eb->pool);
+
+ LDR_DBG(("open_root %p\n", *root_baton));
+
+ if (eb->update_anchor_relpath)
+ {
+ int i;
+ const char *parent_path = eb->update_anchor_relpath;
+ apr_array_header_t *dirs_to_add =
+ apr_array_make(pool, 4, sizeof(const char *));
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ while (! svn_path_is_empty(parent_path))
+ {
+ APR_ARRAY_PUSH(dirs_to_add, const char *) = parent_path;
+ parent_path = svn_relpath_dirname(parent_path, pool);
+ }
+
+ for (i = dirs_to_add->nelts; i; --i)
+ {
+ const char *dir_to_add =
+ APR_ARRAY_IDX(dirs_to_add, i - 1, const char *);
+
+ svn_pool_clear(iterpool);
+
+ /* For parents of the source directory, we just manufacture
+ the adds ourselves. */
+ if (i > 1)
+ {
+ SVN_ERR(dump_mkdir(eb, dir_to_add, iterpool));
+ }
+ else
+ {
+ /* ... 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);
+ 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;
+ }
+ }
+ svn_pool_destroy(iterpool);
+ }
+
+ if (! new_db)
+ {
+ new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
+ edit_baton, NULL, FALSE, pool);
+ }
+
+ *root_baton = new_db;
return SVN_NO_ERROR;
}
@@ -465,10 +662,12 @@ delete_entry(const char *path,
LDR_DBG(("delete_entry %s\n", path));
- SVN_ERR(dump_pending(pb, pool));
+ SVN_ERR(dump_pending(pb->eb, pool));
- /* Add this path to the deleted_entries of the parent directory
- baton. */
+ /* We don't dump this deletion immediate. Rather, we add this path
+ to the deleted_entries of the parent directory baton. That way,
+ we can tell (later) an addition from a replacement. All the real
+ deletions get handled in close_directory(). */
apr_hash_set(pb->deleted_entries, apr_pstrdup(pb->eb->pool, path),
APR_HASH_KEY_STRING, pb);
@@ -490,11 +689,11 @@ add_directory(const char *path,
LDR_DBG(("add_directory %s\n", path));
+ SVN_ERR(dump_pending(pb->eb, pool));
+
new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb,
pb, TRUE, pb->eb->pool);
- SVN_ERR(dump_pending(pb, pool));
-
/* This might be a replacement -- is the path already deleted? */
val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -502,8 +701,7 @@ add_directory(const char *path,
is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
/* Dump the node */
- SVN_ERR(dump_node(pb->eb, new_db->repos_relpath,
- svn_node_dir,
+ SVN_ERR(dump_node(pb->eb, new_db->repos_relpath, new_db, NULL,
val ? svn_node_action_replace : svn_node_action_add,
is_copy,
is_copy ? new_db->copyfrom_path : NULL,
@@ -514,7 +712,11 @@ add_directory(const char *path,
/* Delete the path, it's now been dumped */
apr_hash_set(pb->deleted_entries, path, APR_HASH_KEY_STRING, 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;
*child_baton = new_db;
return SVN_NO_ERROR;
@@ -534,7 +736,7 @@ open_directory(const char *path,
LDR_DBG(("open_directory %s\n", path));
- SVN_ERR(dump_pending(pb, pool));
+ SVN_ERR(dump_pending(pb->eb, pool));
/* If the parent directory has explicit comparison path and rev,
record the same for this one. */
@@ -548,6 +750,7 @@ open_directory(const char *path,
new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb,
FALSE, pb->eb->pool);
+
*child_baton = new_db;
return SVN_NO_ERROR;
}
@@ -558,10 +761,33 @@ close_directory(void *dir_baton,
{
struct dir_baton *db = dir_baton;
apr_hash_index_t *hi;
+ svn_boolean_t this_pending;
LDR_DBG(("close_directory %p\n", dir_baton));
- SVN_ERR(dump_pending(db, pool));
+ /* Remember if this directory is the one currently pending. */
+ this_pending = (db->eb->pending_baton == db);
+
+ SVN_ERR(dump_pending(db->eb, pool));
+
+ /* If this directory was pending, then dump_pending() should have
+ taken care of all the props and such. Of course, the only way
+ that would be the case is if this directory was added/replaced.
+
+ Otherwise, if stuff for this directory has already been written
+ out (at some point in the past, prior to our handling other
+ nodes), we might need to generate a second "change" record just
+ to carry the information we've since learned about the
+ directory. */
+ if ((! this_pending) && (db->dump_props))
+ {
+ SVN_ERR(dump_node(db->eb, db->repos_relpath, db, NULL,
+ svn_node_action_change, FALSE,
+ NULL, SVN_INVALID_REVNUM, pool));
+ db->eb->pending_baton = db;
+ db->eb->pending_kind = svn_node_dir;
+ SVN_ERR(dump_pending(db->eb, pool));
+ }
/* Dump the deleted directory entries */
for (hi = apr_hash_first(pool, db->deleted_entries); hi;
@@ -569,11 +795,13 @@ close_directory(void *dir_baton,
{
const char *path = svn__apr_hash_index_key(hi);
- SVN_ERR(dump_node(db->eb, path, svn_node_unknown, svn_node_action_delete,
+ SVN_ERR(dump_node(db->eb, path, NULL, NULL, svn_node_action_delete,
FALSE, NULL, SVN_INVALID_REVNUM, pool));
}
+ /* ### should be unnecessary */
SVN_ERR(svn_hash__clear(db->deleted_entries, pool));
+
return SVN_NO_ERROR;
}
@@ -586,42 +814,33 @@ add_file(const char *path,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
- struct file_baton *fb = apr_pcalloc(pool, sizeof(*fb));
+ struct file_baton *fb;
void *val;
- svn_boolean_t is_copy;
-
- fb->eb = pb->eb;
- fb->parent_dir_baton = pb;
- fb->repos_relpath = svn_relpath_canonicalize(path, pool);
LDR_DBG(("add_file %s\n", path));
- SVN_ERR(dump_pending(pb, pool));
+ SVN_ERR(dump_pending(pb->eb, pool));
+ /* Make the file baton. */
+ fb = make_file_baton(path, pb, pool);
+
/* This might be a replacement -- is the path already deleted? */
val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
/* Detect add-with-history. */
- is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
-
- /* Dump the node. */
- SVN_ERR(dump_node(pb->eb, fb->repos_relpath,
- svn_node_file,
- val ? svn_node_action_replace : svn_node_action_add,
- is_copy,
- is_copy ? svn_relpath_canonicalize(copyfrom_path, pool)
- : NULL,
- is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
- pool));
+ if (ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev))
+ {
+ fb->copyfrom_path = svn_relpath_canonicalize(copyfrom_path, fb->pool);
+ fb->copyfrom_rev = copyfrom_rev;
+ fb->is_copy = TRUE;
+ }
+ fb->action = val ? svn_node_action_replace : svn_node_action_add;
+ /* Delete the path, it's now been dumped. */
if (val)
- /* delete the path, it's now been dumped. */
apr_hash_set(pb->deleted_entries, path, APR_HASH_KEY_STRING, NULL);
- /* Build a nice file baton to pass to change_file_prop and
- apply_textdelta */
*file_baton = fb;
-
return SVN_NO_ERROR;
}
@@ -633,36 +852,26 @@ open_file(const char *path,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
- struct file_baton *fb = apr_pcalloc(pool, sizeof(*fb));
- const char *copyfrom_path = NULL;
- svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
-
- fb->eb = pb->eb;
- fb->parent_dir_baton = pb;
- fb->repos_relpath = svn_relpath_canonicalize(path, pool);
+ struct file_baton *fb;
LDR_DBG(("open_file %s\n", path));
- SVN_ERR(dump_pending(pb, pool));
+ SVN_ERR(dump_pending(pb->eb, pool));
+
+ /* Make the file baton. */
+ fb = make_file_baton(path, pb, pool);
/* If the parent directory has explicit copyfrom path and rev,
record the same for this one. */
if (ARE_VALID_COPY_ARGS(pb->copyfrom_path, pb->copyfrom_rev))
{
- copyfrom_path = svn_relpath_join(pb->copyfrom_path,
- svn_relpath_basename(path, NULL),
- pb->eb->pool);
- copyfrom_rev = pb->copyfrom_rev;
+ fb->copyfrom_path = svn_relpath_join(pb->copyfrom_path,
+ svn_relpath_basename(path, NULL),
+ pb->eb->pool);
+ fb->copyfrom_rev = pb->copyfrom_rev;
}
- SVN_ERR(dump_node(pb->eb, fb->repos_relpath, svn_node_file,
- svn_node_action_change, FALSE, copyfrom_path,
- copyfrom_rev, pool));
-
- /* Build a nice file baton to pass to change_file_prop and
- apply_textdelta */
*file_baton = fb;
-
return SVN_NO_ERROR;
}
@@ -673,37 +882,30 @@ change_dir_prop(void *parent_baton,
apr_pool_t *pool)
{
struct dir_baton *db = parent_baton;
-
+ svn_boolean_t this_pending;
+
LDR_DBG(("change_dir_prop %p\n", parent_baton));
+ /* This directory is not pending, but something else is, so handle
+ the "something else". */
+ this_pending = (db->eb->pending_baton == db);
+ if (! this_pending)
+ SVN_ERR(dump_pending(db->eb, pool));
+
if (svn_property_kind2(name) != svn_prop_regular_kind)
return SVN_NO_ERROR;
if (value)
- apr_hash_set(db->eb->props, apr_pstrdup(db->eb->pool, name),
- APR_HASH_KEY_STRING, svn_string_dup(value, db->eb->pool));
+ apr_hash_set(db->props, apr_pstrdup(db->pool, name),
+ APR_HASH_KEY_STRING, svn_string_dup(value, db->pool));
else
- apr_hash_set(db->eb->deleted_props, apr_pstrdup(db->eb->pool, name),
+ apr_hash_set(db->deleted_props, apr_pstrdup(db->pool, name),
APR_HASH_KEY_STRING, "");
- if (! db->written_out)
- {
- /* If db->written_out is set, it means that the node information
- corresponding to this directory has already been written: don't
- do anything; do_dump_props() will take care of dumping the
- props. If it not, dump the node itself before dumping the
- props. */
-
- SVN_ERR(dump_node(db->eb, db->repos_relpath, svn_node_dir,
- svn_node_action_change, FALSE, db->copyfrom_path,
- db->copyfrom_rev, pool));
- db->written_out = TRUE;
- }
-
/* Make sure we eventually output the props, and disable printing
a couple of extra newlines */
- db->eb->dump_newlines = FALSE;
- db->eb->dump_props = TRUE;
+ db->dump_newlines = FALSE;
+ db->dump_props = TRUE;
return SVN_NO_ERROR;
}
@@ -715,7 +917,6 @@ change_file_prop(void *file_baton,
apr_pool_t *pool)
{
struct file_baton *fb = file_baton;
- struct dump_edit_baton *eb = fb->eb;
LDR_DBG(("change_file_prop %p\n", file_baton));
@@ -723,16 +924,16 @@ change_file_prop(void *file_baton,
return SVN_NO_ERROR;
if (value)
- apr_hash_set(eb->props, apr_pstrdup(eb->pool, name),
- APR_HASH_KEY_STRING, svn_string_dup(value, eb->pool));
+ apr_hash_set(fb->props, apr_pstrdup(fb->pool, name),
+ APR_HASH_KEY_STRING, svn_string_dup(value, fb->pool));
else
- apr_hash_set(eb->deleted_props, apr_pstrdup(eb->pool, name),
+ apr_hash_set(fb->deleted_props, apr_pstrdup(fb->pool, name),
APR_HASH_KEY_STRING, "");
/* Dump the property headers and wait; close_file might need
to write text headers too depending on whether
apply_textdelta is called */
- eb->dump_props = TRUE;
+ fb->dump_props = TRUE;
return SVN_NO_ERROR;
}
@@ -761,15 +962,14 @@ apply_textdelta(void *file_baton, const
{
struct file_baton *fb = file_baton;
struct dump_edit_baton *eb = fb->eb;
-
- /* Custom handler_baton allocated in a separate pool */
struct handler_baton *hb;
svn_stream_t *delta_filestream;
- hb = apr_pcalloc(eb->pool, sizeof(*hb));
-
LDR_DBG(("apply_textdelta %p\n", file_baton));
+ /* This is custom handler_baton, allocated from a separate pool. */
+ hb = apr_pcalloc(eb->pool, sizeof(*hb));
+
/* Use a temporary file to measure the Text-content-length */
delta_filestream = svn_stream_from_aprfile2(eb->delta_file, TRUE, pool);
@@ -778,7 +978,8 @@ apply_textdelta(void *file_baton, const
delta_filestream, 0,
SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
- eb->dump_text = TRUE;
+ /* Record that there's text to be dumped, and its base checksum. */
+ fb->dump_text = TRUE;
fb->base_checksum = apr_pstrdup(eb->pool, base_checksum);
/* The actual writing takes place when this function has
@@ -798,17 +999,25 @@ close_file(void *file_baton,
struct file_baton *fb = file_baton;
struct dump_edit_baton *eb = fb->eb;
apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t));
-
+ svn_stringbuf_t *propstring;
+
LDR_DBG(("close_file %p\n", file_baton));
- /* Some pending properties to dump? Dump just the headers- dump the
- props only after dumping the text headers too (if present) */
- SVN_ERR(do_dump_props(&eb->propstring, eb->stream,
- eb->props, eb->deleted_props,
- &(eb->dump_props), FALSE, pool, pool));
+ SVN_ERR(dump_pending(eb, pool));
+
+ /* Dump the node. */
+ SVN_ERR(dump_node(eb, fb->repos_relpath, NULL, fb,
+ fb->action, fb->is_copy, fb->copyfrom_path,
+ fb->copyfrom_rev, pool));
+
+ /* 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));
/* Dump the text headers */
- if (eb->dump_text)
+ if (fb->dump_text)
{
apr_status_t err;
@@ -843,31 +1052,31 @@ close_file(void *file_baton,
/* Content-length: 1549 */
/* If both text and props are absent, skip this header */
- if (eb->dump_props)
+ if (fb->dump_props)
SVN_ERR(svn_stream_printf(eb->stream, pool,
SVN_REPOS_DUMPFILE_CONTENT_LENGTH
": %ld\n\n",
- (unsigned long)info->size + eb->propstring->len));
- else if (eb->dump_text)
+ (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));
/* Dump the props now */
- if (eb->dump_props)
+ if (fb->dump_props)
{
- SVN_ERR(svn_stream_write(eb->stream, eb->propstring->data,
- &(eb->propstring->len)));
+ SVN_ERR(svn_stream_write(eb->stream, propstring->data,
+ &(propstring->len)));
/* Cleanup */
- eb->dump_props = FALSE;
- SVN_ERR(svn_hash__clear(eb->props, eb->pool));
- SVN_ERR(svn_hash__clear(eb->deleted_props, eb->pool));
+ fb->dump_props = FALSE;
+ SVN_ERR(svn_hash__clear(fb->props, fb->pool));
+ SVN_ERR(svn_hash__clear(fb->deleted_props, fb->pool));
}
/* Dump the text */
- if (eb->dump_text)
+ if (fb->dump_text)
{
/* Seek to the beginning of the delta file, map it to a stream,
and copy the stream to eb->stream. Then close the stream and
@@ -884,7 +1093,6 @@ close_file(void *file_baton,
/* Cleanup */
SVN_ERR(svn_stream_close(delta_filestream));
SVN_ERR(svn_io_file_trunc(eb->delta_file, 0, pool));
- eb->dump_text = FALSE;
}
/* Write a couple of blank lines for matching output with `svnadmin
@@ -1014,6 +1222,7 @@ svn_rdump__get_dump_editor(const svn_del
svn_revnum_t revision,
svn_stream_t *stream,
svn_ra_session_t *ra_session,
+ const char *update_anchor_relpath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -1026,7 +1235,9 @@ svn_rdump__get_dump_editor(const svn_del
eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton));
eb->stream = stream;
eb->ra_session = ra_session;
+ eb->update_anchor_relpath = update_anchor_relpath;
eb->current_revision = revision;
+ eb->pending_kind = svn_node_none;
/* Create a special per-revision pool */
eb->pool = svn_pool_create(pool);
Modified: subversion/branches/fsfs-format7/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnrdump/load_editor.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/fsfs-format7/subversion/svnrdump/load_editor.c Mon Feb 4 20:48:05 2013
@@ -501,7 +501,8 @@ get_shim_callbacks(struct revision_baton
/* Acquire a lock (of sorts) on the repository associated with the
* given RA SESSION. This lock is just a revprop change attempt in a
- * time-delay loop. This function is duplicated by svnsync in main.c.
+ * time-delay loop. This function is duplicated by svnsync in
+ * svnsync/svnsync.c
*
* ### TODO: Make this function more generic and
* expose it through a header for use by other Subversion
@@ -855,6 +856,8 @@ set_revision_property(void *baton,
{
struct revision_baton *rb = baton;
+ SVN_ERR(svn_rdump__normalize_prop(name, &value, rb->pool));
+
SVN_ERR(svn_repos__validate_prop(name, value, rb->pool));
if (rb->rev > 0)
@@ -934,6 +937,8 @@ set_node_property(void *baton,
}
}
+ SVN_ERR(svn_rdump__normalize_prop(name, &value, pool));
+
SVN_ERR(svn_repos__validate_prop(name, value, pool));
switch (nb->kind)
Modified: subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.c Mon Feb 4 20:48:05 2013
@@ -23,6 +23,7 @@
*/
#include <apr_signal.h>
+#include <apr_uri.h>
#include "svn_pools.h"
#include "svn_cmdline.h"
@@ -79,6 +80,7 @@ enum svn_svnrdump__longopt_t
opt_auth_password,
opt_auth_nocache,
opt_non_interactive,
+ opt_force_interactive,
opt_incremental,
opt_trust_server_cert,
opt_version
@@ -90,7 +92,8 @@ enum svn_svnrdump__longopt_t
opt_auth_password, \
opt_auth_nocache, \
opt_trust_server_cert, \
- opt_non_interactive
+ opt_non_interactive, \
+ opt_force_interactive
static const svn_opt_subcommand_desc2_t svnrdump__cmd_table[] =
{
@@ -126,7 +129,13 @@ static const apr_getopt_option_t svnrdum
{"password", opt_auth_password, 1,
N_("specify a password ARG")},
{"non-interactive", opt_non_interactive, 0,
- N_("do no interactive prompting")},
+ N_("do no interactive prompting (default is to prompt\n"
+ " "
+ "only if standard input is a terminal device)")},
+ {"force-interactive", opt_force_interactive, 0,
+ N_("do interactive prompting even if standard input\n"
+ " "
+ "is not a terminal device")},
{"no-auth-cache", opt_auth_nocache, 0,
N_("do not cache authentication tokens")},
{"help", 'h', 0,
@@ -223,7 +232,7 @@ replay_revstart(svn_revnum_t revision,
SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
rb->stdout_stream, rb->extra_ra_session,
- check_cancel, NULL, pool));
+ NULL, check_cancel, NULL, pool));
return SVN_NO_ERROR;
}
@@ -298,7 +307,7 @@ replay_revstart_v2(svn_revnum_t revision
SVN_ERR(svn_rdump__get_dump_editor_v2(editor, revision,
rb->stdout_stream,
rb->extra_ra_session,
- check_cancel, NULL, pool, pool));
+ NULL, check_cancel, NULL, pool, pool));
return SVN_NO_ERROR;
}
@@ -328,6 +337,8 @@ replay_revend_v2(svn_revnum_t revision,
* allocated from POOL. Use CONFIG_DIR and pass USERNAME, PASSWORD,
* CONFIG_DIR and NO_AUTH_CACHE to initialize the authorization baton.
* CONFIG_OPTIONS (if not NULL) is a list of configuration overrides.
+ * REPOS_URL is used to fiddle with server-specific configuration
+ * options.
*/
static svn_error_t *
init_client_context(svn_client_ctx_t **ctx_p,
@@ -335,13 +346,14 @@ init_client_context(svn_client_ctx_t **c
const char *username,
const char *password,
const char *config_dir,
+ const char *repos_url,
svn_boolean_t no_auth_cache,
svn_boolean_t trust_server_cert,
apr_array_header_t *config_options,
apr_pool_t *pool)
{
svn_client_ctx_t *ctx = NULL;
- svn_config_t *cfg_config;
+ svn_config_t *cfg_config, *cfg_servers;
SVN_ERR(svn_ra_initialize(pool));
@@ -357,6 +369,47 @@ init_client_context(svn_client_ctx_t **c
cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING);
+ /* ### FIXME: This is a hack to work around the fact that our dump
+ ### editor simply can't handle the way ra_serf violates the
+ ### editor v1 drive ordering requirements.
+ ###
+ ### We'll override both the global value and server-specific one
+ ### for the 'http-bulk-updates' and 'http-max-connections'
+ ### options in order to get ra_serf to try a bulk-update if the
+ ### server will allow it, or at least try to limit all its
+ ### auxiliary GETs/PROPFINDs to happening (well-ordered) on a
+ ### single server connection.
+ ###
+ ### See http://subversion.tigris.org/issues/show_bug.cgi?id=4116.
+ */
+ cfg_servers = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_SERVERS,
+ APR_HASH_KEY_STRING);
+ svn_config_set_bool(cfg_servers, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_BULK_UPDATES, TRUE);
+ svn_config_set_int64(cfg_servers, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS, 2);
+ if (cfg_servers)
+ {
+ apr_status_t status;
+ apr_uri_t parsed_url;
+
+ status = apr_uri_parse(pool, repos_url, &parsed_url);
+ if (! status)
+ {
+ const char *server_group;
+
+ server_group = svn_config_find_group(cfg_servers, parsed_url.hostname,
+ SVN_CONFIG_SECTION_GROUPS, pool);
+ if (server_group)
+ {
+ svn_config_set_bool(cfg_servers, server_group,
+ SVN_CONFIG_OPTION_HTTP_BULK_UPDATES, TRUE);
+ svn_config_set_int64(cfg_servers, server_group,
+ SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS, 2);
+ }
+ }
+ }
+
/* Set up our cancellation support. */
ctx->cancel_func = check_cancel;
@@ -413,16 +466,68 @@ dump_revision_header(svn_ra_session_t *s
return SVN_NO_ERROR;
}
+static svn_error_t *
+dump_initial_full_revision(svn_ra_session_t *session,
+ svn_ra_session_t *extra_ra_session,
+ svn_stream_t *stdout_stream,
+ svn_revnum_t revision,
+ svn_boolean_t quiet,
+ apr_pool_t *pool)
+{
+ const svn_ra_reporter3_t *reporter;
+ void *report_baton;
+ const svn_delta_editor_t *dump_editor;
+ void *dump_baton;
+ const char *session_url, *source_relpath;
+
+ /* Determine whether we're dumping the repository root URL or some
+ child thereof. If we're dumping a subtree of the repository
+ rather than the root, we have to jump through some hoops to make
+ our update-driven dump generation work the way a replay-driven
+ one would.
+
+ See http://subversion.tigris.org/issues/show_bug.cgi?id=4101
+ */
+ SVN_ERR(svn_ra_get_session_url(session, &session_url, pool));
+ SVN_ERR(svn_ra_get_path_relative_to_root(session, &source_relpath,
+ session_url, pool));
+
+ /* Start with a revision record header. */
+ SVN_ERR(dump_revision_header(session, stdout_stream, revision, pool));
+
+ /* Then, we'll drive the dump editor with what would look like a
+ full checkout of the repository as it looked in START_REVISION.
+ We do this by manufacturing a basic 'report' to the update
+ reporter, telling it that we have nothing to start with. The
+ delta between nothing and everything-at-REV is, effectively, a
+ full dump of REV. */
+ SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton, revision,
+ stdout_stream, extra_ra_session,
+ source_relpath, check_cancel, NULL, pool));
+ SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton, revision,
+ "", svn_depth_infinity, FALSE,
+ dump_editor, dump_baton, pool));
+ SVN_ERR(reporter->set_path(report_baton, "", revision,
+ svn_depth_infinity, TRUE, NULL, pool));
+ SVN_ERR(reporter->finish_report(report_baton, pool));
+
+ /* All finished with START_REVISION! */
+ if (! quiet)
+ SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+ revision));
+
+ return SVN_NO_ERROR;
+}
+
/* Replay revisions START_REVISION thru END_REVISION (inclusive) of
- * the repository located at URL, using callbacks which generate
- * Subversion repository dumpstreams describing the changes made in
- * those revisions. If QUIET is set, don't generate progress
- * messages.
+ * the repository URL at which SESSION is rooted, using callbacks
+ * which generate Subversion repository dumpstreams describing the
+ * changes made in those revisions. If QUIET is set, don't generate
+ * progress messages.
*/
static svn_error_t *
replay_revisions(svn_ra_session_t *session,
svn_ra_session_t *extra_ra_session,
- const char *url,
svn_revnum_t start_revision,
svn_revnum_t end_revision,
svn_boolean_t quiet,
@@ -465,7 +570,18 @@ replay_revisions(svn_ra_session_t *sessi
incremental = TRUE;
}
- if (incremental)
+ /* If what remains to be dumped is not going to be dumped
+ incrementally, then dump the first revision in full. */
+ if (!incremental)
+ {
+ SVN_ERR(dump_initial_full_revision(session, extra_ra_session,
+ stdout_stream, start_revision,
+ quiet, pool));
+ start_revision++;
+ }
+
+ /* If there are still revisions left to be dumped, do so. */
+ if (start_revision <= end_revision)
{
#ifndef USE_EV2_IMPL
SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
@@ -478,54 +594,6 @@ replay_revisions(svn_ra_session_t *sessi
NULL, NULL, NULL, NULL, pool));
#endif
}
- else
- {
- const svn_ra_reporter3_t *reporter;
- void *report_baton;
- const svn_delta_editor_t *dump_editor;
- void *dump_baton;
-
- /* First, we need to dump the start_revision in full. We'll
- start with a revision record header. */
- SVN_ERR(dump_revision_header(session, stdout_stream,
- start_revision, pool));
-
- /* Then, we'll drive the dump editor with what would look like a
- full checkout of the repository as it looked in
- START_REVISION. We do this by manufacturing a basic 'report'
- to the update reporter, telling it that we have nothing to
- start with. The delta between nothing and everything-at-REV
- is, effectively, a full dump of REV. */
- SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton,
- start_revision,
- stdout_stream, extra_ra_session,
- check_cancel, NULL, pool));
- SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
- start_revision, "", svn_depth_infinity,
- FALSE, dump_editor, dump_baton, pool));
- SVN_ERR(reporter->set_path(report_baton, "", start_revision,
- svn_depth_infinity, TRUE, NULL, pool));
- SVN_ERR(reporter->finish_report(report_baton, pool));
-
- /* All finished with START_REVISION! */
- if (! quiet)
- SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
- start_revision));
- start_revision++;
-
- /* Now go pick up additional revisions in the range, if any. */
- if (start_revision <= end_revision)
-#ifndef USE_EV2_IMPL
- SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
- 0, TRUE, replay_revstart, replay_revend,
- replay_baton, pool));
-#else
- SVN_ERR(svn_ra__replay_range_ev2(session, start_revision, end_revision,
- 0, TRUE, replay_revstart_v2,
- replay_revend_v2, replay_baton,
- NULL, NULL, NULL, NULL, pool));
-#endif
- }
SVN_ERR(svn_stream_close(stdout_stream));
return SVN_NO_ERROR;
@@ -635,7 +703,6 @@ dump_cmd(apr_getopt_t *os,
SVN_ERR(svn_ra_reparent(extra_ra_session, repos_root, pool));
return replay_revisions(opt_baton->session, extra_ra_session,
- opt_baton->url,
opt_baton->start_revision.value.number,
opt_baton->end_revision.value.number,
opt_baton->quiet, opt_baton->incremental, pool);
@@ -780,6 +847,7 @@ main(int argc, const char **argv)
svn_boolean_t no_auth_cache = FALSE;
svn_boolean_t trust_server_cert = FALSE;
svn_boolean_t non_interactive = FALSE;
+ svn_boolean_t force_interactive = FALSE;
apr_array_header_t *config_options = NULL;
apr_getopt_t *os;
const char *first_arg;
@@ -898,6 +966,9 @@ main(int argc, const char **argv)
case opt_non_interactive:
non_interactive = TRUE;
break;
+ case opt_force_interactive:
+ force_interactive = TRUE;
+ break;
case opt_incremental:
opt_baton->incremental = TRUE;
break;
@@ -916,6 +987,19 @@ main(int argc, const char **argv)
}
}
+ /* The --non-interactive and --force-interactive options are mutually
+ * exclusive. */
+ if (non_interactive && force_interactive)
+ {
+ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--non-interactive and --force-interactive "
+ "are mutually exclusive"));
+ return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
+ }
+ else
+ non_interactive = !svn_cmdline__be_interactive(non_interactive,
+ force_interactive);
+
if (opt_baton->help)
{
subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table,
@@ -955,9 +1039,10 @@ main(int argc, const char **argv)
err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, pool);
if (err)
return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
- svn_error_clear(svn_cmdline_fprintf(stderr, pool,
- _("Unknown command: '%s'\n"),
- first_arg_utf8));
+ svn_error_clear(
+ svn_cmdline_fprintf(stderr, pool,
+ _("Unknown subcommand: '%s'\n"),
+ first_arg_utf8));
SVNRDUMP_ERR(help_cmd(NULL, NULL, pool));
svn_pool_destroy(pool);
exit(EXIT_FAILURE);
@@ -1050,6 +1135,7 @@ main(int argc, const char **argv)
username,
password,
config_dir,
+ opt_baton->url,
no_auth_cache,
trust_server_cert,
config_options,
Modified: subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.h?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.h (original)
+++ subversion/branches/fsfs-format7/subversion/svnrdump/svnrdump.h Mon Feb 4 20:48:05 2013
@@ -32,6 +32,8 @@
#include "svn_delta.h"
#include "svn_ra.h"
+#include "private/svn_editor.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -39,9 +41,15 @@ extern "C" {
/**
* Get a dump editor @a editor along with a @a edit_baton allocated in
- * @a pool. The editor will write output to @a stream. Use @a
- * cancel_func and @a cancel_baton to check for user cancellation of
- * the operation (for timely-but-safe termination).
+ * @a pool. The editor will write output to @a stream.
+ *
+ * @a update_anchor_relpath is the repository relative path of the
+ * anchor of the update-style drive which will happen on @a *editor;
+ * if a replay-style drive will instead be used, it should be passed
+ * as @c NULL.
+ *
+ * Use @a cancel_func and @a cancel_baton to check for user
+ * cancellation of the operation (for timely-but-safe termination).
*/
svn_error_t *
svn_rdump__get_dump_editor(const svn_delta_editor_t **editor,
@@ -49,6 +57,7 @@ svn_rdump__get_dump_editor(const svn_del
svn_revnum_t revision,
svn_stream_t *stream,
svn_ra_session_t *ra_session,
+ const char *update_anchor_relpath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool);
@@ -59,6 +68,7 @@ svn_rdump__get_dump_editor_v2(svn_editor
svn_revnum_t revision,
svn_stream_t *stream,
svn_ra_session_t *ra_session,
+ const char *edit_root_relpath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool,
@@ -98,6 +108,20 @@ svn_rdump__normalize_props(apr_hash_t **
apr_hash_t *props,
apr_pool_t *result_pool);
+/* Normalize the line ending style of a single property that "needs
+ * translation" (according to svn_prop_needs_translation(),
+ * currently all svn:* props) so that they contain only LF (\n) line endings.
+ * "\r" characters found mid-line are replaced with "\n".
+ * "\r\n" sequences are replaced with "\n"
+ *
+ * NAME is used to check that VALUE should be normalized, and if this is the
+ * case, VALUE is then normalized, allocated from RESULT_POOL
+ */
+svn_error_t *
+svn_rdump__normalize_prop(const char *name,
+ const svn_string_t **value,
+ apr_pool_t *result_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/fsfs-format7/subversion/svnrdump/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnrdump/util.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnrdump/util.c (original)
+++ subversion/branches/fsfs-format7/subversion/svnrdump/util.c Mon Feb 4 20:48:05 2013
@@ -31,6 +31,25 @@
svn_error_t *
+svn_rdump__normalize_prop(const char *name,
+ const svn_string_t **value,
+ apr_pool_t *result_pool)
+{
+ if (svn_prop_needs_translation(name))
+ {
+ const char *cstring;
+
+ SVN_ERR(svn_subst_translate_cstring2((*value)->data, &cstring,
+ "\n", TRUE,
+ NULL, FALSE,
+ result_pool));
+
+ *value = svn_string_create(cstring, result_pool);
+ }
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_rdump__normalize_props(apr_hash_t **normal_props,
apr_hash_t *props,
apr_pool_t *result_pool)
@@ -45,16 +64,8 @@ svn_rdump__normalize_props(apr_hash_t **
const char *key = svn__apr_hash_index_key(hi);
const svn_string_t *value = svn__apr_hash_index_val(hi);
- if (svn_prop_needs_translation(key))
- {
- const char *cstring;
-
- SVN_ERR(svn_subst_translate_cstring2(value->data, &cstring,
- "\n", TRUE,
- NULL, FALSE,
- result_pool));
- value = svn_string_create(cstring, result_pool);
- }
+ SVN_ERR(svn_rdump__normalize_prop(key, &value,
+ result_pool));
apr_hash_set(*normal_props, key, APR_HASH_KEY_STRING, value);
}
Modified: subversion/branches/fsfs-format7/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnserve/serve.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnserve/serve.c (original)
+++ subversion/branches/fsfs-format7/subversion/svnserve/serve.c Mon Feb 4 20:48:05 2013
@@ -221,37 +221,26 @@ static svn_error_t *log_command(server_b
return log_write(b->log_file, line, nbytes, pool);
}
-svn_error_t *load_configs(svn_config_t **cfg,
- svn_config_t **pwdb,
- svn_authz_t **authzdb,
- enum username_case_type *username_case,
- const char *filename,
- svn_boolean_t must_exist,
- const char *base,
- server_baton_t *server,
- svn_ra_svn_conn_t *conn,
- apr_pool_t *pool)
+svn_error_t *load_pwdb_config(server_baton_t *server,
+ svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool)
{
- const char *pwdb_path, *authzdb_path;
+ const char *pwdb_path;
svn_error_t *err;
- SVN_ERR(svn_config_read2(cfg, filename, must_exist, FALSE, pool));
-
- svn_config_get(*cfg, &pwdb_path, SVN_CONFIG_SECTION_GENERAL,
+ svn_config_get(server->cfg, &pwdb_path, SVN_CONFIG_SECTION_GENERAL,
SVN_CONFIG_OPTION_PASSWORD_DB, NULL);
- *pwdb = NULL;
+ server->pwdb = NULL;
if (pwdb_path)
{
- pwdb_path = svn_dirent_canonicalize(pwdb_path, pool);
- pwdb_path = svn_dirent_join(base, pwdb_path, pool);
+ pwdb_path = svn_dirent_internal_style(pwdb_path, pool);
+ pwdb_path = svn_dirent_join(server->base, pwdb_path, pool);
- err = svn_config_read2(pwdb, pwdb_path, TRUE, FALSE, pool);
+ err = svn_config_read2(&server->pwdb, pwdb_path, TRUE, FALSE, pool);
if (err)
{
- if (server)
- /* Called by listening server; log error no matter what it is. */
- log_server_error(err, server, conn, pool);
+ log_server_error(err, server, conn, pool);
/* Because it may be possible to read the pwdb file with some
access methods and not others, ignore errors reading the pwdb
@@ -265,18 +254,11 @@ svn_error_t *load_configs(svn_config_t *
if (err->apr_err != SVN_ERR_BAD_FILENAME
&& ! APR_STATUS_IS_EACCES(err->apr_err))
{
- if (server)
- {
- /* Called by listening server: Now that we've logged
- * the error, clear it and return a nice, generic
- * error to the user
- * (http://subversion.tigris.org/issues/show_bug.cgi?id=2271). */
- svn_error_clear(err);
- return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL, NULL);
- }
- /* Called during startup; return the error, whereupon it
- * will go to standard error for the admin to see. */
- return err;
+ /* Now that we've logged the error, clear it and return a
+ * nice, generic error to the user:
+ * http://subversion.tigris.org/issues/show_bug.cgi?id=2271 */
+ svn_error_clear(err);
+ return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL, NULL);
}
else
/* Ignore SVN_ERR_BAD_FILENAME and APR_EACCES and proceed. */
@@ -284,51 +266,89 @@ svn_error_t *load_configs(svn_config_t *
}
}
+ return SVN_NO_ERROR;
+}
+
+/* Canonicalize ACCESS_FILE based on the type of argument.
+ * SERVER baton is used to convert relative paths to absolute paths
+ * rooted at the server root. */
+static const char *
+canonicalize_access_file(const char *access_file,
+ server_baton_t *server,
+ apr_pool_t *pool)
+{
+ if (svn_path_is_url(access_file))
+ {
+ access_file = svn_uri_canonicalize(access_file, pool);
+ }
+ else if (!svn_path_is_repos_relative_url(access_file))
+ {
+ access_file = svn_dirent_internal_style(access_file, pool);
+ access_file = svn_dirent_join(server->base, access_file, pool);
+ }
+
+ /* We don't canonicalize repos relative urls since they get
+ * canonicalized inside svn_repos_authz_read2() when they
+ * are resolved. */
+
+ return access_file;
+}
+
+svn_error_t *load_authz_config(server_baton_t *server,
+ svn_ra_svn_conn_t *conn,
+ const char *repos_root,
+ apr_pool_t *pool)
+{
+ const char *authzdb_path;
+ const char *groupsdb_path;
+ svn_error_t *err;
+
/* Read authz configuration. */
- svn_config_get(*cfg, &authzdb_path, SVN_CONFIG_SECTION_GENERAL,
+ svn_config_get(server->cfg, &authzdb_path, SVN_CONFIG_SECTION_GENERAL,
SVN_CONFIG_OPTION_AUTHZ_DB, NULL);
+
+ svn_config_get(server->cfg, &groupsdb_path, SVN_CONFIG_SECTION_GENERAL,
+ SVN_CONFIG_OPTION_GROUPS_DB, NULL);
+
if (authzdb_path)
{
const char *case_force_val;
- authzdb_path = svn_dirent_canonicalize(authzdb_path, pool);
- authzdb_path = svn_dirent_join(base, authzdb_path, pool);
- err = svn_repos_authz_read(authzdb, authzdb_path, TRUE, pool);
+ /* Canonicalize and add the base onto the authzdb_path (if needed). */
+ authzdb_path = canonicalize_access_file(authzdb_path, server, pool);
+
+ /* Same for the groupsdb_path if it is present. */
+ if (groupsdb_path)
+ groupsdb_path = canonicalize_access_file(groupsdb_path,
+ server, pool);
+
+ err = svn_repos_authz_read2(&server->authzdb, authzdb_path,
+ groupsdb_path, TRUE, repos_root, pool);
if (err)
{
- if (server)
- {
- /* Called by listening server: Log the error, clear it,
- * and return a nice, generic error to the user
- * (http://subversion.tigris.org/issues/show_bug.cgi?id=2271). */
- log_server_error(err, server, conn, pool);
- svn_error_clear(err);
- return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, NULL);
- }
- else
- /* Called during startup; return the error, whereupon it
- * will go to standard error for the admin to see. */
- return err;
+ log_server_error(err, server, conn, pool);
+ svn_error_clear(err);
+ return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, NULL);
}
/* Are we going to be case-normalizing usernames when we consult
* this authz file? */
- svn_config_get(*cfg, &case_force_val, SVN_CONFIG_SECTION_GENERAL,
+ svn_config_get(server->cfg, &case_force_val, SVN_CONFIG_SECTION_GENERAL,
SVN_CONFIG_OPTION_FORCE_USERNAME_CASE, NULL);
if (case_force_val)
{
if (strcmp(case_force_val, "upper") == 0)
- *username_case = CASE_FORCE_UPPER;
+ server->username_case = CASE_FORCE_UPPER;
else if (strcmp(case_force_val, "lower") == 0)
- *username_case = CASE_FORCE_LOWER;
+ server->username_case = CASE_FORCE_LOWER;
else
- *username_case = CASE_ASIS;
+ server->username_case = CASE_ASIS;
}
}
else
{
- *authzdb = NULL;
- *username_case = CASE_ASIS;
+ server->authzdb = NULL;
+ server->username_case = CASE_ASIS;
}
return SVN_NO_ERROR;
@@ -1005,7 +1025,7 @@ get_props(apr_hash_t **props,
/* Get any inherited properties the user is authorized to. */
if (iprops)
{
- SVN_ERR(svn_repos_fs_get_inherited_props(iprops, root, path,
+ SVN_ERR(svn_repos_fs_get_inherited_props(iprops, root, path, NULL,
authz_check_access_cb_func(b),
b, pool, pool));
}
@@ -3138,14 +3158,26 @@ static svn_error_t *find_repos(const cha
b->repos_name = b->authz_repos_name;
b->repos_name = svn_path_uri_encode(b->repos_name, pool);
- /* If the svnserve configuration files have not been loaded then
- load them from the repository. */
+ /* If the svnserve configuration has not been loaded then load it from the
+ * repository. */
if (NULL == b->cfg)
- SVN_ERR(load_configs(&b->cfg, &b->pwdb, &b->authzdb, &b->username_case,
- svn_repos_svnserve_conf(b->repos, pool), FALSE,
- svn_repos_conf_dir(b->repos, pool),
- b, conn,
- pool));
+ {
+ b->base = svn_repos_conf_dir(b->repos, pool);
+
+ SVN_ERR(svn_config_read2(&b->cfg, svn_repos_svnserve_conf(b->repos, pool),
+ FALSE, /* must_exist */
+ FALSE, /* section_names_case_sensitive */
+ pool));
+ SVN_ERR(load_pwdb_config(b, conn, pool));
+ SVN_ERR(load_authz_config(b, conn, repos_root, pool));
+ }
+ /* svnserve.conf has been loaded via the --config-file option so need
+ * to load pwdb and authz. */
+ else
+ {
+ SVN_ERR(load_pwdb_config(b, conn, pool));
+ SVN_ERR(load_authz_config(b, conn, repos_root, pool));
+ }
#ifdef SVN_HAVE_SASL
/* Should we use Cyrus SASL? */
@@ -3349,9 +3381,10 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
b.user = NULL;
b.username_case = params->username_case;
b.authz_user = NULL;
+ b.base = params->base;
b.cfg = params->cfg;
- b.pwdb = params->pwdb;
- b.authzdb = params->authzdb;
+ b.pwdb = NULL;
+ b.authzdb = NULL;
b.realm = NULL;
b.log_file = params->log_file;
b.pool = pool;
Modified: subversion/branches/fsfs-format7/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnserve/server.h?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnserve/server.h (original)
+++ subversion/branches/fsfs-format7/subversion/svnserve/server.h Mon Feb 4 20:48:05 2013
@@ -42,6 +42,7 @@ typedef struct server_baton_t {
svn_repos_t *repos;
const char *repos_name; /* URI-encoded name of repository (not for authz) */
svn_fs_t *fs; /* For convenience; same as svn_repos_fs(repos) */
+ const char *base; /* Base directory for config files */
svn_config_t *cfg; /* Parsed repository svnserve.conf */
svn_config_t *pwdb; /* Parsed password database */
svn_authz_t *authzdb; /* Parsed authz rules */
@@ -87,24 +88,15 @@ typedef struct serve_params_t {
which forces all connections to be read-only. */
svn_boolean_t read_only;
+ /* The base directory for any relative configuration files. */
+ const char *base;
+
/* A parsed repository svnserve configuration file, ala
svnserve.conf. If this is NULL, then no configuration file was
specified on the command line. If this is non-NULL, then
per-repository svnserve.conf are not read. */
svn_config_t *cfg;
- /* A parsed repository password database. If this is NULL, then
- either no svnserve configuration file was specified on the
- command line, or it was specified and it did not refer to a
- password database. */
- svn_config_t *pwdb;
-
- /* A parsed repository authorization database. If this is NULL,
- then either no svnserve configuration file was specified on the
- command line, or it was specified and it did not refer to a
- authorization database. */
- svn_authz_t *authzdb;
-
/* A filehandle open for writing logs to; possibly NULL. */
apr_file_t *log_file;
@@ -145,31 +137,24 @@ typedef struct serve_params_t {
svn_error_t *serve(svn_ra_svn_conn_t *conn, serve_params_t *params,
apr_pool_t *pool);
-/* Load a svnserve configuration file located at FILENAME into CFG,
- and if such as found, then:
+/* Load the password database for the listening server based on the
+ entries in the SERVER struct.
- - set *PWDB to any referenced password database,
- - set *AUTHZDB to any referenced authorization database, and
- - set *USERNAME_CASE to the enumerated value of the
- 'force-username-case' configuration value (or its default).
-
- If MUST_EXIST is true and FILENAME does not exist, then return an
- error. BASE may be specified as the base path to any referenced
- password and authorization files found in FILENAME.
-
- If SERVER is not NULL, log the real errors with SERVER and CONN but
- return generic errors to the client. CONN must not be NULL if SERVER
- is not NULL. */
-svn_error_t *load_configs(svn_config_t **cfg,
- svn_config_t **pwdb,
- svn_authz_t **authzdb,
- enum username_case_type *username_case,
- const char *filename,
- svn_boolean_t must_exist,
- const char *base,
- server_baton_t *server,
- svn_ra_svn_conn_t *conn,
- apr_pool_t *pool);
+ SERVER and CONN must not be NULL. The real errors will be logged with
+ SERVER and CONN but return generic errors to the client. */
+svn_error_t *load_pwdb_config(server_baton_t *server,
+ svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool);
+
+/* Load the authz database for the listening server based on the
+ entries in the SERVER struct.
+
+ SERVER and CONN must not be NULL. The real errors will be logged with
+ SERVER and CONN but return generic errors to the client. */
+svn_error_t *load_authz_config(server_baton_t *server,
+ svn_ra_svn_conn_t *conn,
+ const char *repos_root,
+ apr_pool_t *pool);
/* Initialize the Cyrus SASL library. POOL is used for allocations. */
svn_error_t *cyrus_init(apr_pool_t *pool);
Modified: subversion/branches/fsfs-format7/subversion/svnserve/svnserve.8
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnserve/svnserve.8?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnserve/svnserve.8 (original)
+++ subversion/branches/fsfs-format7/subversion/svnserve/svnserve.8 Mon Feb 4 20:48:05 2013
@@ -110,12 +110,12 @@ still backgrounds itself at startup time
.TP 5
\fB\-\-config\-file\fP=\fIfilename\fP
When specified, \fBsvnserve\fP reads \fIfilename\fP once at program
-startup and caches the \fBsvnserve\fP configuration and any passwords
-and authorization configuration referenced from \fIfilename\fP.
-\fBsvnserve\fP will not read any per-repository
-\fBconf/svnserve.conf\fP files when this option is used. See the
-\fBsvnserve.conf\fP(5) man page for details of the file format for
-this option.
+startup and caches the \fBsvnserve\fP configuration. The password
+and authorization configurations referenced from \fIfilename\fP will
+be loaded on each connection. \fBsvnserve\fP will not read any
+per-repository \fBconf/svnserve.conf\fP files when this option is
+used. See the \fBsvnserve.conf\fP(5) man page for details of the
+file format for this option.
.PP
.TP 5
\fB\-\-pid\-file\fP=\fIfilename\fP
Modified: subversion/branches/fsfs-format7/subversion/svnserve/svnserve.conf.5
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/svnserve/svnserve.conf.5?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/svnserve/svnserve.conf.5 (original)
+++ subversion/branches/fsfs-format7/subversion/svnserve/svnserve.conf.5 Mon Feb 4 20:48:05 2013
@@ -61,11 +61,13 @@ uses only one section "users"; each vari
username, and each value is a password.
.PP
.TP 5
-\fBauthz-db\fP = \fIfilename\fP
+\fBauthz-db\fP = \fIpath\fP
The authz-db option controls the location of the authorization
-rules for path-based access control. \fIfilename\fP may be
-relative to the repository conf directory. There is no default value.
-If you don't specify an authz-db, no path-based access control is done.
+rules for path-based access control. \fIpath\fP may be
+relative to the repository conf directory. \fIpath\fP may be a repository
+relative URL (^/) or absolute file:// URL to a text file in a Subversion
+repository. There is no default value. If you don't specify an authz-db,
+no path-based access control is done.
.PP
.TP 5
\fBrealm\fP = \fIrealm\-name\fP
Modified: subversion/branches/fsfs-format7/subversion/tests/README
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/tests/README?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/tests/README (original)
+++ subversion/branches/fsfs-format7/subversion/tests/README Mon Feb 4 20:48:05 2013
@@ -20,7 +20,7 @@ sub-tests it can run. It has a standard
1. If run with a numeric argument N, the program runs sub-test N.
-2. If run with the argument `list', it will list the names of all sub-tests.
+2. If run with the argument `--list', it will list the names of all sub-tests.
3. If run with no arguments, the program runs *all* sub-tests.
Modified: subversion/branches/fsfs-format7/subversion/tests/cmdline/README
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/tests/cmdline/README?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/tests/cmdline/README (original)
+++ subversion/branches/fsfs-format7/subversion/tests/cmdline/README Mon Feb 4 20:48:05 2013
@@ -141,16 +141,17 @@ Note [1]: It would be quite too much to
----------------------------
-[If you want to test with serf instead of neon:
-
- $ ./basic_tests.py --url=http://localhost --http-library=serf
-
- or
-
- $ make check BASE_URL=http://localhost HTTP_LIBRARY=serf
-]
-
+As a shorthand to all of the above, ./davautocheck.sh will generate
+an Apache configuration listening on a random port on localhost and
+run some tests. Without arguments, or when invoking 'make davautocheck'
+on the top-level Makefile, it will run all tests. With arguments,
+it will run just one suite or just one test:
+
+ $ ./davautocheck.sh
+ $ ./davautocheck.sh basic
+ $ ./davautocheck.sh basic 15
+It also respects some environment variables.
Running over ra_svn
-------------------
@@ -188,6 +189,9 @@ $ saslpasswd2 -c -u svntest jconstant
As usual, both users should use the password 'rayjandom'.
+There are 'make svnserveautocheck' and ./svnserveautocheck.sh commands,
+analogous to davautocheck.sh documented above.
+
Running tests in a RAM disk
--------------------------
Modified: subversion/branches/fsfs-format7/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/tests/cmdline/authz_tests.py?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/fsfs-format7/subversion/tests/cmdline/authz_tests.py Mon Feb 4 20:48:05 2013
@@ -137,7 +137,7 @@ def broken_authz_file(sbox):
exit_code, out, err = svntest.main.run_svn(1,
"delete",
sbox.repo_url + "/A",
- "-m", "a log message");
+ "-m", "a log message")
if out:
raise svntest.verify.SVNUnexpectedStdout(out)
if not err:
@@ -1223,12 +1223,13 @@ def authz_tree_conflict(sbox):
expected_output = svntest.wc.State(wc_dir, {})
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
expected_status.tweak('A/C', status='A ', wc_rev='0')
+ expected_status.tweak('A', '', status='! ', wc_rev='1')
svntest.actions.run_and_verify_update(wc_dir,
expected_output,
None,
expected_status,
- "Failed to mark '.*C' absent:",
+ "Failed to mark '.*C' (server|absent):",
None, None, None, None, 0,
'-r', '1', wc_dir)
@@ -1451,6 +1452,69 @@ def remove_subdir_with_authz_and_tc(sbox
None, None, False,
wc_dir)
+@SkipUnless(svntest.main.is_ra_type_svn)
+def authz_svnserve_groups(sbox):
+ "authz with configured global groups"
+
+ sbox.build(create_wc = False)
+
+ svntest.main.write_restrictive_svnserve_conf_with_groups(sbox.repo_dir)
+
+ svntest.main.write_authz_file(sbox, { "/A/B" : "@senate = r",
+ "/A/D" : "@senate = rw",
+ "/A/B/E" : "@senate = " })
+
+ svntest.main.write_groups_file(sbox, { "senate" : "jrandom" })
+
+ root_url = sbox.repo_url
+ A_url = root_url + '/A'
+ B_url = A_url + '/B'
+ E_url = B_url + '/E'
+ F_url = B_url + '/F'
+ D_url = A_url + '/D'
+ G_url = D_url + '/G'
+ lambda_url = B_url + '/lambda'
+ pi_url = G_url + '/pi'
+ alpha_url = E_url + '/alpha'
+
+ expected_err = ".*svn: E170001: Authorization failed.*"
+
+ # read a remote file
+ svntest.actions.run_and_verify_svn(None, ["This is the file 'lambda'.\n"],
+ [], 'cat',
+ lambda_url)
+
+ # read a remote file
+ svntest.actions.run_and_verify_svn(None, ["This is the file 'pi'.\n"],
+ [], 'cat',
+ pi_url)
+
+ # read a remote file, unreadable: should fail
+ svntest.actions.run_and_verify_svn(None,
+ None, expected_err,
+ 'cat',
+ alpha_url)
+
+ # copy a remote file, source is unreadable: should fail
+ svntest.actions.run_and_verify_svn(None,
+ None, expected_err,
+ 'cp',
+ '-m', 'logmsg',
+ alpha_url, B_url)
+
+ # copy a remote folder
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp',
+ '-m', 'logmsg',
+ F_url, D_url)
+
+ # copy a remote folder, source is unreadable: should fail
+ svntest.actions.run_and_verify_svn(None,
+ None, expected_err,
+ 'cp',
+ '-m', 'logmsg',
+ E_url, D_url)
+
########################################################################
# Run the tests
@@ -1480,7 +1544,8 @@ test_list = [ None,
wc_delete,
wc_commit_error_handling,
upgrade_absent,
- remove_subdir_with_authz_and_tc
+ remove_subdir_with_authz_and_tc,
+ authz_svnserve_groups
]
serial_only = True