[Please don’t start polluting the database with unknown consequences as a
quick fix.]
A mixed mode move *is* a copy with replacements, as it always was. It is
nice if we can make it work nicer as part of resolving ut we shouldn’t
make the rest of the wc library much harder to maintain as a consequence.
I don’t see a problem if ‘svn’ warns when you do this, but some api users
can’t do this without breaking usability. You aren’t ‘working on
subversion’ when your IDE performs a refactoring for you. And you don’t
want to break a refactoring half way.
A few weeks ago I proposed updating the database to exactly that move with
replacements on the first update step. This adds the nodes that were not
added by the initial move (aka the copy) in the op-depth of the move. From
that point the normal status api will exactly report the replacements that
will happen when committing. (Before adding those nodes the replacements
would also happen, but you would only see them after the commit)
After that initial step we can help the users who got themselves in this
situation (by moving from a mixed revision working copy) by trying to
remove as much of those replacements as possible.
In many cases it will only be the revision number that has changed. But in
these cases we have two NODES layers on top of each other with the same
repos_id and repos_relpath where the top one has a moved-from set.
We can then -as part of the same sql transaction, or as a different
sql transaction- try to eliminate layers as part of the conflict resolving.
This might involve text and property merges and in some cases installing
new conflicts. We can than remove the shadowing.
Putting everything into a single layer ‘as a quick fix’ makes these options
unavailable, as you no longer have access to both versions. It also
complicates committing and breaks several revert scenarios that are build
on these layers.
Bert Huijben
Sent from Windows Mail
*From:* Philip Martin <philip.martin_at_wandisco.com>
*Sent:* November 12, 2012 1:24 PM
*To:* dev_at_subversion.apache.org
*Subject:* move updating and mixed revisions
Stefan and I wanted to get some move updating into 1.8. Our plan was
limited to getting some simple cases working but it keeps getting more
and more complex as I think about it. The basic plan is as follows:
In wc.db a move A-to-B looks like this:
op-depth local-relpath presence revision moved-to moved-here
0 normal 3
0 A normal 3
0 A/f normal 3
1 A deleted B
1 A/f deleted
1 B normal 3 1
1 B/f normal 3 1
When update attempts to modify the A tree it changes the op-depth=0 tree
and raises a tree-conflict on A stored in the actual node:
op-depth local-relpath presence revision moved-to moved-here
0 normal 6
0 A normal 6
0 A/f normal 6
1 A deleted B
1 A/f deleted
1 B normal 3 1
1 B/f normal 3 1
The plan for move updating is that the tree-conflict resolver would
merge the changes causing the tree-conflict into the working files and
update the B nodes rows. The text/property changes can be derived from
the "before" tree (B) and "after" tree (A) as both are present in wc.db.
The result is a wc.db without a tree-conflict that looks like:
op-depth local-relpath presence revision moved-to moved-here
0 normal 6
0 A normal 6
0 A/f normal 6
1 A deleted B
1 A/f deleted
1 B normal 6 1
1 B/f normal 6 1
Two problems occurred to me over the weekend. First, we have to update
the nodes rows even when there is no tree-conflict otherwise the source
and destination no longer match. Second, we cannot simply use the trees
in wc.db to drive the merge into the working files as we don't know
whether A/f_at_3 and A/f_at_6 are the same node. In order to merge the
changes properly the resolver is going to have to contact the repository
(only the tree changes are required, all the content changes are already
in the wc.db).
The underlying problem is that move only makes sense when source and
destination are the same single-revision while update is a node-by-node,
interruptable, operation that causes single-revision trees to go through
mixed-revision states. Why only single-revision moves? The delete half
of a move can only be committed it if is equivalent to HEAD which means
the move source has to be single revision (or a mixed-revision where the
revisions are equivalent to HEAD). The destination part of a move
should be the same revision as the source part otherwise it is not the
same object being moved.
So mixed-revision moves don't make sense at commit time. Mixed-revision
copies are OK, we represent them as a set of nested copies both in the
working copy and at commit. In wc.db each copy is a single-revision,
single-op-depth copy so the mixed-revision copy is a multiple op-depth
copy. Using that representation, even transiently, for mixed-revision
moves is hard. It would look more like a single-revision move with
nested copies as modifications on top of the move, and any such
representation would clash with a user's modifications.
I suppose we could introduce a single-op-depth, mixed-revision
representation for moves that could be updated in parallel with the
single-op-depth, mixed-revision base node layer. I've been trying to
avoid that as it means all the working copy code has to become aware
that such a representation is valid. The alternative is that we have to
handle "broken" moves where the source and destination revision do no
match. In the end the user has to update to a committable state so
provided we get the move properly updated at that point things should
work. So I think a "broken" move has to be stored as a conflict, or
detected on the fly, and should cause the commit to be impossible until
the move is fixed.
This has been a rather rambling email, really I'm trying to get my
thoughts in order.
--
Certified & Supported Apache Subversion Downloads:
http://www.wandisco.com/subversion/download
Received on 2012-11-12 15:03:42 CET