You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/07/25 18:20:14 UTC
svn commit: r1613462 - in /subversion/branches/svn-auth-x509: ./
subversion/include/ subversion/include/private/ subversion/libsvn_fs/
subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_fs_x/
subversion/libsvn_repos/ subversion/libsv...
Author: breser
Date: Fri Jul 25 16:20:13 2014
New Revision: 1613462
URL: http://svn.apache.org/r1613462
Log:
On svn-auth-x509 branch, catchup merge from trunk for r1603509 through r1613461.
Modified:
subversion/branches/svn-auth-x509/ (props changed)
subversion/branches/svn-auth-x509/subversion/include/private/svn_io_private.h
subversion/branches/svn-auth-x509/subversion/include/private/svn_named_atomic.h
subversion/branches/svn-auth-x509/subversion/include/svn_fs.h
subversion/branches/svn-auth-x509/subversion/include/svn_repos.h
subversion/branches/svn-auth-x509/subversion/include/svn_string.h
subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c
subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.h
subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c
subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c
subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c
subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c
subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.h
subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/ (props changed)
subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c
subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c
subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c
subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c
subversion/branches/svn-auth-x509/subversion/libsvn_subr/named_atomic.c
subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c
subversion/branches/svn-auth-x509/subversion/mod_dav_svn/util.c
subversion/branches/svn-auth-x509/subversion/svn/svn.c
subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c
subversion/branches/svn-auth-x509/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py
subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/string-test.c
Propchange: subversion/branches/svn-auth-x509/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1611809-1613461
Modified: subversion/branches/svn-auth-x509/subversion/include/private/svn_io_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/include/private/svn_io_private.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/include/private/svn_io_private.h (original)
+++ subversion/branches/svn-auth-x509/subversion/include/private/svn_io_private.h Fri Jul 25 16:20:13 2014
@@ -73,6 +73,18 @@ svn_io__is_finfo_read_only(svn_boolean_t
apr_pool_t *pool);
+/**
+ * Lock file at @a lock_file. If that file does not exist, create an empty
+ * file.
+ *
+ * Lock will be automatically released when @a pool is cleared or destroyed.
+ * Use @a pool for memory allocations.
+ */
+svn_error_t *
+svn_io__file_lock_autocreate(const char *lock_file,
+ apr_pool_t *pool);
+
+
/** Buffer test handler function for a generic stream. @see svn_stream_t
* and svn_stream__is_buffered().
*
Modified: subversion/branches/svn-auth-x509/subversion/include/private/svn_named_atomic.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/include/private/svn_named_atomic.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/include/private/svn_named_atomic.h (original)
+++ subversion/branches/svn-auth-x509/subversion/include/private/svn_named_atomic.h Fri Jul 25 16:20:13 2014
@@ -77,6 +77,9 @@ svn_named_atomic__is_efficient(void);
*
* The access object will be allocated in @a result_pool and atomics gotten
* from this object will become invalid when the pool is being cleared.
+ *
+ * @note Although we use shared memory here, the management around it will
+ * take up a few kB of memory per call (until @a result_pool gets cleared).
*/
svn_error_t *
svn_atomic_namespace__create(svn_atomic_namespace__t **ns,
Modified: subversion/branches/svn-auth-x509/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/include/svn_fs.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/include/svn_fs.h (original)
+++ subversion/branches/svn-auth-x509/subversion/include/svn_fs.h Fri Jul 25 16:20:13 2014
@@ -452,6 +452,16 @@ svn_error_t *
svn_fs_delete_fs(const char *path,
apr_pool_t *pool);
+/** The type of a hotcopy notification function. @a start_revision and
+ * @a end_revision indicate the copied revision range. @a baton is the
+ * corresponding baton for the notification function, and @a pool can be
+ * used for temporary allocations, but will be cleared between invocations.
+ */
+typedef void (*svn_fs_hotcopy_notify_t)(void *baton,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ apr_pool_t *pool);
+
/**
* Copy a possibly live Subversion filesystem from @a src_path to
* @a dest_path. If @a clean is @c TRUE, perform cleanup on the
@@ -464,10 +474,35 @@ svn_fs_delete_fs(const char *path,
* incremental hotcopy is not implemented, raise
* #SVN_ERR_UNSUPPORTED_FEATURE.
*
+ * For each revision range copied, @a notify_func will be called with
+ * staring and ending revision numbers (both inclusive and not necessarily
+ * different) and with the @a notify_baton. Currently, this notification
+ * is only supported in the FSFS backend. @a notify_func may be @c NULL
+ * if this notification is not required.
+ *
* Use @a scratch_pool for temporary allocations.
*
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_fs_hotcopy3(const char *src_path,
+ const char *dest_path,
+ svn_boolean_t clean,
+ svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Like svn_fs_hotcopy3(), but with @a notify_func and @a notify_baton
+ * always passed as @c NULL.
+ *
+ * @deprecated Provided for backward compatibility with the 1.8 API.
* @since New in 1.8.
*/
+SVN_DEPRECATED
svn_error_t *
svn_fs_hotcopy2(const char *src_path,
const char *dest_path,
Modified: subversion/branches/svn-auth-x509/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/include/svn_repos.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/include/svn_repos.h (original)
+++ subversion/branches/svn-auth-x509/subversion/include/svn_repos.h Fri Jul 25 16:20:13 2014
@@ -244,7 +244,10 @@ typedef enum svn_repos_notify_action_t
svn_repos_notify_cleanup_revprops,
/** The repository format got bumped. @since New in 1.9. */
- svn_repos_notify_format_bumped
+ svn_repos_notify_format_bumped,
+
+ /** A revision range was copied. @since New in 1.9. */
+ svn_repos_notify_hotcopy_rev_range
} svn_repos_notify_action_t;
/** The type of error occurring.
@@ -343,6 +346,16 @@ typedef struct svn_repos_notify_t
@since New in 1.9. */
svn_error_t *err;
+ /** For #svn_repos_notify_hotcopy_rev_range, the start of the copied
+ revision range.
+ @since New in 1.9. */
+ svn_revnum_t start_revision;
+
+ /** For #svn_repos_notify_hotcopy_rev_range, the end of the copied
+ revision range (might be the same as @a start_revision).
+ @since New in 1.9. */
+ svn_revnum_t end_revision;
+
/* NOTE: Add new fields at the end to preserve binary compatibility.
Also, if you add fields here, you have to update
svn_repos_notify_create(). */
@@ -626,8 +639,35 @@ svn_repos_fs_type(svn_repos_t *repos, ap
* already present in the destination. If incremental hotcopy is not
* implemented by the filesystem backend, raise SVN_ERR_UNSUPPORTED_FEATURE.
*
+ * For each revision range copied, the @a notify_func function will be
+ * called with the @a notify_baton and a notification structure containing
+ * appropriate values in @c start_revision and @c end_revision (both
+ * inclusive). @c start_revision might be equal to @c end_revision in
+ * case the copied range consists of a single revision. Currently, this
+ * notification is only supported for FSFS repositories. @a notify_func
+ * may be @c NULL if this notification is not required.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_repos_hotcopy3(const char *src_path,
+ const char *dst_path,
+ svn_boolean_t clean_logs,
+ svn_boolean_t incremental,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool);
+
+/**
+ * Like svn_repos_hotcopy3(), but with @a notify_func and @a notify_baton
+ * always passed as @c NULL.
+ *
* @since New in 1.8.
+ * @deprecated Provided for backward compatibility with the 1.8 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_repos_hotcopy2(const char *src_path,
const char *dst_path,
Modified: subversion/branches/svn-auth-x509/subversion/include/svn_string.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/include/svn_string.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/include/svn_string.h (original)
+++ subversion/branches/svn-auth-x509/subversion/include/svn_string.h Fri Jul 25 16:20:13 2014
@@ -586,6 +586,16 @@ svn_cstring_atoui64(apr_uint64_t *n, con
svn_error_t *
svn_cstring_atoui(unsigned int *n, const char *str);
+/**
+ * Skip the common prefix @a prefix from the C string @a str, and return
+ * a pointer to the next character after the prefix.
+ * Return @c NULL if @a str does not start with @a prefix.
+ *
+ * @since New in 1.9.
+ */
+const char *
+svn_cstring_skip_prefix(const char *str, const char *prefix);
+
/** @} */
/** @} */
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c Fri Jul 25 16:20:13 2014
@@ -614,9 +614,12 @@ svn_fs_delete_fs(const char *path, apr_p
}
svn_error_t *
-svn_fs_hotcopy2(const char *src_path, const char *dst_path,
+svn_fs_hotcopy3(const char *src_path, const char *dst_path,
svn_boolean_t clean, svn_boolean_t incremental,
- svn_cancel_func_t cancel_func, void *cancel_baton,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *scratch_pool)
{
fs_library_vtable_t *vtable;
@@ -669,12 +672,25 @@ svn_fs_hotcopy2(const char *src_path, co
}
SVN_ERR(vtable->hotcopy(src_fs, dst_fs, src_path, dst_path, clean,
- incremental, cancel_func, cancel_baton,
- common_pool_lock, scratch_pool, common_pool));
+ incremental, notify_func, notify_baton,
+ cancel_func, cancel_baton, common_pool_lock,
+ scratch_pool, common_pool));
return svn_error_trace(write_fs_type(dst_path, src_fs_type, scratch_pool));
}
svn_error_t *
+svn_fs_hotcopy2(const char *src_path, const char *dest_path,
+ svn_boolean_t clean, svn_boolean_t incremental,
+ svn_cancel_func_t cancel_func, void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(svn_fs_hotcopy3(src_path, dest_path, clean,
+ incremental, NULL, NULL,
+ cancel_func, cancel_baton,
+ scratch_pool));
+}
+
+svn_error_t *
svn_fs_hotcopy(const char *src_path, const char *dest_path,
svn_boolean_t clean, apr_pool_t *pool)
{
@@ -789,8 +805,9 @@ svn_error_t *
svn_fs_hotcopy_berkeley(const char *src_path, const char *dest_path,
svn_boolean_t clean_logs, apr_pool_t *pool)
{
- return svn_error_trace(svn_fs_hotcopy2(src_path, dest_path, clean_logs,
- FALSE, NULL, NULL, pool));
+ return svn_error_trace(svn_fs_hotcopy3(src_path, dest_path, clean_logs,
+ FALSE, NULL, NULL, NULL, NULL,
+ pool));
}
svn_error_t *
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.h Fri Jul 25 16:20:13 2014
@@ -118,6 +118,8 @@ typedef struct fs_library_vtable_t
const char *dst_path,
svn_boolean_t clean,
svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_mutex__t *common_pool_lock,
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c Fri Jul 25 16:20:13 2014
@@ -1291,6 +1291,8 @@ base_hotcopy(svn_fs_t *src_fs,
const char *dest_path,
svn_boolean_t clean_logs,
svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_mutex__t *common_pool_lock,
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c Fri Jul 25 16:20:13 2014
@@ -376,7 +376,8 @@ fs_pack(svn_fs_t *fs,
DST_FS at DEST_PATH. If INCREMENTAL is TRUE, make an effort not to
re-copy data which already exists in DST_FS.
The CLEAN_LOGS argument is ignored and included for Subversion
- 1.0.x compatibility. Perform all temporary allocations in POOL. */
+ 1.0.x compatibility. Indicate progress via the optional NOTIFY_FUNC
+ callback using NOTIFY_BATON. Perform all temporary allocations in POOL. */
static svn_error_t *
fs_hotcopy(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
@@ -384,6 +385,8 @@ fs_hotcopy(svn_fs_t *src_fs,
const char *dst_path,
svn_boolean_t clean_logs,
svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_mutex__t *common_pool_lock,
@@ -407,8 +410,9 @@ fs_hotcopy(svn_fs_t *src_fs,
SVN_ERR(cancel_func(cancel_baton));
/* Now, we may copy data as needed ... */
- return svn_fs_fs__hotcopy(src_fs, dst_fs,
- incremental, cancel_func, cancel_baton, pool);
+ return svn_fs_fs__hotcopy(src_fs, dst_fs, incremental,
+ notify_func, notify_baton,
+ cancel_func, cancel_baton, pool);
}
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c Fri Jul 25 16:20:13 2014
@@ -43,6 +43,7 @@
#include "util.h"
#include "private/svn_fs_util.h"
+#include "private/svn_io_private.h"
#include "private/svn_string_private.h"
#include "private/svn_subr_private.h"
#include "../libsvn_fs/fs-loader.h"
@@ -114,20 +115,7 @@ static svn_error_t *
get_lock_on_filesystem(const char *lock_filename,
apr_pool_t *pool)
{
- svn_error_t *err = svn_io_file_lock2(lock_filename, TRUE, FALSE, pool);
-
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- /* No lock file? No big deal; these are just empty files
- anyway. Create it and try again. */
- svn_error_clear(err);
- err = NULL;
-
- SVN_ERR(svn_io_file_create_empty(lock_filename, pool));
- SVN_ERR(svn_io_file_lock2(lock_filename, TRUE, FALSE, pool));
- }
-
- return svn_error_trace(err);
+ return svn_error_trace(svn_io__file_lock_autocreate(lock_filename, pool));
}
/* Reset the HAS_WRITE_LOCK member in the FFD given as BATON_VOID.
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c Fri Jul 25 16:20:13 2014
@@ -35,9 +35,13 @@
#include "svn_private_config.h"
/* Like svn_io_dir_file_copy(), but doesn't copy files that exist at
- * the destination and do not differ in terms of kind, size, and mtime. */
+ * the destination and do not differ in terms of kind, size, and mtime.
+ * Set *SKIPPED_P to FALSE only if the file was copied, do not change
+ * the value in *SKIPPED_P otherwise. SKIPPED_P may be NULL if not
+ * required. */
static svn_error_t *
-hotcopy_io_dir_file_copy(const char *src_path,
+hotcopy_io_dir_file_copy(svn_boolean_t *skipped_p,
+ const char *src_path,
const char *dst_path,
const char *file,
apr_pool_t *scratch_pool)
@@ -65,6 +69,9 @@ hotcopy_io_dir_file_copy(const char *src
return SVN_NO_ERROR;
}
+ if (skipped_p)
+ *skipped_p = FALSE;
+
return svn_error_trace(svn_io_dir_file_copy(src_path, dst_path, file,
scratch_pool));
}
@@ -106,9 +113,12 @@ entry_name_to_utf8(const char **name_p,
/* Like svn_io_copy_dir_recursively() but doesn't copy regular files that
* exist in the destination and do not differ from the source in terms of
- * kind, size, and mtime. */
+ * kind, size, and mtime. Set *SKIPPED_P to FALSE only if at least one
+ * file was copied, do not change the value in *SKIPPED_P otherwise.
+ * SKIPPED_P may be NULL if not required. */
static svn_error_t *
-hotcopy_io_copy_dir_recursively(const char *src,
+hotcopy_io_copy_dir_recursively(svn_boolean_t *skipped_p,
+ const char *src,
const char *dst_parent,
const char *dst_basename,
svn_boolean_t copy_perms,
@@ -174,8 +184,8 @@ hotcopy_io_copy_dir_recursively(const ch
src, subpool));
if (this_entry.filetype == APR_REG) /* regular file */
{
- SVN_ERR(hotcopy_io_dir_file_copy(src, dst_path, entryname_utf8,
- subpool));
+ SVN_ERR(hotcopy_io_dir_file_copy(skipped_p, src, dst_path,
+ entryname_utf8, subpool));
}
else if (this_entry.filetype == APR_LNK) /* symlink */
{
@@ -198,7 +208,8 @@ hotcopy_io_copy_dir_recursively(const ch
continue;
src_target = svn_dirent_join(src, entryname_utf8, subpool);
- SVN_ERR(hotcopy_io_copy_dir_recursively(src_target,
+ SVN_ERR(hotcopy_io_copy_dir_recursively(skipped_p,
+ src_target,
dst_path,
entryname_utf8,
copy_perms,
@@ -228,9 +239,12 @@ hotcopy_io_copy_dir_recursively(const ch
/* Copy an un-packed revision or revprop file for revision REV from SRC_SUBDIR
* to DST_SUBDIR. Assume a sharding layout based on MAX_FILES_PER_DIR.
+ * Set *SKIPPED_P to FALSE only if the file was copied, do not change the
+ * value in *SKIPPED_P otherwise. SKIPPED_P may be NULL if not required.
* Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
-hotcopy_copy_shard_file(const char *src_subdir,
+hotcopy_copy_shard_file(svn_boolean_t *skipped_p,
+ const char *src_subdir,
const char *dst_subdir,
svn_revnum_t rev,
int max_files_per_dir,
@@ -254,7 +268,8 @@ hotcopy_copy_shard_file(const char *src_
}
}
- SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard,
+ SVN_ERR(hotcopy_io_dir_file_copy(skipped_p,
+ src_subdir_shard, dst_subdir_shard,
apr_psprintf(scratch_pool, "%ld", rev),
scratch_pool));
@@ -266,9 +281,13 @@ hotcopy_copy_shard_file(const char *src_
* MAX_FILES_PER_DIR revisions, from SRC_FS to DST_FS.
* Update *DST_MIN_UNPACKED_REV in case the shard is new in DST_FS.
* Do not re-copy data which already exists in DST_FS.
+ * Set *SKIPPED_P to FALSE only if at least one part of the shard
+ * was copied, do not change the value in *SKIPPED_P otherwise.
+ * SKIPPED_P may be NULL if not required.
* Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
-hotcopy_copy_packed_shard(svn_revnum_t *dst_min_unpacked_rev,
+hotcopy_copy_packed_shard(svn_boolean_t *skipped_p,
+ svn_revnum_t *dst_min_unpacked_rev,
svn_fs_t *src_fs,
svn_fs_t *dst_fs,
svn_revnum_t rev,
@@ -290,7 +309,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
rev / max_files_per_dir);
src_subdir_packed_shard = svn_dirent_join(src_subdir, packed_shard,
scratch_pool);
- SVN_ERR(hotcopy_io_copy_dir_recursively(src_subdir_packed_shard,
+ SVN_ERR(hotcopy_io_copy_dir_recursively(skipped_p, src_subdir_packed_shard,
dst_subdir, packed_shard,
TRUE /* copy_perms */,
NULL /* cancel_func */, NULL,
@@ -311,7 +330,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
{
svn_pool_clear(iterpool);
- SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir,
+ SVN_ERR(hotcopy_copy_shard_file(skipped_p, src_subdir, dst_subdir,
revprop_rev, max_files_per_dir,
iterpool));
}
@@ -321,7 +340,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
{
/* revprop for revision 0 will never be packed */
if (rev == 0)
- SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir,
+ SVN_ERR(hotcopy_copy_shard_file(skipped_p, src_subdir, dst_subdir,
0, max_files_per_dir,
scratch_pool));
@@ -330,7 +349,8 @@ hotcopy_copy_packed_shard(svn_revnum_t *
rev / max_files_per_dir);
src_subdir_packed_shard = svn_dirent_join(src_subdir, packed_shard,
scratch_pool);
- SVN_ERR(hotcopy_io_copy_dir_recursively(src_subdir_packed_shard,
+ SVN_ERR(hotcopy_io_copy_dir_recursively(skipped_p,
+ src_subdir_packed_shard,
dst_subdir, packed_shard,
TRUE /* copy_perms */,
NULL /* cancel_func */, NULL,
@@ -349,58 +369,6 @@ hotcopy_copy_packed_shard(svn_revnum_t *
return SVN_NO_ERROR;
}
-/* If NEW_YOUNGEST is younger than *DST_YOUNGEST, update the 'current' file
- * in DST_FS and set *DST_YOUNGEST to NEW_YOUNGEST. DST_FS is expected to
- * be in a new format, i.e. storing only the youngest revision number in
- * the 'current' file. Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-hotcopy_update_current(svn_revnum_t *dst_youngest,
- svn_fs_t *dst_fs,
- svn_revnum_t new_youngest,
- apr_pool_t *scratch_pool)
-{
- fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
-
- SVN_ERR_ASSERT(dst_ffd->format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT);
-
- if (*dst_youngest < new_youngest)
- {
- SVN_ERR(svn_fs_fs__write_current(dst_fs, new_youngest,
- 0, 0, scratch_pool));
- *dst_youngest = new_youngest;
- }
-
- return SVN_NO_ERROR;
-}
-
-/* If NEW_YOUNGEST is younger than *DST_YOUNGEST, update the 'current' file
- * in DST_FS and set *DST_YOUNGEST to NEW_YOUNGEST. DST_FS is expected to
- * be in an old format, i.e. storing the youngest revision and the two next-ID
- * parameters. Those are updated with NEW_YOUNGEST, NEXT_NODE_ID and
- * NEXT_COPY_ID respectively. Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-hotcopy_update_current_old(svn_revnum_t *dst_youngest,
- svn_fs_t *dst_fs,
- svn_revnum_t new_youngest,
- apr_uint64_t next_node_id,
- apr_uint64_t next_copy_id,
- apr_pool_t *scratch_pool)
-{
- fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
-
- SVN_ERR_ASSERT(dst_ffd->format < SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT);
-
- if (*dst_youngest < new_youngest)
- {
- SVN_ERR(svn_fs_fs__write_current(dst_fs, new_youngest,
- next_node_id, next_copy_id,
- scratch_pool));
- *dst_youngest = new_youngest;
- }
-
- return SVN_NO_ERROR;
-}
-
/* Remove FILE in SHARD folder. Use POOL for temporary allocations. */
static svn_error_t *
hotcopy_remove_file(const char *shard,
@@ -579,18 +547,21 @@ remove_folder(const char *path,
* When copying packed or unpacked shards, checkpoint the result in DST_FS
* for every shard by updating the 'current' file if necessary. Assume
* the >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT filesystem format without
- * global next-ID counters. Use POOL for temporary allocations.
+ * global next-ID counters. Indicate progress via the optional NOTIFY_FUNC
+ * callback using NOTIFY_BATON. Use POOL for temporary allocations.
*/
static svn_error_t *
-hotcopy_revisions(svn_revnum_t *dst_youngest,
- svn_fs_t *src_fs,
+hotcopy_revisions(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
svn_revnum_t src_youngest,
+ svn_revnum_t dst_youngest,
svn_boolean_t incremental,
const char *src_revs_dir,
const char *dst_revs_dir,
const char *src_revprops_dir,
const char *dst_revprops_dir,
+ svn_fs_hotcopy_notify_t notify_func,
+ void* notify_baton,
svn_cancel_func_t cancel_func,
void* cancel_baton,
apr_pool_t *pool)
@@ -643,22 +614,38 @@ hotcopy_revisions(svn_revnum_t *dst_youn
/* First, copy packed shards. */
for (rev = 0; rev < src_min_unpacked_rev; rev += max_files_per_dir)
{
+ svn_boolean_t skipped = TRUE;
+ svn_revnum_t pack_end_rev;
+
svn_pool_clear(iterpool);
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
/* Copy the packed shard. */
- SVN_ERR(hotcopy_copy_packed_shard(&dst_min_unpacked_rev,
+ SVN_ERR(hotcopy_copy_packed_shard(&skipped, &dst_min_unpacked_rev,
src_fs, dst_fs,
rev, max_files_per_dir,
iterpool));
- /* If necessary, update 'current' to the most recent packed rev,
- * so readers can see new revisions which arrived in this pack. */
- SVN_ERR(hotcopy_update_current(dst_youngest, dst_fs,
- rev + max_files_per_dir - 1,
- iterpool));
+ pack_end_rev = rev + max_files_per_dir - 1;
+
+ /* Whenever this pack did not previously exist in the destination,
+ * update 'current' to the most recent packed rev (so readers can see
+ * new revisions which arrived in this pack). */
+ if (pack_end_rev > dst_youngest)
+ {
+ SVN_ERR(svn_fs_fs__write_current(dst_fs, pack_end_rev, 0, 0,
+ iterpool));
+ }
+
+ /* When notifying about packed shards, make things simpler by either
+ * reporting a full revision range, i.e [pack start, pack end] or
+ * reporting nothing. There is one case when this approach might not
+ * be exact (incremental hotcopy with a pack replacing last unpacked
+ * revisions), but generally this is good enough. */
+ if (notify_func && !skipped)
+ notify_func(notify_baton, rev, pack_end_rev, iterpool);
/* Remove revision files which are now packed. */
if (incremental)
@@ -693,6 +680,8 @@ hotcopy_revisions(svn_revnum_t *dst_youn
* If necessary, update 'current' after copying all files from a shard. */
for (; rev <= src_youngest; rev++)
{
+ svn_boolean_t skipped = TRUE;
+
svn_pool_clear(iterpool);
if (cancel_func)
@@ -712,18 +701,30 @@ hotcopy_revisions(svn_revnum_t *dst_youn
* longer where we expect it to be). */
/* Copy the rev file. */
- SVN_ERR(hotcopy_copy_shard_file(src_revs_dir, dst_revs_dir,
- rev, max_files_per_dir,
+ SVN_ERR(hotcopy_copy_shard_file(&skipped,
+ src_revs_dir, dst_revs_dir, rev,
+ max_files_per_dir,
iterpool));
/* Copy the revprop file. */
- SVN_ERR(hotcopy_copy_shard_file(src_revprops_dir,
- dst_revprops_dir,
- rev, max_files_per_dir,
+ SVN_ERR(hotcopy_copy_shard_file(&skipped,
+ src_revprops_dir, dst_revprops_dir,
+ rev, max_files_per_dir,
iterpool));
- /* After completing a full shard, update 'current'. */
- if (max_files_per_dir && rev % max_files_per_dir == 0)
- SVN_ERR(hotcopy_update_current(dst_youngest, dst_fs, rev, iterpool));
+ /* Whenever this revision did not previously exist in the destination,
+ * checkpoint the progress via 'current' (do that once per full shard
+ * in order not to slow things down). */
+ if (rev > dst_youngest)
+ {
+ if (max_files_per_dir && (rev % max_files_per_dir == 0))
+ {
+ SVN_ERR(svn_fs_fs__write_current(dst_fs, rev, 0, 0,
+ iterpool));
+ }
+ }
+
+ if (notify_func && !skipped)
+ notify_func(notify_baton, rev, rev, iterpool);
}
svn_pool_destroy(iterpool);
@@ -738,8 +739,9 @@ hotcopy_revisions(svn_revnum_t *dst_youn
* filesystems without sharding and packing. Copy the non-sharded revision
* and revprop files from SRC_FS to DST_FS. Do not re-copy data which
* already exists in DST_FS. Do not somehow checkpoint the results in
- * the 'current' file in DST_FS. Use POOL for temporary allocations.
- * Also see hotcopy_revisions().
+ * the 'current' file in DST_FS. Indicate progress via the optional
+ * NOTIFY_FUNC callback using NOTIFY_BATON. Use POOL for temporary
+ * allocations. Also see hotcopy_revisions().
*/
static svn_error_t *
hotcopy_revisions_old(svn_fs_t *src_fs,
@@ -749,6 +751,8 @@ hotcopy_revisions_old(svn_fs_t *src_fs,
const char *dst_revs_dir,
const char *src_revprops_dir,
const char *dst_revprops_dir,
+ svn_fs_hotcopy_notify_t notify_func,
+ void* notify_baton,
svn_cancel_func_t cancel_func,
void* cancel_baton,
apr_pool_t *pool)
@@ -758,17 +762,23 @@ hotcopy_revisions_old(svn_fs_t *src_fs,
for (rev = 0; rev <= src_youngest; rev++)
{
+ svn_boolean_t skipped = TRUE;
+
svn_pool_clear(iterpool);
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
- SVN_ERR(hotcopy_io_dir_file_copy(src_revs_dir, dst_revs_dir,
+ SVN_ERR(hotcopy_io_dir_file_copy(&skipped, src_revs_dir, dst_revs_dir,
apr_psprintf(iterpool, "%ld", rev),
iterpool));
- SVN_ERR(hotcopy_io_dir_file_copy(src_revprops_dir, dst_revprops_dir,
+ SVN_ERR(hotcopy_io_dir_file_copy(&skipped, src_revprops_dir,
+ dst_revprops_dir,
apr_psprintf(iterpool, "%ld", rev),
iterpool));
+
+ if (notify_func && !skipped)
+ notify_func(notify_baton, rev, rev, iterpool);
}
svn_pool_destroy(iterpool);
@@ -780,6 +790,8 @@ struct hotcopy_body_baton {
svn_fs_t *src_fs;
svn_fs_t *dst_fs;
svn_boolean_t incremental;
+ svn_fs_hotcopy_notify_t notify_func;
+ void *notify_baton;
svn_cancel_func_t cancel_func;
void *cancel_baton;
};
@@ -811,6 +823,8 @@ hotcopy_body(void *baton, apr_pool_t *po
svn_fs_t *dst_fs = hbb->dst_fs;
fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
svn_boolean_t incremental = hbb->incremental;
+ svn_fs_hotcopy_notify_t notify_func = hbb->notify_func;
+ void* notify_baton = hbb->notify_baton;
svn_cancel_func_t cancel_func = hbb->cancel_func;
void* cancel_baton = hbb->cancel_baton;
svn_revnum_t src_youngest;
@@ -925,22 +939,22 @@ hotcopy_body(void *baton, apr_pool_t *po
* revision number, but also the next-ID counters). */
if (src_ffd->format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT)
{
- SVN_ERR(hotcopy_revisions(&dst_youngest, src_fs, dst_fs, src_youngest,
+ SVN_ERR(hotcopy_revisions(src_fs, dst_fs, src_youngest, dst_youngest,
incremental, src_revs_dir, dst_revs_dir,
src_revprops_dir, dst_revprops_dir,
+ notify_func, notify_baton,
cancel_func, cancel_baton, pool));
- SVN_ERR(hotcopy_update_current(&dst_youngest, dst_fs, src_youngest,
- pool));
+ SVN_ERR(svn_fs_fs__write_current(dst_fs, src_youngest, 0, 0, pool));
}
else
{
SVN_ERR(hotcopy_revisions_old(src_fs, dst_fs, src_youngest,
src_revs_dir, dst_revs_dir,
src_revprops_dir, dst_revprops_dir,
+ notify_func, notify_baton,
cancel_func, cancel_baton, pool));
- SVN_ERR(hotcopy_update_current_old(&dst_youngest, dst_fs, src_youngest,
- src_next_node_id, src_next_copy_id,
- pool));
+ SVN_ERR(svn_fs_fs__write_current(dst_fs, src_youngest, src_next_node_id,
+ src_next_copy_id, pool));
}
/* Replace the locks tree.
@@ -961,7 +975,7 @@ hotcopy_body(void *baton, apr_pool_t *po
src_subdir = svn_dirent_join(src_fs->path, PATH_NODE_ORIGINS_DIR, pool);
SVN_ERR(svn_io_check_path(src_subdir, &kind, pool));
if (kind == svn_node_dir)
- SVN_ERR(hotcopy_io_copy_dir_recursively(src_subdir, dst_fs->path,
+ SVN_ERR(hotcopy_io_copy_dir_recursively(NULL, src_subdir, dst_fs->path,
PATH_NODE_ORIGINS_DIR, TRUE,
cancel_func, cancel_baton, pool));
@@ -973,14 +987,14 @@ hotcopy_body(void *baton, apr_pool_t *po
if (dst_ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT)
{
/* Copy the rep cache and then remove entries for revisions
- * younger than the destination's youngest revision. */
+ /* that did not make it into the destination. */
src_subdir = svn_dirent_join(src_fs->path, REP_CACHE_DB_NAME, pool);
dst_subdir = svn_dirent_join(dst_fs->path, REP_CACHE_DB_NAME, pool);
SVN_ERR(svn_io_check_path(src_subdir, &kind, pool));
if (kind == svn_node_file)
{
SVN_ERR(svn_sqlite__hotcopy(src_subdir, dst_subdir, pool));
- SVN_ERR(svn_fs_fs__del_rep_reference(dst_fs, dst_youngest, pool));
+ SVN_ERR(svn_fs_fs__del_rep_reference(dst_fs, src_youngest, pool));
}
}
@@ -1144,6 +1158,8 @@ svn_error_t *
svn_fs_fs__hotcopy(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -1153,6 +1169,8 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
hbb.src_fs = src_fs;
hbb.dst_fs = dst_fs;
hbb.incremental = incremental;
+ hbb.notify_func = notify_func;
+ hbb.notify_baton = notify_baton;
hbb.cancel_func = cancel_func;
hbb.cancel_baton = cancel_baton;
SVN_ERR(svn_fs_fs__with_write_lock(dst_fs, hotcopy_locking_src_body, &hbb,
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.h?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.h Fri Jul 25 16:20:13 2014
@@ -36,11 +36,14 @@ svn_fs_fs__hotcopy_prepare_target(svn_fs
apr_pool_t *pool);
/* Copy the fsfs filesystem SRC_FS into DST_FS. If INCREMENTAL is TRUE, do
- * not re-copy data which already exists in DST_FS. Use POOL for temporary
- * allocations. */
+ * not re-copy data which already exists in DST_FS. Indicate progress via
+ * the optional NOTIFY_FUNC callback using NOTIFY_BATON. Use POOL for
+ * temporary allocations. */
svn_error_t * svn_fs_fs__hotcopy(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool);
Propchange: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/libsvn_fs_x:r1611809-1613461
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c Fri Jul 25 16:20:13 2014
@@ -382,7 +382,8 @@ x_pack(svn_fs_t *fs,
DST_FS at DEST_PATH. If INCREMENTAL is TRUE, make an effort not to
re-copy data which already exists in DST_FS.
The CLEAN_LOGS argument is ignored and included for Subversion
- 1.0.x compatibility. Perform all temporary allocations in POOL. */
+ 1.0.x compatibility. The NOTIFY_FUNC and NOTIFY_BATON arguments
+ are also currently ignored. Perform all temporary allocations in POOL. */
static svn_error_t *
x_hotcopy(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
@@ -390,6 +391,8 @@ x_hotcopy(svn_fs_t *src_fs,
const char *dst_path,
svn_boolean_t clean_logs,
svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_mutex__t *common_pool_lock,
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c Fri Jul 25 16:20:13 2014
@@ -46,6 +46,7 @@
#include "private/svn_sorts_private.h"
#include "private/svn_string_private.h"
#include "private/svn_subr_private.h"
+#include "private/svn_io_private.h"
#include "../libsvn_fs/fs-loader.h"
#include "svn_private_config.h"
@@ -185,20 +186,7 @@ static svn_error_t *
get_lock_on_filesystem(const char *lock_filename,
apr_pool_t *pool)
{
- svn_error_t *err = svn_io_file_lock2(lock_filename, TRUE, FALSE, pool);
-
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- /* No lock file? No big deal; these are just empty files
- anyway. Create it and try again. */
- svn_error_clear(err);
- err = NULL;
-
- SVN_ERR(svn_io_file_create_empty(lock_filename, pool));
- SVN_ERR(svn_io_file_lock2(lock_filename, TRUE, FALSE, pool));
- }
-
- return svn_error_trace(err);
+ return svn_error_trace(svn_io__file_lock_autocreate(lock_filename, pool));
}
/* Reset the HAS_WRITE_LOCK member in the FFD given as BATON_VOID.
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c Fri Jul 25 16:20:13 2014
@@ -2119,22 +2119,54 @@ lock_db_logs_file(svn_repos_t *repos,
}
+/* Baton used with fs_hotcopy_notify(), specifying the svn_repos layer
+ * notification parameters.
+ */
+struct fs_hotcopy_notify_baton_t
+{
+ svn_repos_notify_func_t notify_func;
+ void *notify_baton;
+};
+
+/* Implements svn_fs_hotcopy_notify_t as forwarding to a
+ * svn_repos_notify_func_t passed in a fs_hotcopy_notify_baton_t* BATON.
+ */
+static void
+fs_hotcopy_notify(void *baton,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ apr_pool_t *pool)
+{
+ struct fs_hotcopy_notify_baton_t *fs_baton = baton;
+ svn_repos_notify_t *notify;
+
+ notify = svn_repos_notify_create(svn_repos_notify_hotcopy_rev_range, pool);
+ notify->start_revision = start_revision;
+ notify->end_revision = end_revision;
+
+ fs_baton->notify_func(fs_baton->notify_baton, notify, pool);
+}
+
/* Make a copy of a repository with hot backup of fs. */
svn_error_t *
-svn_repos_hotcopy2(const char *src_path,
+svn_repos_hotcopy3(const char *src_path,
const char *dst_path,
svn_boolean_t clean_logs,
svn_boolean_t incremental,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
{
- svn_repos_t *src_repos;
- svn_repos_t *dst_repos;
+ svn_fs_hotcopy_notify_t fs_notify_func;
+ struct fs_hotcopy_notify_baton_t fs_notify_baton;
struct hotcopy_ctx_t hotcopy_context;
- svn_error_t *err;
const char *src_abspath;
const char *dst_abspath;
+ svn_repos_t *src_repos;
+ svn_repos_t *dst_repos;
+ svn_error_t *err;
SVN_ERR(svn_dirent_get_absolute(&src_abspath, src_path, pool));
SVN_ERR(svn_dirent_get_absolute(&dst_abspath, dst_path, pool));
@@ -2200,8 +2232,13 @@ svn_repos_hotcopy2(const char *src_path,
No one should be accessing it at the moment */
SVN_ERR(lock_repos(dst_repos, TRUE, FALSE, pool));
- SVN_ERR(svn_fs_hotcopy2(src_repos->db_path, dst_repos->db_path,
+ fs_notify_func = notify_func ? fs_hotcopy_notify : NULL;
+ fs_notify_baton.notify_func = notify_func;
+ fs_notify_baton.notify_baton = notify_baton;
+
+ SVN_ERR(svn_fs_hotcopy3(src_repos->db_path, dst_repos->db_path,
clean_logs, incremental,
+ fs_notify_func, &fs_notify_baton,
cancel_func, cancel_baton, pool));
/* Destination repository is ready. Stamp it with a format number. */
@@ -2211,6 +2248,20 @@ svn_repos_hotcopy2(const char *src_path,
}
svn_error_t *
+svn_repos_hotcopy2(const char *src_path,
+ const char *dst_path,
+ svn_boolean_t clean_logs,
+ svn_boolean_t incremental,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_repos_hotcopy3(src_path, dst_path, clean_logs,
+ incremental, NULL, NULL,
+ cancel_func, cancel_baton, pool));
+}
+
+svn_error_t *
svn_repos_hotcopy(const char *src_path,
const char *dst_path,
svn_boolean_t clean_logs,
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c Fri Jul 25 16:20:13 2014
@@ -2238,6 +2238,35 @@ svn_io_file_lock2(const char *lock_file,
return svn_io_lock_open_file(lockfile_handle, exclusive, nonblocking, pool);
}
+svn_error_t *
+svn_io__file_lock_autocreate(const char *lock_file,
+ apr_pool_t *pool)
+{
+ svn_error_t *err
+ = svn_io_file_lock2(lock_file, TRUE, FALSE, pool);
+ if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+ {
+ /* No lock file? No big deal; these are just empty files anyway.
+ Create it and try again. */
+ svn_error_clear(err);
+
+ /* This file creation is racy.
+ We don't care as long as file gets created at all. */
+ err = svn_io_file_create_empty(lock_file, pool);
+ if (err && APR_STATUS_IS_EEXIST(err->apr_err))
+ {
+ svn_error_clear(err);
+ err = NULL;
+ }
+
+ /* Finally, lock the file - if it exists */
+ if (!err)
+ err = svn_io_file_lock2(lock_file, TRUE, FALSE, pool);
+ }
+
+ return svn_error_trace(err);
+}
+
/* Data consistency/coherency operations. */
@@ -5007,8 +5036,25 @@ svn_io_open_unique_file3(apr_file_t **fi
* case, but only if the umask allows it. */
if (!using_system_temp_dir)
{
+ svn_error_t *err;
+
SVN_ERR(merge_default_file_perms(tempfile, &perms, scratch_pool));
- SVN_ERR(file_perms_set2(tempfile, perms, scratch_pool));
+ err = file_perms_set2(tempfile, perms, scratch_pool);
+ if (err)
+ {
+ if (APR_STATUS_IS_INCOMPLETE(err->apr_err) ||
+ APR_STATUS_IS_ENOTIMPL(err->apr_err))
+ svn_error_clear(err);
+ else
+ {
+ const char *message;
+ message = apr_psprintf(scratch_pool,
+ _("Can't set permissions on '%s'"),
+ svn_dirent_local_style(tempname,
+ scratch_pool));
+ return svn_error_quick_wrap(err, message);
+ }
+ }
}
#endif
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/named_atomic.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/named_atomic.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/named_atomic.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/named_atomic.c Fri Jul 25 16:20:13 2014
@@ -32,6 +32,7 @@
#include "svn_pools.h"
#include "svn_dirent_uri.h"
#include "svn_io.h"
+#include "private/svn_io_private.h"
/* Implementation aspects.
*
@@ -274,28 +275,10 @@ init_thread_mutex(void *baton, apr_pool_
static svn_error_t *
lock(struct mutex_t *mutex)
{
- svn_error_t *err;
-
- /* Intra-process lock */
- SVN_ERR(svn_mutex__lock(thread_mutex));
-
- /* Inter-process lock. */
- err = svn_io_file_lock2(mutex->lock_name, TRUE, FALSE, mutex->pool);
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- /* No lock file? No big deal; these are just empty files anyway.
- Create it and try again. */
- svn_error_clear(err);
- err = NULL;
-
- SVN_ERR(svn_io_file_create_empty(mutex->lock_name, mutex->pool));
- SVN_ERR(svn_io_file_lock2(mutex->lock_name, TRUE, FALSE, mutex->pool));
- }
-
- /* Don't leave us in a semi-locked state ... */
- return err
- ? svn_mutex__unlock(thread_mutex, err)
- : err;
+ SVN_MUTEX__WITH_LOCK(thread_mutex,
+ svn_io__file_lock_autocreate(mutex->lock_name,
+ mutex->pool));
+ return SVN_NO_ERROR;
}
/* Utility that releases the lock previously acquired via lock(). If the
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c Fri Jul 25 16:20:13 2014
@@ -1465,4 +1465,17 @@ svn_cstring__reverse_match_length(const
return max_len;
}
+const char *
+svn_cstring_skip_prefix(const char *str, const char *prefix)
+{
+ apr_size_t len = strlen(prefix);
+ if (strncmp(str, prefix, len) == 0)
+ {
+ return str + len;
+ }
+ else
+ {
+ return NULL;
+ }
+}
Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/util.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/util.c Fri Jul 25 16:20:13 2014
@@ -1,5 +1,8 @@
/*
- * util.c: some handy utility functions
+ * util.c:
+ * # ****************************************************************************
+ * # TRASHY LITTLE SUBROUTINES
+ * # ****************************************************************************
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
Modified: subversion/branches/svn-auth-x509/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svn/svn.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svn/svn.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svn/svn.c Fri Jul 25 16:20:13 2014
@@ -191,7 +191,10 @@ const apr_getopt_option_t svn_cl__option
{"verbose", 'v', 0, N_("print extra information")},
{"show-updates", 'u', 0, N_("display update information")},
{"username", opt_auth_username, 1, N_("specify a username ARG")},
- {"password", opt_auth_password, 1, N_("specify a password ARG")},
+ {"password", opt_auth_password, 1,
+ N_("specify a password ARG (caution: on many operating\n"
+ " "
+ "systems, other users will be able to see this)")},
{"extensions", 'x', 1,
N_("Specify differencing options for external diff or\n"
" "
Modified: subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c Fri Jul 25 16:20:13 2014
@@ -410,7 +410,7 @@ static const svn_opt_subcommand_desc2_t
"Make a hot copy of a repository.\n"
"If --incremental is passed, data which already exists at the destination\n"
"is not copied again. Incremental mode is implemented for FSFS repositories.\n"),
- {svnadmin__clean_logs, svnadmin__incremental} },
+ {svnadmin__clean_logs, svnadmin__incremental, 'q'} },
{"info", subcommand_info, {0}, N_
("usage: svnadmin info REPOS_PATH\n\n"
@@ -872,7 +872,8 @@ struct repos_notify_handler_baton {
};
/* Implementation of svn_repos_notify_func_t to wrap the output to a
- response stream for svn_repos_dump_fs2() and svn_repos_verify_fs() */
+ response stream for svn_repos_dump_fs2(), svn_repos_verify_fs(),
+ svn_repos_hotcopy3() and others. */
static void
repos_notify_handler(void *baton,
const svn_repos_notify_t *notify,
@@ -1088,6 +1089,21 @@ repos_notify_handler(void *baton,
svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool,
_("Bumped repository format to %ld\n"),
notify->revision));
+ return;
+
+ case svn_repos_notify_hotcopy_rev_range:
+ if (notify->start_revision == notify->end_revision)
+ {
+ svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool,
+ _("* Copied revision %ld.\n"),
+ notify->start_revision));
+ }
+ else
+ {
+ svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool,
+ _("* Copied revisions from %ld to %ld.\n"),
+ notify->start_revision, notify->end_revision));
+ }
default:
return;
@@ -1872,6 +1888,7 @@ svn_error_t *
subcommand_hotcopy(apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
+ struct repos_notify_handler_baton notify_baton = { 0 };
apr_array_header_t *targets;
const char *new_repos_path;
@@ -1880,9 +1897,14 @@ subcommand_hotcopy(apr_getopt_t *os, voi
new_repos_path = APR_ARRAY_IDX(targets, 0, const char *);
SVN_ERR(target_arg_to_dirent(&new_repos_path, new_repos_path, pool));
- return svn_repos_hotcopy2(opt_state->repository_path, new_repos_path,
+ /* Progress feedback goes to STDOUT, unless they asked to suppress it. */
+ if (! opt_state->quiet)
+ notify_baton.feedback_stream = recode_stream_create(stdout, pool);
+
+ return svn_repos_hotcopy3(opt_state->repository_path, new_repos_path,
opt_state->clean_logs, opt_state->incremental,
- check_cancel, NULL, pool);
+ !opt_state->quiet ? repos_notify_handler : NULL,
+ ¬ify_baton, check_cancel, NULL, pool);
}
svn_error_t *
Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Fri Jul 25 16:20:13 2014
@@ -115,7 +115,8 @@ Valid options:
Global options:
--username ARG : specify a username ARG
- --password ARG : specify a password ARG
+ --password ARG : specify a password ARG (caution: on many operating
+ systems, other users will be able to see this)
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting (default is to prompt
only if standard input is a terminal device)
@@ -198,7 +199,8 @@ Valid options:
Global options:
--username ARG : specify a username ARG
- --password ARG : specify a password ARG
+ --password ARG : specify a password ARG (caution: on many operating
+ systems, other users will be able to see this)
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting (default is to prompt
only if standard input is a terminal device)
Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py Fri Jul 25 16:20:13 2014
@@ -2647,6 +2647,240 @@ def verify_quickly(sbox):
raise svntest.Failure
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+@SkipUnless(svntest.main.fs_has_pack)
+def fsfs_hotcopy_progress(sbox):
+ "hotcopy progress reporting"
+
+ # Check how 'svnadmin hotcopy' reports progress for non-incremental
+ # and incremental scenarios. The progress output can be affected by
+ # the --fsfs-packing option, so skip the test if that is the case.
+ if svntest.main.options.fsfs_packing:
+ raise svntest.Skip
+
+ # Create an empty repository, configure three files per shard.
+ sbox.build(create_wc=False)
+ svntest.main.safe_rmtree(sbox.repo_dir, True)
+ svntest.main.create_repos(sbox.repo_dir)
+
+ if svntest.main.options.server_minor_version >= 9:
+ format = "7\nlayout sharded 3\naddressing logical 0\n"
+ elif svntest.main.options.server_minor_version < 9:
+ format = "6\nlayout sharded 3\n"
+ else:
+ raise svntest.Failure
+
+ format_file = open(os.path.join(sbox.repo_dir, 'db', 'format'), 'wb')
+ format_file.write(format)
+ format_file.close()
+
+ inc_backup_dir, inc_backup_url = sbox.add_repo_path('incremental-backup')
+
+ # Nothing really exciting for the empty repository.
+ expected_full = [
+ "* Copied revision 0.\n"
+ ]
+ expected_incremental = [
+ "* Copied revision 0.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup-0')
+ svntest.actions.run_and_verify_svnadmin(None, expected_full, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+ svntest.actions.run_and_verify_svnadmin(None, expected_incremental, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, inc_backup_dir)
+
+ # Commit three revisions. After this step we have a full shard
+ # (r0, r1, r2) and the second shard (r3) with a single revision.
+ for i in range(3):
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ '-m', svntest.main.make_log_msg(),
+ sbox.repo_url + '/dir-%i' % i)
+ expected_full = [
+ "* Copied revision 0.\n",
+ "* Copied revision 1.\n",
+ "* Copied revision 2.\n",
+ "* Copied revision 3.\n",
+ ]
+ expected_incremental = [
+ "* Copied revision 1.\n",
+ "* Copied revision 2.\n",
+ "* Copied revision 3.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup-1')
+ svntest.actions.run_and_verify_svnadmin(None, expected_full, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+ svntest.actions.run_and_verify_svnadmin(None, expected_incremental, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, inc_backup_dir)
+
+ # Pack everything (r3 is still unpacked) and hotcopy again. In this case,
+ # the --incremental output should track the incoming (r0, r1, r2) pack and
+ # should not mention r3, because it is already a part of the destination
+ # and is *not* a part of the incoming pack.
+ svntest.actions.run_and_verify_svnadmin(None, None, [], 'pack',
+ sbox.repo_dir)
+ expected_full = [
+ "* Copied revisions from 0 to 2.\n",
+ "* Copied revision 3.\n",
+ ]
+ expected_incremental = [
+ "* Copied revisions from 0 to 2.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup-2')
+ svntest.actions.run_and_verify_svnadmin(None, expected_full, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+ svntest.actions.run_and_verify_svnadmin(None, expected_incremental, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, inc_backup_dir)
+
+ # Fill the second shard, pack again, commit several unpacked revisions
+ # on top of it. Rerun the hotcopy and check the progress output.
+ for i in range(4, 6):
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ '-m', svntest.main.make_log_msg(),
+ sbox.repo_url + '/dir-%i' % i)
+
+ svntest.actions.run_and_verify_svnadmin(None, None, [], 'pack',
+ sbox.repo_dir)
+
+ for i in range(6, 8):
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ '-m', svntest.main.make_log_msg(),
+ sbox.repo_url + '/dir-%i' % i)
+ expected_full = [
+ "* Copied revisions from 0 to 2.\n",
+ "* Copied revisions from 3 to 5.\n",
+ "* Copied revision 6.\n",
+ "* Copied revision 7.\n",
+ ]
+ expected_incremental = [
+ "* Copied revisions from 3 to 5.\n",
+ "* Copied revision 6.\n",
+ "* Copied revision 7.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup-3')
+ svntest.actions.run_and_verify_svnadmin(None, expected_full, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+ svntest.actions.run_and_verify_svnadmin(None, expected_incremental, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, inc_backup_dir)
+
+
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+def fsfs_hotcopy_progress_with_revprop_changes(sbox):
+ "incremental hotcopy progress with changed revprops"
+
+ # The progress output can be affected by the --fsfs-packing
+ # option, so skip the test if that is the case.
+ if svntest.main.options.fsfs_packing:
+ raise svntest.Skip
+
+ # Create an empty repository, commit several revisions and hotcopy it.
+ sbox.build(create_wc=False)
+ svntest.main.safe_rmtree(sbox.repo_dir, True)
+ svntest.main.create_repos(sbox.repo_dir)
+
+ for i in range(6):
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ '-m', svntest.main.make_log_msg(),
+ sbox.repo_url + '/dir-%i' % i)
+ expected_output = [
+ "* Copied revision 0.\n",
+ "* Copied revision 1.\n",
+ "* Copied revision 2.\n",
+ "* Copied revision 3.\n",
+ "* Copied revision 4.\n",
+ "* Copied revision 5.\n",
+ "* Copied revision 6.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup')
+ svntest.actions.run_and_verify_svnadmin(None, expected_output, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+
+ # Amend a few log messages in the source, run the --incremental hotcopy.
+ # The progress output should only mention the corresponding revisions.
+ revprop_file = sbox.get_tempname()
+ svntest.main.file_write(revprop_file, "Modified log message.")
+
+ for i in [1, 3, 6]:
+ svntest.actions.run_and_verify_svnadmin(None, None, [],
+ 'setrevprop',
+ sbox.repo_dir, '-r', i,
+ 'svn:log', revprop_file)
+ expected_output = [
+ "* Copied revision 1.\n",
+ "* Copied revision 3.\n",
+ "* Copied revision 6.\n",
+ ]
+ svntest.actions.run_and_verify_svnadmin(None, expected_output, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, backup_dir)
+
+
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+def fsfs_hotcopy_progress_old(sbox):
+ "hotcopy --compatible-version=1.3 progress"
+
+ sbox.build(create_wc=False)
+ svntest.main.safe_rmtree(sbox.repo_dir, True)
+ svntest.main.create_repos(sbox.repo_dir, minor_version=3)
+
+ inc_backup_dir, inc_backup_url = sbox.add_repo_path('incremental-backup')
+
+ # Nothing really exciting for the empty repository.
+ expected_full = [
+ "* Copied revision 0.\n"
+ ]
+ expected_incremental = [
+ "* Copied revision 0.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup-0')
+ svntest.actions.run_and_verify_svnadmin(None, expected_full, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+ svntest.actions.run_and_verify_svnadmin(None, expected_incremental, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, inc_backup_dir)
+
+ # Commit three revisions, hotcopy and check the progress output.
+ for i in range(3):
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ '-m', svntest.main.make_log_msg(),
+ sbox.repo_url + '/dir-%i' % i)
+
+ expected_full = [
+ "* Copied revision 0.\n",
+ "* Copied revision 1.\n",
+ "* Copied revision 2.\n",
+ "* Copied revision 3.\n",
+ ]
+ expected_incremental = [
+ "* Copied revision 1.\n",
+ "* Copied revision 2.\n",
+ "* Copied revision 3.\n",
+ ]
+
+ backup_dir, backup_url = sbox.add_repo_path('backup-1')
+ svntest.actions.run_and_verify_svnadmin(None, expected_full, [],
+ 'hotcopy',
+ sbox.repo_dir, backup_dir)
+ svntest.actions.run_and_verify_svnadmin(None, expected_incremental, [],
+ 'hotcopy', '--incremental',
+ sbox.repo_dir, inc_backup_dir)
+
+
########################################################################
# Run the tests
@@ -2695,6 +2929,9 @@ test_list = [ None,
freeze_freeze,
verify_metadata_only,
verify_quickly,
+ fsfs_hotcopy_progress,
+ fsfs_hotcopy_progress_with_revprop_changes,
+ fsfs_hotcopy_progress_old,
]
if __name__ == '__main__':
Modified: subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/string-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/string-test.c?rev=1613462&r1=1613461&r2=1613462&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/string-test.c (original)
+++ subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/string-test.c Fri Jul 25 16:20:13 2014
@@ -825,6 +825,27 @@ test_string_matching(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_string_skip_prefix(apr_pool_t *pool)
+{
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", "12345"),
+ "");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", "123"),
+ "45");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", ""),
+ "12345");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", "23"),
+ NULL);
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("1", "12"),
+ NULL);
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("", ""),
+ "");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("", "12"),
+ NULL);
+
+ return SVN_NO_ERROR;
+}
+
/*
====================================================================
If you add a new test to this file, update this array.
@@ -899,6 +920,8 @@ static struct svn_test_descriptor_t test
"test string similarity scores"),
SVN_TEST_PASS2(test_string_matching,
"test string matching"),
+ SVN_TEST_PASS2(test_string_skip_prefix,
+ "test svn_cstring_skip_prefix()"),
SVN_TEST_NULL
};