You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Julian Foad <ju...@btopenworld.com> on 2008/03/10 20:33:23 UTC
Tree conflicts - thoughts on use cases, merging, and tests
Stephen,
I'm thinking about all the different things a user can do (including renames
and such like) and how the user can do these things in one branch, do other
such things in another branch, and try to merge the two together. Then I'm
thinking about how Subversion maps these many different user-level changes down
onto a smaller set of delta-editor operations under the hood, and how that's
the place where we're trying to detect conflicts having lost the information
about the user's original intention.
This email doesn't have a conclusion, it's just me conveying my thought process
in the hope that it will help us to communicate.
USE CASES
I have started by categorising all the user actions I can think of into four
categories that reflect whether they delete and/or create an object. This is a
list of all possible kinds of change to the file object at a particular path
(or, for creation, about to live at that path). Listed below each kind of
change are non-exhaustive examples of user-level actions that cause that change.
I'm not entirely sure that these four categories are the best way to split up
the possibilities, but they are serving a useful purpose for me for the time being.
Kinds of change, and user-level actions that cause them:
CREATE
add (a new object without history)
copy(+modify?) (from any object in any revision)
move(+modify?) (from any object in the head revision)
GO-AWAY
delete
move(+modify?) (to another name and/or into another dir)
REPLACE
replace with different kind (DELETE by any means, and CREATE by any means
an object of the same name)
replace with same kind (DELETE by any means, and CREATE by any means an
object of the same name)
revert (delete, and copy(+modify?) from this object's history - a special
case of replace)
MODIFY
modify (any text and/or property mods including creation and deletion of
properties)
Next I thought briefly about the behaviour I would expect when merging a pair
of changes, and tabulated the results according to those four categories.
Desired behaviour for merging two modifications that each start from the same
base (as in "svn update"):
(For files)
Action ... merged onto ... "Reason"
| |
v | CREATE GO-AWAY REPLACE MODIFY
------- + ------- ------- ------- -------
CREATE | C X X X
|
GO-AWAY | X C C C
|
REPLACE | X C C C
|
MODIFY | X C C ok
C = conflict (unless same change to same thing and policy allows it)
X = can't happen if branch was synchronised (so flag an error or a conflict)
ok = merge in the obvious way
Summary of the kinds of change covered by the use cases 1 to 6:
(For files)
Action ... merged onto ... "Reason"
| |
v | CREATE GO-AWAY REPLACE MODIFY
------- + ------- ------- ------- -------
CREATE |
|
GO-AWAY | 3,,6 2,,5
|
REPLACE | (7)
|
MODIFY | 1,,4 (7)
#,#,# = use case number for {update,switch,merge}
We talked about a "use case 7" involving replacement and modification; that
needs splitting into separate use cases and formalising.
We ought to think through some more use cases to fill in the gaps, but I don't
think it's critical to do that early. We can look at them later, and see if the
implementation or the proposed design would do something sensible.
DIFFERENCE BETWEEN "UPDATE" AND "MERGE"
With "svn update", we are merging one CHANGE (described by a delta editor
drive) against the base revision with another CHANGE (described by the WC's
"schedule" information) against the same base revision. We are pretty clear
about how to do this.
With "svn merge", are we attempting to merge the incoming CHANGE with an
existing CHANGE in the target branch against some "base" (whatever that may
be)? Or are we attempting to merge the incoming CHANGE onto a single tree that
exists at a point in time, without regard to how that tree has changed?
I think the ultimate answer is the former: we can only do a good job of merging
if we consider how the target branch has changed already. However, I wonder
whether we are trying to do the latter (apply a change onto a single tree) and
whether in fact that is good enough to get us the behaviour we want.
TESTS
I was looking at the Python tests in the tree-conflicts branch. It's great that
you've already written tests.
I noticed that the test function "set_up_tree_conflicts()" claims to be setting
up for use cases 1, 2 and 3, but it does so by using "delete" commands whereas
the use cases call for "move". I know that a "move" and a "delete" will both
get handled by the same code path in your implementation because they both
contain a delta-editor "delete-file" command, but I think we should write the
use-case tests to describe as accurately as possible the actual use cases. In
addition, we can have tests for other similar and different actions that we
think ought to trigger the conflict detection as well.
I don't know whether you even noticed there was this difference, but I want to
make sure we don't accidentally end up testing only what we think we need to
test and not what the user is going to try doing.
Regards,
- Julian
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Tree conflicts - thoughts on use cases, merging, and tests
Posted by Nico Schellingerhout <ni...@philips.com>.
Stefan Sperling <st...@elego.de> wrote on 03/21/2008 01:39:40 PM:
>
> By "true renames", I essentially mean that functionality you
> describe, but implemented in a manner that would make the client
> side trivial to implement. The biggest feature would be the
> editor function I mentioned, because it would unambiguously
> identify moves on the client side, without any logic necessary
> in the client to tell moves apart from deletes.
Ok, I'm glad to hear that.
>
> But true renames a dream of course, and I don't really want to
> analyze the relationship between true renames and tree conflicts
> deeply. Doing so would be a waste of time for now since we already
> have a plan mapped out that does not require true renames.
>
> > The real problem appears to be twofold:
> > (1) the fact that the client is not given the chance to do this,
> > because
> > the server omits the copy-from information for adds, leaving the
> > client
> > in the dark about the user intentions.
> > (2) there is no API call "whereis", defined as follows:
> > whereis(URL:rev, targetbranchURL:rev), tells you where a file
> > identified by URL:rev (on a source branch, for example), can be
> > found
> > in the targetbranch (note: whereis may return [0:N] URLs because
> > of
> > possible cloning on the target branch). (Note that this requires
> > the ability to search "forward" through the logs efficiently, a
> > feature that Subversion does not provide right now AFAIK.)
>
> Indeed, Subversion doesn't do that. As an aside, one of the first things
> I did with the Subversion code base was adding support for "copied-to"
> properties that simulated just that (all copied files got special
properties
> stating where they got copied at which revisions). An elego client
wanted
> the feature badly enough to fund its implementation, however it turns
> out it was never used in practice.
>
> > Now, I have no clue about performance impact of these extensions,
> > and I
> > may be missing ugly consequences, but to me this looks like a path
> > worth investigating to not only detect and raise tree conflicts,
> > but to
> > handle them as well.
> >
>
> Performance was quite good once the copied-to pointers were in place,
> but handling the insane amount of log output a query like "show me all
> logs for copies of a given file for all branches it was ever copied to"
> produces was quite a nuisance :)
Nice. We have developed a helper tool that crawls through the logs
to build a forward-referencing "cache" to help us determine whereis.
>
> But I will keep this point in mind and may raise it in future design
> discussions when we'll try to get tree-conflicts to the next level.
> Right now it's out of scope.
>
> > Of course, for the initial phase of tree conflicts (raising
> > conflicts,
> > not resolving them), we will have to make do with what Subversion
> > provides, and make the best of it.
>
> Yes indeed.
>
> > However, I do not understand
> > the
> > point in detection.txt that the update editor would have to have
> > the
> > complete list of all adds with history just to _detect_ tree
> > conflicts:
> > UC1 and 3 are triggered simply by trying to change or delete an
> > absent
> > file. That should be enough to flag this as a tree conflict,
> > right?
>
> It is enough to flag tree conflicts, but at the moment we are also
> flagging double deletes of a file as a tree-conflict, even though
> that isn't a tree conflict. The list would be required to tell whether
I'm not so sure. Deleting a file that has already been deleted may be
'safe' in the sense that the second delete will not cause any problems
by itself, but I cannot help thinking that it is an indication of
'fishiness': The deletes either have the same intent behind them, in
which case the development team has a serious communication problem, or
have different intents, in which case further inspection is also
warranted. A version control tool complaining about double deletes may
be regarded by users as overly pedantic, but given the frequency of
double deletes (very rare), I would rather be warned, than be left
in the dark.
> there is a file that was added with history at all in the update, and
> also to relate this file to a file deleted by the update, searching
> copy-from info. Only then we could be certain whether a delete was due
> to a move operation or not.
>
> Essentially, the rant in detection.txt is the result of me and my
> colleague Neels sitting down for a whole evening trying to determine
> how we could eliminate all false positives in tree-conflict detection,
> and discovering that it is impossible to do so with the current design.
Ok. Let me just reiterate the point that the false-positive rate for
this use case is low, simply because the use case itself pops up
very rarely (drawing on experience with a long-living archive with a
constant stream of refactoring involving moves going on).
>
> Does the point make sense to you now? Should I update that section
> of the file to make its background more clear?
Some clarification may be in order: the analysis is based on the
assumption that merging "move a b" onto "move a b" is safe, and that
merging "move a b" onto "move a c" is not. Now, anyone would agree to
the second part, but the first may be debatable (similar arguments
as for double deletes).
The trouble with merging is that (in my opinion) there is no absolute
"truth": whenever you merge, you are making assumptions on what has
happened/was intended, and different assumptions will lead to different
results.
In this case, the more "pedantic" behaviour is much easier to implement,
is safer, and leads to false positives rarely, so to me that seems to
be the way forward.
Happy Easter,
Nico
Re: Tree conflicts - thoughts on use cases, merging, and tests
Posted by Stefan Sperling <st...@elego.de>.
[Nico, sorry, you are getting this twice. I forgot to Cc the list
in my original reply.]
On Thu, Mar 20, 2008 at 08:58:27PM +0100, Nico Schellingerhout wrote:
> Stefan Sperling <st...@elego.de> wrote on 03/11/2008 09:28:40 AM:
>
> > Hey Nico,
> >
> > On Tue, Mar 11, 2008 at 01:48:09AM +0100, Nico Schellingerhout
> wrote:
> > > I agree, a move should be treated as a first class citizen:
> for
> > > detecting
> > > conflicts it doesn't matter, but for resolving them
> > > (semi)automatically, it
> > > does.
> >
> > It does matter for detection. Detection would be much, much
> > easier already if we had an update editor callback like
> > move_file(source, target);
> >
> > See the section "TREE CONFLICT DETECTION WITH TRUE RENAMES" in
> >
> http://svn.collab.net/repos/svn/trunk/notes/tree-conflicts/detection.txt
> I have read through the section you mentioned, and I am not sure
> what you mean by "true renames".
By "true renames", I essentially mean that functionality you
describe, but implemented in a manner that would make the client
side trivial to implement. The biggest feature would be the
editor function I mentioned, because it would unambiguously
identify moves on the client side, without any logic necessary
in the client to tell moves apart from deletes.
But true renames a dream of course, and I don't really want to
analyze the relationship between true renames and tree conflicts
deeply. Doing so would be a waste of time for now since we already
have a plan mapped out that does not require true renames.
> The real problem appears to be twofold:
> (1) the fact that the client is not given the chance to do this,
> because
> the server omits the copy-from information for adds, leaving the
> client
> in the dark about the user intentions.
> (2) there is no API call "whereis", defined as follows:
> whereis(URL:rev, targetbranchURL:rev), tells you where a file
> identified by URL:rev (on a source branch, for example), can be
> found
> in the targetbranch (note: whereis may return [0:N] URLs because
> of
> possible cloning on the target branch). (Note that this requires
> the ability to search "forward" through the logs efficiently, a
> feature that Subversion does not provide right now AFAIK.)
Indeed, Subversion doesn't do that. As an aside, one of the first things
I did with the Subversion code base was adding support for "copied-to"
properties that simulated just that (all copied files got special properties
stating where they got copied at which revisions). An elego client wanted
the feature badly enough to fund its implementation, however it turns
out it was never used in practice.
> Now, I have no clue about performance impact of these extensions,
> and I
> may be missing ugly consequences, but to me this looks like a path
> worth investigating to not only detect and raise tree conflicts,
> but to
> handle them as well.
>
Performance was quite good once the copied-to pointers were in place,
but handling the insane amount of log output a query like "show me all
logs for copies of a given file for all branches it was ever copied to"
produces was quite a nuisance :)
But I will keep this point in mind and may raise it in future design
discussions when we'll try to get tree-conflicts to the next level.
Right now it's out of scope.
> Of course, for the initial phase of tree conflicts (raising
> conflicts,
> not resolving them), we will have to make do with what Subversion
> provides, and make the best of it.
Yes indeed.
> However, I do not understand
> the
> point in detection.txt that the update editor would have to have
> the
> complete list of all adds with history just to _detect_ tree
> conflicts:
> UC1 and 3 are triggered simply by trying to change or delete an
> absent
> file. That should be enough to flag this as a tree conflict,
> right?
It is enough to flag tree conflicts, but at the moment we are also
flagging double deletes of a file as a tree-conflict, even though
that isn't a tree conflict. The list would be required to tell whether
there is a file that was added with history at all in the update, and
also to relate this file to a file deleted by the update, searching
copy-from info. Only then we could be certain whether a delete was due
to a move operation or not.
Essentially, the rant in detection.txt is the result of me and my
colleague Neels sitting down for a whole evening trying to determine
how we could eliminate all false positives in tree-conflict detection,
and discovering that it is impossible to do so with the current design.
Does the point make sense to you now? Should I update that section
of the file to make its background more clear?
--
Stefan Sperling <st...@elego.de> Software Developer
elego Software Solutions GmbH HRB 77719
Gustav-Meyer-Allee 25, Gebaeude 12 Tel: +49 30 23 45 86 96
13355 Berlin Fax: +49 30 23 45 86 95
http://www.elego.de Geschaeftsfuehrer: Olaf Wagner
Re: Tree conflicts - thoughts on use cases, merging, and tests
Posted by Nico Schellingerhout <ni...@philips.com>.
Stefan Sperling <st...@elego.de> wrote on 03/11/2008 09:28:40 AM:
> Hey Nico,
>
> On Tue, Mar 11, 2008 at 01:48:09AM +0100, Nico Schellingerhout wrote:
> > I agree, a move should be treated as a first class citizen: for
> > detecting
> > conflicts it doesn't matter, but for resolving them
> > (semi)automatically, it
> > does.
>
> It does matter for detection. Detection would be much, much
> easier already if we had an update editor callback like
> move_file(source, target);
>
> See the section "TREE CONFLICT DETECTION WITH TRUE RENAMES" in
> http://svn.collab.net/repos/svn/trunk/notes/tree-conflicts/detection.txt
Hi Stefan,
I have read through the section you mentioned, and I am not sure what
you mean by "true renames". The way I see it is that Subversion has all
the concepts in place to achieve what we want. By simply inspecting
logs on source and target branches, it is perfectly possible (albeit very
expensive, currently) to trace the location and a name of the file, and
unambiguously correlate a file in the source branch to a corresponding
file in the target branch (there are exceptions: a file could be cloned
on the target branch, but that could be considered a corner case, for
which tool-support is less strong). This is actually what our integrators
are doing now by hand on a daily basis to resolve "tree conflicts"
(quoted because the "tree conflict" concept does not exist as such in a
Subversion release yet).
The real problem appears to be twofold:
(1) the fact that the client is not given the chance to do this, because
the server omits the copy-from information for adds, leaving the client
in the dark about the user intentions.
(2) there is no API call "whereis", defined as follows:
whereis(URL:rev, targetbranchURL:rev), tells you where a file
identified by URL:rev (on a source branch, for example), can be found
in the targetbranch (note: whereis may return [0:N] URLs because of
possible cloning on the target branch). (Note that this requires
the ability to search "forward" through the logs efficiently, a
feature that Subversion does not provide right now AFAIK.)
If (1) and (2) were there, the client could - in principle - replay
"moves" on the source branch to corresponding "moves" on the target
branch. Note that (1) and (2) do not require additional metadata to
be stored in the server (true renames would require that, I guess),
Subversion would just be using the metadata it keeps more "smartly"
to implement the simple heuristic of
"delete with associated add-with-history constitutes a move"
Now, I have no clue about performance impact of these extensions, and I
may be missing ugly consequences, but to me this looks like a path
worth investigating to not only detect and raise tree conflicts, but to
handle them as well.
Of course, for the initial phase of tree conflicts (raising conflicts,
not resolving them), we will have to make do with what Subversion
provides, and make the best of it. However, I do not understand the
point in detection.txt that the update editor would have to have the
complete list of all adds with history just to _detect_ tree conflicts:
UC1 and 3 are triggered simply by trying to change or delete an absent
file. That should be enough to flag this as a tree conflict, right?
- Nico
Re: Tree conflicts - thoughts on use cases, merging, and tests
Posted by Stefan Sperling <st...@elego.de>.
Hey Nico,
On Tue, Mar 11, 2008 at 01:48:09AM +0100, Nico Schellingerhout wrote:
> I agree, a move should be treated as a first class citizen: for
> detecting
> conflicts it doesn't matter, but for resolving them
> (semi)automatically, it
> does.
It does matter for detection. Detection would be much, much
easier already if we had an update editor callback like
move_file(source, target);
See the section "TREE CONFLICT DETECTION WITH TRUE RENAMES" in
http://svn.collab.net/repos/svn/trunk/notes/tree-conflicts/detection.txt
Great to see you posting by the way. I don't have time to follow
this discussion thoroughly right now, but starting next week
I will have time to catch up and participate more actively again.
See you,
--
Stefan Sperling <st...@elego.de> Software Developer
elego Software Solutions GmbH HRB 77719
Gustav-Meyer-Allee 25, Gebaeude 12 Tel: +49 30 23 45 86 96
13355 Berlin Fax: +49 30 23 45 86 95
http://www.elego.de Geschaeftsfuehrer: Olaf Wagner
Re: Tree conflicts - thoughts on use cases, merging, and tests
Posted by Nico Schellingerhout <ni...@philips.com>.
Julian Foad <ju...@btopenworld.com> wrote on 03/10/2008 09:33:23 PM:
> Stephen,
>
> I'm thinking about all the different things a user can do (including
renames
> and such like) and how the user can do these things in one branch, do
other
> such things in another branch, and try to merge the two together. Then
I'm
> thinking about how Subversion maps these many different user-level
> changes down
> onto a smaller set of delta-editor operations under the hood, and how
that's
> the place where we're trying to detect conflicts having lost the
information
> about the user's original intention.
>
> This email doesn't have a conclusion, it's just me conveying my
> thought process
> in the hope that it will help us to communicate.
>
>
> USE CASES
>
> I have started by categorising all the user actions I can think of into
four
> categories that reflect whether they delete and/or create an object.This
is a
> list of all possible kinds of change to the file object at a particular
path
> (or, for creation, about to live at that path). Listed below each kind
of
> change are non-exhaustive examples of user-level actions that cause
> that change.
>
> I'm not entirely sure that these four categories are the best way
tosplit up
> the possibilities, but they are serving a useful purpose for me for
> the time being.
>
> Kinds of change, and user-level actions that cause them:
>
> CREATE
> add (a new object without history)
> copy(+modify?) (from any object in any revision)
> move(+modify?) (from any object in the head revision)
>
> GO-AWAY
> delete
> move(+modify?) (to another name and/or into another dir)
>
> REPLACE
> replace with different kind (DELETE by any means, and CREATE byany
means
> an object of the same name)
> replace with same kind (DELETE by any means, and CREATE by any
means an
> object of the same name)
> revert (delete, and copy(+modify?) from this object's history -a
special
> case of replace)
>
> MODIFY
> modify (any text and/or property mods including creation and
deletion of
> properties)
>
>
> Next I thought briefly about the behaviour I would expect when merging a
pair
> of changes, and tabulated the results according to those four
categories.
>
> Desired behaviour for merging two modifications that each start fromthe
same
> base (as in "svn update"):
>
> (For files)
>
> Action ... merged onto ... "Reason"
> | |
> v | CREATE GO-AWAY REPLACE MODIFY
> ------- + ------- ------- ------- -------
> CREATE | C X X X
> |
> GO-AWAY | X C C C
> |
> REPLACE | X C C C
> |
> MODIFY | X C C ok
>
> C = conflict (unless same change to same thing and policy allows it)
> X = can't happen if branch was synchronised (so flag an error or
> a conflict)
> ok = merge in the obvious way
>
>
> Summary of the kinds of change covered by the use cases 1 to 6:
>
> (For files)
>
> Action ... merged onto ... "Reason"
> | |
> v | CREATE GO-AWAY REPLACE MODIFY
> ------- + ------- ------- ------- -------
> CREATE |
> |
> GO-AWAY | 3,,6 2,,5
> |
> REPLACE | (7)
> |
> MODIFY | 1,,4 (7)
>
> #,#,# = use case number for {update,switch,merge}
Julian, Steven,
Thanks for the write ups. I have interpreted the tables as "what should
happen if an action of type 1 is merged onto an action of type 2".
However, I don't think there is a difference between GO-AWAY and REPLACE
when used purely in this way. The difference between the two is slightly
more subtle: it involves taking the history on a branch into account.
>
> We talked about a "use case 7" involving replacement and modification;
that
> needs splitting into separate use cases and formalising.
Actually, I think UC7, which I raised earlier off-list, and that we
discussed
earlier over the phone is different from what you indicate:
UC7 can be read in your notation as:
"MODIFY merged onto a file that has been REPLACEd in an not-yet merged
change on either branch"
As far as I can see this case does not present new problems for update:
1. There has been a REPLACE and a MODIFY in two different revisions on
the archive. Updating should pull these changes in consecutively and
there should not be a conflict.
2. There has been a REPLACE on the archive, and a local MODIFY. Update
reduces to UC2 (merge a move onto a modified file).
3. There has been a MODIFY on the archive, and a local REPLACE. Update
reduces to UC1 (merge a modification on to a file being moved away).
However, there are problems for merging between branches:
1. There has been a REPLACE and a MODIFY in two different revisions on
the source branch. Merging should pull these changes in consecutively and
there should not be a conflict.
2a. There has been a REPLACE on the source branch, and a MODIFY on the
target.
Merging the REPLACE onto the source reduces to UC5.
2b. There has been a REPLACE and a MODIFY on the source branch.
Merging the MODIFY is a new case:
r1 r2 r3 r4
x->a edit x merge r2:3
source: x(x) a(x) a(x')
a(a)
target: x(x) x(x) x(x) x(x') OR? x(x)
a(a) a(a) a(a) a(x) a(x')
Notation: f(x) is a file with name "f" and contents "x". Files with the
same "identity" are written on the same line.
It is not easy to determine the right behaviour here. (I would favour
the first of the two options, because one could merge r1:2 later on and
would end up with two identical branches, which would be a good thing.)
The user could be warned to make the right call.
3. There has been a MODIFY on the source branch, and a REPLACE on target.
Merging the MODIFY onto the target is a new use case:
r1 r2 r3 r4
edit a merge r2:3
source: x(x) x(x) x(x)
a(a) a(a) a(a')
x->a
target: x(x) a(x) a(x) a(x) OR? a(a')
a(a)
It is not easy to determine the right behaviour here. (I would favour the
first of the two options, because merging r1:2 from target to source
would bring both branches into sync.)
The user could be warned to make the right call.
The problem with cases 2b and 3 is that the detection that works for all
other cases (seeing that a modify is to be merged onto a file that is
scheduled for deletion or is not there at all, or merging a delete on a
file that differs from the file being deleted), does not work here:
this is the perfectly "normal" case of a textual change being
merged on top of a file that does exist.
The only way to determine that these cases are actually conflicts (or at
the very least require special treatment) is to take the complete history
of the pair of files to be merged into account and determine if they share
a common history.
In case 2b a(x') on source and a(a) on target do not share a history,
because they started out as x(x) and a(a), respectively.
In case 3 a(a') on source and a(x) on target do not share a history,
because they started out as a(a) and x(x), respectively.
Some final remarks on UC4-6:
----------------------------
UC4:
----
In my opinion UC4 is obviously a tree conflict: you are trying to merge
a change onto a file that does not exist in the target branch. Something
weird must be going on (a tree conflict).
UC5: (move merged onto a file that has some changes in the target branch)
---
The condition for a conflict here could be that the file in the target
branch differs from the file in the source branch just before the delete.
However, this condition is only necessary because Subversion treats such
a merge as a copy from source to target, completely ignoring the
content of the original file on the target branch.
A better merge algorithm would be:
1. If the corresponding file on target exists (and shares a history),
perform the move on the target branch (instead of modeling it as a copy
from the source branch).
2. Merge the optional changes that may be in the same revision onto the
moved file on the target branch.
Example:
source/x(x) -> source/y(x') (arrow indicates a D/A+ pair)
Should be merged onto x(x'') as follows:
target/x(x'') -> target/y(x''') [where x''' stands for the textual merge
of
delta(x,x') onto x'']
Instead of the current behaviour:
source/y(x') -> target/y(x')
Note that this requires the merge algorithm to "understand" how to
translate source/x(x) -> source/y(x) to target/x(x) -> target/y(x).
This is trivial if it is just a rename in the same directory, but more
complex if it is a move across directories (the destination directory
on the target may differ from the destination directory on the source).
Again, the notion of sharing history is crucial here, but here the
identity of the target parent directory is involved.
UC6: again, obviously always a tree conflict.
---
[...]
> TESTS
>
> I was looking at the Python tests in the tree-conflicts branch. It's
> great that
> you've already written tests.
>
> I noticed that the test function "set_up_tree_conflicts()" claims to
> be setting
> up for use cases 1, 2 and 3, but it does so by using "delete"
> commands whereas
> the use cases call for "move". I know that a "move" and a "delete" will
both
> get handled by the same code path in your implementation because they
both
> contain a delta-editor "delete-file" command, but I think we should
write the
> use-case tests to describe as accurately as possible the actual use
cases. In
> addition, we can have tests for other similar and different actions that
we
> think ought to trigger the conflict detection as well.
I agree, a move should be treated as a first class citizen: for detecting
conflicts it doesn't matter, but for resolving them (semi)automatically,
it
does.
Just my 2 cts.
- Nico