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

Re: Tree conflicts - problem handling when local directory is deleted

From: Stephen Butler <sbutler_at_elego.de>
Date: Fri, 23 Jan 2009 19:56:53 +0100

Quoting Julian Foad <julianfoad_at_btopenworld.com>:

> On Thu, 2009-01-22 at 17:07 +0100, Stephen Butler wrote:
>> Quoting Mark Phippard <mphippard_at_collab.net>:
>> > On Thu, Jan 22, 2009 at 9:56 AM, Julian Foad
>> > <julianfoad_at_btopenworld.com> wrote:
>> >> FYI I'm just about to look at this.
>> >
>> > I added an svn info to the script to look at the tree conflict. The
>> > problem is that after running update the local revision in the WC for
>> > the folder is 1 when it should have been updated to 2 by the update
>> > command. So this is why it is out of date when you try to commit.
>> > When the tree conflict was created it should have still allowed the WC
>> > revision to be updated.
>> Turning off the skipping of tree conflict victims is pretty
>> straightforward, at least for this use case (#1 in
>> notes/tree-conflicts/detection.txt).
> Is it? "Turning off skipping" means "designing and implementing some
> behaviour other than skipping". The local node is scheduled for
> deletion. The incoming change is to modify it. I assume the existing
> "update" code would not handle this case already.
> The behavior we want for UC1 is: the WC should end up scheduled for
> delete, but with an updated base, like it would if we reverted the local
> delete, updated, and then re-did the local delete.
> I am doing the corresponding thing for Use Case 2 (where the deletion is
> incoming and the modification is local) in issue #3334. It is
> straightforward in concept, but hard because the WC entry state
> manipulations are so hard to get right.
> It would be great if we can do this for Use Case 1 too. It sounds like
> it is important.


I'd also like to do something similar for UC3 "local delete, incoming
delete on update". I suspect it will be simpler than UC1 or UC2.

>> What should we do if the user runs update again without resolving the
>> existing tree conflict first? Skipping is not an option.
> Why is skipping not an option when there's an existing tree conflict?
> Skipping is exactly what we should do when there's any existing conflict
> (tree or otherwise), as per the comment I put at the top of
> libsvn_wc/update_editor.c.

Sorry I didn't explain my "Skipping is not an option" remark above.
Here's an exceedingly elaborate elaboration. But, hey, it's a major
design change we're talking about!

What I really meant was, "Skipping trees is intended to avoid
confusion. Unfortunately, skipping makes it more difficult for the
user to figure out the state of a working copy."

Skipping tends to leave the working copy with mixed revisions.
After update, the user expects one consistent revision throughout
the working copy, in the absence of errors, even if conflicts are

Is it even practical to skip only "old" tree conflicts? Let's see...

In UC1 "local delete, incoming edit on update", the update editor
walks the local tree as far as necessary to handle the incoming edits.
Same for the "local add, incoming add on update" case.

Various callbacks check for an existing tree conflict in the current
item and its ancestor dirs in the working copy. We implement
skipping, notification, etc in each callback.

For the proposed "skip only the pre-existing tree conflicts" feature,
each callback's behavior should depend on whether the existing tree
conflict is new in the current update, or is left over from an earlier

TC is new: without raising a new tree conflict, let the callback do
            its thing (modify a property, bump the revision number,
            or whatever).

TC is old: interrupt the callback before it touches the item or its
            metadata, notifying the user at most once per update-run.

The update command is very flexible. It handles mixed revisions and
missing items, tolerates interruptions without rolling back, and
doesn't worry much about ordering (e.g., you can update an item before
updating its parent dir). AFAIK, the only transaction-like feature,
aside from low-level loggy ops, is the boolean "incomplete" flag in a
dir's metadata.

This flexibility means that the user may *intend* the current update
to finish what some previous update or updates started. Updating
with interruptions should lead to the *same* end result as an
uninterrupted update (assuming the target revision is the same).

In the interrupted case, a tree conflict raised by an interrupted
update should *not* be skipped. Otherwise the user rides the
merry-go-round, at least for a while. Here's an imaginary transcript:

   update A (new TC at A/B; but update of A/B is interrupted)
   update A (skips A/B due to old TC)
   resolve --accept=working A/B
   commit A (fails: A/B is out of date)
   update A/B (new TC at A/B)
   update A (skips A/B due to TC)
   resolve --accept=working A/B
   commit A (fails: A/B is out of date)

Generally there's a shorter workaround, often involving svn revert and
a non-svn copy, as you mention in


but I fear most users (or even committers!) won't see it at first.

Maybe we can achieve the "don't skip TCs of interrupted updates"
feature by disallowing update within a directory that is still marked
incomplete. If starting an update from an incomplete directory, treat
existing TCs as if they were new.

At any rate, we would have to juggle two lists of tree conflicts (old
and new), and three sets of rules for updating an item (normal,
new-tree-conflict, skip).

An alternative is never to skip updating inside an existing tree
conflict. We'd have one list of existing tree conflicts and two sets
of rules for updating an item (normal, tree-conflict). Simpler.

Note: For UC2 and UC3 "*, incoming delete on update", we have to walk the
local tree from within the delete_entry() callback, with a single
callback that is called for each entry. But this walk can also be
interrupted, which I think leads to the same problem with skipping.

Received on 2009-01-23 19:57:23 CET

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