You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/11/17 11:02:41 UTC
svn commit: r1542685 [3/5] - in
/subversion/branches/invoke-diff-cmd-feature: ./ build/ build/ac-macros/
build/generator/ build/generator/templates/ build/win32/
contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/
subversion/bindin...
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/config_pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/config_pool.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/config_pool.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/config_pool.c Sun Nov 17 10:02:39 2013
@@ -24,8 +24,6 @@
-#include <assert.h>
-
#include "svn_checksum.h"
#include "svn_config.h"
#include "svn_error.h"
@@ -34,22 +32,21 @@
#include "svn_pools.h"
#include "svn_repos.h"
-#include "private/svn_atomic.h"
+#include "private/svn_dep_compat.h"
#include "private/svn_mutex.h"
#include "private/svn_subr_private.h"
#include "private/svn_repos_private.h"
+#include "private/svn_object_pool.h"
#include "svn_private_config.h"
-/* A reference counting wrapper around a parsed svn_config_t* instance. All
- * data in CFG is expanded (to make it thread-safe) and considered read-only.
+/* Our wrapper structure for parsed svn_config_t* instances. All data in
+ * CS_CFG and CI_CFG is expanded (to make it thread-safe) and considered
+ * read-only.
*/
-typedef struct config_ref_t
+typedef struct config_object_t
{
- /* reference to the parent container */
- svn_repos__config_pool_t *config_pool;
-
/* UUID of the configuration contents.
* This is a SHA1 checksum of the parsed textual representation of CFG. */
svn_checksum_t *key;
@@ -62,14 +59,7 @@ typedef struct config_ref_t
/* Case-insensitive config. May be NULL */
svn_config_t *ci_cfg;
-
- /* private pool. This instance and its other members got allocated in it.
- * Will be destroyed when this instance is cleaned up. */
- apr_pool_t *pool;
-
- /* Number of references to this data struct */
- volatile svn_atomic_t ref_count;
-} config_ref_t;
+} config_object_t;
/* Data structure used to short-circuit the repository access for configs
@@ -78,8 +68,8 @@ typedef struct config_ref_t
* the repository.
*
* As this is only an optimization and may create many entries in
- * svn_config_pool__t's IN_REPO_HASH_POOL index, we clean them up once in
- * a while.
+ * svn_repos__config_pool_t's IN_REPO_HASH_POOL index, we clean them up
+ * once in a while.
*/
typedef struct in_repo_config_t
{
@@ -97,10 +87,8 @@ typedef struct in_repo_config_t
} in_repo_config_t;
-/* Core data structure. All access to it must be serialized using MUTEX.
- *
- * CONFIGS maps a SHA1 checksum of the config text to the config_ref_t with
- * the parsed configuration in it.
+/* Core data structure extending the encapsulated OBJECT_POOL. All access
+ * to it must be serialized using the OBJECT_POOL->MUTEX.
*
* To speed up URL@HEAD lookups, we maintain IN_REPO_CONFIGS as a secondary
* hash index. It maps URLs as provided by the caller onto in_repo_config_t
@@ -109,263 +97,97 @@ typedef struct in_repo_config_t
* the respective repository.
*
* Unused configurations that are kept in the IN_REPO_CONFIGS hash and may
- * be cleaned up when the hash is about to grow. We use various pools to
- * ensure that we can release unused memory for each data structure:
- *
- * - every config_ref_t uses its own pool
- * (gets destroyed when config is removed from cache)
- * - CONFIGS_HASH_POOL is used for configs only
- * - IN_REPO_HASH_POOL is used for IN_REPO_CONFIGS and the in_repo_config_t
- * structure in it
- *
- * References handed out to callers must remain valid until released. In
- * that case, cleaning up the config pool will only set READY_FOR_CLEANUP
- * and the last reference being returned will actually trigger the
- * destruction.
+ * be cleaned up when the hash is about to grow.
*/
struct svn_repos__config_pool_t
{
- /* serialization object for all non-atomic data in this struct */
- svn_mutex__t *mutex;
-
- /* set to TRUE when pool passed to svn_config_pool__create() gets cleaned
- * up. When set, the last config reference released must also destroy
- * this config pool object. */
- volatile svn_atomic_t ready_for_cleanup;
-
- /* SHA1 -> config_ref_t* mapping */
- apr_hash_t *configs;
-
- /* number of entries in CONFIGS with a reference count > 0 */
- volatile svn_atomic_t used_config_count;
+ svn_object_pool__t *object_pool;
/* URL -> in_repo_config_t* mapping.
* This is only a partial index and will get cleared regularly. */
apr_hash_t *in_repo_configs;
- /* the root pool owning this structure */
- apr_pool_t *root_pool;
-
- /* allocate the CONFIGS index here */
- apr_pool_t *configs_hash_pool;
-
/* allocate the IN_REPO_CONFIGS index and in_repo_config_t here */
apr_pool_t *in_repo_hash_pool;
};
-/* Destructor function for the whole config pool.
- */
-static apr_status_t
-destroy_config_pool(svn_repos__config_pool_t *config_pool)
-{
- svn_mutex__lock(config_pool->mutex);
-
- /* there should be no outstanding references to any config in this pool */
- assert(svn_atomic_read(&config_pool->used_config_count) == 0);
-
- /* make future attempts to access this pool cause definitive segfaults */
- config_pool->configs = NULL;
- config_pool->in_repo_configs = NULL;
-
- /* This is the actual point of destruction. */
- /* Destroying the pool will also release the lock. */
- svn_pool_destroy(config_pool->root_pool);
-
- return APR_SUCCESS;
-}
-
-/* Pool cleanup function for the whole config pool. Actual destruction will
- * be deferred until no configurations are left in use.
- */
-static apr_status_t
-config_pool_cleanup(void *baton)
-{
- svn_repos__config_pool_t *config_pool = baton;
-
- /* from now on, anyone is allowed to destroy the config_pool */
- svn_atomic_set(&config_pool->ready_for_cleanup, TRUE);
-
- /* are there no more external references and can we grab the cleanup flag? */
- if ( svn_atomic_read(&config_pool->used_config_count) == 0
- && svn_atomic_cas(&config_pool->ready_for_cleanup, FALSE, TRUE) == TRUE)
- {
- /* Attempts to get a configuration from a pool whose cleanup has
- * already started is illegal.
- * So, used_config_count must not increase again.
- */
- destroy_config_pool(config_pool);
- }
-
- return APR_SUCCESS;
-}
-
-/* Cleanup function called when a config_ref_t gets released.
- */
-static apr_status_t
-config_ref_cleanup(void *baton)
-{
- config_ref_t *config = baton;
- svn_repos__config_pool_t *config_pool = config->config_pool;
-
- /* Maintain reference counters and handle object cleanup */
- if ( svn_atomic_dec(&config->ref_count) == 0
- && svn_atomic_dec(&config_pool->used_config_count) == 0
- && svn_atomic_cas(&config_pool->ready_for_cleanup, FALSE, TRUE) == TRUE)
- {
- /* There cannot be any future references to a config in this pool.
- * So, we are the last one and need to finally clean it up.
- */
- destroy_config_pool(config_pool);
- }
-
- return APR_SUCCESS;
-}
-
/* Return an automatic reference to the CFG member in CONFIG that will be
- * released when POOL gets cleaned up. CASE_SENSITIVE controls option and
- * section name matching.
+ * released when POOL gets cleaned up. The case sensitivity flag in *BATON
+ * selects the desired option and section name matching mode.
*/
-static svn_config_t *
-return_config_ref(config_ref_t *config,
- svn_boolean_t case_sensitive,
- apr_pool_t *pool)
+static void *
+getter(void *object,
+ void *baton,
+ apr_pool_t *pool)
{
- if (svn_atomic_inc(&config->ref_count) == 0)
- svn_atomic_inc(&config->config_pool->used_config_count);
-
- apr_pool_cleanup_register(pool, config, config_ref_cleanup,
- apr_pool_cleanup_null);
- return svn_config__shallow_copy(case_sensitive ? config->cs_cfg
- : config->ci_cfg,
- pool);
-}
-
-/* Set *CFG to the configuration with a parsed textual matching CHECKSUM.
- * Set *CFG to NULL if no such config can be found in CONFIG_POOL.
- * CASE_SENSITIVE controls option and section name matching.
- *
- * RESULT_POOL determines the lifetime of the returned reference.
- *
- * Requires external serialization on CONFIG_POOL.
- */
-static svn_error_t *
-config_by_checksum(svn_config_t **cfg,
- svn_repos__config_pool_t *config_pool,
- svn_checksum_t *checksum,
- svn_boolean_t case_sensitive,
- apr_pool_t *result_pool)
-{
- config_ref_t *config_ref = apr_hash_get(config_pool->configs,
- checksum->digest,
- svn_checksum_size(checksum));
- *cfg = config_ref
- ? return_config_ref(config_ref, case_sensitive, result_pool)
- : NULL;
+ config_object_t *wrapper = object;
+ svn_boolean_t *case_sensitive = baton;
+ svn_config_t *config = *case_sensitive ? wrapper->cs_cfg : wrapper->ci_cfg;
- return SVN_NO_ERROR;
+ /* we need to duplicate the root structure as it contains temp. buffers */
+ return config ? svn_config__shallow_copy(config, pool) : NULL;
}
-/* Re-allocate CONFIGS in CONFIG_POOL and remove all unused configurations
- * to minimize memory consumption.
- *
- * Requires external serialization on CONFIG_POOL.
+/* Return a memory buffer structure allocated in POOL and containing the
+ * data from CHECKSUM.
*/
-static void
-remove_unused_configs(svn_repos__config_pool_t *config_pool)
+static svn_membuf_t *
+checksum_as_key(svn_checksum_t *checksum,
+ apr_pool_t *pool)
{
- apr_pool_t *new_pool = svn_pool_create(config_pool->root_pool);
- apr_hash_t *new_hash = svn_hash__make(new_pool);
+ svn_membuf_t *result = apr_pcalloc(pool, sizeof(*result));
+ apr_size_t size = svn_checksum_size(checksum);
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(config_pool->configs_hash_pool,
- config_pool->configs);
- hi != NULL;
- hi = apr_hash_next(hi))
- {
- config_ref_t *config_ref = svn__apr_hash_index_val(hi);
- if (config_ref->ref_count == 0)
- svn_pool_destroy(config_ref->pool);
- else
- apr_hash_set(new_hash, config_ref->key->digest,
- svn_checksum_size(config_ref->key), config_ref);
- }
+ svn_membuf__create(result, size, pool);
+ result->size = size; /* exact length is required! */
+ memcpy(result->data, checksum->digest, size);
- svn_pool_destroy(config_pool->configs_hash_pool);
- config_pool->configs = new_hash;
- config_pool->configs_hash_pool = new_pool;
+ return result;
}
-/* Cache config_ref* in CONFIG_POOL and return a reference to it in *CFG.
- * RESULT_POOL determines the lifetime of that reference.
- * CASE_SENSITIVE controls option and section name matching.
- *
- * Requires external serialization on CONFIG_POOL.
+/* Copy the configuration from the wrapper in SOURCE to the wrapper in
+ * *TARGET with the case sensitivity flag in *BATON selecting the config
+ * to copy. This is usually done to add the missing case-(in)-sensitive
+ * variant. Since we must hold all data in *TARGET from the same POOL,
+ * a deep copy is required.
*/
static svn_error_t *
-config_add(svn_config_t **cfg,
- svn_repos__config_pool_t *config_pool,
- config_ref_t *config_ref,
- svn_boolean_t case_sensitive,
- apr_pool_t *result_pool)
+setter(void **target,
+ void *source,
+ void *baton,
+ apr_pool_t *pool)
{
- config_ref_t *config = apr_hash_get(config_ref->config_pool->configs,
- config_ref->key->digest,
- svn_checksum_size(config_ref->key));
- if (config)
- {
- /* entry already exists (e.g. race condition) */
-
- /* Maybe, we created a variant with different case sensitivity? */
- if (case_sensitive && config->cs_cfg == NULL)
- {
- SVN_ERR(svn_config_dup(&config->cs_cfg, config_ref->cs_cfg,
- config->pool));
- svn_config__set_read_only(config->cs_cfg, config_ref->pool);
- }
- else if (!case_sensitive && config->ci_cfg == NULL)
- {
- SVN_ERR(svn_config_dup(&config->ci_cfg, config_ref->ci_cfg,
- config->pool));
- svn_config__set_read_only(config->ci_cfg, config_ref->pool);
- }
+ svn_boolean_t *case_sensitive = baton;
+ config_object_t *target_cfg = *(config_object_t **)target;
+ config_object_t *source_cfg = source;
- /* Destroy the new one and return a reference to the existing one
- * because the existing one may already have references on it.
- */
- svn_pool_destroy(config_ref->pool);
- config_ref = config;
+ /* Maybe, we created a variant with different case sensitivity? */
+ if (*case_sensitive && target_cfg->cs_cfg == NULL)
+ {
+ SVN_ERR(svn_config_dup(&target_cfg->cs_cfg, source_cfg->cs_cfg, pool));
+ svn_config__set_read_only(target_cfg->cs_cfg, pool);
}
- else
+ else if (!*case_sensitive && target_cfg->ci_cfg == NULL)
{
- /* Release unused configurations if there are relatively frequent. */
- if ( config_pool->used_config_count * 2 + 4
- < apr_hash_count(config_pool->configs))
- {
- remove_unused_configs(config_pool);
- }
-
- /* add new index entry */
- apr_hash_set(config_ref->config_pool->configs,
- config_ref->key->digest,
- svn_checksum_size(config_ref->key),
- config_ref);
+ SVN_ERR(svn_config_dup(&target_cfg->ci_cfg, source_cfg->ci_cfg, pool));
+ svn_config__set_read_only(target_cfg->ci_cfg, pool);
}
- *cfg = return_config_ref(config_ref, case_sensitive, result_pool);
-
return SVN_NO_ERROR;
}
-/* Set *CFG to the configuration passed in as text in CONTENTS. If no such
- * configuration exists in CONFIG_POOL, yet, parse CONTENTS and cache the
- * result. CASE_SENSITIVE controls option and section name matching.
- *
+/* Set *CFG to the configuration passed in as text in CONTENTS and *KEY to
+ * the corresponding object pool key. If no such configuration exists in
+ * CONFIG_POOL, yet, parse CONTENTS and cache the result. CASE_SENSITIVE
+ * controls option and section name matching.
+ *
* RESULT_POOL determines the lifetime of the returned reference and
* SCRATCH_POOL is being used for temporary allocations.
*/
static svn_error_t *
auto_parse(svn_config_t **cfg,
+ svn_membuf_t **key,
svn_repos__config_pool_t *config_pool,
svn_stringbuf_t *contents,
svn_boolean_t case_sensitive,
@@ -373,7 +195,7 @@ auto_parse(svn_config_t **cfg,
apr_pool_t *scratch_pool)
{
svn_checksum_t *checksum;
- config_ref_t *config_ref;
+ config_object_t *config_object;
apr_pool_t *cfg_pool;
/* calculate SHA1 over the whole file contents */
@@ -383,50 +205,36 @@ auto_parse(svn_config_t **cfg,
&checksum, NULL, svn_checksum_sha1, TRUE, scratch_pool)));
/* return reference to suitable config object if that already exists */
- *cfg = NULL;
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_by_checksum(cfg, config_pool, checksum,
- case_sensitive, result_pool));
-
+ *key = checksum_as_key(checksum, scratch_pool);
+ SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool,
+ *key, &case_sensitive, result_pool));
if (*cfg)
return SVN_NO_ERROR;
/* create a pool for the new config object and parse the data into it */
+ cfg_pool = svn_pool_create(svn_object_pool__pool(config_pool->object_pool));
- /* the following is thread-safe because the allocator is thread-safe */
- cfg_pool = svn_pool_create(config_pool->root_pool);
+ config_object = apr_pcalloc(cfg_pool, sizeof(*config_object));
- config_ref = apr_pcalloc(cfg_pool, sizeof(*config_ref));
- config_ref->config_pool = config_pool;
- config_ref->key = svn_checksum_dup(checksum, cfg_pool);
- config_ref->pool = cfg_pool;
- config_ref->ref_count = 0;
-
- SVN_ERR(svn_config_parse(case_sensitive ? &config_ref->cs_cfg
- : &config_ref->ci_cfg,
+ SVN_ERR(svn_config_parse(case_sensitive ? &config_object->cs_cfg
+ : &config_object->ci_cfg,
svn_stream_from_stringbuf(contents, scratch_pool),
case_sensitive, case_sensitive, cfg_pool));
/* switch config data to r/o mode to guarantee thread-safe access */
- svn_config__set_read_only(case_sensitive ? config_ref->cs_cfg
- : config_ref->ci_cfg,
+ svn_config__set_read_only(case_sensitive ? config_object->cs_cfg
+ : config_object->ci_cfg,
cfg_pool);
/* add config in pool, handle loads races and return the right config */
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_add(cfg, config_pool, config_ref,
- case_sensitive, result_pool));
+ SVN_ERR(svn_object_pool__insert((void **)cfg, config_pool->object_pool,
+ *key, config_object, &case_sensitive,
+ cfg_pool, result_pool));
return SVN_NO_ERROR;
}
-/* Set *CFG to the configuration stored in URL@HEAD and cache it in
- * CONFIG_POOL.
- *
- * RESULT_POOL determines the lifetime of the returned reference and
- * SCRATCH_POOL is being used for temporary allocations.
- *
- * Requires external serialization on CONFIG_POOL.
+/* Store a URL@REVISION to CHECKSUM, REPOS_ROOT in CONFIG_POOL.
*/
static svn_error_t *
add_checksum(svn_repos__config_pool_t *config_pool,
@@ -454,7 +262,7 @@ add_checksum(svn_repos__config_pool_t *c
{
/* insert a new entry.
* Limit memory consumption by cyclically clearing pool and hash. */
- if (2 * apr_hash_count(config_pool->configs)
+ if (2 * svn_object_pool__count(config_pool->object_pool)
< apr_hash_count(config_pool->in_repo_configs))
{
svn_pool_clear(pool);
@@ -476,7 +284,7 @@ add_checksum(svn_repos__config_pool_t *c
}
/* Set *CFG to the configuration stored in URL@HEAD and cache it in
- * CONFIG_POOL. ### Always returns a NULL CFG. CASE_SENSITIVE controls
+ * CONFIG_POOL. CASE_SENSITIVE controls
* option and section name matching. If PREFERRED_REPOS is given,
* use that if it also matches URL.
*
@@ -485,6 +293,7 @@ add_checksum(svn_repos__config_pool_t *c
*/
static svn_error_t *
find_repos_config(svn_config_t **cfg,
+ svn_membuf_t **key,
svn_repos__config_pool_t *config_pool,
const char *url,
svn_boolean_t case_sensitive,
@@ -544,9 +353,11 @@ find_repos_config(svn_config_t **cfg,
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root, fs_path,
FALSE, scratch_pool));
if (checksum)
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_by_checksum(cfg, config_pool, checksum,
- case_sensitive, result_pool));
+ {
+ *key = checksum_as_key(checksum, scratch_pool);
+ SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool,
+ *key, &case_sensitive, result_pool));
+ }
/* not parsed, yet? */
if (!*cfg)
@@ -564,70 +375,57 @@ find_repos_config(svn_config_t **cfg,
(apr_size_t)length, scratch_pool));
/* handle it like ordinary file contents and cache it */
- SVN_ERR(auto_parse(cfg, config_pool, contents, case_sensitive,
+ SVN_ERR(auto_parse(cfg, key, config_pool, contents, case_sensitive,
result_pool, scratch_pool));
}
/* store the (path,rev) -> checksum mapping as well */
if (*cfg)
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
+ SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool),
add_checksum(config_pool, url, repos_root_dirent,
youngest_rev, checksum));
return SVN_NO_ERROR;
}
-/* Set *CFG to the configuration cached in CONFIG_POOL for URL. If no
- * suitable config has been cached or if it is potentially outdated, set
- * *CFG to NULL. CASE_SENSITIVE controls option and section name matching.
- *
- * RESULT_POOL determines the lifetime of the returned reference and
- * SCRATCH_POOL is being used for temporary allocations.
+/* Given the URL, search the CONFIG_POOL for an entry that maps it URL to
+ * a content checksum and is still up-to-date. If this could be found,
+ * return the object's *KEY. Use POOL for allocations.
*
* Requires external serialization on CONFIG_POOL.
+ *
+ * Note that this is only the URL(+rev) -> Checksum lookup and does not
+ * guarantee that there is actually a config object available for *KEY.
*/
static svn_error_t *
-config_by_url(svn_config_t **cfg,
- svn_repos__config_pool_t *config_pool,
- const char *url,
- svn_boolean_t case_sensitive,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+key_by_url(svn_membuf_t **key,
+ svn_repos__config_pool_t *config_pool,
+ const char *url,
+ apr_pool_t *pool)
{
svn_error_t *err;
- config_ref_t *config_ref = NULL;
svn_stringbuf_t *contents;
apr_int64_t current;
/* hash lookup url -> sha1 -> config */
in_repo_config_t *config = svn_hash_gets(config_pool->in_repo_configs, url);
- *cfg = NULL;
- if (config)
- config_ref = apr_hash_get(config_pool->configs,
- config->key->digest,
- svn_checksum_size(config->key));
- if (!config_ref)
- return SVN_NO_ERROR;
-
- /* available with the desired case sensitivity? */
- if (case_sensitive && config_ref->cs_cfg == NULL)
- return SVN_NO_ERROR;
- if (!case_sensitive && config_ref->ci_cfg == NULL)
+ *key = NULL;
+ if (!config)
return SVN_NO_ERROR;
- /* found *some* configuration.
+ /* found *some* reference to a configuration.
* Verify that it is still current. Will fail for BDB repos. */
err = svn_stringbuf_from_file2(&contents,
svn_dirent_join(config->repo_root,
- "db/current", scratch_pool),
- scratch_pool);
+ "db/current", pool),
+ pool);
if (!err)
err = svn_cstring_atoi64(¤t, contents->data);
if (err)
svn_error_clear(err);
else if (current == config->revision)
- *cfg = return_config_ref(config_ref, case_sensitive, result_pool);
+ *key = checksum_as_key(config->key, pool);
return SVN_NO_ERROR;
}
@@ -636,27 +434,25 @@ config_by_url(svn_config_t **cfg,
svn_error_t *
svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
+ svn_boolean_t thread_safe,
apr_pool_t *pool)
{
- /* our allocator must be thread-safe */
- apr_pool_t *root_pool
- = apr_allocator_owner_get(svn_pool_create_allocator(TRUE));
+ svn_repos__config_pool_t *result;
+ svn_object_pool__t *object_pool;
+ apr_pool_t *root_pool;
+
+ SVN_ERR(svn_object_pool__create(&object_pool, getter, setter,
+ 4, APR_UINT32_MAX, TRUE, thread_safe,
+ pool));
+ root_pool = svn_object_pool__pool(object_pool);
/* construct the config pool in our private ROOT_POOL to survive POOL
* cleanup and to prevent threading issues with the allocator */
- svn_repos__config_pool_t *result = apr_pcalloc(root_pool, sizeof(*result));
- SVN_ERR(svn_mutex__init(&result->mutex, TRUE, root_pool));
+ result = apr_pcalloc(root_pool, sizeof(*result));
- result->root_pool = root_pool;
- result->configs_hash_pool = svn_pool_create(root_pool);
+ result->object_pool = object_pool;
result->in_repo_hash_pool = svn_pool_create(root_pool);
- result->configs = svn_hash__make(result->configs_hash_pool);
result->in_repo_configs = svn_hash__make(result->in_repo_hash_pool);
- result->ready_for_cleanup = FALSE;
-
- /* make sure we clean up nicely */
- apr_pool_cleanup_register(pool, result, config_pool_cleanup,
- apr_pool_cleanup_null);
*config_pool = result;
return SVN_NO_ERROR;
@@ -664,6 +460,7 @@ svn_repos__config_pool_create(svn_repos_
svn_error_t *
svn_repos__config_pool_get(svn_config_t **cfg,
+ svn_membuf_t **key,
svn_repos__config_pool_t *config_pool,
const char *path,
svn_boolean_t must_exist,
@@ -674,22 +471,33 @@ svn_repos__config_pool_get(svn_config_t
svn_error_t *err = SVN_NO_ERROR;
apr_pool_t *scratch_pool = svn_pool_create(pool);
+ /* make sure we always have a *KEY object */
+ svn_membuf_t *local_key = NULL;
+ if (key == NULL)
+ key = &local_key;
+ else
+ *key = NULL;
+
if (svn_path_is_url(path))
{
/* Read config file from repository.
* Attempt a quick lookup first. */
- SVN_MUTEX__WITH_LOCK(config_pool->mutex,
- config_by_url(cfg, config_pool, path,
- case_sensitive, pool,
- scratch_pool));
- if (*cfg)
+ SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool),
+ key_by_url(key, config_pool, path, pool));
+ if (*key)
{
- svn_pool_destroy(scratch_pool);
- return SVN_NO_ERROR;
+ SVN_ERR(svn_object_pool__lookup((void **)cfg,
+ config_pool->object_pool,
+ *key, &case_sensitive, pool));
+ if (*cfg)
+ {
+ svn_pool_destroy(scratch_pool);
+ return SVN_NO_ERROR;
+ }
}
/* Read and cache the configuration. This may fail. */
- err = find_repos_config(cfg, config_pool, path, case_sensitive,
+ err = find_repos_config(cfg, key, config_pool, path, case_sensitive,
preferred_repos, pool, scratch_pool);
if (err || !*cfg)
{
@@ -714,7 +522,7 @@ svn_repos__config_pool_get(svn_config_t
else
{
/* parsing and caching will always succeed */
- err = auto_parse(cfg, config_pool, contents, case_sensitive,
+ err = auto_parse(cfg, key, config_pool, contents, case_sensitive,
pool, scratch_pool);
}
}
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/dump.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/dump.c Sun Nov 17 10:02:39 2013
@@ -134,9 +134,9 @@ tracker_create(svn_revnum_t revision,
* we encounter a new tree change.
*/
static void
-tracker__trim(path_tracker_t *tracker,
- const char *path,
- svn_boolean_t allow_exact_match)
+tracker_trim(path_tracker_t *tracker,
+ const char *path,
+ svn_boolean_t allow_exact_match)
{
/* remove everything that is unrelated to PATH.
Note that TRACKER->STACK is depth-ordered,
@@ -176,7 +176,7 @@ tracker_lookup(const char **orig_path,
const char *path,
apr_pool_t *pool)
{
- tracker__trim(tracker, path, TRUE);
+ tracker_trim(tracker, path, TRUE);
if (tracker->depth == 0)
{
/* no tree changes -> paths are the same as in the previous rev. */
@@ -230,11 +230,11 @@ tracker_lookup(const char **orig_path,
will have undefined values.
*/
static path_tracker_entry_t *
-tracker__add_entry(path_tracker_t *tracker,
- const char *path)
+tracker_add_entry(path_tracker_t *tracker,
+ const char *path)
{
path_tracker_entry_t *entry;
- tracker__trim(tracker, path, FALSE);
+ tracker_trim(tracker, path, FALSE);
if (tracker->depth == tracker->stack->nelts)
{
@@ -263,7 +263,7 @@ tracker_path_copy(path_tracker_t *tracke
const char *copyfrom_path,
svn_revnum_t copyfrom_rev)
{
- path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+ path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
svn_stringbuf_set(entry->copyfrom_path, copyfrom_path);
entry->copyfrom_rev = copyfrom_rev;
@@ -276,7 +276,7 @@ static void
tracker_path_add(path_tracker_t *tracker,
const char *path)
{
- path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+ path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
svn_stringbuf_setempty(entry->copyfrom_path);
entry->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -301,7 +301,7 @@ static void
tracker_path_delete(path_tracker_t *tracker,
const char *path)
{
- path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+ path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
svn_stringbuf_setempty(entry->copyfrom_path);
entry->copyfrom_rev = SVN_INVALID_REVNUM;
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/repos.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/repos.h Sun Nov 17 10:02:39 2013
@@ -382,6 +382,11 @@ svn_repos__authz_read(svn_authz_t **auth
svn_boolean_t accept_urls,
apr_pool_t *pool);
+/* Walk the configuration in AUTHZ looking for any errors. */
+svn_error_t *
+svn_repos__authz_validate(svn_authz_t *authz,
+ apr_pool_t *pool);
+
/*** Utility Functions ***/
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c Sun Nov 17 10:02:39 2013
@@ -30,6 +30,7 @@
#include "svn_types.h"
#include "svn_dirent_uri.h"
#include "svn_auth.h"
+#include "svn_hash.h"
#include "svn_subst.h"
#include "svn_utf.h"
#include "svn_pools.h"
@@ -490,6 +491,18 @@ svn_config__shallow_copy(svn_config_t *s
return cfg;
}
+void
+svn_config__shallow_replace_section(svn_config_t *target,
+ svn_config_t *source,
+ const char *section)
+{
+ if (target->read_only)
+ target->sections = apr_hash_copy(target->pool, target->sections);
+
+ svn_hash_sets(target->sections, section,
+ svn_hash_gets(source->sections, section));
+}
+
svn_error_t *
svn_config__parse_file(svn_config_t *cfg, const char *file,
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/iter.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/iter.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/iter.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/iter.c Sun Nov 17 10:02:39 2013
@@ -193,24 +193,36 @@ svn_iter__break(void)
const void *svn__apr_hash_index_key(const apr_hash_index_t *hi)
{
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+ return apr_hash_this_key((apr_hash_index_t *)hi);
+#else
const void *key;
apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL);
return key;
+#endif
}
apr_ssize_t svn__apr_hash_index_klen(const apr_hash_index_t *hi)
{
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+ return apr_hash_this_key_len((apr_hash_index_t *)hi);
+#else
apr_ssize_t klen;
apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL);
return klen;
+#endif
}
void *svn__apr_hash_index_val(const apr_hash_index_t *hi)
{
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+ return apr_hash_this_val((apr_hash_index_t *)hi);
+#else
void *val;
apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val);
return val;
+#endif
}
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/diff_local.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/diff_local.c Sun Nov 17 10:02:39 2013
@@ -115,13 +115,20 @@ ensure_state(struct diff_baton *eb,
apr_pool_t *ns_pool;
if (!eb->cur)
{
- if (!svn_dirent_is_ancestor(eb->anchor_abspath, local_abspath))
+ const char *relpath;
+
+ relpath = svn_dirent_skip_ancestor(eb->anchor_abspath, local_abspath);
+ if (! relpath)
return SVN_NO_ERROR;
- SVN_ERR(ensure_state(eb,
- svn_dirent_dirname(local_abspath,scratch_pool),
- FALSE,
- scratch_pool));
+ /* Don't recurse on the anchor, as that might loop infinately because
+ svn_dirent_dirname("/",...) -> "/"
+ svn_dirent_dirname("C:/",...) -> "C:/" (Windows) */
+ if (*relpath)
+ SVN_ERR(ensure_state(eb,
+ svn_dirent_dirname(local_abspath,scratch_pool),
+ FALSE,
+ scratch_pool));
}
else if (svn_dirent_is_child(eb->cur->local_abspath, local_abspath, NULL))
SVN_ERR(ensure_state(eb, svn_dirent_dirname(local_abspath,scratch_pool),
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/upgrade.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/upgrade.c Sun Nov 17 10:02:39 2013
@@ -755,13 +755,13 @@ migrate_single_tree_conflict_data(svn_sq
{
/* There is an existing ACTUAL row, so just update it. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_ACTUAL_CONFLICT_DATA));
+ STMT_UPDATE_ACTUAL_CONFLICT));
}
else
{
/* We need to insert an ACTUAL row with the tree conflict data. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_INSERT_ACTUAL_CONFLICT_DATA));
+ STMT_INSERT_ACTUAL_CONFLICT));
}
SVN_ERR(svn_sqlite__bindf(stmt, "iss", wc_id, conflict_relpath,
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql Sun Nov 17 10:02:39 2013
@@ -325,7 +325,7 @@ WHERE wc_id = ?1 AND op_depth = ?3
-- STMT_COMMIT_DESCENDANTS_TO_BASE
UPDATE NODES SET op_depth = 0,
repos_id = ?4,
- repos_path = ?5 || SUBSTR(local_relpath, LENGTH(?2)+1),
+ repos_path = RELPATH_SKIP_JOIN(?2, ?5, local_relpath),
revision = ?6,
dav_cache = NULL,
moved_here = NULL,
@@ -425,24 +425,23 @@ WHERE work.wc_id = ?1 AND work.local_rel
LIMIT 1
-- STMT_SELECT_OP_DEPTH_MOVED_TO
-SELECT op_depth, moved_to, repos_path, revision
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2
- AND op_depth <= (SELECT MIN(op_depth) FROM nodes
- WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3)
-ORDER BY op_depth DESC
+SELECT n.op_depth, n.moved_to, p.repos_path, p.revision
+FROM nodes p
+LEFT JOIN nodes n
+ ON p.wc_id=n.wc_id AND p.local_relpath = n.local_relpath
+ AND n.op_depth = (SELECT MIN(d.op_depth)
+ FROM nodes d
+ WHERE d.wc_id = ?1
+ AND d.local_relpath = n.local_relpath
+ AND d.op_depth > ?3)
+WHERE p.wc_id = ?1 AND p.local_relpath = ?2 AND p.op_depth = ?3
+LIMIT 1
-- STMT_SELECT_MOVED_TO
SELECT moved_to
FROM nodes
WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
--- STMT_SELECT_MOVED_HERE
-SELECT moved_here, presence, repos_path, revision
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth >= ?3
-ORDER BY op_depth
-
-- STMT_SELECT_MOVED_BACK
SELECT u.local_relpath,
u.presence, u.repos_id, u.repos_path, u.revision,
@@ -468,13 +467,6 @@ WHERE u.wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(u.local_relpath, ?2)
AND u.op_depth = ?4
--- STMT_DELETE_MOVED_BACK
-DELETE FROM nodes
-WHERE wc_id = ?1
- AND (local_relpath = ?2
- OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
- AND op_depth = ?3
-
-- STMT_DELETE_LOCK
DELETE FROM lock
WHERE repos_id = ?1 AND repos_relpath = ?2
@@ -925,7 +917,7 @@ VALUES (?1, ?2, 0,
AND op_depth = 0))
-- STMT_INSTALL_WORKING_NODE_FOR_DELETE
-INSERT OR REPLACE INTO nodes (
+INSERT INTO nodes (
wc_id, local_relpath, op_depth,
parent_relpath, presence, kind)
VALUES(?1, ?2, ?3, ?4, MAP_BASE_DELETED, ?5)
@@ -1214,14 +1206,6 @@ VALUES (?1, ?2, ?3, ?4, ?5, ?6)
/* these are used in upgrade.c */
--- STMT_UPDATE_ACTUAL_CONFLICT_DATA
-UPDATE actual_node SET conflict_data = ?3
-WHERE wc_id = ?1 AND local_relpath = ?2
-
--- STMT_INSERT_ACTUAL_CONFLICT_DATA
-INSERT INTO actual_node (wc_id, local_relpath, conflict_data, parent_relpath)
-VALUES (?1, ?2, ?3, ?4)
-
-- STMT_SELECT_ALL_FILES
SELECT local_relpath FROM nodes_current
WHERE wc_id = ?1 AND parent_relpath = ?2 AND kind = MAP_FILE
@@ -1574,21 +1558,6 @@ UPDATE nodes SET moved_to = NULL
WHERE wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(moved_to, ?2)
-
-/* This statement returns pairs of move-roots below the path ?2 in WC_ID ?1,
- * where the original source of the move is within the subtree rooted at path
- * ?2 at op_depth ?3. (The move is recorded immediately above op_depth ?3) */
--- STMT_SELECT_MOVED_PAIRS_DEPTH
-SELECT local_relpath, moved_to, op_depth FROM nodes n
-WHERE wc_id = ?1
- AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
- AND moved_to IS NOT NULL
- AND op_depth > ?3
- AND op_depth = (SELECT MIN(op_depth) FROM nodes o
- WHERE o.wc_id = ?1
- AND o.local_relpath = n.local_relpath
- AND o.op_depth > ?3)
-
-- STMT_SELECT_MOVED_PAIR3
SELECT local_relpath, moved_to, op_depth, kind FROM nodes
WHERE wc_id = ?1
@@ -1637,12 +1606,8 @@ WHERE n.wc_id = ?1
AND h.moved_to IS NOT NULL
-- STMT_COMMIT_UPDATE_ORIGIN
-/* Note that the only reason this SUBSTR() trick is valid is that you
- can move neither the working copy nor the repository root.
-
- SUBSTR(local_relpath, LENGTH(?2)+1) includes the '/' of the path */
UPDATE nodes SET repos_id = ?4,
- repos_path = ?5 || SUBSTR(local_relpath, LENGTH(?2)+1),
+ repos_path = RELPATH_SKIP_JOIN(?2, ?5, local_relpath),
revision = ?6
WHERE wc_id = ?1
AND (local_relpath = ?2
@@ -1662,14 +1627,16 @@ ORDER BY local_relpath
-- STMT_SELECT_HAS_NON_FILE_CHILDREN
SELECT 1 FROM nodes
-WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0 AND kind != MAP_FILE
+WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = ?3 AND kind != MAP_FILE
+LIMIT 1
-- STMT_SELECT_HAS_GRANDCHILDREN
SELECT 1 FROM nodes
WHERE wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(parent_relpath, ?2)
- AND op_depth = 0
+ AND op_depth = ?3
AND file_external IS NULL
+LIMIT 1
/* ------------------------------------------------------------------------- */
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c Sun Nov 17 10:02:39 2013
@@ -661,21 +661,38 @@ svn_wc__db_retract_parent_delete(svn_wc_
if (moved_to)
{
- /* ### TODO: Turn the move into a copy to keep the NODES table
- valid */
+ /* Turn the move into a copy to keep the NODES table valid */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_CLEAR_MOVED_HERE_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ moved_to, relpath_depth(moved_to)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ /* This leaves just the moved_to information on the origin,
+ which we will remove in the next step */
}
if (presence == svn_wc__db_status_base_deleted)
{
+ /* Nothing left to shadow; remove the base-deleted node */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_DELETE_NODE));
-
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
- working_depth));
-
- SVN_ERR(svn_sqlite__update(NULL, stmt));
+ }
+ else if (moved_to)
+ {
+ /* Clear moved to information, as this node is no longer base-deleted */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_CLEAR_MOVED_TO_RELPATH));
+ }
+ else
+ {
+ /* Nothing to update */
+ return SVN_NO_ERROR;
}
- return SVN_NO_ERROR;
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
+ working_depth));
+
+ return svn_error_trace(svn_sqlite__update(NULL, stmt));
}
@@ -2084,28 +2101,29 @@ svn_wc__db_base_add_not_present_node(svn
}
/* Recursively clear moved-here information at the copy-half of the move
- * which moved the node at SRC_RELPATH away. This transforms the move into
- * a simple copy. */
+ * which moved a node to MOVED_TO_RELPATH. This transforms this side of the
+ * move into a simple copy.
+ */
static svn_error_t *
-clear_moved_here(const char *src_relpath,
- svn_wc__db_wcroot_t *wcroot,
+clear_moved_here(svn_wc__db_wcroot_t *wcroot,
+ const char *moved_to_relpath,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
- const char *dst_relpath;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_MOVED_TO));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
- src_relpath, relpath_depth(src_relpath)));
- SVN_ERR(svn_sqlite__step_row(stmt));
- dst_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
- SVN_ERR(svn_sqlite__reset(stmt));
+ int affected_rows;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_CLEAR_MOVED_HERE_RECURSIVE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
- dst_relpath, relpath_depth(dst_relpath)));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, moved_to_relpath,
+ relpath_depth(moved_to_relpath)));
+
+ SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+ if (affected_rows == 0)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ path_for_error_message(wcroot, moved_to_relpath,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -2296,12 +2314,12 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
iterpool = svn_pool_create(scratch_pool);
while (have_row)
{
- const char *child_relpath;
+ const char *moved_to_relpath;
svn_error_t *err;
svn_pool_clear(iterpool);
- child_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
- err = clear_moved_here(child_relpath, wcroot, iterpool);
+ moved_to_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
+ err = clear_moved_here(wcroot, moved_to_relpath, iterpool);
if (err)
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -4876,7 +4894,7 @@ handle_move_back(svn_boolean_t *moved_ba
generally these values should be the same anyway as it was
a no-op move. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_DELETE_MOVED_BACK));
+ STMT_DELETE_WORKING_OP_DEPTH));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
local_relpath,
@@ -5748,6 +5766,25 @@ set_actual_props(apr_int64_t wc_id,
return svn_error_trace(svn_sqlite__step_done(stmt));
}
+svn_error_t *
+svn_wc__db_op_set_props_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_hash_t *props,
+ svn_boolean_t clear_recorded_info,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(set_actual_props(wcroot->wc_id, local_relpath,
+ props, wcroot->sdb, scratch_pool));
+
+ if (clear_recorded_info)
+ {
+ SVN_ERR(db_record_fileinfo(wcroot, local_relpath,
+ SVN_INVALID_FILESIZE, 0,
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
/* The body of svn_wc__db_op_set_props().
@@ -5783,15 +5820,8 @@ set_props_txn(svn_wc__db_wcroot_t *wcroo
props = NULL;
}
- SVN_ERR(set_actual_props(wcroot->wc_id, local_relpath,
- props, wcroot->sdb, scratch_pool));
-
- if (clear_recorded_info)
- {
- SVN_ERR(db_record_fileinfo(wcroot, local_relpath,
- SVN_INVALID_FILESIZE, 0,
- scratch_pool));
- }
+ SVN_ERR(svn_wc__db_op_set_props_internal(wcroot, local_relpath, props,
+ clear_recorded_info, scratch_pool));
/* And finally. */
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
@@ -6355,36 +6385,36 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
return SVN_NO_ERROR;
}
-/* Clear moved-to information at the delete-half of the move which
- * moved LOCAL_RELPATH here. This transforms the move into a simple delete. */
+/* Clear moved-to information at the delete-half of the move which moved
+ * MOVED_TO_RELPATH here. This transforms the delete part of the move into a
+ * normal delete.
+ *
+ * Note that the moved-to location is always an op-root, while this is not the
+ * case for a moved-from location.
+ */
static svn_error_t *
-clear_moved_to(const char *local_relpath,
- svn_wc__db_wcroot_t *wcroot,
+clear_moved_to(svn_wc__db_wcroot_t *wcroot,
+ const char *moved_to_relpath,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
const char *moved_from_relpath;
+ int moved_from_op_depth;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_MOVED_FROM_RELPATH));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (!have_row)
- {
- SVN_ERR(svn_sqlite__reset(stmt));
- return SVN_NO_ERROR;
- }
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, moved_to_relpath));
+ SVN_ERR(svn_sqlite__step_row(stmt));
moved_from_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
+ moved_from_op_depth = svn_sqlite__column_int(stmt, 1);
SVN_ERR(svn_sqlite__reset(stmt));
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_CLEAR_MOVED_TO_RELPATH));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
- moved_from_relpath,
- relpath_depth(moved_from_relpath)));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ moved_from_relpath, moved_from_op_depth));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
return SVN_NO_ERROR;
}
@@ -6540,7 +6570,7 @@ op_revert_txn(void *baton,
/* If this node was moved-here, clear moved-to at the move source. */
if (moved_here)
- SVN_ERR(clear_moved_to(local_relpath, wcroot, scratch_pool));
+ SVN_ERR(clear_moved_to(wcroot, local_relpath, scratch_pool));
}
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -6683,7 +6713,7 @@ op_revert_recursive_txn(void *baton,
svn_pool_clear(iterpool);
moved_here_child_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
- err = clear_moved_to(moved_here_child_relpath, wcroot, iterpool);
+ err = clear_moved_to(wcroot, moved_here_child_relpath, iterpool);
if (err)
return svn_error_trace(svn_error_compose_create(
err,
@@ -6697,7 +6727,7 @@ op_revert_recursive_txn(void *baton,
/* Clear potential moved-to pointing at the target node itself. */
if (op_depth > 0 && op_depth == relpath_depth(local_relpath)
&& moved_here)
- SVN_ERR(clear_moved_to(local_relpath, wcroot, scratch_pool));
+ SVN_ERR(clear_moved_to(wcroot, local_relpath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -9563,12 +9593,12 @@ svn_wc__db_read_props_streamily(svn_wc__
/* Helper for svn_wc__db_read_props().
*/
-static svn_error_t *
-db_read_props(apr_hash_t **props,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__db_read_props_internal(apr_hash_t **props,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -9625,8 +9655,10 @@ svn_wc__db_read_props(apr_hash_t **props
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- SVN_WC__DB_WITH_TXN(db_read_props(props, wcroot, local_relpath,
- result_pool, scratch_pool),
+ SVN_WC__DB_WITH_TXN(svn_wc__db_read_props_internal(props, wcroot,
+ local_relpath,
+ result_pool,
+ scratch_pool),
wcroot);
return SVN_NO_ERROR;
@@ -12183,23 +12215,20 @@ svn_wc__db_scan_moved(const char **moved
/* ###
*/
static svn_error_t *
-follow_moved_to(apr_array_header_t **moved_tos,
- int op_depth,
- const char *repos_path,
- svn_revnum_t revision,
- svn_wc__db_wcroot_t *wcroot,
+follow_moved_to(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ int op_depth,
+ apr_array_header_t **moved_tos,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
int working_op_depth;
- const char *ancestor_relpath, *node_moved_to = NULL;
+ const char *ancestor_relpath;
+ const char *node_moved_to = NULL;
int i;
- SVN_ERR_ASSERT((!op_depth && !repos_path) || (op_depth && repos_path));
-
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_OP_DEPTH_MOVED_TO));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
@@ -12209,50 +12238,26 @@ follow_moved_to(apr_array_header_t **mov
{
working_op_depth = svn_sqlite__column_int(stmt, 0);
node_moved_to = svn_sqlite__column_text(stmt, 1, result_pool);
- if (!repos_path)
- {
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (!have_row || svn_sqlite__column_revnum(stmt, 0))
- return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
- svn_sqlite__reset(stmt),
- _("The base node '%s' was not found."),
- path_for_error_message(wcroot,
- local_relpath,
- scratch_pool));
- repos_path = svn_sqlite__column_text(stmt, 2, scratch_pool);
- revision = svn_sqlite__column_revnum(stmt, 3);
- }
- }
- SVN_ERR(svn_sqlite__reset(stmt));
- if (node_moved_to)
- {
- svn_boolean_t have_row2;
+ if (node_moved_to)
+ {
+ struct svn_wc__db_moved_to_t *moved_to;
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_MOVED_HERE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, node_moved_to,
- relpath_depth(node_moved_to)));
- SVN_ERR(svn_sqlite__step(&have_row2, stmt));
- if (!have_row2 || !svn_sqlite__column_int(stmt, 0)
- || revision != svn_sqlite__column_revnum(stmt, 3)
- || strcmp(repos_path, svn_sqlite__column_text(stmt, 2, NULL)))
- node_moved_to = NULL;
- SVN_ERR(svn_sqlite__reset(stmt));
+ moved_to = apr_palloc(result_pool, sizeof(*moved_to));
+ moved_to->op_depth = working_op_depth;
+ moved_to->local_relpath = node_moved_to;
+ APR_ARRAY_PUSH(*moved_tos, struct svn_wc__db_moved_to_t *) = moved_to;
+ }
}
- if (node_moved_to)
- {
- struct svn_wc__db_moved_to_t *moved_to;
-
- moved_to = apr_palloc(result_pool, sizeof(*moved_to));
- moved_to->op_depth = working_op_depth;
- moved_to->local_relpath = node_moved_to;
- APR_ARRAY_PUSH(*moved_tos, struct svn_wc__db_moved_to_t *) = moved_to;
- }
+ SVN_ERR(svn_sqlite__reset(stmt));
- /* A working row with moved_to, or no working row, and we are done. */
- if (node_moved_to || !have_row)
+ if (!have_row)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ path_for_error_message(wcroot, local_relpath,
+ scratch_pool));
+ else if (node_moved_to)
return SVN_NO_ERROR;
/* Need to handle being moved via an ancestor. */
@@ -12267,55 +12272,29 @@ follow_moved_to(apr_array_header_t **mov
STMT_SELECT_MOVED_TO));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, ancestor_relpath,
working_op_depth));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- SVN_ERR_ASSERT(have_row);
+ SVN_ERR(svn_sqlite__step_row(stmt));
+
ancestor_moved_to = svn_sqlite__column_text(stmt, 0, scratch_pool);
SVN_ERR(svn_sqlite__reset(stmt));
if (ancestor_moved_to)
{
- node_moved_to
- = svn_relpath_join(ancestor_moved_to,
- svn_relpath_skip_ancestor(ancestor_relpath,
- local_relpath),
- result_pool);
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_MOVED_HERE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, node_moved_to,
- relpath_depth(ancestor_moved_to)));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (!have_row)
- ancestor_moved_to = NULL;
- else if (!svn_sqlite__column_int(stmt, 0))
- {
- svn_wc__db_status_t presence
- = svn_sqlite__column_token(stmt, 1, presence_map);
- if (presence != svn_wc__db_status_not_present)
- ancestor_moved_to = NULL;
- else
- {
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (!have_row && !svn_sqlite__column_int(stmt, 0))
- ancestor_moved_to = NULL;
- }
- }
- SVN_ERR(svn_sqlite__reset(stmt));
- if (!ancestor_moved_to)
- break;
- /* verify repos_path points back? */
- }
- if (ancestor_moved_to)
- {
struct svn_wc__db_moved_to_t *moved_to;
+ node_moved_to
+ = svn_relpath_join(ancestor_moved_to,
+ svn_relpath_skip_ancestor(ancestor_relpath,
+ local_relpath),
+ result_pool);
+
moved_to = apr_palloc(result_pool, sizeof(*moved_to));
moved_to->op_depth = working_op_depth;
moved_to->local_relpath = node_moved_to;
APR_ARRAY_PUSH(*moved_tos, struct svn_wc__db_moved_to_t *) = moved_to;
- SVN_ERR(follow_moved_to(moved_tos, relpath_depth(ancestor_moved_to),
- repos_path, revision, wcroot, node_moved_to,
- result_pool, scratch_pool));
+ SVN_ERR(follow_moved_to(wcroot, node_moved_to,
+ relpath_depth(ancestor_moved_to),
+ moved_tos, result_pool, scratch_pool));
+
break;
}
}
@@ -12343,9 +12322,9 @@ svn_wc__db_follow_moved_to(apr_array_hea
sizeof(struct svn_wc__db_moved_to_t *));
/* ### Wrap in a transaction */
- SVN_ERR(follow_moved_to(moved_tos, 0, NULL, SVN_INVALID_REVNUM,
- wcroot, local_relpath,
- result_pool, scratch_pool));
+ SVN_WC__DB_WITH_TXN(follow_moved_to(wcroot, local_relpath, 0, moved_tos,
+ result_pool, scratch_pool),
+ wcroot);
/* ### Convert moved_to to abspath */
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h Sun Nov 17 10:02:39 2013
@@ -466,6 +466,23 @@ svn_wc__db_op_depth_moved_to(const char
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Like svn_wc__db_op_set_props, but updates ACTUAL_NODE directly without
+ comparing with the pristine properties, etc.
+*/
+svn_error_t *
+svn_wc__db_op_set_props_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_hash_t *props,
+ svn_boolean_t clear_recorded_info,
+ apr_pool_t *scratch_pool);
+
+svn_error_t *
+svn_wc__db_read_props_internal(apr_hash_t **props,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Do a post-drive revision bump for the moved-away destination for
any move sources under LOCAL_RELPATH. This is called from within
the revision bump transaction after the tree at LOCAL_RELPATH has