D.J. Heap wrote:
> However, IIRC from past discussions, the desired direction is for the
> api's to take a single 'depth' argument indicating how far to recurse --
> can a core developer verify?
Here is an alternative patch, that does it that way. As I said, I don't
feel strongly about which approach is better.
For consistency, I've also changed svn_wc_adm_probe_try().
(If anyone prefers the original patch, I'll update that to change this
function, too).
Attached patch is against the trunk, revision 8867.
[[[
Fix issue #1680: Don't lock entire tree in svn status --non-recursive
* svn_wc.h
(svn_wc_adm_open_depth, svn_wc_adm_probe_open_depth,
svn_wc_adm_probe_try_depth): New functions.
(svn_wc_adm_open, svn_wc_adm_probe_open, svn_wc_adm_probe_try):
Changed comments.
* libsvn_wc/lock.c
(do_open): Replace tree_lock parameter with depth, and use it.
(svn_wc__adm_pre_open): Fixup call to do_open.
(svn_wc_adm_open_depth): New function.
(svn_wc_adm_open): Reimplement as trivial wrapper.
(svn_wc_adm_probe_open_depth): New function.
(svn_wc_adm_probe_open): Reimplement as trivial wrapper.
(svn_wc_adm_probe_try_depth): New function.
(svn_wc_adm_probe_try): Reimplement as trivial wrapper.
* libsvn_client/status.c
(svn_client_status): Use svn_wc_adm_probe_open_depth to avoid excessive
recursion if --non-recursive.
]]]
Kind regards,
Jon Foster
Index: subversion/include/svn_wc.h
===================================================================
--- subversion/include/svn_wc.h (revision 8867)
+++ subversion/include/svn_wc.h (working copy)
@@ -76,14 +76,18 @@
* to the set containing @a associated. @a associated can be @c NULL, in
* which case @a adm_access is the start of a new set.
*
- * If @a tree_lock is @c TRUE then the working copy directory hierarchy under
- * @a path will be locked. All the access batons will become part of the set
- * containing @a adm_access. This is an all-or-nothing option, if it is not
- * possible to lock the entire tree then an error will be returned and
- * @a adm_access will be invalid, with the exception that subdirectories of
- * @a path that are missing from the physical filesystem will not be locked
- * and will not cause an error. The error @c SVN_ERR_WC_LOCKED will be
- * returned if a subdirectory of @a path is already write locked.
+ * @a depth specifies how much to lock. Zero means just the specified
+ * directory. Any negative value means to lock the entire working copy
+ * directory hierarchy under @a path. A positive value indicates the number of
+ * levels of directories to lock - 1 means just immediate subdirectories, 2
+ * means immediate subdirectories and their subdirectories, etc. All the
+ * access batons will become part of the set containing @a adm_access. This
+ * is an all-or-nothing option, if it is not possible to lock all the
+ * requested directories then an error will be returned and @a adm_access will
+ * be invalid, with the exception that subdirectories of @a path that are
+ * missing from the physical filesystem will not be locked and will not cause
+ * an error. The error @c SVN_ERR_WC_LOCKED will be returned if a
+ * subdirectory of @a path is already write locked.
*
* @a pool will be used to allocate memory for the baton and any subsequently
* cached items. If @a adm_access has not been closed when the pool is
@@ -95,6 +99,19 @@
* the longest lifetime of all the batons in the set. This implies it must be
* the root of the hierarchy.
*/
+svn_error_t *svn_wc_adm_open_depth (svn_wc_adm_access_t **adm_access,
+ svn_wc_adm_access_t *associated,
+ const char *path,
+ svn_boolean_t write_lock,
+ int depth,
+ apr_pool_t *pool);
+
+/**
+ * Same as svn_wc_adm_open_depth(). @a depth is set to -1 if @a tree_lock is
+ * @c TRUE, else 0.
+ *
+ * Provided for backward compatibility with the Subversion 1.0.0 API.
+ */
svn_error_t *svn_wc_adm_open (svn_wc_adm_access_t **adm_access,
svn_wc_adm_access_t *associated,
const char *path,
@@ -104,14 +121,27 @@
/** Checks the working copy to determine the node type of @a path. If
* @a path is a versioned directory then the behaviour is like that of
- * @c svn_wc_adm_open, otherwise, if @a path is a file or does not
- * exist, then the behaviour is like that of @c svn_wc_adm_open with
+ * @c svn_wc_adm_open_depth, otherwise, if @a path is a file or does not
+ * exist, then the behaviour is like that of @c svn_wc_adm_open_depth with
* @a path replaced by the parent directory of @a path. If @a path is
* an unversioned directory, the behaviour is also like that of
- * @c svn_wc_adm_open on the parent, except that if the open fails,
+ * @c svn_wc_adm_open_depth on the parent, except that if the open fails,
* then the returned SVN_ERR_WC_NOT_DIRECTORY error refers to @a path,
* not to @a path's parent.
*/
+svn_error_t *svn_wc_adm_probe_open_depth (svn_wc_adm_access_t **adm_access,
+ svn_wc_adm_access_t *associated,
+ const char *path,
+ svn_boolean_t write_lock,
+ int depth,
+ apr_pool_t *pool);
+
+/**
+ * Same as svn_wc_adm_probe_open_depth(). @a depth is set to -1 if
+ * @a tree_lock is @c TRUE, else 0.
+ *
+ * Provided for backward compatibility with the Subversion 1.0.0 API.
+ */
svn_error_t *svn_wc_adm_probe_open (svn_wc_adm_access_t **adm_access,
svn_wc_adm_access_t *associated,
const char *path,
@@ -149,8 +179,8 @@
*
* First, try to obtain @a *adm_access via @c svn_wc_adm_probe_retrieve(),
* but if this fails because @a associated can't give a baton for
- * @a path or @a path's parent, then try @c svn_wc_adm_probe_open(),
- * this time passing @a write_lock and @a tree_lock. If there is
+ * @a path or @a path's parent, then try @c svn_wc_adm_probe_open_depth(),
+ * this time passing @a write_lock and @a depth. If there is
* still no access because @a path is not a versioned directory, then
* just set @a *adm_access to null and return success. But if it is
* because @a path is locked, then return the error @c SVN_ERR_WC_LOCKED,
@@ -163,6 +193,19 @@
*
* Use @a pool only for local processing, not to allocate @a *adm_access.
*/
+svn_error_t *svn_wc_adm_probe_try_depth (svn_wc_adm_access_t **adm_access,
+ svn_wc_adm_access_t *associated,
+ const char *path,
+ svn_boolean_t write_lock,
+ int depth,
+ apr_pool_t *pool);
+
+/**
+ * Same as svn_wc_adm_probe_try_depth(). @a depth is set to -1 if
+ * @a tree_lock is @c TRUE, else 0.
+ *
+ * Provided for backward compatibility with the Subversion 1.0.0 API.
+ */
svn_error_t *svn_wc_adm_probe_try (svn_wc_adm_access_t **adm_access,
svn_wc_adm_access_t *associated,
const char *path,
Index: subversion/libsvn_wc/lock.c
===================================================================
--- subversion/libsvn_wc/lock.c (revision 8867)
+++ subversion/libsvn_wc/lock.c (working copy)
@@ -331,7 +331,7 @@
svn_wc_adm_access_t *associated,
const char *path,
svn_boolean_t write_lock,
- svn_boolean_t tree_lock,
+ int depth,
svn_boolean_t under_construction,
apr_pool_t *pool)
{
@@ -396,12 +396,16 @@
SVN_ERR (maybe_upgrade_format (lock, pool));
}
- if (tree_lock)
+ if (depth != 0)
{
apr_hash_t *entries;
apr_hash_index_t *hi;
apr_pool_t *subpool = svn_pool_create (pool);
+ /* Reduce depth since we are about to recurse */
+ if (depth > 0)
+ depth--;
+
/* Ask for the deleted entries because most operations request them
at some stage, getting them now avoids a second file parse. */
SVN_ERR (svn_wc_entries_read (&entries, lock, TRUE, subpool));
@@ -429,7 +433,7 @@
entry_path = svn_path_join (lock->path, entry->name, subpool);
/* Don't use the subpool pool here, the lock needs to persist */
- err = do_open (&entry_access, lock, entry_path, write_lock, tree_lock,
+ err = do_open (&entry_access, lock, entry_path, write_lock, depth,
FALSE, lock->pool);
if (err)
{
@@ -496,6 +500,7 @@
return SVN_NO_ERROR;
}
+/* This kludge is to preserve API compatibility with 1.0 */
svn_error_t *
svn_wc_adm_open (svn_wc_adm_access_t **adm_access,
svn_wc_adm_access_t *associated,
@@ -504,7 +509,19 @@
svn_boolean_t tree_lock,
apr_pool_t *pool)
{
- return do_open (adm_access, associated, path, write_lock, tree_lock, FALSE,
+ return svn_wc_adm_open_depth (adm_access, associated, path, write_lock,
+ (tree_lock ? -1 : 0), pool);
+}
+
+svn_error_t *
+svn_wc_adm_open_depth (svn_wc_adm_access_t **adm_access,
+ svn_wc_adm_access_t *associated,
+ const char *path,
+ svn_boolean_t write_lock,
+ int depth,
+ apr_pool_t *pool)
+{
+ return do_open (adm_access, associated, path, write_lock, depth, FALSE,
pool);
}
@@ -513,10 +530,11 @@
const char *path,
apr_pool_t *pool)
{
- return do_open (adm_access, NULL, path, TRUE, FALSE, TRUE, pool);
+ return do_open (adm_access, NULL, path, TRUE, 0, TRUE, pool);
}
-
+
+/* This kludge is to preserve API compatibility with 1.0 */
svn_error_t *
svn_wc_adm_probe_open (svn_wc_adm_access_t **adm_access,
svn_wc_adm_access_t *associated,
@@ -525,6 +543,19 @@
svn_boolean_t tree_lock,
apr_pool_t *pool)
{
+ return svn_wc_adm_probe_open_depth (adm_access, associated, path,
+ write_lock, (tree_lock ? -1 : 0), pool);
+}
+
+
+svn_error_t *
+svn_wc_adm_probe_open_depth (svn_wc_adm_access_t **adm_access,
+ svn_wc_adm_access_t *associated,
+ const char *path,
+ svn_boolean_t write_lock,
+ int depth,
+ apr_pool_t *pool)
+{
svn_error_t *err;
const char *dir;
int wc_format;
@@ -532,14 +563,14 @@
SVN_ERR (probe (&dir, path, &wc_format, pool));
/* If we moved up a directory, then the path is not a directory, or it
- is not under version control. In either case, the notion of a tree_lock
+ is not under version control. In either case, the notion of a depth
does not apply to the provided path. Disable it so that we don't end
up trying to lock more than we need. */
if (dir != path)
- tree_lock = FALSE;
+ depth = 0;
- err = svn_wc_adm_open (adm_access, associated, dir, write_lock, tree_lock,
- pool);
+ err = svn_wc_adm_open_depth (adm_access, associated, dir, write_lock,
+ depth, pool);
if (err)
{
svn_error_t *err2;
@@ -636,6 +667,7 @@
}
+/* This kludge is to preserve API compatibility with 1.0 */
svn_error_t *
svn_wc_adm_probe_try (svn_wc_adm_access_t **adm_access,
svn_wc_adm_access_t *associated,
@@ -644,6 +676,18 @@
svn_boolean_t tree_lock,
apr_pool_t *pool)
{
+ return svn_wc_adm_probe_try_depth (adm_access, associated, path, write_lock,
+ (tree_lock ? -1 : 0), pool);
+}
+
+svn_error_t *
+svn_wc_adm_probe_try_depth (svn_wc_adm_access_t **adm_access,
+ svn_wc_adm_access_t *associated,
+ const char *path,
+ svn_boolean_t write_lock,
+ int depth,
+ apr_pool_t *pool)
+{
svn_error_t *err;
err = svn_wc_adm_probe_retrieve (adm_access, associated, path, pool);
@@ -654,9 +698,9 @@
if (err && (err->apr_err == SVN_ERR_WC_NOT_LOCKED))
{
svn_error_clear (err);
- err = svn_wc_adm_probe_open (adm_access, associated,
- path, write_lock, tree_lock,
- svn_wc_adm_access_pool (associated));
+ err = svn_wc_adm_probe_open_depth (adm_access, associated,
+ path, write_lock, depth,
+ svn_wc_adm_access_pool (associated));
/* If the path is not a versioned directory, we just return a
null access baton with no error. Note that of the errors we
Index: subversion/libsvn_client/status.c
===================================================================
--- subversion/libsvn_client/status.c (revision 8867)
+++ subversion/libsvn_client/status.c (working copy)
@@ -121,10 +121,11 @@
/* Close up our ADM area. We'll be re-opening soon. */
SVN_ERR (svn_wc_adm_close (adm_access));
- /* Need to lock the tree as even a non-recursive status requires the
- immediate directories to be locked. */
- SVN_ERR (svn_wc_adm_probe_open (&adm_access, NULL, anchor,
- FALSE, TRUE, pool));
+ /* Need to lock the tree. A non-recursive status requires the
+ immediate subdirectories to be locked. A recursive status
+ requires us to lock the whole tree. */
+ SVN_ERR (svn_wc_adm_probe_open_depth (&adm_access, NULL, anchor,
+ FALSE, (descend ? -1 : 1), pool));
/* Get the status edit, and use our wrapping status function/baton
as the callback pair. */
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sun Feb 29 14:14:18 2004