Hi!
I just spent some time thinking about the fact that it is (to me
surprisingly) easy to create collisions even if there is a single
working copy accessing the repository. I want to discuss a way to
improve this situation.
For example:
$ svnadmin create $PWD/repo
$ svn co file://$PWD/repo wc
$ svn mkdir wc/foo
$ echo baz > wc/foo/bar
$ svn add wc/foo/bar
$ svn ci wc -m ""
$ svn up wc
$ echo "mod" > wc/foo/bar
$ svn ci wc -m ""
$ svn rm wc/foo
$ svn ci wc -m ""
Deleting wc/foo
svn: Commit failed (details follow):
svn: Directory '/foo' is out of date
$ svn up wc
Tree conflicts: 1
$ svn status wc
D C wc/foo
> local delete, incoming edit upon update
D wc/foo/bar
A few clarifications up front, to guide this thread.
I think I know why this error happens. So I don't need any suggestions
as to when I should update in order to avoid this, or basic explanation
as to why this happens in the current implementation. Although I know,
novice users don't, and neither do they know how to resolve conflicts.
Instead, I want to outline an idea how this might be made to work, and
discuss the feasibility of it. I focus on the conflict introduced by the
update. So the commit failing due to outdated tree is acceptable to me,
but I want to avoid the update introducing a conflict.
Short outline at the situation of the tree just before the second
commit. The modified file bar is at revision 2, while all directories
are at revision 1. The deletion of foo is therefore done against r1, and
probably cannot be safely committed to a repo at revision 2. The update
tries to update the whole tree to revision 2. To do so, it fetches
modifications from the server, namely the modificaton of bar. As that
modification lies within a tree that is to be updated, it declares a
conflict.
So svn thinks "I deleted foo, while someone else modified something
inside foo at the same time, causing a conflict". The novice user, on
the other hand, thinks "I first modified bar, comitted it, and only
after that did I delete foo. So there should be nothing coming my way
which is not already included in my tree".
The solution I'd like to suggest is this:
ALLOW TRIVIAL UPDATES INSIDE DELETED DIRECTORIES
The way I see it (and correct me if I'm wrong), svn update declares a
conflict if it receives any modification at all concerning an object
inside a directory marked for deletion in the working copy.
If it were to try the update within the directory, and would notice that
everything in there is already up to date, then it could go ahead and
bump the revision of the directory, still keeping it marked for
deletion. The "conflict" would be resolved automatically, the user
wouldn't have to deal with it, and a subsequent commit would work.
Every modification within the tree should be checked against the
following scenarios, although the list might not be exhaustive:
1. The corresponding part of the (mixed-revision) wc is up to date. This
is the case in the example above: the update is to r2 but the affected
file bar already is at r2. Nothing to do, go ahead.
2. The modification is a delete and the deletion is already implemented
in the wc. To achieve this, it might be necessary to store the revision
when an object was deleted in the same place where the current revision
of a life object would be stored in current setup. I.e. "file xy was
deleted at r7" along with "file xz is now at r5". This way, the same
mechanism as for 1. could be applied to detect that the deletion was
one we know about, probably committed ourselves, so we can go ahead.
3. Any other modification would have put the dir in a state different
from the state it had when it was marked for deletion. This is a real
conflict, should be declared as such, and has to be resolved manually.
Put in different terms: if an update on a directory would only have
changed some current revision numbers, but modified nothing else (like
file contents, tree structure, properties), then it should be possible
to delete and then update that directory without introducing a conflict.
All this is for updates to HEAD, other updates would require some
additional thought.
Do you agree that this should work in theory?
Do you agree that this would be desirable?
Do you believe this could be implemented in svn?
How much effort do you think this would take?
I hope for some fruitful discussion on this topic, and maybe some
usability improvement. Pointers at relevant past discussions welcome as
well.
This mail is the result of a discussion on irc, logged at
http://colabti.de/irclogger/irclogger_log/svn?date=2009-07-24#l671
Greetings,
Martin von Gagern
------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2375380
Received on 2009-07-24 21:54:08 CEST