The attached patch makes some improvements to how we report that the WC
is locked or busy (the 'run cleanup' messages).  I need a sanity check
to make sure I've understood the relationship between how we want to
handle 'the work queue is busy' and 'there is a write lock on a WC
directory'.

When the WC is locked we may (depending on the timing) see:

  $ svn up -q & svn up -q
  svn: E155004: Working copy '/home/...' locked.
  svn: E155004: '/home/...' is already locked.
  svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for
details)

(or, depending on the timing, there may be two 'database is locked'
lines instead of the 'is already locked' line), or

  $ svn up & svn commit
  svn: E155004: Commit failed (details follow):
  svn: E155004: Working copy '/home/...' locked.
  svn: E155004: '/home/...' is already locked.
  svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for
details)

When the work queue is not empty, we see:

  $ svn status
  svn: E155037: Previous operation has not finished; run 'cleanup' if it
was interrupted


My recommendations, mainly for the WQ-not-empty case:

1.  The 'E155037' message shown above comes from libsvn_wc.  But the
part about running 'cleanup' should be added by 'svn', since in other
clients it may have a different name or may not be applicable at all,
especially if the client can find out that in fact the other operation
is still running.  So libsvn_wc would say just:

  "A previous operation on the working copy has not finished"

and 'svn' would wrap that in:

  "Run 'svn cleanup' if the previous operation was interrupted"

See also point (2).

2.  Consider wrapping this SVN_ERR_WC_CLEANUP_REQUIRED (E155037) error
in a SVN_ERR_WC_LOCKED (E155004) error to preserve API compatibility
w.r.t. this kind of situation.  Inside libsvn_wc, of course the
condition being reported here is not the same as a 'lock', but to an
outside caller the net effect is basically that it's a lock.

If we don't wrap this in SVN_ERR_WC_LOCKED, then in order to support
(1), 'svn' should learn to recognize the new error code as well, at the
point where it determines whether to suggest the user should run
'cleanup'.

3.  The error code SVN_ERR_WC_CLEANUP_REQUIRED is misnamed, since
libsvn_wc does not know whether cleanup is required.  Rename it to
SVN_ERR_WC_BUSY or SVN_ERR_WC_WORK_QUEUE_NOT_EMPTY.

4.  libsvn_wc should include the WC root in the error message:

  "A previous operation on the working copy at '<wcroot_abspath>' has
not finished"

5.  'svn' should print its message about running 'cleanup' via the
standard error message mechanism instead of using cmdline_fputs(), so
that the message appears in the standard (new) format with the
'Ennnnnn:' prefix.  This suggestion is independent of the others so I'll
commit it separately, but it's included in this patch for you to see.


With this patch, typical results are:

  $ svn up -q & svn up -q
  svn: E155004: Run 'svn cleanup' to remove locks (type 'svn help
cleanup' for details)
  svn: E155004: Working copy '/home/...' locked.
  svn: E155004: '/home/...' is already locked.

  $ svn up -q & svn commit
  svn: E155004: Run 'svn cleanup' to remove locks (type 'svn help
cleanup' for details)
  svn: E155004: Commit failed (details follow):
  svn: E155004: Working copy '/home/...' locked.
  svn: E155004: '/home/...' is already locked.

and for the more interesting, WQ-not-empty, case:

  $ svn status
  svn: E155037: Run 'svn cleanup' to remove locks (type 'svn help
cleanup' for details)
  svn: E155037: A previous operation on the working copy at '/home/...'
has not finished


I would propose all of this for 1.7.0 back-port.

Concerns?

- Julian

Improve how we report that the WC is locked or busy (the 'run cleanup'
messages).

* subversion/include/svn_error_codes.h
  (SVN_ERR_WC_CLEANUP_REQUIRED): Rename to SVN_ERR_WC_BUSY and remove the
    words about running 'cleanup', since libsvn_wc doesn't know whether
    cleanup is required.

* subversion/libsvn_wc/wc_db_wcroot.c
  (verify_no_work): Take the WC root path and include that in the error
    message. Add a doc string.
  (svn_wc__db_pdh_create_wcroot): Adjust accordingly.

* subversion/svn/main.c
  (main): Print the message about running 'cleanup' when the subcommand
    returned SVN_ERR_WC_BUSY as well as when it returned SVN_ERR_WC_LOCKED.
    Print the message about running 'cleanup' using the standard mechanism
    for error messages (so, for example, the error code will be displayed).
--This line, and those below, will be ignored--

Index: subversion/include/svn_error_codes.h
===================================================================
--- subversion/include/svn_error_codes.h	(revision 1145998)
+++ subversion/include/svn_error_codes.h	(working copy)
@@ -520,10 +520,9 @@ SVN_ERROR_START
              "The working copy needs to be upgraded")
 
   /** @since New in 1.7. */
-  SVN_ERRDEF(SVN_ERR_WC_CLEANUP_REQUIRED,
+  SVN_ERRDEF(SVN_ERR_WC_BUSY,
              SVN_ERR_WC_CATEGORY_START + 37,
-             "Previous operation has not finished; "
-             "run 'cleanup' if it was interrupted")
+             "A previous operation on the working copy has not finished")
 
   /** @since New in 1.7. */
   SVN_ERRDEF(SVN_ERR_WC_INVALID_OPERATION_DEPTH,
Index: subversion/libsvn_wc/wc_db_wcroot.c
===================================================================
--- subversion/libsvn_wc/wc_db_wcroot.c	(revision 1145998)
+++ subversion/libsvn_wc/wc_db_wcroot.c	(working copy)
@@ -139,9 +139,12 @@ get_path_kind(svn_wc__db_t *db,
 }
 
 
-/* */
+/* Return an error if the work queue in SDB is non-empty.  WCROOT_ABSPATH
+ * is used in the error message. */
 static svn_error_t *
-verify_no_work(svn_sqlite__db_t *sdb)
+verify_no_work(svn_sqlite__db_t *sdb,
+               const char *wcroot_abspath,
+               apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
@@ -151,8 +154,11 @@ verify_no_work(svn_sqlite__db_t *sdb)
   SVN_ERR(svn_sqlite__reset(stmt));
 
   if (have_row)
-    return svn_error_create(SVN_ERR_WC_CLEANUP_REQUIRED, NULL,
-                            NULL /* nothing to add.  */);
+    return svn_error_createf(SVN_ERR_WC_BUSY, NULL,
+                             _("A previous operation on the working "
+                               "copy at '%s' has not finished"),
+                             svn_dirent_local_style(wcroot_abspath,
+                                                    scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -275,12 +281,12 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_
   if (format >= SVN_WC__HAS_WORK_QUEUE
       && (enforce_empty_wq || (format < SVN_WC__VERSION && auto_upgrade)))
     {
-      svn_error_t *err = verify_no_work(sdb);
+      svn_error_t *err = verify_no_work(sdb, wcroot_abspath, scratch_pool);
       if (err)
         {
           /* Special message for attempts to upgrade a 1.7-dev wc with
              outstanding workqueue items. */
-          if (err->apr_err == SVN_ERR_WC_CLEANUP_REQUIRED
+          if (err->apr_err == SVN_ERR_WC_BUSY
               && format < SVN_WC__VERSION && auto_upgrade)
             err = svn_error_quick_wrap(err, _("Cleanup with an older 1.7 "
                                               "client before upgrading with "
Index: subversion/svn/main.c
===================================================================
--- subversion/svn/main.c	(revision 1145998)
+++ subversion/svn/main.c	(working copy)
@@ -2596,6 +2596,14 @@ main(int argc, const char *argv[])
                                      _("Please see the 'svn upgrade' command"));
         }
 
+      /* Tell the user about 'svn cleanup' if any error on the stack
+         was about locked working copies. */
+      if (svn_error_find_cause(err, SVN_ERR_WC_LOCKED)
+          || svn_error_find_cause(err, SVN_ERR_WC_BUSY))
+        err = svn_error_quick_wrap(err,
+                                   _("Run 'svn cleanup' to remove locks "
+                                     "(type 'svn help cleanup' for details)"));
+
       /* Issue #3014:
        * Don't print anything on broken pipes. The pipe was likely
        * closed by the process at the other end. We expect that
@@ -2606,14 +2614,6 @@ main(int argc, const char *argv[])
       if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
         svn_handle_error2(err, stderr, FALSE, "svn: ");
 
-      /* Tell the user about 'svn cleanup' if any error on the stack
-         was about locked working copies. */
-      if (svn_error_find_cause(err, SVN_ERR_WC_LOCKED))
-        svn_error_clear(svn_cmdline_fputs(_("svn: run 'svn cleanup' to "
-                                            "remove locks (type 'svn help "
-                                            "cleanup' for details)\n"),
-                                          stderr, pool));
-
       svn_error_clear(err);
       svn_pool_destroy(pool);
       return EXIT_FAILURE;

Reply via email to