Reputation: 17968
My confusion arises from the following statement taken from here:
When pulling patches that conflict each other (e.g., change the same part of the file) Darcs detects the conflict and marks it in the repository content. It then lets the user resolve the problem.
This seemed inconsistent with what I was seeing, so I created the following work-flow using darcs 2.5.2:
After taking these steps I ran darcs whatsnew
in bar, and was shown two 'patch primitives':
My question is: Why is there no mention of the line added and recorded in bar?
If I run darcs revert
in bar, then everything makes sense: I see the "non-empty file" affected by neither conflicting patch, as per this statement taken from here:
The command darcs revert will remove the conflict marking and back up to state before conflicting patches.
But then if I run darcs mark-conflicts
I am back to the same state as after the pull, with the two 'patch primitives' mentioned above, and no mention of the the line added and recorded in bar.
For reference / reproduction here is my complete work-flow from the command line:
$ mkdir foo
$ cd foo/
foo$ darcs initialize
foo$ touch shopping
foo$ vi shopping <-- add a couple of lines
foo$ darcs add shopping
foo$ darcs record
addfile ./shopping
Shall I record this change? (1/2) [ynW...], or ? for more options: y
hunk ./shopping 1
+cake
+pie
Shall I record this change? (2/2) [ynW...], or ? for more options: y
What is the patch name? Added shopping
Do you want to add a long comment? [yn]n
Finished recording patch 'Added shopping'
foo$ cd ..
$ darcs get foo/ bar
$ cd bar/
bar$ vi shopping <-- add another line
bar$ darcs record
hunk ./shopping 2
+beer
Shall I record this change? (1/1) [ynW...], or ? for more options: y
What is the patch name? Added beer
Do you want to add a long comment? [yn]n
Finished recording patch 'Added beer'
bar$ cd ../foo
foo$ rm shopping
foo$ darcs record
hunk ./shopping 1
-cake
-pie
Shall I record this change? (1/2) [ynW...], or ? for more options: y
rmfile ./shopping
Shall I record this change? (2/2) [ynW...], or ? for more options: y
What is the patch name? Removed shopping
Do you want to add a long comment? [yn]n
Finished recording patch 'Removed shopping'
foo$ cd ../bar
bar$ darcs pull
Pulling from "../foo"...
Mon Nov 14 19:26:44 GMT 2011 [email protected]
* Removed shopping
Shall I pull this patch? (1/1) [ynW...], or ? for more options: y
Backing up ./shopping(-darcs-backup0)
We have conflicts in the following files:
./shopping
Finished pulling and applying.
bar$ darcs whatsnew
hunk ./shopping 1
-cake
-pie
rmfile ./shopping
Upvotes: 4
Views: 332
Reputation: 518
If you run darcs changes -v
inside bar, you'll see the history of your
changes, including the conflictor introduced as a result of you pulling
conflicting patches.
I've summarised your example to something everso slightly shorter:
DARCS=/usr/bin/darcs
$DARCS init --repo foo
cd foo
echo 'a' > myfile
$DARCS add myfile && $DARCS record -am 'Add myfile'
$DARCS get . ../bar
rm myfile
$DARCS record -am 'Remove myfile'
cd ../bar
echo 'b' >> myfile
$DARCS record -am 'Change myfile'
$DARCS pull -a ../foo
$DARCS changes -v
Now, after that, I see this output from darcs changes -v
Tue Nov 15 19:44:38 GMT 2011 Owen Stephens <[email protected]>
* Remove myfile
conflictor [
hunk ./myfile 2
+b
]
|:
hunk ./myfile 1
-a
conflictor {{
|:
hunk ./myfile 2
+b
|:
hunk ./myfile 1
-a
}} []
|hunk ./myfile 1
|-a
|:
rmfile ./myfile
Tue Nov 15 19:44:38 GMT 2011 Owen Stephens <[email protected]>
* Change myfile
hunk ./myfile 2
+b
Tue Nov 15 19:44:38 GMT 2011 Owen Stephens <[email protected]>
* Add myfile
addfile ./myfile
hunk ./myfile 1
+a
So, let's explain the crazy output of "Remove myfile". "Remove myfile" exists as the following in foo:
Tue Nov 15 19:44:38 GMT 2011 Owen Stephens <[email protected]>
* Remove myfile
hunk ./myfile 1
-a
rmfile ./myfile
So, a hunk at line 1 and removal of the file.
Pulling "remove myfile" into bar, we modify the patch contents by introducing special "conflictor" primitives that represent the primitives within "Remove myfile" that conflict with other primitves in bar. N.b. there is no information loss here - we can always get back to the original primitives by unpulling the conflicting changes - in this case, unpulling "change myfile".
Conflictors are confusing, but AFAICT essentially separate changes that conflict with a current patch, x into 2 sets: "ix" which is the set of patches that includes: i) patches that conflict with x and some other patch in the repo ii) patches that conflict with a patch that conflicts with x "xx" which is the sequence of patches that only conflict with the patch x. I think the reason that this is done, is that Conflictors have the effect of "undoing" primitives that cause conflicts, but only those that haven't been undone by another Conflictor.
The output we see is something like:
"conflictor" ix "[" xx "]" x
I'm abusing notation, but hopefully you can somewhat decipher that (see src/Darcs/Patch/V2/(Real.hs|Non.hs) in the darcs.net repo for the full story)
In this case, "Remove myfile" has 2 primitive patches, and (in this case) 2 corresponding conflictors when pulled into bar.
The first primitive (remove line 1 from myfile) only conflicts with the primitive within "Change myfile" (add 'b' to line 2 of myfile) and so that's the first conflictor:
conflictor [ <--- The start of xx (no ix here)
hunk ./myfile 2
+b
] <--- The end of xx
|:
hunk ./myfile 1 <--- x
-a
N.B ( "|:" is a marker that delimits a "Non" primitve's context from the primitive itself - I won't try and explain it further, just read below |: to see the primitive in question)
The second primitive (remove myfile) is only slightly more complicated: (rmfile myfile) conflicts with (add 'b' to line 2 of myfile) which as we know conflicts with (remove line 1 from myfile), so they both go into "ix", with no patches in "xx". I'll remove the unnecessary "|:" delimiters and space things out:
conflictor {{
hunk ./myfile 2
+b
hunk ./myfile 1
-a
}}
[] <--- no xx
|hunk ./myfile 1 <--- start of x
|-a
|:
rmfile ./myfile <--- end of x
The final (rmfile myfile) has some context to indentify the exact primitive that we're referring to (I'm not really sure why/how this is required, but there we are), which is marked by leading '|'s and delimited by "|:".
Finally, to attempt explain the output of darcs whatsnew
in foo; when
multiple patches conflict, I think the actual effect of the conflictor is to
"undo" any conflicting patches, giving the effect of neither;
gives the start of some explanations: http://en.wikibooks.org/wiki/Understanding_Darcs/Patch_theory_and_conflicts.
I think what you're seeing is the result of the forced commutation of "Change myfile" and "Remove myfile" call them A
and B
respectively. Then to merge the two, Darcs creates A^-1
and commutes A^-1
and B
to give B'
and (A^-1)'
where B'
has the effect of A^-1
(since we're forcing the commutation to work), meaning that the effect of B'
(i.e. the merged "remove myfile") is actually to just undo the adding of the line made by "Change myfile".
I haven't had time to look at how darcs mark-conflicts
works, so I can't yet explain the working changes you're seeing with darcs changes
in bar.
Upvotes: 7