Author: stsp Date: Thu Feb 12 16:14:28 2015 New Revision: 1659301 URL: http://svn.apache.org/r1659301 Log: On the pin-externals branch, merge outstanding changes from trunk.
Added: subversion/branches/pin-externals/subversion/svnbench/ - copied from r1659295, subversion/trunk/subversion/svnbench/ Removed: subversion/branches/pin-externals/subversion/svn-bench/ Modified: subversion/branches/pin-externals/ (props changed) subversion/branches/pin-externals/Makefile.in subversion/branches/pin-externals/build.conf subversion/branches/pin-externals/subversion/include/private/svn_repos_private.h subversion/branches/pin-externals/subversion/libsvn_delta/compat.c subversion/branches/pin-externals/subversion/libsvn_fs_base/fs.c subversion/branches/pin-externals/subversion/libsvn_fs_fs/lock.c subversion/branches/pin-externals/subversion/libsvn_repos/dump.c subversion/branches/pin-externals/subversion/libsvn_repos/repos.c subversion/branches/pin-externals/subversion/libsvn_subr/dso.c subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c subversion/branches/pin-externals/subversion/libsvn_wc/token-map.h subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.h subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c subversion/branches/pin-externals/subversion/mod_dav_svn/deadprops.c subversion/branches/pin-externals/subversion/svn/cl-conflicts.c subversion/branches/pin-externals/subversion/svn/cl-conflicts.h subversion/branches/pin-externals/subversion/svn/info-cmd.c subversion/branches/pin-externals/subversion/svndumpfilter/svndumpfilter.c subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c subversion/branches/pin-externals/subversion/tests/cmdline/move_tests.py subversion/branches/pin-externals/subversion/tests/cmdline/prop_tests.py subversion/branches/pin-externals/subversion/tests/libsvn_fs/fs-test.c subversion/branches/pin-externals/subversion/tests/libsvn_ra/ra-test.c subversion/branches/pin-externals/subversion/tests/libsvn_wc/op-depth-test.c subversion/branches/pin-externals/subversion/tests/libsvn_wc/wc-test-queries.sql subversion/branches/pin-externals/subversion/tests/svn_test.h subversion/branches/pin-externals/subversion/tests/svn_test_main.c Propchange: subversion/branches/pin-externals/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Feb 12 16:14:28 2015 @@ -87,4 +87,4 @@ /subversion/branches/verify-at-commit:1462039-1462408 /subversion/branches/verify-keep-going:1439280-1546110 /subversion/branches/wc-collate-path:1402685-1480384 -/subversion/trunk:1643755-1658683 +/subversion/trunk:1643755-1659295 Modified: subversion/branches/pin-externals/Makefile.in URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/Makefile.in?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/Makefile.in (original) +++ subversion/branches/pin-externals/Makefile.in Thu Feb 12 16:14:28 2015 @@ -981,4 +981,5 @@ INSTALL_EXTRA_TOOLS=\ ln -sf svnmucc$(EXEEXT) $(DESTDIR)$(bindir)/svnsyitf$(EXEEXT); \ if test "$(DESTDIR)$(bindir)" != "$(DESTDIR)$(toolsdir)"; then \ ln -sf $(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \ + ln -sf $(bindir)/svnbench$(EXEEXT) $(DESTDIR)$(toolsdir)/svn-bench$(EXEEXT); \ fi Modified: subversion/branches/pin-externals/build.conf URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/build.conf?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/build.conf (original) +++ subversion/branches/pin-externals/build.conf Thu Feb 12 16:14:28 2015 @@ -56,6 +56,7 @@ private-built-includes = subversion/libsvn_wc/wc-queries.h subversion/libsvn_wc/wc-checks.h subversion/libsvn_subr/internal_statements.h + subversion/tests/libsvn_wc/wc-test-queries.h subversion/bindings/swig/proxy/swig_python_external_runtime.swg subversion/bindings/swig/proxy/swig_perl_external_runtime.swg subversion/bindings/swig/proxy/swig_ruby_external_runtime.swg @@ -1475,7 +1476,7 @@ libs = svn svnadmin svndumpfilter svnloo svnversion mod_authz_svn mod_dav_svn mod_dontdothat svnauthz svnauthz-validate svnraisetreeconflict - svnfsfs svn-bench + svnfsfs svnbench [__ALL_TESTS__] type = project @@ -1583,9 +1584,9 @@ sources = diff4.c install = tools libs = libsvn_diff libsvn_subr apriconv apr -[svn-bench] +[svnbench] type = exe -path = subversion/svn-bench +path = subversion/svnbench install = tools libs = libsvn_client libsvn_wc libsvn_ra libsvn_subr libsvn_delta apriconv apr Modified: subversion/branches/pin-externals/subversion/include/private/svn_repos_private.h URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/include/private/svn_repos_private.h?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/include/private/svn_repos_private.h (original) +++ subversion/branches/pin-externals/subversion/include/private/svn_repos_private.h Thu Feb 12 16:14:28 2015 @@ -293,19 +293,13 @@ svn_repos__adjust_mergeinfo_property(svn apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* A header entry. - * - * (The headers are currently declared here to be of type apr_array_header_t - * with svn_repos__dumpfile_header_entry_t entries, but the types could - * instead be made opaque.) - */ -typedef struct svn_repos__dumpfile_header_entry_t { - const char *key, *val; -} svn_repos__dumpfile_header_entry_t; +/* A (nearly) opaque representation of an ordered list of header lines. + */ +typedef struct apr_array_header_t svn_repos__dumpfile_headers_t; /* Create an empty set of headers. */ -apr_array_header_t * +svn_repos__dumpfile_headers_t * svn_repos__dumpfile_headers_create(apr_pool_t *pool); /* Push the header (KEY, VAL) onto HEADERS. @@ -313,7 +307,7 @@ svn_repos__dumpfile_headers_create(apr_p * Duplicate the key and value into HEADERS's pool. */ void -svn_repos__dumpfile_header_push(apr_array_header_t *headers, +svn_repos__dumpfile_header_push(svn_repos__dumpfile_headers_t *headers, const char *key, const char *val); @@ -322,20 +316,17 @@ svn_repos__dumpfile_header_push(apr_arra * Duplicate the key and value into HEADERS's pool. */ void -svn_repos__dumpfile_header_pushf(apr_array_header_t *headers, +svn_repos__dumpfile_header_pushf(svn_repos__dumpfile_headers_t *headers, const char *key, const char *val_fmt, ...) __attribute__((format(printf, 3, 4))); /* Write to STREAM the headers in HEADERS followed by a blank line. - * - * HEADERS is an array of struct {const char *key, *val;}. */ svn_error_t * svn_repos__dump_headers(svn_stream_t *stream, - apr_array_header_t *headers, - svn_boolean_t terminate, + svn_repos__dumpfile_headers_t *headers, apr_pool_t *scratch_pool); /* Write a revision record to DUMP_STREAM for revision REVISION with revision @@ -384,7 +375,7 @@ svn_repos__dump_revision_record(svn_stre */ svn_error_t * svn_repos__dump_node_record(svn_stream_t *dump_stream, - apr_array_header_t *headers, + svn_repos__dumpfile_headers_t *headers, svn_stringbuf_t *props_str, svn_boolean_t has_text, svn_filesize_t text_content_length, Modified: subversion/branches/pin-externals/subversion/libsvn_delta/compat.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_delta/compat.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_delta/compat.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_delta/compat.c Thu Feb 12 16:14:28 2015 @@ -1233,12 +1233,12 @@ alter_file_cb(void *baton, if (contents) { /* We may need to re-checksum these contents */ - if (!(checksum && checksum->kind == svn_checksum_md5)) + if (checksum && checksum->kind == svn_checksum_md5) + md5_checksum = (svn_checksum_t *)checksum; + else contents = svn_stream_checksummed2(contents, &md5_checksum, NULL, svn_checksum_md5, TRUE, scratch_pool); - else - md5_checksum = (svn_checksum_t *)checksum; /* Spool the contents to a tempfile, and provide that to the driver. */ SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_filename, NULL, Modified: subversion/branches/pin-externals/subversion/libsvn_fs_base/fs.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_base/fs.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_base/fs.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_base/fs.c Thu Feb 12 16:14:28 2015 @@ -783,8 +783,8 @@ base_create(svn_fs_t *fs, return SVN_NO_ERROR;; error: - svn_error_clear(cleanup_fs(fs)); - return svn_err; + return svn_error_compose_create(svn_err, + svn_error_trace(cleanup_fs(fs))); } @@ -871,8 +871,8 @@ base_open(svn_fs_t *fs, return SVN_NO_ERROR; error: - svn_error_clear(cleanup_fs(fs)); - return svn_err; + return svn_error_compose_create(svn_err, + svn_error_trace(cleanup_fs(fs))); } Modified: subversion/branches/pin-externals/subversion/libsvn_fs_fs/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_fs/lock.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_fs/lock.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_fs/lock.c Thu Feb 12 16:14:28 2015 @@ -451,6 +451,12 @@ unlock_single(svn_fs_t *fs, svn_lock_t *lock, apr_pool_t *pool); +/* Check if LOCK has been already expired. */ +static svn_boolean_t lock_expired(const svn_lock_t *lock) +{ + return lock->expiration_date && (apr_time_now() > lock->expiration_date); +} + /* Set *LOCK_P to the lock for PATH in FS. HAVE_WRITE_LOCK should be TRUE if the caller (or one of its callers) has taken out the repository-wide write lock, FALSE otherwise. If MUST_EXIST is @@ -480,7 +486,7 @@ get_lock(svn_lock_t **lock_p, return must_exist ? SVN_FS__ERR_NO_SUCH_LOCK(fs, path) : SVN_NO_ERROR; /* Don't return an expired lock. */ - if (lock->expiration_date && (apr_time_now() > lock->expiration_date)) + if (lock_expired(lock)) { /* Only remove the lock if we have the write lock. Read operations shouldn't change the filesystem. */ @@ -527,67 +533,17 @@ get_lock_helper(svn_fs_t *fs, } -/* Baton for locks_walker(). */ -struct walk_locks_baton { - svn_fs_get_locks_callback_t get_locks_func; - void *get_locks_baton; - svn_fs_t *fs; -}; - -/* Implements walk_digests_callback_t. */ -static svn_error_t * -locks_walker(void *baton, - const char *fs_path, - const char *digest_path, - svn_lock_t *lock, - svn_boolean_t have_write_lock, - apr_pool_t *pool) -{ - struct walk_locks_baton *wlb = baton; - - if (lock) - { - /* Don't report an expired lock. */ - if (lock->expiration_date == 0 - || (apr_time_now() <= lock->expiration_date)) - { - if (wlb->get_locks_func) - SVN_ERR(wlb->get_locks_func(wlb->get_locks_baton, lock, pool)); - } - else - { - /* Only remove the lock if we have the write lock. - Read operations shouldn't change the filesystem. */ - if (have_write_lock) - SVN_ERR(unlock_single(wlb->fs, lock, pool)); - } - } - - return SVN_NO_ERROR; -} - -/* Callback type for walk_digest_files(). - * - * LOCK come from a read_digest_file(digest_path) call. - */ -typedef svn_error_t *(*walk_digests_callback_t)(void *baton, - const char *fs_path, - const char *digest_path, - svn_lock_t *lock, - svn_boolean_t have_write_lock, - apr_pool_t *pool); - -/* A function that calls WALK_DIGESTS_FUNC/WALK_DIGESTS_BATON for - all lock digest files in and under PATH in FS. +/* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for + all locks in and under PATH in FS. HAVE_WRITE_LOCK should be true if the caller (directly or indirectly) has the FS write lock. */ static svn_error_t * -walk_digest_files(const char *fs_path, - const char *digest_path, - walk_digests_callback_t walk_digests_func, - void *walk_digests_baton, - svn_boolean_t have_write_lock, - apr_pool_t *pool) +walk_locks(svn_fs_t *fs, + const char *digest_path, + svn_fs_get_locks_callback_t get_locks_func, + void *get_locks_baton, + svn_boolean_t have_write_lock, + apr_pool_t *pool) { apr_hash_index_t *hi; apr_hash_t *children; @@ -595,10 +551,19 @@ walk_digest_files(const char *fs_path, svn_lock_t *lock; /* First, send up any locks in the current digest file. */ - SVN_ERR(read_digest_file(&children, &lock, fs_path, digest_path, pool)); + SVN_ERR(read_digest_file(&children, &lock, fs->path, digest_path, pool)); - SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock, - have_write_lock, pool)); + if (lock && lock_expired(lock)) + { + /* Only remove the lock if we have the write lock. + Read operations shouldn't change the filesystem. */ + if (have_write_lock) + SVN_ERR(unlock_single(fs, lock, pool)); + } + else if (lock) + { + SVN_ERR(get_locks_func(get_locks_baton, lock, pool)); + } /* Now, report all the child entries (if any; bail otherwise). */ if (! apr_hash_count(children)) @@ -610,38 +575,25 @@ walk_digest_files(const char *fs_path, svn_pool_clear(subpool); SVN_ERR(read_digest_file - (NULL, &lock, fs_path, - digest_path_from_digest(fs_path, digest, subpool), subpool)); + (NULL, &lock, fs->path, + digest_path_from_digest(fs->path, digest, subpool), subpool)); - SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock, - have_write_lock, subpool)); + if (lock && lock_expired(lock)) + { + /* Only remove the lock if we have the write lock. + Read operations shouldn't change the filesystem. */ + if (have_write_lock) + SVN_ERR(unlock_single(fs, lock, pool)); + } + else if (lock) + { + SVN_ERR(get_locks_func(get_locks_baton, lock, pool)); + } } svn_pool_destroy(subpool); return SVN_NO_ERROR; } -/* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for - all locks in and under PATH in FS. - HAVE_WRITE_LOCK should be true if the caller (directly or indirectly) - has the FS write lock. */ -static svn_error_t * -walk_locks(svn_fs_t *fs, - const char *digest_path, - svn_fs_get_locks_callback_t get_locks_func, - void *get_locks_baton, - svn_boolean_t have_write_lock, - apr_pool_t *pool) -{ - struct walk_locks_baton wlb; - - wlb.get_locks_func = get_locks_func; - wlb.get_locks_baton = get_locks_baton; - wlb.fs = fs; - SVN_ERR(walk_digest_files(fs->path, digest_path, locks_walker, &wlb, - have_write_lock, pool)); - return SVN_NO_ERROR; -} - /* Utility function: verify that a lock can be used. Interesting errors returned from this function: @@ -716,6 +668,35 @@ svn_fs_fs__allow_locked_operation(const return SVN_NO_ERROR; } +/* Helper function called from the lock and unlock code. + UPDATES is a map from "const char *" parent paths to "apr_array_header_t *" + arrays of child paths. For all of the parent paths of PATH this function + adds PATH to the corresponding array of child paths. */ +static void +schedule_index_update(apr_hash_t *updates, + const char *path, + apr_pool_t *scratch_pool) +{ + apr_pool_t *hashpool = apr_hash_pool_get(updates); + const char *parent_path = path; + + while (! svn_fspath__is_root(parent_path, strlen(parent_path))) + { + apr_array_header_t *children; + + parent_path = svn_fspath__dirname(parent_path, scratch_pool); + children = svn_hash_gets(updates, parent_path); + + if (! children) + { + children = apr_array_make(hashpool, 8, sizeof(const char *)); + svn_hash_sets(updates, apr_pstrdup(hashpool, parent_path), children); + } + + APR_ARRAY_PUSH(children, const char *) = path; + } +} + /* The effective arguments for lock_body() below. */ struct lock_baton { svn_fs_t *fs; @@ -828,7 +809,6 @@ check_lock(svn_error_t **fs_err, struct lock_info_t { const char *path; - const char *component; svn_lock_t *lock; svn_error_t *fs_err; }; @@ -851,7 +831,9 @@ lock_body(void *baton, apr_pool_t *pool) svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; - int i, outstanding = 0; + int i; + apr_hash_t *index_updates = apr_hash_make(pool); + apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); /* Until we implement directory locks someday, we only allow locks @@ -865,34 +847,28 @@ lock_body(void *baton, apr_pool_t *pool) { const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t); - const svn_fs_lock_target_t *target = item->value; struct lock_info_t info; svn_pool_clear(iterpool); info.path = item->key; - SVN_ERR(check_lock(&info.fs_err, info.path, target, lb, root, iterpool)); info.lock = NULL; - info.component = NULL; - APR_ARRAY_PUSH(lb->infos, struct lock_info_t) = info; + info.fs_err = SVN_NO_ERROR; + + SVN_ERR(check_lock(&info.fs_err, info.path, item->value, lb, root, + iterpool)); + + /* If no error occurred while pre-checking, schedule the index updates for + this path. */ if (!info.fs_err) - ++outstanding; + schedule_index_update(index_updates, info.path, iterpool); + + APR_ARRAY_PUSH(lb->infos, struct lock_info_t) = info; } rev_0_path = svn_fs_fs__path_rev_absolute(lb->fs, 0, pool); - /* Given the paths: - - /foo/bar/f - /foo/bar/g - /zig/x - - we loop through repeatedly. The first pass sees '/' on all paths - and writes the '/' index. The second pass sees '/foo' twice and - writes that index followed by '/zig' and that index. The third - pass sees '/foo/bar' twice and writes that index, and then writes - the lock for '/zig/x'. The fourth pass writes the locks for - '/foo/bar/f' and '/foo/bar/g'. + /* We apply the scheduled index updates before writing the actual locks. Writing indices before locks is correct: if interrupted it leaves indices without locks rather than locks without indices. An @@ -901,92 +877,47 @@ lock_body(void *baton, apr_pool_t *pool) index is inconsistent, svn_fs_fs__allow_locked_operation will show locked on the file but unlocked on the parent. */ - - while (outstanding) + for (hi = apr_hash_first(pool, index_updates); hi; hi = apr_hash_next(hi)) { - const char *last_path = NULL; - apr_array_header_t *paths; + const char *path = apr_hash_this_key(hi); + apr_array_header_t *children = apr_hash_this_val(hi); svn_pool_clear(iterpool); - paths = apr_array_make(iterpool, 1, sizeof(const char *)); + SVN_ERR(add_to_digest(lb->fs->path, children, path, rev_0_path, + iterpool)); + } - for (i = 0; i < lb->infos->nelts; ++i) + for (i = 0; i < lb->infos->nelts; ++i) + { + struct lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, + struct lock_info_t); + svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t); + svn_fs_lock_target_t *target = item->value; + + svn_pool_clear(iterpool); + + if (! info->fs_err) { - struct lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, - struct lock_info_t); - const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, - svn_sort__item_t); - const svn_fs_lock_target_t *target = item->value; - - if (!info->fs_err && !info->lock) - { - if (!info->component) - { - info->component = info->path; - APR_ARRAY_PUSH(paths, const char *) = info->path; - last_path = "/"; - } - else - { - info->component = strchr(info->component + 1, '/'); - if (!info->component) - { - /* The component is a path to lock, this cannot - match a previous path that need to be indexed. */ - if (paths->nelts) - { - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - - info->lock = svn_lock_create(lb->result_pool); - if (target->token) - info->lock->token = target->token; - else - SVN_ERR(svn_fs_fs__generate_lock_token( - &(info->lock->token), lb->fs, - lb->result_pool)); - info->lock->path = info->path; - info->lock->owner = lb->fs->access_ctx->username; - info->lock->comment = lb->comment; - info->lock->is_dav_comment = lb->is_dav_comment; - info->lock->creation_date = apr_time_now(); - info->lock->expiration_date = lb->expiration_date; - - info->fs_err = set_lock(lb->fs->path, info->lock, - rev_0_path, iterpool); - --outstanding; - } - else - { - /* The component is a path to an index. */ - apr_size_t len = info->component - info->path; - - if (last_path - && (strncmp(last_path, info->path, len) - || strlen(last_path) != len)) - { - /* No match to the previous paths to index. */ - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - APR_ARRAY_PUSH(paths, const char *) = info->path; - if (!last_path) - last_path = apr_pstrndup(iterpool, info->path, len); - } - } - } - - if (last_path && i == lb->infos->nelts - 1) - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); + info->lock = svn_lock_create(lb->result_pool); + if (target->token) + info->lock->token = target->token; + else + SVN_ERR(svn_fs_fs__generate_lock_token(&(info->lock->token), lb->fs, + lb->result_pool)); + + info->lock->path = info->path; + info->lock->owner = lb->fs->access_ctx->username; + info->lock->comment = lb->comment; + info->lock->is_dav_comment = lb->is_dav_comment; + info->lock->creation_date = apr_time_now(); + info->lock->expiration_date = lb->expiration_date; + + info->fs_err = set_lock(lb->fs->path, info->lock, rev_0_path, + iterpool); } } - + + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1027,10 +958,8 @@ check_unlock(svn_error_t **fs_err, struct unlock_info_t { const char *path; - const char *component; svn_error_t *fs_err; svn_boolean_t done; - int components; }; /* The body of svn_fs_fs__unlock(), which see. @@ -1051,7 +980,9 @@ unlock_body(void *baton, apr_pool_t *poo svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; - int i, max_components = 0, outstanding = 0; + int i; + apr_hash_t *indices_updates = apr_hash_make(pool); + apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); SVN_ERR(ub->fs->vtable->youngest_rev(&youngest, ub->fs, pool)); @@ -1062,96 +993,56 @@ unlock_body(void *baton, apr_pool_t *poo const svn_sort__item_t *item = &APR_ARRAY_IDX(ub->targets, i, svn_sort__item_t); const char *token = item->value; - struct unlock_info_t info = { 0 }; + struct unlock_info_t info; svn_pool_clear(iterpool); info.path = item->key; + info.fs_err = SVN_NO_ERROR; + info.done = FALSE; + if (!ub->skip_check) SVN_ERR(check_unlock(&info.fs_err, info.path, token, ub, root, iterpool)); - if (!info.fs_err) - { - const char *s; - info.components = 1; - info.component = info.path; - while((s = strchr(info.component + 1, '/'))) - { - info.component = s; - ++info.components; - } - - if (info.components > max_components) - max_components = info.components; + /* If no error occurred while pre-checking, schedule the index updates for + this path. */ + if (!info.fs_err) + schedule_index_update(indices_updates, info.path, iterpool); - ++outstanding; - } APR_ARRAY_PUSH(ub->infos, struct unlock_info_t) = info; } rev_0_path = svn_fs_fs__path_rev_absolute(ub->fs, 0, pool); - for (i = max_components; i >= 0; --i) + /* Unlike the lock_body(), we need to delete locks *before* we start to + update indices. */ + + for (i = 0; i < ub->infos->nelts; ++i) { - const char *last_path = NULL; - apr_array_header_t *paths; - int j; + struct unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, i, + struct unlock_info_t); svn_pool_clear(iterpool); - paths = apr_array_make(pool, 1, sizeof(const char *)); - for (j = 0; j < ub->infos->nelts; ++j) + if (! info->fs_err) { - struct unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, j, - struct unlock_info_t); + SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool)); + info->done = TRUE; + } + } - if (!info->fs_err && info->path) - { + for (hi = apr_hash_first(pool, indices_updates); hi; hi = apr_hash_next(hi)) + { + const char *path = apr_hash_this_key(hi); + apr_array_header_t *children = apr_hash_this_val(hi); - if (info->components == i) - { - SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool)); - info->done = TRUE; - } - else if (info->components > i) - { - apr_size_t len = info->component - info->path; - - if (last_path - && strcmp(last_path, "/") - && (strncmp(last_path, info->path, len) - || strlen(last_path) != len)) - { - SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - APR_ARRAY_PUSH(paths, const char *) = info->path; - if (!last_path) - { - if (info->component > info->path) - last_path = apr_pstrndup(pool, info->path, len); - else - last_path = "/"; - } - - if (info->component > info->path) - { - --info->component; - while(info->component[0] != '/') - --info->component; - } - } - } - - if (last_path && j == ub->infos->nelts - 1) - SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path, - rev_0_path, iterpool)); - } + svn_pool_clear(iterpool); + SVN_ERR(delete_from_digest(ub->fs->path, children, path, rev_0_path, + iterpool)); } + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } Modified: subversion/branches/pin-externals/subversion/libsvn_repos/dump.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_repos/dump.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_repos/dump.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_repos/dump.c Thu Feb 12 16:14:28 2015 @@ -445,17 +445,24 @@ write_revision_headers(svn_stream_t *str return SVN_NO_ERROR; } -apr_array_header_t * +/* A header entry: the element type of the apr_array_header_t which is + * the real type of svn_repos__dumpfile_headers_t. + */ +typedef struct svn_repos__dumpfile_header_entry_t { + const char *key, *val; +} svn_repos__dumpfile_header_entry_t; + +svn_repos__dumpfile_headers_t * svn_repos__dumpfile_headers_create(apr_pool_t *pool) { - apr_array_header_t *headers + svn_repos__dumpfile_headers_t *headers = apr_array_make(pool, 5, sizeof(svn_repos__dumpfile_header_entry_t)); return headers; } void -svn_repos__dumpfile_header_push(apr_array_header_t *headers, +svn_repos__dumpfile_header_push(svn_repos__dumpfile_headers_t *headers, const char *key, const char *val) { @@ -467,7 +474,7 @@ svn_repos__dumpfile_header_push(apr_arra } void -svn_repos__dumpfile_header_pushf(apr_array_header_t *headers, +svn_repos__dumpfile_header_pushf(svn_repos__dumpfile_headers_t *headers, const char *key, const char *val_fmt, ...) @@ -484,8 +491,7 @@ svn_repos__dumpfile_header_pushf(apr_arr svn_error_t * svn_repos__dump_headers(svn_stream_t *stream, - apr_array_header_t *headers, - svn_boolean_t terminate, + svn_repos__dumpfile_headers_t *headers, apr_pool_t *scratch_pool) { int i; @@ -500,8 +506,7 @@ svn_repos__dump_headers(svn_stream_t *st } /* End of headers */ - if (terminate) - SVN_ERR(svn_stream_puts(stream, "\n")); + SVN_ERR(svn_stream_puts(stream, "\n")); return SVN_NO_ERROR; } @@ -565,7 +570,7 @@ svn_repos__dump_revision_record(svn_stre svn_error_t * svn_repos__dump_node_record(svn_stream_t *dump_stream, - apr_array_header_t *headers, + svn_repos__dumpfile_headers_t *headers, svn_stringbuf_t *props_str, svn_boolean_t has_text, svn_filesize_t text_content_length, @@ -597,7 +602,7 @@ svn_repos__dump_node_record(svn_stream_t } /* write the headers */ - SVN_ERR(svn_repos__dump_headers(dump_stream, headers, TRUE, scratch_pool)); + SVN_ERR(svn_repos__dump_headers(dump_stream, headers, scratch_pool)); /* write the props */ if (props_str) @@ -1048,7 +1053,8 @@ dump_node_delete(svn_stream_t *stream, const char *node_relpath, apr_pool_t *pool) { - apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool); + svn_repos__dumpfile_headers_t *headers + = svn_repos__dumpfile_headers_create(pool); /* Node-path: ... */ svn_repos__dumpfile_header_push( @@ -1058,7 +1064,7 @@ dump_node_delete(svn_stream_t *stream, svn_repos__dumpfile_header_push( headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); - SVN_ERR(svn_repos__dump_headers(stream, headers, TRUE, pool)); + SVN_ERR(svn_repos__dump_headers(stream, headers, pool)); return SVN_NO_ERROR; } @@ -1091,7 +1097,8 @@ dump_node(struct edit_baton *eb, svn_revnum_t compare_rev = eb->current_rev - 1; svn_fs_root_t *compare_root = NULL; apr_file_t *delta_file = NULL; - apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool); + svn_repos__dumpfile_headers_t *headers + = svn_repos__dumpfile_headers_create(pool); svn_filesize_t textlen; /* Maybe validate the path. */ @@ -1324,7 +1331,7 @@ dump_node(struct edit_baton *eb, then our dumpstream format demands that at a *minimum*, we see a lone "PROPS-END" as a divider between text and props content within the content-block. */ - SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool)); + SVN_ERR(svn_repos__dump_headers(eb->stream, headers, pool)); len = 1; return svn_stream_write(eb->stream, "\n", &len); /* ### needed? */ } Modified: subversion/branches/pin-externals/subversion/libsvn_repos/repos.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_repos/repos.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_repos/repos.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_repos/repos.c Thu Feb 12 16:14:28 2015 @@ -291,10 +291,76 @@ create_locks(svn_repos_t *repos, apr_poo "# For similar reasons, you should also add a trailing @ to URLs which" NL \ "# are passed to SVN commands accepting URLs with peg revisions." NL +/* Return template text for a hook script named SCRIPT_NAME. Include + * DESCRIPTION and SCRIPT in the template text. + */ +static const char * +hook_template_text(const char *script_name, + const char *description, + const char *script, + apr_pool_t *result_pool) +{ + return apr_pstrcat(result_pool, +"#!/bin/sh" NL +"" NL, + description, +"#" NL +"# The default working directory for the invocation is undefined, so" NL +"# the program should set one explicitly if it cares." NL +"#" NL +"# On a Unix system, the normal procedure is to have '", script_name, "'" NL +"# invoke other programs to do the real work, though it may do the" NL +"# work itself too." NL +"#" NL +"# Note that '", script_name, "' must be executable by the user(s) who will" NL +"# invoke it (typically the user httpd runs as), and that user must" NL +"# have filesystem-level permission to access the repository." NL +"#" NL +"# On a Windows system, you should name the hook program" NL +"# '", script_name, ".bat' or '", script_name, ".exe'," NL +"# but the basic idea is the same." NL +"#" NL +HOOKS_ENVIRONMENT_TEXT +"#" NL +HOOKS_QUOTE_ARGUMENTS_TEXT +"#" NL +"# Here is an example hook script, for a Unix /bin/sh interpreter." NL +PREWRITTEN_HOOKS_TEXT +"" NL +"" NL, + script, + SVN_VA_NULL); +} + +/* Write a template file for a hook script named SCRIPT_NAME (appending + * '.tmpl' to that name) in REPOS. Include DESCRIPTION and SCRIPT in the + * template text. + */ +static svn_error_t * +write_hook_template_file(svn_repos_t *repos, const char *script_name, + const char *description, + const char *script, + apr_pool_t *pool) +{ + const char *template_path + = svn_dirent_join(repos->hook_path, + apr_psprintf(pool, "%s%s", + script_name, SVN_REPOS__HOOK_DESC_EXT), + pool); + const char *contents + = hook_template_text(script_name, description, script, pool); + + SVN_ERR(svn_io_file_create(template_path, contents, pool)); + SVN_ERR(svn_io_set_file_executable(template_path, TRUE, FALSE, pool)); + return SVN_NO_ERROR; +} + +/* Write the hook template files in REPOS. + */ static svn_error_t * create_hooks(svn_repos_t *repos, apr_pool_t *pool) { - const char *this_path, *contents; + const char *description, *script; /* Create the hook directory. */ SVN_ERR_W(create_repos_dir(repos->hook_path, pool), @@ -303,16 +369,9 @@ create_hooks(svn_repos_t *repos, apr_poo /*** Write a default template for each standard hook file. */ /* Start-commit hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_start_commit_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_START_COMMIT - contents = -"#!/bin/sh" NL -"" NL + description = "# START-COMMIT HOOK" NL "#" NL "# The start-commit hook is invoked immediately after a Subversion txn is" NL @@ -343,33 +402,10 @@ create_hooks(svn_repos_t *repos, apr_poo "# make security assumptions based on the capabilities list, nor should" NL "# you assume that clients reliably report every capability they have." NL "#" NL -"# The working directory for this hook program's invocation is undefined," NL -"# so the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the commit continues; but" NL "# if it exits with failure (non-zero), the commit is stopped before" NL -"# a Subversion txn is created, and STDERR is returned to the client." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# a Subversion txn is created, and STDERR is returned to the client." NL; + script = "REPOS=\"$1\"" NL "USER=\"$2\"" NL "" NL @@ -379,25 +415,17 @@ PREWRITTEN_HOOKS_TEXT "# All checks passed, so allow the commit." NL "exit 0" NL; -#undef SCRIPT_NAME + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating start-commit hook")); - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating start-commit hook")); +#undef SCRIPT_NAME - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end start-commit hook */ /* Pre-commit hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_commit_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_COMMIT - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-COMMIT HOOK" NL "#" NL "# The pre-commit hook is invoked before a Subversion txn is" NL @@ -419,18 +447,11 @@ PREWRITTEN_HOOKS_TEXT "# by the separator character '|', followed by the lock token string," NL "# followed by a newline." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the txn is committed; but" NL "# if it exits with failure (non-zero), the txn is aborted, no commit" NL "# takes place, and STDERR is returned to the client. The hook" NL "# program can use the 'svnlook' utility to help it examine the txn." NL "#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL "# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT ***" NL "# *** FOR REVISION PROPERTIES (like svn:log or svn:author). ***" NL "#" NL @@ -439,24 +460,8 @@ PREWRITTEN_HOOKS_TEXT "# hooks should not modify the versioned data in txns, or else come" NL "# up with a mechanism to make it safe to do so (by informing the" NL "# committing client of the changes). However, right now neither" NL -"# mechanism is implemented, so hook writers just have to be careful." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# mechanism is implemented, so hook writers just have to be careful." NL; + script = "REPOS=\"$1\"" NL "TXN=\"$2\"" NL "" NL @@ -473,26 +478,17 @@ PREWRITTEN_HOOKS_TEXT "# All checks passed, so allow the commit." NL "exit 0" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating pre-commit hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-commit hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-commit hook */ +#undef SCRIPT_NAME /* Pre-revprop-change hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_revprop_change_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_REVPROP_CHANGE - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-REVPROP-CHANGE HOOK" NL "#" NL "# The pre-revprop-change hook is invoked before a revision property" NL @@ -520,28 +516,8 @@ PREWRITTEN_HOOKS_TEXT "# will behave as if the hook were present, but failed. The reason" NL "# for this is that revision properties are UNVERSIONED, meaning that" NL "# a successful propchange is destructive; the old value is gone" NL -"# forever. We recommend the hook back up the old value somewhere." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# forever. We recommend the hook back up the old value somewhere." NL; + script = "REPOS=\"$1\"" NL "REV=\"$2\"" NL "USER=\"$3\"" NL @@ -553,26 +529,17 @@ PREWRITTEN_HOOKS_TEXT "echo \"Changing revision properties other than svn:log is prohibited\" >&2" NL "exit 1" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating pre-revprop-change hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-revprop-change hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-revprop-change hook */ +#undef SCRIPT_NAME /* Pre-lock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_lock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_LOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-LOCK HOOK" NL "#" NL "# The pre-lock hook is invoked before an exclusive lock is" NL @@ -591,29 +558,10 @@ PREWRITTEN_HOOKS_TEXT "# this feature, you must guarantee the tokens generated are unique across" NL "# the repository each time." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the lock is created; but" NL "# if it exits with failure (non-zero), the lock action is aborted" NL -"# and STDERR is returned to the client." NL -"" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# and STDERR is returned to the client." NL; + script = "REPOS=\"$1\"" NL "PATH=\"$2\"" NL "USER=\"$3\"" NL @@ -647,26 +595,17 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "echo \"Error: $PATH already locked by ${LOCK_OWNER}.\" 1>&2" NL "exit 1" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating pre-lock hook"); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-lock hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-lock hook */ +#undef SCRIPT_NAME /* Pre-unlock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_unlock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_UNLOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-UNLOCK HOOK" NL "#" NL "# The pre-unlock hook is invoked before an exclusive lock is" NL @@ -680,29 +619,10 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "# [4] TOKEN (the lock token to be destroyed)" NL "# [5] BREAK-UNLOCK (1 if the user is breaking the lock, else 0)" NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the lock is destroyed; but" NL "# if it exits with failure (non-zero), the unlock action is aborted" NL -"# and STDERR is returned to the client." NL -"" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# and STDERR is returned to the client." NL; + script = "REPOS=\"$1\"" NL "PATH=\"$2\"" NL "USER=\"$3\"" NL @@ -733,27 +653,17 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "echo \"Error: $PATH locked by ${LOCK_OWNER}.\" 1>&2" NL "exit 1" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating pre-unlock hook"); - - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-unlock hook */ + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-unlock hook")); +#undef SCRIPT_NAME /* Post-commit hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_commit_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_COMMIT - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-COMMIT HOOK" NL "#" NL "# The post-commit hook is invoked after a commit. Subversion runs" NL @@ -765,60 +675,28 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "# [2] REV (the number of the revision just committed)" NL "# [3] TXN-NAME (the name of the transaction that has become REV)" NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# Because the commit has already completed and cannot be undone," NL "# the exit code of the hook program is ignored. The hook program" NL "# can use the 'svnlook' utility to help it examine the" NL -"# newly-committed tree." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# newly-committed tree." NL; + script = "REPOS=\"$1\"" NL "REV=\"$2\"" NL "TXN_NAME=\"$3\"" NL NL "mailer.py commit \"$REPOS\" \"$REV\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating post-commit hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-commit hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-commit hook */ +#undef SCRIPT_NAME /* Post-lock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_lock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_LOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-LOCK HOOK" NL "#" NL "# The post-lock hook is run after a path is locked. Subversion runs" NL @@ -831,57 +709,29 @@ PREWRITTEN_HOOKS_TEXT "#" NL "# The paths that were just locked are passed to the hook via STDIN." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# Because the locks have already been created and cannot be undone," NL "# the exit code of the hook program is ignored. The hook program" NL "# can use the 'svnlook' utility to examine the paths in the repository" NL "# but since the hook is invoked asyncronously the newly-created locks" NL -"# may no longer be present." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# may no longer be present." NL; + script = "REPOS=\"$1\"" NL "USER=\"$2\"" NL "" NL "# Send email to interested parties, let them know a lock was created:" NL "mailer.py lock \"$REPOS\" \"$USER\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating post-lock hook"); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-lock hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-lock hook */ +#undef SCRIPT_NAME /* Post-unlock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_unlock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_UNLOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-UNLOCK HOOK" NL "#" NL "# The post-unlock hook runs after a path is unlocked. Subversion runs" NL @@ -894,54 +744,26 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "#" NL "# The paths that were just unlocked are passed to the hook via STDIN." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# Because the lock has already been destroyed and cannot be undone," NL -"# the exit code of the hook program is ignored." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# the exit code of the hook program is ignored." NL; + script = "REPOS=\"$1\"" NL "USER=\"$2\"" NL "" NL "# Send email to interested parties, let them know a lock was removed:" NL "mailer.py unlock \"$REPOS\" \"$USER\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating post-unlock hook"); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-unlock hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-unlock hook */ +#undef SCRIPT_NAME /* Post-revprop-change hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_revprop_change_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_REVPROP_CHANGE - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-REVPROP-CHANGE HOOK" NL "#" NL "# The post-revprop-change hook is invoked after a revision property" NL @@ -961,28 +783,8 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "# Because the propchange has already completed and cannot be undone," NL "# the exit code of the hook program is ignored. The hook program" NL "# can use the 'svnlook' utility to help it examine the" NL -"# new property value." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# new property value." NL; + script = "REPOS=\"$1\"" NL "REV=\"$2\"" NL "USER=\"$3\"" NL @@ -992,13 +794,11 @@ PREWRITTEN_HOOKS_TEXT "mailer.py propchange2 \"$REPOS\" \"$REV\" \"$USER\" \"$PROPNAME\" " "\"$ACTION\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating post-revprop-change hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-revprop-change hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-revprop-change hook */ +#undef SCRIPT_NAME return SVN_NO_ERROR; } Modified: subversion/branches/pin-externals/subversion/libsvn_subr/dso.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_subr/dso.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_subr/dso.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_subr/dso.c Thu Feb 12 16:14:28 2015 @@ -28,6 +28,7 @@ #include "svn_private_config.h" #include "private/svn_mutex.h" +#include "private/svn_atomic.h" /* A mutex to protect our global pool and cache. */ static svn_mutex__t *dso_mutex = NULL; @@ -41,6 +42,8 @@ static apr_hash_t *dso_cache; /* Just an arbitrary location in memory... */ static int not_there_sentinel; +static volatile svn_atomic_t atomic_init_status = 0; + /* A specific value we store in the dso_cache to indicate that the library wasn't found. This keeps us from allocating extra memory from dso_pool when trying to find libraries we already know aren't @@ -61,6 +64,14 @@ svn_dso_initialize2(void) return SVN_NO_ERROR; } +static svn_error_t * +atomic_init_func(void *baton, + apr_pool_t *pool) +{ + SVN_ERR(svn_dso_initialize2()); + return SVN_NO_ERROR; +} + #if APR_HAS_DSO static svn_error_t * svn_dso_load_internal(apr_dso_handle_t **dso, const char *fname) @@ -107,8 +118,8 @@ svn_dso_load_internal(apr_dso_handle_t * svn_error_t * svn_dso_load(apr_dso_handle_t **dso, const char *fname) { - if (! dso_pool) - SVN_ERR(svn_dso_initialize2()); + SVN_ERR(svn_atomic__init_once(&atomic_init_status, atomic_init_func, + NULL, NULL)); SVN_MUTEX__WITH_LOCK(dso_mutex, svn_dso_load_internal(dso, fname)); Modified: subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c Thu Feb 12 16:14:28 2015 @@ -1817,7 +1817,9 @@ read_tree_conflict_desc(svn_wc_conflict_ operation == svn_wc_operation_switch) { /* For updates, the left version corresponds to the pre-update state. */ - if (left_version) + if (left_version + && reason != svn_wc_conflict_reason_added + && reason != svn_wc_conflict_reason_replaced) local_kind = left_version->node_kind; else { @@ -2126,8 +2128,8 @@ read_prop_conflict_descs(apr_array_heade return SVN_NO_ERROR; } - SVN_ERR(svn_wc__db_base_get_props(&base_props, db, local_abspath, - result_pool, scratch_pool)); + SVN_ERR(svn_wc__db_read_pristine_props(&base_props, db, local_abspath, + result_pool, scratch_pool)); iterpool = svn_pool_create(scratch_pool); for (hi = apr_hash_first(scratch_pool, conflicted_props); hi; @@ -2609,9 +2611,10 @@ resolve_tree_conflict_on_node(svn_boolea if (conflict_choice == svn_wc_conflict_choose_mine_conflict) { err = svn_wc__db_update_moved_away_conflict_victim( - db, local_abspath, - notify_func, notify_baton, + db, local_abspath, src_op_root_abspath, + operation, action, reason, cancel_func, cancel_baton, + notify_func, notify_baton, scratch_pool); if (err) Modified: subversion/branches/pin-externals/subversion/libsvn_wc/token-map.h URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/token-map.h?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_wc/token-map.h (original) +++ subversion/branches/pin-externals/subversion/libsvn_wc/token-map.h Thu Feb 12 16:14:28 2015 @@ -33,6 +33,7 @@ extern "C" { #endif +/* The kind values used on NODES */ static const svn_token_map_t kind_map[] = { { "file", svn_node_file }, /* MAP_FILE */ { "dir", svn_node_dir }, /* MAP_DIR */ @@ -41,6 +42,16 @@ static const svn_token_map_t kind_map[] { NULL } }; +/* Like kind_map, but also supports 'none' */ +static const svn_token_map_t kind_map_none[] = { + { "none", svn_node_none }, + { "file", svn_node_file }, + { "dir", svn_node_dir }, + { "symlink", svn_node_symlink }, + { "unknown", svn_node_unknown }, + { NULL } +}; + /* Note: we only decode presence values from the database. These are a subset of all the status values. */ static const svn_token_map_t presence_map[] = { Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql?rev=1659301&r1=1659300&r2=1659301&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql (original) +++ subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql Thu Feb 12 16:14:28 2015 @@ -1388,8 +1388,9 @@ BEGIN WHERE n.wc_id = OLD.wc_id AND n.local_relpath = OLD.local_relpath) THEN 1 - ELSE NULL - END; + END notify + WHERE OLD.conflict_data IS NOT NULL + OR notify IS NOT NULL; END; DROP TRIGGER IF EXISTS trigger_revert_list_actual_update; CREATE TEMPORARY TRIGGER trigger_revert_list_actual_update @@ -1405,8 +1406,9 @@ BEGIN WHERE n.wc_id = OLD.wc_id AND n.local_relpath = OLD.local_relpath) THEN 1 - ELSE NULL - END; + END notify + WHERE OLD.conflict_data IS NOT NULL + OR notify IS NOT NULL; END -- STMT_DROP_REVERT_LIST_TRIGGERS @@ -1432,12 +1434,15 @@ ORDER BY local_relpath DELETE FROM revert_list WHERE local_relpath = ?1 -- STMT_SELECT_REVERT_LIST_RECURSIVE -SELECT DISTINCT local_relpath -FROM revert_list -WHERE (local_relpath = ?1 - OR IS_STRICT_DESCENDANT_OF(local_relpath, ?1)) - AND (notify OR actual = 0) -ORDER BY local_relpath +SELECT p.local_relpath, n.kind, a.notify, a.kind +FROM (SELECT DISTINCT local_relpath + FROM revert_list + WHERE (local_relpath = ?1 + OR IS_STRICT_DESCENDANT_OF(local_relpath, ?1))) p + +LEFT JOIN revert_list n ON n.local_relpath=p.local_relpath AND n.actual=0 +LEFT JOIN revert_list a ON a.local_relpath=p.local_relpath AND a.actual=1 +ORDER BY p.local_relpath -- STMT_DELETE_REVERT_LIST_RECURSIVE DELETE FROM revert_list @@ -1486,7 +1491,7 @@ CREATE TEMPORARY TABLE update_move_list ### working copies. queries, etc will need to be adjusted. */ local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE, action INTEGER NOT NULL, - kind INTEGER NOT NULL, + kind TEXT NOT NULL, content_state INTEGER NOT NULL, prop_state INTEGER NOT NULL ) @@ -1504,6 +1509,11 @@ ORDER BY local_relpath -- STMT_FINALIZE_UPDATE_MOVE DROP TABLE IF EXISTS update_move_list +-- STMT_MOVE_NOTIFY_TO_REVERT +INSERT INTO revert_list (local_relpath, notify, kind, actual) + SELECT local_relpath, 2, kind, 1 FROM update_move_list; +DROP TABLE update_move_list + /* ------------------------------------------------------------------------- */ /* Queries for revision status. */