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/10/30 02:56:29 UTC
svn commit: r1536953 - in /subversion/branches/1.8.x-r1536854: ./ CHANGES
configure.ac subversion/libsvn_repos/dump.c subversion/svn/svn.c
subversion/tests/cmdline/svnadmin_tests.py tools/dist/make-deps-tarball.sh
Author: stefan2
Date: Wed Oct 30 01:56:28 2013
New Revision: 1536953
URL: http://svn.apache.org/r1536953
Log:
On the 1.8.x-r1536854 branch:
Merge r1536854 from /trunk and resolve conflict in svnadmin_tests.py
Modified:
subversion/branches/1.8.x-r1536854/ (props changed)
subversion/branches/1.8.x-r1536854/CHANGES (props changed)
subversion/branches/1.8.x-r1536854/configure.ac (props changed)
subversion/branches/1.8.x-r1536854/subversion/libsvn_repos/dump.c
subversion/branches/1.8.x-r1536854/subversion/svn/svn.c (props changed)
subversion/branches/1.8.x-r1536854/subversion/tests/cmdline/svnadmin_tests.py
subversion/branches/1.8.x-r1536854/tools/dist/make-deps-tarball.sh (props changed)
Propchange: subversion/branches/1.8.x-r1536854/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1536854
Propchange: subversion/branches/1.8.x-r1536854/CHANGES
------------------------------------------------------------------------------
Merged /subversion/trunk/CHANGES:r1536854
Propchange: subversion/branches/1.8.x-r1536854/configure.ac
------------------------------------------------------------------------------
Merged /subversion/trunk/configure.ac:r1536854
Modified: subversion/branches/1.8.x-r1536854/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x-r1536854/subversion/libsvn_repos/dump.c?rev=1536953&r1=1536952&r2=1536953&view=diff
==============================================================================
--- subversion/branches/1.8.x-r1536854/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/1.8.x-r1536854/subversion/libsvn_repos/dump.c Wed Oct 30 01:56:28 2013
@@ -44,6 +44,269 @@
/*----------------------------------------------------------------------*/
+/* To be able to check whether a path exists in the current revision
+ (as changes come in), we need to track the relevant tree changes.
+
+ In particular, we remember deletions, additions and copies including
+ their copy-from info. Since the dump performs a pre-order tree walk,
+ we only need to store the data for the stack of parent folders.
+
+ The problem that we are trying to solve is that the dump receives
+ transforming operations whose validity depends on previous operations
+ in the same revision but cannot be checked against the final state
+ as stored in the repository as that is the state *after* we applied
+ the respective tree changes.
+
+ Note that the tracker functions don't perform any sanity or validity
+ checks. Those higher-level tests have to be done in the calling code.
+ However, there is no way to corrupt the data structure using the
+ provided functions.
+ */
+
+/* Single entry in the path tracker. Not all levels along the path
+ hierarchy do need to have an instance of this struct but only those
+ that got changed by a tree modification.
+
+ Please note that the path info in this struct is stored in re-usable
+ stringbuf objects such that we don't need to allocate more memory than
+ the longest path we encounter.
+ */
+typedef struct path_tracker_entry_t
+{
+ /* path in the current tree */
+ svn_stringbuf_t *path;
+
+ /* copy-from path (must be empty if COPYFROM_REV is SVN_INVALID_REVNUM) */
+ svn_stringbuf_t *copyfrom_path;
+
+ /* copy-from revision (SVN_INVALID_REVNUM for additions / replacements
+ that don't copy history, i.e. with no sub-tree) */
+ svn_revnum_t copyfrom_rev;
+
+ /* if FALSE, PATH has been deleted */
+ svn_boolean_t exists;
+} path_tracker_entry_t;
+
+/* Tracks all tree modifications above the current path.
+ */
+typedef struct path_tracker_t
+{
+ /* Container for all relevant tree changes in depth order.
+ May contain more entries than DEPTH to allow for reusing memory.
+ Only entries 0 .. DEPTH-1 are valid.
+ */
+ apr_array_header_t *stack;
+
+ /* Number of relevant entries in STACK. May be 0 */
+ int depth;
+
+ /* Revision that we current track. If DEPTH is 0, paths are exist in
+ REVISION exactly when they exist in REVISION-1. This applies only
+ to the current state of our tree walk.
+ */
+ svn_revnum_t revision;
+
+ /* Allocate container entries here. */
+ apr_pool_t *pool;
+} path_tracker_t;
+
+/* Return a new path tracker object for REVISION, allocated in POOL.
+ */
+static path_tracker_t *
+tracker_create(svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ path_tracker_t *result = apr_pcalloc(pool, sizeof(*result));
+ result->stack = apr_array_make(pool, 16, sizeof(path_tracker_entry_t));
+ result->revision = revision;
+ result->pool = pool;
+
+ return result;
+}
+
+/* Remove all entries from TRACKER that are not relevant to PATH anymore.
+ * If ALLOW_EXACT_MATCH is FALSE, keep only entries that pertain to
+ * parent folders but not to PATH itself.
+ *
+ * This internal function implicitly updates the tracker state during the
+ * tree by removing "past" entries. Other functions will add entries when
+ * we encounter a new tree change.
+ */
+static void
+tracker__trim(path_tracker_t *tracker,
+ const char *path,
+ svn_boolean_t allow_exact_match)
+{
+ /* remove everything that is unrelated to PATH.
+ Note that TRACKER->STACK is depth-ordered,
+ i.e. stack[N] is a (maybe indirect) parent of stack[N+1]
+ for N+1 < DEPTH.
+ */
+ for (; tracker->depth; --tracker->depth)
+ {
+ path_tracker_entry_t *parent = &APR_ARRAY_IDX(tracker->stack,
+ tracker->depth - 1,
+ path_tracker_entry_t);
+ const char *rel_path
+ = svn_dirent_skip_ancestor(parent->path->data, path);
+
+ /* always keep parents. Keep exact matches when allowed. */
+ if (rel_path && (allow_exact_match || *rel_path != '\0'))
+ break;
+ }
+}
+
+/* Using TRACKER, check what path at what revision in the repository must
+ be checked to decide that whether PATH exists. Return the info in
+ *ORIG_PATH and *ORIG_REV, respectively.
+
+ If the path is known to not exist, *ORIG_PATH will be NULL and *ORIG_REV
+ will be SVN_INVALID_REVNUM. If *ORIG_REV is SVN_INVALID_REVNUM, PATH
+ has just been added in the revision currently being tracked.
+
+ Use POOL for allocations. Note that *ORIG_PATH may be allocated in POOL,
+ a reference to internal data with the same lifetime as TRACKER or just
+ PATH.
+ */
+static void
+tracker_lookup(const char **orig_path,
+ svn_revnum_t *orig_rev,
+ path_tracker_t *tracker,
+ const char *path,
+ apr_pool_t *pool)
+{
+ tracker__trim(tracker, path, TRUE);
+ if (tracker->depth == 0)
+ {
+ /* no tree changes -> paths are the same as in the previous rev. */
+ *orig_path = path;
+ *orig_rev = tracker->revision - 1;
+ }
+ else
+ {
+ path_tracker_entry_t *parent = &APR_ARRAY_IDX(tracker->stack,
+ tracker->depth - 1,
+ path_tracker_entry_t);
+ if (parent->exists)
+ {
+ const char *rel_path
+ = svn_dirent_skip_ancestor(parent->path->data, path);
+
+ if (parent->copyfrom_rev != SVN_INVALID_REVNUM)
+ {
+ /* parent is a copy with history. Translate path. */
+ *orig_path = svn_dirent_join(parent->copyfrom_path->data,
+ rel_path, pool);
+ *orig_rev = parent->copyfrom_rev;
+ }
+ else if (*rel_path == '\0')
+ {
+ /* added in this revision with no history */
+ *orig_path = path;
+ *orig_rev = tracker->revision;
+ }
+ else
+ {
+ /* parent got added but not this path */
+ *orig_path = NULL;
+ *orig_rev = SVN_INVALID_REVNUM;
+ }
+ }
+ else
+ {
+ /* (maybe parent) path has been deleted */
+ *orig_path = NULL;
+ *orig_rev = SVN_INVALID_REVNUM;
+ }
+ }
+}
+
+/* Return a reference to the stack entry in TRACKER for PATH. If no
+ suitable entry exists, add one. Implicitly updates the tracked tree
+ location.
+
+ Only the PATH member of the result is being updated. All other members
+ will have undefined values.
+ */
+static path_tracker_entry_t *
+tracker__add_entry(path_tracker_t *tracker,
+ const char *path)
+{
+ path_tracker_entry_t *entry;
+ tracker__trim(tracker, path, FALSE);
+
+ if (tracker->depth == tracker->stack->nelts)
+ {
+ entry = apr_array_push(tracker->stack);
+ entry->path = svn_stringbuf_create_empty(tracker->pool);
+ entry->copyfrom_path = svn_stringbuf_create_empty(tracker->pool);
+ }
+ else
+ {
+ entry = &APR_ARRAY_IDX(tracker->stack, tracker->depth,
+ path_tracker_entry_t);
+ }
+
+ svn_stringbuf_set(entry->path, path);
+ ++tracker->depth;
+
+ return entry;
+}
+
+/* Update the TRACKER with a copy from COPYFROM_PATH@COPYFROM_REV to
+ PATH in the tracked revision.
+ */
+static void
+tracker_path_copy(path_tracker_t *tracker,
+ const char *path,
+ const char *copyfrom_path,
+ svn_revnum_t copyfrom_rev)
+{
+ path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+
+ svn_stringbuf_set(entry->copyfrom_path, copyfrom_path);
+ entry->copyfrom_rev = copyfrom_rev;
+ entry->exists = TRUE;
+}
+
+/* Update the TRACKER with a plain addition of PATH (without history).
+ */
+static void
+tracker_path_add(path_tracker_t *tracker,
+ const char *path)
+{
+ path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+
+ svn_stringbuf_setempty(entry->copyfrom_path);
+ entry->copyfrom_rev = SVN_INVALID_REVNUM;
+ entry->exists = TRUE;
+}
+
+/* Update the TRACKER with a replacement of PATH with a plain addition
+ (without history).
+ */
+static void
+tracker_path_replace(path_tracker_t *tracker,
+ const char *path)
+{
+ /* this will implicitly purge all previous sub-tree info from STACK.
+ Thus, no need to tack the deletion explicitly. */
+ tracker_path_add(tracker, path);
+}
+
+/* Update the TRACKER with a deletion of PATH.
+ */
+static void
+tracker_path_delete(path_tracker_t *tracker,
+ const char *path)
+{
+ path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+
+ svn_stringbuf_setempty(entry->copyfrom_path);
+ entry->copyfrom_rev = SVN_INVALID_REVNUM;
+ entry->exists = FALSE;
+}
+
/* Compute the delta between OLDROOT/OLDPATH and NEWROOT/NEWPATH and
store it into a new temporary file *TEMPFILE. OLDROOT may be NULL,
@@ -130,6 +393,10 @@ struct edit_baton
/* reusable buffer for writing file contents */
char buffer[SVN__STREAM_CHUNK_SIZE];
apr_size_t bufsize;
+
+ /* Structure allows us to verify the paths currently being dumped.
+ If NULL, validity checks are being skipped. */
+ path_tracker_t *path_tracker;
};
struct dir_baton
@@ -216,6 +483,95 @@ make_dir_baton(const char *path,
return new_db;
}
+static svn_error_t *
+fetch_kind_func(svn_node_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool);
+
+/* Return an error when PATH in REVISION does not exist or is of a
+ different kind than EXPECTED_KIND. If the latter is svn_node_unknown,
+ skip that check. Use EB for context information. If REVISION is the
+ current revision, use EB's path tracker to follow renames, deletions,
+ etc.
+
+ Use SCRATCH_POOL for temporary allocations.
+ No-op if EB's path tracker has not been initialized.
+ */
+static svn_error_t *
+node_must_exist(struct edit_baton *eb,
+ const char *path,
+ svn_revnum_t revision,
+ svn_node_kind_t expected_kind,
+ apr_pool_t *scratch_pool)
+{
+ svn_node_kind_t kind = svn_node_none;
+
+ /* in case the caller is trying something stupid ... */
+ if (eb->path_tracker == NULL)
+ return SVN_NO_ERROR;
+
+ /* paths pertaining to the revision currently being processed must
+ be translated / checked using our path tracker. */
+ if (revision == eb->path_tracker->revision)
+ tracker_lookup(&path, &revision, eb->path_tracker, path, scratch_pool);
+
+ /* determine the node type (default: no such node) */
+ if (path)
+ SVN_ERR(fetch_kind_func(&kind, eb, path, revision, scratch_pool));
+
+ /* check results */
+ if (kind == svn_node_none)
+ return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+ _("Path '%s' not found in r%ld."),
+ path, revision);
+
+ if (expected_kind != kind && expected_kind != svn_node_unknown)
+ return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+ _("Unexpected node kind %d for '%s' at r%ld. "
+ "Expected kind was %d."),
+ kind, path, revision, expected_kind);
+
+ return SVN_NO_ERROR;
+}
+
+/* Return an error when PATH exists in REVISION. Use EB for context
+ information. If REVISION is the current revision, use EB's path
+ tracker to follow renames, deletions, etc.
+
+ Use SCRATCH_POOL for temporary allocations.
+ No-op if EB's path tracker has not been initialized.
+ */
+static svn_error_t *
+node_must_not_exist(struct edit_baton *eb,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *scratch_pool)
+{
+ svn_node_kind_t kind = svn_node_none;
+
+ /* in case the caller is trying something stupid ... */
+ if (eb->path_tracker == NULL)
+ return SVN_NO_ERROR;
+
+ /* paths pertaining to the revision currently being processed must
+ be translated / checked using our path tracker. */
+ if (revision == eb->path_tracker->revision)
+ tracker_lookup(&path, &revision, eb->path_tracker, path, scratch_pool);
+
+ /* determine the node type (default: no such node) */
+ if (path)
+ SVN_ERR(fetch_kind_func(&kind, eb, path, revision, scratch_pool));
+
+ /* check results */
+ if (kind != svn_node_none)
+ return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
+ _("Path '%s' exists in r%ld."),
+ path, revision);
+
+ return SVN_NO_ERROR;
+}
/* This helper is the main "meat" of the editor -- it does all the
work of writing a node record.
@@ -303,6 +659,11 @@ dump_node(struct edit_baton *eb,
if (action == svn_node_action_change)
{
+ if (eb->path_tracker)
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
+ apr_psprintf(pool, _("Change invalid path '%s' in r%ld"),
+ path, eb->current_rev));
+
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
@@ -321,8 +682,18 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_replace)
{
+ if (eb->path_tracker)
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev,
+ svn_node_unknown, pool),
+ apr_psprintf(pool,
+ _("Replacing non-existent path '%s' in r%ld"),
+ path, eb->current_rev));
+
if (! is_copy)
{
+ if (eb->path_tracker)
+ tracker_path_replace(eb->path_tracker, path);
+
/* a simple delete+add, implied by a single 'replace' action. */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION
@@ -335,6 +706,20 @@ dump_node(struct edit_baton *eb,
}
else
{
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev,
+ kind, pool),
+ apr_psprintf(pool,
+ _("Replacing path '%s' in r%ld "
+ "with invalid path"),
+ path, eb->current_rev));
+
+ /* we will call dump_node again with an addition further
+ down the road */
+ tracker_path_delete(eb->path_tracker, path);
+ }
+
/* more complex: delete original, then add-with-history. */
/* the path & kind headers have already been printed; just
@@ -355,6 +740,14 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_delete)
{
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
+ apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"),
+ path, eb->current_rev));
+ tracker_path_delete(eb->path_tracker, path);
+ }
+
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
@@ -365,11 +758,20 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_add)
{
+ if (eb->path_tracker)
+ SVN_ERR_W(node_must_not_exist(eb, path, eb->current_rev, pool),
+ apr_psprintf(pool,
+ _("Adding already existing path '%s' in r%ld"),
+ path, eb->current_rev));
+
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
if (! is_copy)
{
+ if (eb->path_tracker)
+ tracker_path_add(eb->path_tracker, path);
+
/* Dump all contents for a simple 'add'. */
if (kind == svn_node_file)
must_dump_text = TRUE;
@@ -377,6 +779,18 @@ dump_node(struct edit_baton *eb,
}
else
{
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev,
+ kind, pool),
+ apr_psprintf(pool,
+ _("Copying from invalid path to "
+ "'%s' in r%ld"),
+ path, eb->current_rev));
+ tracker_path_copy(eb->path_tracker, path, compare_path,
+ compare_rev);
+ }
+
if (!eb->verify && cmp_rev < eb->oldest_dumped_rev
&& eb->notify_func)
{
@@ -985,6 +1399,14 @@ get_dump_editor(const svn_delta_editor_t
eb->found_old_reference = found_old_reference;
eb->found_old_mergeinfo = found_old_mergeinfo;
+ /* In non-verification mode, we will allow anything to be dumped because
+ it might be an incremental dump with possible manual intervention.
+ Also, this might be the last resort when it comes to data recovery.
+
+ Else, make sure that all paths exists at their respective revisions.
+ */
+ eb->path_tracker = verify ? tracker_create(to_rev, pool) : NULL;
+
/* Set up the editor. */
dump_editor->open_root = open_root;
dump_editor->delete_entry = delete_entry;
Propchange: subversion/branches/1.8.x-r1536854/subversion/svn/svn.c
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/svn/svn.c:r1536854
Modified: subversion/branches/1.8.x-r1536854/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x-r1536854/subversion/tests/cmdline/svnadmin_tests.py?rev=1536953&r1=1536952&r2=1536953&view=diff
==============================================================================
--- subversion/branches/1.8.x-r1536854/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/1.8.x-r1536854/subversion/tests/cmdline/svnadmin_tests.py Wed Oct 30 01:56:28 2013
@@ -238,6 +238,27 @@ def load_dumpstream(sbox, dump, *varargs
return load_and_verify_dumpstream(sbox, None, None, None, False, dump,
*varargs)
+def set_changed_path_list(filename, changes):
+ """ Replace the changed paths list in the file given by FILENAME
+ with the text CHANGES."""
+
+ # read full file
+ fp = open(filename, 'r+b')
+ contents = fp.read()
+
+ # replace the changed paths list
+ length = len(contents)
+ header = contents[contents.rfind('\n', length - 64, length - 1):]
+ body_len = long(header.split(' ')[1])
+
+ contents = contents[:body_len] + changes + header
+
+ # set new contents
+ fp.seek(0)
+ fp.write(contents)
+ fp.truncate()
+ fp.close()
+
######################################################################
# Tests
@@ -1823,6 +1844,117 @@ def recover_old(sbox):
svntest.main.create_repos(sbox.repo_dir, minor_version=0)
svntest.main.run_svnadmin("recover", sbox.repo_dir)
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+def verify_invalid_path_changes(sbox):
+ "detect invalid changed path list entries"
+
+ sbox.build(create_wc = False)
+ repo_url = sbox.repo_url
+ B_url = sbox.repo_url + '/B'
+ C_url = sbox.repo_url + '/C'
+
+ # Create A/B/E/bravo in r2.
+ for r in range(2,20):
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', '-m', 'log_msg',
+ sbox.repo_url + '/B' + str(r))
+
+ # modify every other revision to make sure that errors are not simply
+ # "carried over" but that all corrupts we get detected independently
+
+ # add existing node
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '2'),
+ "_0.0.t1-1 add-dir false false /A\n\n")
+
+ # add into non-existent parent
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '4'),
+ "_0.0.t3-2 add-dir false false /C/X\n\n")
+
+ # del non-existent node
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '6'),
+ "_0.0.t5-2 del-dir false false /C\n\n")
+
+ # del existent node of the wrong kind
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '8'),
+ "_0.0.t7-2 dev-file false false /B3\n\n")
+
+ # copy from non-existent node
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '10'),
+ "_0.0.t9-2 add-dir false false /B10\n"
+ "6 /B8\n")
+
+ # copy from existing node of the wrong kind
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '12'),
+ "_0.0.t11-2 add-file false false /B12\n"
+ "9 /B8\n")
+
+ # modify non-existent node
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '14'),
+ "_0.0.t13-2 modify-file false false /A/D/H/foo\n\n")
+
+ # modify existent node of the wrong kind
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '16'),
+ "_0.0.t15-2 modify-file false false /B12\n\n")
+
+ # replace non-existent node
+ set_changed_path_list(fsfs_file(sbox.repo_dir, 'revs', '18'),
+ "_0.0.t17-2 replace-file false false /A/D/H/foo\n\n")
+
+ # find corruptions
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ "--keep-going",
+ sbox.repo_dir)
+
+ exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
+ ".*Verified revision 0.",
+ ".*Verified revision 1.",
+ ".*Error verifying revision 2.",
+ ".*Verified revision 3.",
+ ".*Error verifying revision 4.",
+ ".*Verified revision 5.",
+ ".*Error verifying revision 6.",
+ ".*Verified revision 7.",
+ ".*Error verifying revision 8.",
+ ".*Verified revision 9.",
+ ".*Error verifying revision 10.",
+ ".*Verified revision 11.",
+ ".*Error verifying revision 12.",
+ ".*Verified revision 13.",
+ ".*Error verifying revision 14.",
+ ".*Verified revision 15.",
+ ".*Error verifying revision 16.",
+ ".*Verified revision 17.",
+ ".*Error verifying revision 18.",
+ ".*Verified revision 19."])
+
+ exp_err = svntest.verify.RegexListOutput(["svnadmin: E160020:.*",
+ "svnadmin: E165011:.*"], False)
+
+
+ if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
+ output, errput, exp_out, exp_err):
+ raise svntest.Failure
+
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ sbox.repo_dir)
+
+ exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
+ ".*Verified revision 0.",
+ ".*Verified revision 1.",
+ ".*Error verifying revision 2."])
+
+ if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
+ output, errput, exp_out, exp_err):
+ raise svntest.Failure
+
+
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ "--quiet",
+ sbox.repo_dir)
+
+ if svntest.verify.verify_outputs("Output of 'svnadmin verify' is unexpected.",
+ None, errput, None, "svnadmin: E165011:.*"):
+ raise svntest.Failure
########################################################################
# Run the tests
@@ -1860,6 +1992,7 @@ test_list = [ None,
locking,
mergeinfo_race,
recover_old,
+ verify_invalid_path_changes,
]
if __name__ == '__main__':
Propchange: subversion/branches/1.8.x-r1536854/tools/dist/make-deps-tarball.sh
------------------------------------------------------------------------------
Merged /subversion/trunk/tools/dist/make-deps-tarball.sh:r1536854