On Fri, Dec 18, 2009 at 10:04:37AM +0000, Philip Martin wrote:
> Daniel Näslund <dan...@longitudo.com> writes:
> 
> > On Thu, Dec 17, 2009 at 06:10:18PM +0000, Philip Martin wrote:
> >> Daniel Näslund <dan...@longitudo.com> writes:
> >> >  
> >> > +      SVN_ERR(svn_wc__release_write_lock(ib->ctx->wc_ctx, 
> >> > +                                         remove_target_abspath,
> >> > +                                         ib->iter_pool));
> >> > +
> >> 
> >> Why the change in behaviour?  The old code would leave the locks if
> >> the remove call failed. Is this because you are no longer locking the
> >> external?
> >
> > A comment in svn_wc_acquire_write_locks():
> >
> > [[[
> >   /* The current lock paradigm is that each directory holds a lock for 
> > itself,
> >      and there are no inherited locks.  In the eventual wc-ng paradigm, a
> >      lock on a directory, would imply a infinite-depth lock on the children.
> >      But since we aren't quite there yet, we do the infinite locking
> >      manually (and be sure to release them in svn_wc__release_write_lock(). 
> > */
> > ]]]
> >
> > Why leave locks we have created if the operation we attempted to do
> > failed?
> 
> That's how locks work.
> 
>  - take the lock
>  - make changes possibly leaving the wc inconsistent
>  - complete changes making the wc consistent
>  - remove lock
>
> If an error occurs that aborts the operation while the wc is
> inconsistent then the lock should not be removed.

I didn't know that. I've learned something new. A good thing for me! :-)
 
> The original code was ignoring LEFT_LOCAL_MOD errors, treating them as
> not-an-error, so it removed locks in that case.  For other errors it
> left the locks.

I did that since I thought the locks weren't neccessary once the
operation had failed.
 
> The other problem with your new code is that if the
> svn_wc__release_write_lock call returns an error any error from the
> svn_wc_remove_from_revision_control2 call will leak.

Fixed.

I've used svn_wc_locked2() for checking if there already exists a
write_lock. 

make check passed!

[[[
Use recursive locking when deleting an external. No need to make a
distinction between files and dirs as the previous code did.

* subversion/libsvn_client/externals.c
  (handle_external_item_change): Remove the adm_access functions and use
    svn_wc_{acqurire,release}write_lock instead and svn_wc_locked()
    instead.

Patch by: Daniel Näslund <daniel{_AT_}longitudo.com>
Review by: philip
]]]

/Daniel
Index: subversion/libsvn_client/externals.c
===================================================================
--- subversion/libsvn_client/externals.c	(revision 892468)
+++ subversion/libsvn_client/externals.c	(arbetskopia)
@@ -894,51 +894,22 @@
          just be renamed to a new one. */
 
       svn_error_t *err;
-      svn_wc_adm_access_t *adm_access;
-      svn_boolean_t close_access_baton_when_done;
-
       const char *remove_target_abspath;
+      svn_boolean_t lock_existed; 
 
-      /* Determine if a directory or file external is being removed.
-         Try to handle the case when the user deletes the external by
-         hand or it is missing.  First try to open the directory for a
-         directory external.  If that doesn't work, get the access
-         baton for the parent directory and remove the entry for the
-         external. */
-      err = svn_wc__adm_open_in_context(&adm_access, ib->ctx->wc_ctx, path,
-                                        TRUE, -1, ib->ctx->cancel_func,
-                                        ib->ctx->cancel_baton, ib->iter_pool);
-      if (err)
-        {
-          const char *anchor;
-          const char *target;
-          svn_error_t *err2;
+      SVN_ERR(svn_dirent_get_absolute(&remove_target_abspath,
+                                      path,
+                                      ib->iter_pool));
 
-          SVN_ERR(svn_wc_get_actual_target2(&anchor, &target, ib->ctx->wc_ctx,
-                                            path, ib->iter_pool,
-                                            ib->iter_pool));
+      SVN_ERR(svn_wc_locked2(&lock_existed, NULL, ib->ctx->wc_ctx,
+                             remove_target_abspath, ib->iter_pool));
 
-          err2 = svn_wc_adm_retrieve(&adm_access, ib->adm_access, anchor,
-                                     ib->iter_pool);
-          if (err2)
-            {
-              svn_error_clear(err2);
-              return svn_error_return(err);
-            }
-          else
-            {
-              svn_error_clear(err);
-            }
-          close_access_baton_when_done = FALSE;
-          SVN_ERR(svn_dirent_get_absolute(&remove_target_abspath, target,
-                                          ib->iter_pool));
-        }
-      else
+      if (! lock_existed)
         {
-          close_access_baton_when_done = TRUE;
-          SVN_ERR(svn_dirent_get_absolute(&remove_target_abspath,
-                                          svn_wc_adm_access_path(adm_access),
-                                          ib->iter_pool));
+          SVN_ERR(svn_wc__acquire_write_lock(NULL, ib->ctx->wc_ctx,
+                                             remove_target_abspath, 
+                                             ib->iter_pool,
+                                             ib->iter_pool));
         }
 
       /* We don't use relegate_dir_external() here, because we know that
@@ -965,13 +936,15 @@
         }
 
       /* ### Ugly. Unlock only if not going to return an error. Revisit */
-      if (close_access_baton_when_done &&
-          (!err || err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
+      if (! lock_existed
+          && (! err || err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
         {
-          svn_error_t *err2 = svn_wc_adm_close2(adm_access, ib->iter_pool);
+          svn_error_t *err2 = svn_wc__release_write_lock(ib->ctx->wc_ctx, 
+                                                         remove_target_abspath,
+                                                         ib->iter_pool);
           if (err2)
             {
-              if (!err)
+              if (! err)
                 err = err2;
               else
                 svn_error_clear(err2);

Reply via email to