[PATCHES] dirstate bug (was: Re: -X and -I for addremove and others)

Thomas Arendsen Hein thomas at intevation.de
Wed Aug 10 02:55:08 CDT 2005


* Thomas Arendsen Hein <thomas at intevation.de> [20050723 19:25]:
> Attached is a dirty fix for the problem, I currently have no time to
> clean this up.

Now I have the real fix, attached and pullable from me.

Thomas

-- 
Email: thomas at intevation.de
http://intevation.de/~thomas/
-------------- next part --------------
# HG changeset patch
# User Thomas Arendsen Hein <thomas at intevation.de>
# Node ID d70c1c31fd458a6bcff03175b03b2a553930ce20
# Parent  cbe5c4d016b712283add05545165551f47166c92
Fix 3-way-merge of original parent, workdir and new parent.

The dirstate has to match what is in the repository (what would be
checked out with 'hg update -C'), because the resulting file may be
identical to the new parent, or it may be completely different.
Previously the dirstate wasn't updated, so if you changed the file to
look like the original parent, it might be considered unmodified
relative to the new parent.

diff -r cbe5c4d016b712283add05545165551f47166c92 -r d70c1c31fd458a6bcff03175b03b2a553930ce20 mercurial/hg.py
--- a/mercurial/hg.py	Tue Aug  9 10:32:30 2005
+++ b/mercurial/hg.py	Wed Aug 10 05:47:46 2005
@@ -392,7 +392,7 @@
     def copied(self, file):
         return self.copies.get(file, None)
 
-    def update(self, files, state):
+    def update(self, files, state, **kw):
         ''' current states:
         n  normal
         m  needs merging
@@ -407,7 +407,10 @@
                 self.map[f] = ('r', 0, 0, 0)
             else:
                 s = os.stat(os.path.join(self.root, f))
-                self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime)
+                st_mode = kw.get('st_mode', s.st_mode)
+                st_size = kw.get('st_size', s.st_size)
+                st_mtime = kw.get('st_mtime', s.st_mtime)
+                self.map[f] = (state, st_mode, st_size, st_mtime)
 
     def forget(self, files):
         if not files: return
@@ -1571,10 +1574,21 @@
             m, o, flag = merge[f]
             self.merge3(f, m, o)
             util.set_exec(self.wjoin(f), flag)
-            if moddirstate and mode == 'm':
-                # only update dirstate on branch merge, otherwise we
-                # could mark files with changes as unchanged
-                self.dirstate.update([f], mode)
+            if moddirstate:
+                if mode == 'm':
+                    # only update dirstate on branch merge, otherwise we
+                    # could mark files with changes as unchanged
+                    self.dirstate.update([f], mode)
+                elif p2 == nullid:
+                    # update dirstate from parent1's manifest
+                    m1n = self.changelog.read(p1)[0]
+                    m1 = self.manifest.read(m1n)
+                    file_ = self.file(f)
+                    f_len = file_.length(file_.rev(m1[f]))
+                    self.dirstate.update([f], mode, st_size=f_len, st_mtime=0)
+                else:
+                    self.ui.warn("Second parent without branch merge!?\n"
+                                 "Dirstate for file %s may be wrong.\n" % f)
 
         remove.sort()
         for f in remove:
diff -r cbe5c4d016b712283add05545165551f47166c92 -r d70c1c31fd458a6bcff03175b03b2a553930ce20 tests/test-merge-revert.out
--- a/tests/test-merge-revert.out	Tue Aug  9 10:32:30 2005
+++ b/tests/test-merge-revert.out	Wed Aug 10 05:47:46 2005
@@ -26,7 +26,6 @@
 + hg update
 merging file1
 + hg diff
-FIXME: This is a known bug:
 + hg status
 + hg id
 3aa14bbc23d9 tip
diff -r cbe5c4d016b712283add05545165551f47166c92 -r d70c1c31fd458a6bcff03175b03b2a553930ce20 tests/test-merge-revert2.out
--- a/tests/test-merge-revert2.out	Tue Aug  9 10:32:30 2005
+++ b/tests/test-merge-revert2.out	Wed Aug 10 05:47:46 2005
@@ -44,7 +44,6 @@
 3aa14bbc23d9+ tip
 + hg revert
 + hg diff
-FIXME: This is a known bug:
 + hg status
 + hg id
 3aa14bbc23d9 tip
-------------- next part --------------
# HG changeset patch
# User Thomas Arendsen Hein <thomas at intevation.de>
# Node ID a7e95e3606c7fc4758922d961f8465117ada2098
# Parent  d70c1c31fd458a6bcff03175b03b2a553930ce20
Use length of file instead of length of change for the dirstate entry.

diff -r d70c1c31fd458a6bcff03175b03b2a553930ce20 -r a7e95e3606c7fc4758922d961f8465117ada2098 mercurial/hg.py
--- a/mercurial/hg.py	Wed Aug 10 05:47:46 2005
+++ b/mercurial/hg.py	Wed Aug 10 06:51:37 2005
@@ -1584,7 +1584,7 @@
                     m1n = self.changelog.read(p1)[0]
                     m1 = self.manifest.read(m1n)
                     file_ = self.file(f)
-                    f_len = file_.length(file_.rev(m1[f]))
+                    f_len = len(file_.read(m1[f]))
                     self.dirstate.update([f], mode, st_size=f_len, st_mtime=0)
                 else:
                     self.ui.warn("Second parent without branch merge!?\n"
-------------- next part --------------
# HG changeset patch
# User Thomas Arendsen Hein <thomas at intevation.de>
# Node ID 6225bd773c51b811bc47a3c3e2008741c92765d5
# Parent  a7e95e3606c7fc4758922d961f8465117ada2098
Extended test case to test dirstate length bug fixed in a7e95e3606c7.

diff -r a7e95e3606c7fc4758922d961f8465117ada2098 -r 6225bd773c51b811bc47a3c3e2008741c92765d5 tests/test-merge-revert2
--- a/tests/test-merge-revert2	Wed Aug 10 06:51:37 2005
+++ b/tests/test-merge-revert2	Wed Aug 10 07:23:42 2005
@@ -4,6 +4,7 @@
 cd t
 hg init
 echo "added file1" > file1
+echo "another line of text" >> file1
 echo "added file2" > file2
 hg add file1 file2
 hg commit -m "added file1 and file2" -d "0 0" -u user
diff -r a7e95e3606c7fc4758922d961f8465117ada2098 -r 6225bd773c51b811bc47a3c3e2008741c92765d5 tests/test-merge-revert2.out
--- a/tests/test-merge-revert2.out	Wed Aug 10 06:51:37 2005
+++ b/tests/test-merge-revert2.out	Wed Aug 10 07:23:42 2005
@@ -3,36 +3,37 @@
 + hg commit -m added file1 and file2 -d 0 0 -u user
 + hg commit -m changed file1 -d 0 0 -u user
 + hg -q log
-1:3aa14bbc23d90e3f8b5b639b4a43d76509bae76c
-0:8633637036c18f021d771208e16ae3508ab81d28
+1:f4d7a8c73d231bc078e2a5e791325e55e8a4c252
+0:232e179b3f294d467cfa66e1439bc5b0d44e4a93
 + hg id
-3aa14bbc23d9 tip
+f4d7a8c73d23 tip
 + hg update -C 0
 + hg id
-8633637036c1
+232e179b3f29
 + hg id
-8633637036c1+
+232e179b3f29+
 + hg revert
 + hg diff
 + hg status
 + hg id
-8633637036c1
+232e179b3f29
 + hg update
 + hg diff
 + hg status
 + hg id
-3aa14bbc23d9 tip
+f4d7a8c73d23 tip
 + hg update -C 0
 + hg update
 merge: warning: conflicts during merge
 merging file1
 merging file1 failed!
 + hg diff
-diff -r 3aa14bbc23d9 file1
+diff -r f4d7a8c73d23 file1
 --- a/file1
 +++ b/file1
-@@ -1,2 +1,6 @@
+@@ -1,3 +1,7 @@
  added file1
+ another line of text
 +<<<<<<<
 +changed file1 different
 +=======
@@ -41,19 +42,19 @@
 + hg status
 M file1
 + hg id
-3aa14bbc23d9+ tip
+f4d7a8c73d23+ tip
 + hg revert
 + hg diff
 + hg status
 + hg id
-3aa14bbc23d9 tip
+f4d7a8c73d23 tip
 + hg revert -r tip
 + hg diff
 + hg status
 + hg id
-3aa14bbc23d9 tip
+f4d7a8c73d23 tip
 + hg update -C
 + hg diff
 + hg status
 + hg id
-3aa14bbc23d9 tip
+f4d7a8c73d23 tip
-------------- next part --------------
# HG changeset patch
# User Thomas Arendsen Hein <thomas at intevation.de>
# Node ID 2d2fee33ec680a2c04383dc7f1ed1477335bca51
# Parent  6225bd773c51b811bc47a3c3e2008741c92765d5
Cleanup after previous changes:
- there are only two states for the exec bit, so no need to override it.
- file_ variable is only once now, so it self.file(f) can be used directly.

diff -r 6225bd773c51b811bc47a3c3e2008741c92765d5 -r 2d2fee33ec680a2c04383dc7f1ed1477335bca51 mercurial/hg.py
--- a/mercurial/hg.py	Wed Aug 10 07:23:42 2005
+++ b/mercurial/hg.py	Wed Aug 10 07:41:23 2005
@@ -407,10 +407,9 @@
                 self.map[f] = ('r', 0, 0, 0)
             else:
                 s = os.stat(os.path.join(self.root, f))
-                st_mode = kw.get('st_mode', s.st_mode)
                 st_size = kw.get('st_size', s.st_size)
                 st_mtime = kw.get('st_mtime', s.st_mtime)
-                self.map[f] = (state, st_mode, st_size, st_mtime)
+                self.map[f] = (state, s.st_mode, st_size, st_mtime)
 
     def forget(self, files):
         if not files: return
@@ -1583,8 +1582,7 @@
                     # update dirstate from parent1's manifest
                     m1n = self.changelog.read(p1)[0]
                     m1 = self.manifest.read(m1n)
-                    file_ = self.file(f)
-                    f_len = len(file_.read(m1[f]))
+                    f_len = len(self.file(f).read(m1[f]))
                     self.dirstate.update([f], mode, st_size=f_len, st_mtime=0)
                 else:
                     self.ui.warn("Second parent without branch merge!?\n"


More information about the Mercurial mailing list