[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] svn status --non-recursive should not recurse

From: Jon Foster <jon_at_jon-foster.co.uk>
Date: 2004-02-29 14:15:05 CET

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

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.