[PATCH] merge: avoid to break the dirstate copy status on moved files

Gilles Moris gilles.moris at free.fr
Thu May 13 14:56:59 CDT 2010


On Thursday 13 May 2010 06:55:56 pm Matt Mackall wrote:
> What's the state of this patch?

Benoit asked me to go beyond my simple bug fix and try to restructure the
code a little bit:

On Wednesday 05 May 2010 12:22:06 am Benoit Boissinot wrote:
> I think, instead of not calling normallookup(), we should unify the
> branchmerge and non-branchmerge cases (move the part calling
> dirstate.copy() out of the if).

I admit that I am much less confident on that task, as I am mainly
discovering merge and dirstate. Currently with the below patch, status -C
seems to be OK and the whole test suite pass OK, but diff -g seems to
disagree.

hg init repo
cd repo
echo a > file
hg ci -Am a
echo b >> file
hg ci -m b
hg up 0
hg mv file renamed
hg st -C
  A renamed
    file
  R file
hg diff -g
  diff --git a/file b/renamed
  rename from file
  rename to renamed
hg up 1
hg st -C
  M renamed
    file
  R file
hg diff -g
  diff --git a/file b/file
  deleted file mode 100644
  --- a/file
  +++ /dev/null
  @@ -1,2 +0,0 @@
  -a
  -b
  diff --git a/renamed b/renamed
  --- /dev/null
  +++ b/renamed
  @@ -0,0 +1,2 @@
  +a
  +b

See how after the update, the status of renamed changes from A to M, though
the copy seems recorded, but this is no more the case for the git diff.
So to me, this below patch does not work. Right?

Regards.
Gilles.

diff -r 72b7ec3fc610 mercurial/merge.py
--- a/mercurial/merge.py        Thu Feb 12 22:55:51 2009 +0100
+++ b/mercurial/merge.py        Thu May 13 21:51:48 2010 +0200
@@ -373,13 +373,8 @@
                 # We've done a branch merge, mark this file as merged
                 # so that we properly record the merger later
                 repo.dirstate.merge(fd)
-                if f != f2: # copy/rename
-                    if move:
-                        repo.dirstate.remove(f)
-                    if f != fd:
-                        repo.dirstate.copy(f, fd)
-                    else:
-                        repo.dirstate.copy(f2, fd)
+                if f != f2 and move:
+                    repo.dirstate.remove(f)
             else:
                 # We've update-merged a locally modified file, so
                 # we set the dirstate to emulate a normal checkout
@@ -389,6 +384,12 @@
                 repo.dirstate.normallookup(fd)
                 if move:
                     repo.dirstate.forget(f)
+
+            if f != f2: # copy/rename
+                if f != fd:
+                    repo.dirstate.copy(f, fd)
+                else:
+                    repo.dirstate.copy(f2, fd)
         elif m == "d": # directory rename
             f2, fd, flag = a[2:]
             if not f2 and f not in repo.dirstate:


More information about the Mercurial-devel mailing list