Author: cmpilato
Date: Wed Jun 23 01:22:00 2010
New Revision: 957094
URL: http://svn.apache.org/viewvc?rev=957094&view=rev
Log:
Finish issue #3661: RA get-locks inefficiencies.
Add depth support to the process of querying repository locks in the
repository and RA layers for the sake of performance. Prior to this
change, 'svn ls -v SOME_PATH' (non-recursive) asked the repository for
the locks on all paths in and under SOME_PATH (fully recursive),
resulting in potentially far more information being transmitted across
the network than is necessary.
* subversion/include/svn_fs.h
(svn_fs_get_locks2): New.
(svn_fs_get_locks): Deprecate this.
* subversion/libsvn_fs/fs-loader.h
(fs_vtable_t): Add 'depth' to get_locks() vtable function.
* subversion/libsvn_fs/fs-loader.c
(svn_fs_get_locks2): New.
(svn_fs_get_locks): Make this just a wrapper around svn_fs_get_locks2().
* subversion/libsvn_fs_base/lock.h
(svn_fs_base__get_locks): Add 'depth' parameter.
* subversion/libsvn_fs_base/lock.c
(struct locks_get_args): Add 'depth' member.
(svn_fs_base__allow_locked_operation, txn_body_get_locks): Update
call to svn_fs_bdb__locks_get().
(svn_fs_base__get_locks): Add 'depth' parameter, used to populate
new baton member.
* subversion/libsvn_fs_base/bdb/locks-table.h
(svn_fs_bdb__locks_get): Add 'depth' parameter.
* subversion/libsvn_fs_base/bdb/locks-table.c
(svn_fs_bdb__locks_get): Add 'depth' parameter, and use it to filter
the reported depths.
* subversion/libsvn_fs_fs/lock.h
(svn_fs_fs__get_locks): Add 'depth' paramater.
* subversion/libsvn_fs_fs/lock.c
(get_locks_filter_baton_t): New baton structure.
(get_locks_filter_func): New callback wrapper function.
(svn_fs_fs__get_locks): Add 'depth' paramater, and employ the
get_locks_filter_func and baton when calling walk_digest_files().
* subversion/include/svn_repos.h
(svn_repos_fs_get_locks2): New revision of svn_repos_fs_get_locks()
which adds support for a specified 'depth'.
(svn_repos_fs_get_locks): Deprecate this.
* subversion/libsvn_repos/fs-wrap.c
(svn_repos_fs_get_locks2): Was svn_repos_fs_get_locks(). Now calls
svn_fs_get_locks2().
(svn_repos_fs_get_locks): Make this just a wrapper around
svn_repos_fs_get_locks2(), now.
* subversion/mod_dav_svn/reports/get-locks.c
(dav_svn__get_locks_report): Look for new (optional) depth
parameter, and use it to drive what's now a call to
svn_repos_fs_get_locks2().
* build.conf
(svnserve): Add dependency on libsvn_ra.
* subversion/svnserve/serve.c
(get_locks): Look for optional depth in the get-locks request, and
use it in what is now a call to svn_repos_fs_get_locks2().
* subversion/include/svn_ra.h
(svn_ra_get_locks2): New flavor of svn_ra_get_lock(), this time with
depth support.
(svn_ra_get_lock): Deprecate.
* subversion/libsvn_ra/ra_loader.h
(svn_ra__vtable_t): Add 'depth' parameter to 'get_locks' function.
* subversion/libsvn_ra/ra_loader.c
(svn_ra_get_locks2): New.
(svn_ra_get_locks): Make this just a wrapper around
svn_ra_get_locks2().
* subversion/libsvn_ra_local/ra_plugin.c
(svn_ra_local__get_locks): Add 'depth' parameter, and now use
svn_repos_fs_get_locks2().
* subversion/libsvn_ra_neon/ra_neon.h
(svn_ra_neon__get_locks): Add 'depth' parameter.
* subversion/libsvn_ra_neon/get_locks.c
(get_locks_baton_t): Add 'path' and 'requested_depth' members.
(getlocks_end_element): Filter unwanted locks out of the hash.
(svn_ra_neon__get_locks): Add 'depth' parameter, embed it into the
get-locks request, and populate the new baton members.
* subversion/libsvn_ra_serf/ra_serf.h
(svn_ra_serf__get_locks): Add 'depth' parameter.
* subversion/libsvn_ra_serf/getlocks.c
(lock_context_t): Add 'path' and 'requested_depth' members.
(end_getlocks): Filter unwanted locks out of the hash.
(create_getlocks_body): Stuff depth value from baton into the
request body.
(svn_ra_serf__get_locks): Add 'depth' parameter,
* subversion/libsvn_ra_svn/client.c
(ra_svn_get_locks): Add 'depth' parameter, and pass it to the server
in case the server can make use of it. Also, filter out unwanted
locks (returned by servers that *can't* make use of it).
* subversion/libsvn_client/list.c
(svn_client_list2): Now use svn_ra_get_locks2(), passing depth along.
Modified:
subversion/trunk/build.conf
subversion/trunk/subversion/include/svn_fs.h
subversion/trunk/subversion/include/svn_ra.h
subversion/trunk/subversion/include/svn_repos.h
subversion/trunk/subversion/libsvn_client/list.c
subversion/trunk/subversion/libsvn_fs/fs-loader.c
subversion/trunk/subversion/libsvn_fs/fs-loader.h
subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.c
subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.h
subversion/trunk/subversion/libsvn_fs_base/lock.c
subversion/trunk/subversion/libsvn_fs_base/lock.h
subversion/trunk/subversion/libsvn_fs_fs/lock.c
subversion/trunk/subversion/libsvn_fs_fs/lock.h
subversion/trunk/subversion/libsvn_ra/ra_loader.c
subversion/trunk/subversion/libsvn_ra/ra_loader.h
subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
subversion/trunk/subversion/libsvn_ra_neon/get_locks.c
subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h
subversion/trunk/subversion/libsvn_ra_serf/getlocks.c
subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
subversion/trunk/subversion/libsvn_ra_svn/client.c
subversion/trunk/subversion/libsvn_repos/fs-wrap.c
subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c
subversion/trunk/subversion/svnserve/serve.c
Modified: subversion/trunk/build.conf
URL:
http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Wed Jun 23 01:22:00 2010
@@ -147,7 +147,7 @@ type = exe
path = subversion/svnserve
install = bin
manpages = subversion/svnserve/svnserve.8 subversion/svnserve/svnserve.conf.5
-libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr libsvn_ra_svn
+libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr libsvn_ra libsvn_ra_svn
apriconv apr sasl
msvc-libs = advapi32.lib ws2_32.lib
Modified: subversion/trunk/subversion/include/svn_fs.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_fs.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_fs.h (original)
+++ subversion/trunk/subversion/include/svn_fs.h Wed Jun 23 01:22:00 2010
@@ -2126,6 +2126,11 @@ typedef svn_error_t *(*svn_fs_get_locks_
* get_locks_func / @a get_locks_baton. Use @a pool for necessary
* allocations.
*
+ * @depth limits the reported locks to those associated with paths
+ * within the specified depth of @path, and must be one of the
+ * following values: #svn_depth_empty, #svn_depth_files,
+ * #svn_depth_immediates, or #svn_depth_infinity.
+ *
* If the @a get_locks_func callback implementation returns an error,
* lock iteration will terminate and that error will be returned by
* this function.
@@ -2137,7 +2142,24 @@ typedef svn_error_t *(*svn_fs_get_locks_
* start a new Berkeley DB transaction (which is most of this svn_fs
* API). Yes, this is a nasty implementation detail to have to be
* aware of. We hope to fix this problem in the future.
+ *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_fs_get_locks2(svn_fs_t *fs,
+ const char *path,
+ svn_depth_t depth,
+ svn_fs_get_locks_callback_t get_locks_func,
+ void *get_locks_baton,
+ apr_pool_t *pool);
+
+/**
+ * Similar to svn_fs_get_locks2(), but with @a depth always passed as
+ * svn_depth_infinity.
+ *
+ * @deprecated Provided for backward compatibility with the 1.6 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_fs_get_locks(svn_fs_t *fs,
const char *path,
Modified: subversion/trunk/subversion/include/svn_ra.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_ra.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_ra.h (original)
+++ subversion/trunk/subversion/include/svn_ra.h Wed Jun 23 01:22:00 2010
@@ -1689,6 +1689,11 @@ svn_ra_get_lock(svn_ra_session_t *sessio
* Set @a *locks to a hashtable which represents all locks on or
* below @a path.
*
+ * @depth limits the returned locks to those associated with paths
+ * within the specified depth of @path, and must be one of the
+ * following values: #svn_depth_empty, #svn_depth_files,
+ * #svn_depth_immediates, or #svn_depth_infinity.
+ *
* The hashtable maps (const char *) absolute fs paths to (const
* svn_lock_t *) structures. The hashtable -- and all keys and
* values -- are allocated in @a pool.
@@ -1700,8 +1705,23 @@ svn_ra_get_lock(svn_ra_session_t *sessio
* server doesn't implement it, an @c SVN_ERR_RA_NOT_IMPLEMENTED error is
* returned.
*
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_ra_get_locks2(svn_ra_session_t *session,
+ apr_hash_t **locks,
+ const char *path,
+ svn_depth_t depth,
+ apr_pool_t *pool);
+
+/**
+ * Similar to svn_ra_get_locks2(), but with @a depth always passed as
+ * #svn_depth_infinity.
+ *
* @since New in 1.2.
+ * @deprecated Provided for backward compatibility with the 1.6 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_ra_get_locks(svn_ra_session_t *session,
apr_hash_t **locks,
Modified: subversion/trunk/subversion/include/svn_repos.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_repos.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_repos.h (original)
+++ subversion/trunk/subversion/include/svn_repos.h Wed Jun 23 01:22:00 2010
@@ -1954,7 +1954,30 @@ svn_repos_fs_unlock(svn_repos_t *repos,
* authz_read_func and @a authz_read_baton to "screen" all returned
* locks. That is: do not return any locks on any paths that are
* unreadable in HEAD, just silently omit them.
+ *
+ * @depth limits the returned locks to those associated with paths
+ * within the specified depth of @path, and must be one of the
+ * following values: #svn_depth_empty, #svn_depth_files,
+ * #svn_depth_immediates, or #svn_depth_infinity.
+ *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_repos_fs_get_locks2(apr_hash_t **locks,
+ svn_repos_t *repos,
+ const char *path,
+ svn_depth_t depth,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *pool);
+
+/**
+ * Similar to svn_repos_fs_get_locks2(), but with @a depth always
+ * passed as svn_depth_infinity.
+ *
+ * @deprecated Provided for backward compatibility with the 1.6 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_repos_fs_get_locks(apr_hash_t **locks,
svn_repos_t *repos,
Modified: subversion/trunk/subversion/libsvn_client/list.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/list.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/list.c (original)
+++ subversion/trunk/subversion/libsvn_client/list.c Wed Jun 23 01:22:00 2010
@@ -245,7 +245,7 @@ svn_client_list2(const char *path_or_url
{
/* IMPORTANT: If locks are stored in a more temporary pool, we need
to fix store_dirent below to duplicate the locks. */
- err = svn_ra_get_locks(ra_session, &locks, "", pool);
+ err = svn_ra_get_locks2(ra_session, &locks, "", depth, pool);
if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
{
Modified: subversion/trunk/subversion/libsvn_fs/fs-loader.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.c Wed Jun 23 01:22:00 2010
@@ -1301,16 +1301,29 @@ svn_fs_get_lock(svn_lock_t **lock, svn_f
}
svn_error_t *
+svn_fs_get_locks2(svn_fs_t *fs, const char *path, svn_depth_t depth,
+ svn_fs_get_locks_callback_t get_locks_func,
+ void *get_locks_baton, apr_pool_t *pool)
+{
+ SVN_ERR_ASSERT((depth == svn_depth_empty) ||
+ (depth == svn_depth_files) ||
+ (depth == svn_depth_immediates) ||
+ (depth == svn_depth_infinity));
+ return svn_error_return(fs->vtable->get_locks(fs, path, depth,
+ get_locks_func,
+ get_locks_baton, pool));
+}
+
+svn_error_t *
svn_fs_get_locks(svn_fs_t *fs, const char *path,
svn_fs_get_locks_callback_t get_locks_func,
- void *get_locks_baton,
- apr_pool_t *pool)
+ void *get_locks_baton, apr_pool_t *pool)
{
- return svn_error_return(fs->vtable->get_locks(fs, path, get_locks_func,
- get_locks_baton, pool));
+ return svn_error_return(svn_fs_get_locks2(fs, path, svn_depth_infinity,
+ get_locks_func, get_locks_baton,
+ pool));
}
-
/* --- History functions --- */
Modified: subversion/trunk/subversion/libsvn_fs/fs-loader.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.h Wed Jun 23 01:22:00 2010
@@ -190,7 +190,7 @@ typedef struct fs_vtable_t
svn_boolean_t break_lock, apr_pool_t *pool);
svn_error_t *(*get_lock)(svn_lock_t **lock, svn_fs_t *fs,
const char *path, apr_pool_t *pool);
- svn_error_t *(*get_locks)(svn_fs_t *fs, const char *path,
+ svn_error_t *(*get_locks)(svn_fs_t *fs, const char *path, svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool);
Modified: subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.c Wed Jun 23
01:22:00 2010
@@ -191,6 +191,7 @@ get_lock(svn_lock_t **lock_p,
svn_error_t *
svn_fs_bdb__locks_get(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
trail_t *trail,
@@ -225,9 +226,11 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
}
+ /* If we're only looking at PATH itself (depth = empty), stop here. */
+ if (depth == svn_depth_empty)
+ return SVN_NO_ERROR;
+
/* Now go hunt for possible children of PATH. */
- if (strcmp(path, "/") != 0)
- lookup_path = apr_pstrcat(pool, path, "/", NULL);
svn_fs_base__trail_debug(trail, "lock-tokens", "cursor");
db_err = bfd->lock_tokens->cursor(bfd->lock_tokens, trail->db_txn,
@@ -246,6 +249,8 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
/* As long as the prefix of the returned KEY matches LOOKUP_PATH we
know it is either LOOKUP_PATH or a decendant thereof. */
+ if (strcmp(path, "/") != 0)
+ lookup_path = apr_pstrcat(pool, path, "/", NULL);
while ((! db_err)
&& strncmp(lookup_path, key.data, strlen(lookup_path)) == 0)
{
@@ -260,6 +265,18 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
child_path = apr_pstrmemdup(subpool, key.data, key.size);
lock_token = apr_pstrmemdup(subpool, value.data, value.size);
+ if ((depth == svn_depth_files) || (depth == svn_depth_immediates))
+ {
+ /* On the assumption that we only store locks for files,
+ depth=files and depth=immediates should boil down to the
+ same set of results. So just see if CHILD_PATH is an
+ immediate child of PATH. If not, we don't care about
+ this item. */
+ const char *rel_uri = svn_uri_is_child(path, child_path, subpool);
+ if (!rel_uri || (svn_path_component_count(rel_uri) != 1))
+ goto loop_it;
+ }
+
/* Get the lock for CHILD_PATH. */
err = get_lock(&lock, fs, child_path, lock_token, trail, subpool);
if (err)
@@ -279,6 +296,7 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
}
}
+ loop_it:
svn_fs_base__result_dbt(&key);
svn_fs_base__result_dbt(&value);
db_err = svn_bdb_dbc_get(cursor, &key, &value, DB_NEXT);
Modified: subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.h (original)
+++ subversion/trunk/subversion/libsvn_fs_base/bdb/locks-table.h Wed Jun 23
01:22:00 2010
@@ -86,12 +86,16 @@ svn_error_t *svn_fs_bdb__lock_get(svn_lo
in FS. Pass each lock to GET_LOCKS_FUNC callback along with
GET_LOCKS_BATON.
+ Use DEPTH to filter the reported locks to only those within the
+ requested depth of PATH.
+
This function promises to auto-expire any locks encountered while
building the hash. That means that the caller can trust that each
returned lock hasn't yet expired.
*/
svn_error_t *svn_fs_bdb__locks_get(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
trail_t *trail,
Modified: subversion/trunk/subversion/libsvn_fs_base/lock.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/lock.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/lock.c Wed Jun 23 01:22:00 2010
@@ -396,6 +396,7 @@ svn_fs_base__get_lock(svn_lock_t **lock,
struct locks_get_args
{
const char *path;
+ svn_depth_t depth;
svn_fs_get_locks_callback_t get_locks_func;
void *get_locks_baton;
};
@@ -405,7 +406,7 @@ static svn_error_t *
txn_body_get_locks(void *baton, trail_t *trail)
{
struct locks_get_args *args = baton;
- return svn_fs_bdb__locks_get(trail->fs, args->path,
+ return svn_fs_bdb__locks_get(trail->fs, args->path, args->depth,
args->get_locks_func, args->get_locks_baton,
trail, trail->pool);
}
@@ -414,6 +415,7 @@ txn_body_get_locks(void *baton, trail_t
svn_error_t *
svn_fs_base__get_locks(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool)
@@ -422,6 +424,7 @@ svn_fs_base__get_locks(svn_fs_t *fs,
SVN_ERR(svn_fs__check_fs(fs, TRUE));
args.path = svn_fs__canonicalize_abspath(path, pool);
+ args.depth = depth;
args.get_locks_func = get_locks_func;
args.get_locks_baton = get_locks_baton;
return svn_fs_base__retry_txn(fs, txn_body_get_locks, &args, FALSE, pool);
@@ -490,7 +493,8 @@ svn_fs_base__allow_locked_operation(cons
if (recurse)
{
/* Discover all locks at or below the path. */
- SVN_ERR(svn_fs_bdb__locks_get(trail->fs, path, get_locks_callback,
+ SVN_ERR(svn_fs_bdb__locks_get(trail->fs, path, svn_depth_infinity,
+ get_locks_callback,
trail->fs, trail, pool));
}
else
Modified: subversion/trunk/subversion/libsvn_fs_base/lock.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/lock.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/lock.h (original)
+++ subversion/trunk/subversion/libsvn_fs_base/lock.h Wed Jun 23 01:22:00 2010
@@ -64,6 +64,7 @@ svn_error_t *svn_fs_base__get_lock(svn_l
svn_error_t *
svn_fs_base__get_locks(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool);
Modified: subversion/trunk/subversion/libsvn_fs_fs/lock.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/lock.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/lock.c Wed Jun 23 01:22:00 2010
@@ -901,20 +901,82 @@ svn_fs_fs__get_lock(svn_lock_t **lock_p,
}
+/* Baton for get_locks_filter_func(). */
+typedef struct
+{
+ const char *path;
+ svn_depth_t requested_depth;
+ svn_fs_get_locks_callback_t get_locks_func;
+ void *get_locks_baton;
+
+} get_locks_filter_baton_t;
+
+
+/* A wrapper for the GET_LOCKS_FUNC passed to svn_fs_fs__get_locks()
+ which filters out locks on paths that aren't within
+ BATON->requested_depth of BATON->path before called
+ BATON->get_locks_func() with BATON->get_locks_baton.
+
+ NOTE: See issue #3660 for details about how the FSFS lock
+ management code is inconsistent. Until that inconsistency is
+ resolved, we take this filtering approach rather than honoring
+ depth requests closer to the crawling code. In other words, once
+ we decide how to resolve issue #3660, there might be a more
+ performant way to honor the depth passed to svn_fs_fs__get_locks(). */
+static svn_error_t *
+get_locks_filter_func(void *baton,
+ svn_lock_t *lock,
+ apr_pool_t *pool)
+{
+ get_locks_filter_baton_t *b = baton;
+
+ /* Filter out unwanted paths. Since Subversion only allows
+ locks on files, we can treat depth=immediates the same as
+ depth=files for filtering purposes. Meaning, we'll keep
+ this lock if:
+
+ a) its path is the very path we queried, or
+ b) we've asked for a fully recursive answer, or
+ c) we've asked for depth=files or depth=immediates, and this
+ lock is on an immediate child of our query path.
+ */
+ if ((strcmp(b->path, lock->path) == 0)
+ || (b->requested_depth == svn_depth_infinity))
+ {
+ SVN_ERR(b->get_locks_func(b->get_locks_baton, lock, pool));
+ }
+ else if ((b->requested_depth == svn_depth_files) ||
+ (b->requested_depth == svn_depth_immediates))
+ {
+ const char *rel_uri = svn_uri_is_child(b->path, lock->path, pool);
+ if (rel_uri && (svn_path_component_count(rel_uri) == 1))
+ SVN_ERR(b->get_locks_func(b->get_locks_baton, lock, pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_fs_fs__get_locks(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool)
{
const char *digest_path;
+ get_locks_filter_baton_t glfb;
SVN_ERR(svn_fs__check_fs(fs, TRUE));
path = svn_fs__canonicalize_abspath(path, pool);
+ glfb.path = path;
+ glfb.requested_depth = depth;
+ glfb.get_locks_func = get_locks_func;
+ glfb.get_locks_baton = get_locks_baton;
+
/* Get the top digest path in our tree of interest, and then walk it. */
digest_path = digest_path_from_path(fs, path, pool);
- return walk_digest_files(fs, digest_path, get_locks_func,
- get_locks_baton, FALSE, pool);
+ return walk_digest_files(fs, digest_path, get_locks_filter_func, &glfb,
+ FALSE, pool);
}
Modified: subversion/trunk/subversion/libsvn_fs_fs/lock.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/lock.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/lock.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/lock.h Wed Jun 23 01:22:00 2010
@@ -60,6 +60,7 @@ svn_error_t *svn_fs_fs__get_lock(svn_loc
svn_error_t *svn_fs_fs__get_locks(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool);
Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.c Wed Jun 23 01:22:00 2010
@@ -1014,13 +1014,26 @@ svn_error_t *svn_ra_get_lock(svn_ra_sess
return session->vtable->get_lock(session, lock, path, pool);
}
+svn_error_t *svn_ra_get_locks2(svn_ra_session_t *session,
+ apr_hash_t **locks,
+ const char *path,
+ svn_depth_t depth,
+ apr_pool_t *pool)
+{
+ SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT((depth == svn_depth_empty) ||
+ (depth == svn_depth_files) ||
+ (depth == svn_depth_immediates) ||
+ (depth == svn_depth_infinity));
+ return session->vtable->get_locks(session, locks, path, depth, pool);
+}
+
svn_error_t *svn_ra_get_locks(svn_ra_session_t *session,
apr_hash_t **locks,
const char *path,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
- return session->vtable->get_locks(session, locks, path, pool);
+ return svn_ra_get_locks2(session, locks, path, svn_depth_infinity, pool);
}
svn_error_t *svn_ra_replay(svn_ra_session_t *session,
Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.h Wed Jun 23 01:22:00 2010
@@ -230,6 +230,7 @@ typedef struct svn_ra__vtable_t {
svn_error_t *(*get_locks)(svn_ra_session_t *session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool);
svn_error_t *(*replay)(svn_ra_session_t *session,
svn_revnum_t revision,
Modified: subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c Wed Jun 23 01:22:00
2010
@@ -1323,6 +1323,7 @@ static svn_error_t *
svn_ra_local__get_locks(svn_ra_session_t *session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
@@ -1330,8 +1331,8 @@ svn_ra_local__get_locks(svn_ra_session_t
/* Kinda silly to call the repos wrapper, since we have no authz
func to give it. But heck, why not. */
- return svn_repos_fs_get_locks(locks, sess->repos, abs_path,
- NULL, NULL, pool);
+ return svn_repos_fs_get_locks2(locks, sess->repos, abs_path, depth,
+ NULL, NULL, pool);
}
Modified: subversion/trunk/subversion/libsvn_ra_neon/get_locks.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_neon/get_locks.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_neon/get_locks.c (original)
+++ subversion/trunk/subversion/libsvn_ra_neon/get_locks.c Wed Jun 23 01:22:00
2010
@@ -85,7 +85,7 @@ static const svn_ra_neon__xml_elm_t getl
* The get-locks-report xml request body is super-simple.
* The server doesn't need anything but the URI in the REPORT request line.
*
- * <S:get-locks-report xmlns...>
+ * <S:get-locks-report [depth=DEPTH] xmlns...>
* </S:get-locks-report>
*
* The get-locks-report xml response is just a list of svn_lock_t's
@@ -121,6 +121,8 @@ static const svn_ra_neon__xml_elm_t getl
/* Context for parsing server's response. */
typedef struct {
+ const char *path; /* target of the report */
+ svn_depth_t requested_depth; /* requested depth of the report */
svn_lock_t *current_lock; /* the lock being constructed */
svn_stringbuf_t *cdata_accum; /* a place to accumulate cdata */
const char *encoding; /* normally NULL, else the value of
@@ -235,8 +237,33 @@ getlocks_end_element(void *userdata, int
SVN_ERR(svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
_("Incomplete lock data returned")));
- apr_hash_set(baton->lock_hash, baton->current_lock->path,
- APR_HASH_KEY_STRING, baton->current_lock);
+ /* Filter out unwanted paths. Since Subversion only allows
+ locks on files, we can treat depth=immediates the same as
+ depth=files for filtering purposes. Meaning, we'll keep
+ this lock if:
+
+ a) its path is the very path we queried, or
+ b) we've asked for a fully recursive answer, or
+ c) we've asked for depth=files or depth=immediates, and this
+ lock is on an immediate child of our query path.
+ */
+ if ((strcmp(baton->path, baton->current_lock->path) == 0)
+ || (baton->requested_depth == svn_depth_infinity))
+ {
+ apr_hash_set(baton->lock_hash, baton->current_lock->path,
+ APR_HASH_KEY_STRING, baton->current_lock);
+ }
+ else if ((baton->requested_depth == svn_depth_files) ||
+ (baton->requested_depth == svn_depth_immediates))
+ {
+ const char *rel_uri = svn_uri_is_child(baton->path,
+ baton->current_lock->path,
+ baton->scratchpool);
+ if (rel_uri && (svn_path_component_count(rel_uri) == 1))
+ apr_hash_set(baton->lock_hash, baton->current_lock->path,
+ APR_HASH_KEY_STRING, baton->current_lock);
+ svn_pool_clear(baton->scratchpool);
+ }
break;
case ELEM_lock_path:
@@ -335,15 +362,25 @@ svn_error_t *
svn_ra_neon__get_locks(svn_ra_session_t *session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool)
{
svn_ra_neon__session_t *ras = session->priv;
- const char *body, *url;
+ const char *body, *url, *rel_path;
svn_error_t *err;
int status_code = 0;
get_locks_baton_t baton;
+ /* We always run the report on the 'public' URL, which represents
+ HEAD anyway. If the path doesn't exist in HEAD, then there can't
+ possibly be a lock, so we just return no locks. */
+ url = svn_path_url_add_component2(ras->url->data, path, pool);
+
+ SVN_ERR(svn_ra_get_path_relative_to_root(session, &rel_path, url, pool));
+
baton.lock_hash = apr_hash_make(pool);
+ baton.path = apr_pstrcat(pool, "/", rel_path, NULL);
+ baton.requested_depth = depth;
baton.pool = pool;
baton.scratchpool = svn_pool_create(pool);
baton.current_lock = NULL;
@@ -353,14 +390,10 @@ svn_ra_neon__get_locks(svn_ra_session_t
body = apr_psprintf(pool,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<S:get-locks-report xmlns:S=\"" SVN_XML_NAMESPACE "\" "
- "xmlns:D=\"DAV:\">"
- "</S:get-locks-report>");
-
+ "xmlns:D=\"DAV:\" depth=\"%s\">"
+ "</S:get-locks-report>",
+ svn_depth_to_word(depth));
- /* We always run the report on the 'public' URL, which represents
- HEAD anyway. If the path doesn't exist in HEAD, then there can't
- possibly be a lock, so we just return no locks. */
- url = svn_path_url_add_component(ras->url->data, path, pool);
err = svn_ra_neon__parsed_request(ras, "REPORT", url,
body, NULL, NULL,
Modified: subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h Wed Jun 23 01:22:00
2010
@@ -1022,6 +1022,7 @@ svn_error_t *
svn_ra_neon__get_locks(svn_ra_session_t *session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool);
/*
Modified: subversion/trunk/subversion/libsvn_ra_serf/getlocks.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/getlocks.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/getlocks.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/getlocks.c Wed Jun 23 01:22:00
2010
@@ -76,6 +76,10 @@ typedef struct {
typedef struct {
apr_pool_t *pool;
+ /* target and requested depth of the operation. */
+ const char *path;
+ svn_depth_t requested_depth;
+
/* return hash */
apr_hash_t *hash;
@@ -180,8 +184,32 @@ end_getlocks(svn_ra_serf__xml_parser_t *
else if (state == LOCK &&
strcmp(name.name, "lock") == 0)
{
- apr_hash_set(lock_ctx->hash, info->lock->path, APR_HASH_KEY_STRING,
- info->lock);
+ /* Filter out unwanted paths. Since Subversion only allows
+ locks on files, we can treat depth=immediates the same as
+ depth=files for filtering purposes. Meaning, we'll keep
+ this lock if:
+
+ a) its path is the very path we queried, or
+ b) we've asked for a fully recursive answer, or
+ c) we've asked for depth=files or depth=immediates, and this
+ lock is on an immediate child of our query path.
+ */
+ if ((strcmp(lock_ctx->path, info->lock->path) == 0)
+ || (lock_ctx->requested_depth == svn_depth_infinity))
+ {
+ apr_hash_set(lock_ctx->hash, info->lock->path,
+ APR_HASH_KEY_STRING, info->lock);
+ }
+ else if ((lock_ctx->requested_depth == svn_depth_files) ||
+ (lock_ctx->requested_depth == svn_depth_immediates))
+ {
+ const char *rel_uri = svn_uri_is_child(lock_ctx->path,
+ info->lock->path,
+ info->pool);
+ if (rel_uri && (svn_path_component_count(rel_uri) == 1))
+ apr_hash_set(lock_ctx->hash, info->lock->path,
+ APR_HASH_KEY_STRING, info->lock);
+ }
svn_ra_serf__xml_pop_state(parser);
}
@@ -272,13 +300,14 @@ create_getlocks_body(void *baton,
serf_bucket_alloc_t *alloc,
apr_pool_t *pool)
{
+ lock_context_t *lock_ctx = baton;
serf_bucket_t *buckets;
buckets = serf_bucket_aggregate_create(alloc);
- svn_ra_serf__add_open_tag_buckets(buckets, alloc, "S:get-locks-report",
- "xmlns:S", SVN_XML_NAMESPACE,
- NULL);
+ svn_ra_serf__add_open_tag_buckets(
+ buckets, alloc, "S:get-locks-report", "xmlns:S", SVN_XML_NAMESPACE,
+ "depth", svn_depth_to_word(lock_ctx->requested_depth), NULL);
svn_ra_serf__add_close_tag_buckets(buckets, alloc, "S:get-locks-report");
return buckets;
@@ -288,22 +317,27 @@ svn_error_t *
svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool)
{
lock_context_t *lock_ctx;
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_parser_t *parser_ctx;
- const char *req_url;
+ const char *req_url, *rel_path;
int status_code;
+ req_url = svn_path_url_add_component2(session->repos_url.path, path, pool);
+ SVN_ERR(svn_ra_serf__get_relative_path(&rel_path, req_url, session,
+ NULL, pool));
+
lock_ctx = apr_pcalloc(pool, sizeof(*lock_ctx));
lock_ctx->pool = pool;
+ lock_ctx->path = apr_pstrcat(pool, "/", rel_path, NULL);
+ lock_ctx->requested_depth = depth;
lock_ctx->hash = apr_hash_make(pool);
lock_ctx->done = FALSE;
- req_url = svn_path_url_add_component2(session->repos_url.path, path, pool);
-
handler = apr_pcalloc(pool, sizeof(*handler));
handler->method = "REPORT";
Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Wed Jun 23 01:22:00
2010
@@ -1347,6 +1347,7 @@ svn_error_t *
svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool);
svn_error_t * svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
Modified: subversion/trunk/subversion/libsvn_ra_svn/client.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/client.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/client.c Wed Jun 23 01:22:00 2010
@@ -2210,14 +2210,23 @@ static svn_error_t *ra_svn_get_lock(svn_
static svn_error_t *ra_svn_get_locks(svn_ra_session_t *session,
apr_hash_t **locks,
const char *path,
+ svn_depth_t depth,
apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess = session->priv;
svn_ra_svn_conn_t* conn = sess->conn;
apr_array_header_t *list;
+ const char *abs_path;
int i;
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-locks", "c", path));
+ /* Figure out the repository abspath from PATH. */
+ abs_path = svn_path_url_add_component2(sess->url, path, pool);
+ SVN_ERR(svn_ra_get_path_relative_to_root(session, &abs_path,
+ abs_path, pool));
+ abs_path = apr_pstrcat(pool, "/", abs_path, NULL);
+
+ SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-locks", "c?w", path,
+ svn_depth_to_word(depth)));
/* Servers before 1.2 doesn't support locking. Check this here. */
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess, pool),
@@ -2237,7 +2246,27 @@ static svn_error_t *ra_svn_get_locks(svn
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Lock element not a list"));
SVN_ERR(parse_lock(elt->u.list, pool, &lock));
- apr_hash_set(*locks, lock->path, APR_HASH_KEY_STRING, lock);
+
+ /* Filter out unwanted paths. Since Subversion only allows
+ locks on files, we can treat depth=immediates the same as
+ depth=files for filtering purposes. Meaning, we'll keep
+ this lock if:
+
+ a) its path is the very path we queried, or
+ b) we've asked for a fully recursive answer, or
+ c) we've asked for depth=files or depth=immediates, and this
+ lock is on an immediate child of our query path.
+ */
+ if ((strcmp(abs_path, lock->path) == 0) || (depth == svn_depth_infinity))
+ {
+ apr_hash_set(*locks, lock->path, APR_HASH_KEY_STRING, lock);
+ }
+ else if ((depth == svn_depth_files) || (depth == svn_depth_immediates))
+ {
+ const char *rel_uri = svn_uri_is_child(abs_path, lock->path, pool);
+ if (rel_uri && (svn_path_component_count(rel_uri) == 1))
+ apr_hash_set(*locks, lock->path, APR_HASH_KEY_STRING, lock);
+ }
}
return SVN_NO_ERROR;
Modified: subversion/trunk/subversion/libsvn_repos/fs-wrap.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/fs-wrap.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/trunk/subversion/libsvn_repos/fs-wrap.c Wed Jun 23 01:22:00 2010
@@ -528,10 +528,8 @@ get_locks_callback(void *baton,
/* If there's auth to deal with, deal with it. */
if (b->authz_read_func)
- {
- SVN_ERR(b->authz_read_func(&readable, b->head_root, lock->path,
- b->authz_read_baton, pool));
- }
+ SVN_ERR(b->authz_read_func(&readable, b->head_root, lock->path,
+ b->authz_read_baton, pool));
/* If we can read this lock path, add the lock to the return hash. */
if (readable)
@@ -543,19 +541,23 @@ get_locks_callback(void *baton,
svn_error_t *
-svn_repos_fs_get_locks(apr_hash_t **locks,
- svn_repos_t *repos,
- const char *path,
- svn_repos_authz_func_t authz_read_func,
- void *authz_read_baton,
- apr_pool_t *pool)
+svn_repos_fs_get_locks2(apr_hash_t **locks,
+ svn_repos_t *repos,
+ const char *path,
+ svn_depth_t depth,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *pool)
{
apr_hash_t *all_locks = apr_hash_make(pool);
svn_revnum_t head_rev;
struct get_locks_baton_t baton;
- /* Locks are always said to apply to HEAD revision, so we'll check
- to see if locked-paths are readable in HEAD as well. */
+ SVN_ERR_ASSERT((depth == svn_depth_empty) ||
+ (depth == svn_depth_files) ||
+ (depth == svn_depth_immediates) ||
+ (depth == svn_depth_infinity));
+
SVN_ERR(svn_fs_youngest_rev(&head_rev, repos->fs, pool));
/* Populate our callback baton. */
@@ -567,8 +569,8 @@ svn_repos_fs_get_locks(apr_hash_t **lock
head_rev, pool));
/* Get all the locks. */
- SVN_ERR(svn_fs_get_locks(repos->fs, path, get_locks_callback,
- &baton, pool));
+ SVN_ERR(svn_fs_get_locks2(repos->fs, path, depth,
+ get_locks_callback, &baton, pool));
*locks = baton.locks;
return SVN_NO_ERROR;
@@ -576,6 +578,21 @@ svn_repos_fs_get_locks(apr_hash_t **lock
svn_error_t *
+svn_repos_fs_get_locks(apr_hash_t **locks,
+ svn_repos_t *repos,
+ const char *path,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_return(svn_repos_fs_get_locks2(locks, repos, path,
+ svn_depth_infinity,
+ authz_read_func,
+ authz_read_baton, pool));
+}
+
+
+svn_error_t *
svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo,
svn_repos_t *repos,
const apr_array_header_t *paths,
Modified: subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c Wed Jun 23
01:22:00 2010
@@ -186,6 +186,9 @@ dav_svn__get_locks_report(const dav_reso
apr_status_t apr_err;
apr_hash_t *locks;
dav_svn__authz_read_baton arb;
+ svn_depth_t depth = svn_depth_unknown;
+ apr_pool_t *pool = resource->pool;
+ apr_xml_attr *this_attr;
/* The request URI should be a public one representing an fs path. */
if ((! resource->info->repos_path)
@@ -197,12 +200,33 @@ dav_svn__get_locks_report(const dav_reso
arb.r = resource->info->r;
arb.repos = resource->info->repos;
+ /* See if the client provided additional information for this request. */
+ for (this_attr = doc->root->attr; this_attr; this_attr = this_attr->next)
+ {
+ if (strcmp(this_attr->name, "depth") == 0)
+ {
+ depth = svn_depth_from_word(this_attr->value);
+ if ((depth != svn_depth_empty) &&
+ (depth != svn_depth_files) &&
+ (depth != svn_depth_immediates) &&
+ (depth != svn_depth_infinity))
+ return dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+ "Invalid 'depth' specified in "
+ "get-locks-report request.");
+ continue;
+ }
+ }
+
+ /* For compatibility, our default depth is infinity. */
+ if (depth == svn_depth_unknown)
+ depth = svn_depth_infinity;
+
/* Fetch the locks, but allow authz_read checks to happen on each. */
- if ((err = svn_repos_fs_get_locks(&locks,
- resource->info->repos->repos,
- resource->info->repos_path,
- dav_svn__authz_read_func(&arb), &arb,
- resource->pool)) != SVN_NO_ERROR)
+ if ((err = svn_repos_fs_get_locks2(&locks,
+ resource->info->repos->repos,
+ resource->info->repos_path, depth,
+ dav_svn__authz_read_func(&arb), &arb,
+ resource->pool)) != SVN_NO_ERROR)
return dav_svn__convert_err(err, HTTP_INTERNAL_SERVER_ERROR,
err->message, resource->pool);
Modified: subversion/trunk/subversion/svnserve/serve.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/serve.c?rev=957094&r1=957093&r2=957094&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/serve.c (original)
+++ subversion/trunk/subversion/svnserve/serve.c Wed Jun 23 01:22:00 2010
@@ -2572,21 +2572,23 @@ static svn_error_t *get_locks(svn_ra_svn
server_baton_t *b = baton;
const char *path;
const char *full_path;
+ const char *depth_word;
+ svn_depth_t depth;
apr_hash_t *locks;
apr_hash_index_t *hi;
- SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c", &path));
+ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c?w", &path, &depth_word));
- full_path = svn_uri_join(b->fs_path->data, svn_uri_canonicalize(path,
- pool),
- pool);
+ depth = depth_word ? svn_depth_from_word(depth_word) : svn_depth_infinity;
+ full_path = svn_uri_join(b->fs_path->data,
+ svn_uri_canonicalize(path, pool), pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
SVN_ERR(log_command(b, conn, pool, "get-locks %s",
svn_path_uri_encode(full_path, pool)));
- SVN_CMD_ERR(svn_repos_fs_get_locks(&locks, b->repos, full_path,
- authz_check_access_cb_func(b), b, pool));
+ SVN_CMD_ERR(svn_repos_fs_get_locks2(&locks, b->repos, full_path, depth,
+ authz_check_access_cb_func(b), b, pool));
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "success"));
for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi))