changeset 1002:254ab35709e6

Merge with MPM.
author bos@eng-25.internal.keyresearch.com
date Mon, 22 Aug 2005 13:06:43 -0700
parents f859e9cba1b9 (diff) ab3939ccbf10 (current diff)
children 6dfc9cc71f42
files
diffstat 7 files changed, 211 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Mon Aug 22 03:41:09 2005 -0700
+++ b/mercurial/commands.py	Mon Aug 22 13:06:43 2005 -0700
@@ -613,12 +613,12 @@
     """dump the contents of an index file"""
     r = hg.revlog(hg.opener(""), file_, "")
     ui.write("   rev    offset  length   base linkrev" +
-             " p1           p2           nodeid\n")
+             " nodeid       p1           p2\n")
     for i in range(r.count()):
         e = r.index[i]
-        ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % (
+        ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
                 i, e[0], e[1], e[2], e[3],
-            hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])))
+            hg.short(e[6]), hg.short(e[4]), hg.short(e[5])))
 
 def debugindexdot(ui, file_):
     """dump an index DAG as a .dot file"""
--- a/mercurial/hg.py	Mon Aug 22 03:41:09 2005 -0700
+++ b/mercurial/hg.py	Mon Aug 22 13:06:43 2005 -0700
@@ -824,6 +824,7 @@
         m1 = self.manifest.read(c1[0])
         mf1 = self.manifest.readflags(c1[0])
         m2 = self.manifest.read(c2[0])
+        changed = []
 
         if orig_parent == p1:
             update_dirstate = 1
@@ -840,8 +841,31 @@
                 tm = util.is_exec(self.wjoin(f), mfm.get(f, False))
                 r = self.file(f)
                 mfm[f] = tm
-                mm[f] = r.add(t, {}, tr, linkrev,
-                              m1.get(f, nullid), m2.get(f, nullid))
+
+                fp1 = m1.get(f, nullid)
+                fp2 = m2.get(f, nullid)
+
+                # is the same revision on two branches of a merge?
+                if fp2 == fp1:
+                    fp2 = nullid
+
+                if fp2 != nullid:
+                    # is one parent an ancestor of the other?
+                    fpa = r.ancestor(fp1, fp2)
+                    if fpa == fp1:
+                        fp1, fp2 = fp2, nullid
+                    elif fpa == fp2:
+                        fp2 = nullid
+
+                    # is the file unmodified from the parent?
+                    if t == r.read(fp1):
+                        # record the proper existing parent in manifest
+                        # no need to add a revision
+                        mm[f] = fp1
+                        continue
+
+                mm[f] = r.add(t, {}, tr, linkrev, fp1, fp2)
+                changed.append(f)
                 if update_dirstate:
                     self.dirstate.update([f], "n")
             except IOError:
@@ -856,7 +880,7 @@
 
         mnode = self.manifest.add(mm, mfm, tr, linkrev, c1[0], c2[0])
         user = user or self.ui.username()
-        n = self.changelog.add(mnode, files, text, tr, p1, p2, user, date)
+        n = self.changelog.add(mnode, changed, text, tr, p1, p2, user, date)
         tr.close()
         if update_dirstate:
             self.dirstate.setparents(n, nullid)
@@ -865,6 +889,8 @@
                match = util.always, force=False):
         commit = []
         remove = []
+        changed = []
+
         if files:
             for f in files:
                 s = self.dirstate.state(f)
@@ -879,19 +905,20 @@
             commit = c + a
             remove = d
 
-        if not commit and not remove and not force:
+        p1, p2 = self.dirstate.parents()
+        c1 = self.changelog.read(p1)
+        c2 = self.changelog.read(p2)
+        m1 = self.manifest.read(c1[0])
+        mf1 = self.manifest.readflags(c1[0])
+        m2 = self.manifest.read(c2[0])
+
+        if not commit and not remove and not force and p2 == nullid:
             self.ui.status("nothing changed\n")
             return None
 
         if not self.hook("precommit"):
             return None
 
-        p1, p2 = self.dirstate.parents()
-        c1 = self.changelog.read(p1)
-        c2 = self.changelog.read(p2)
-        m1 = self.manifest.read(c1[0])
-        mf1 = self.manifest.readflags(c1[0])
-        m2 = self.manifest.read(c2[0])
         lock = self.lock()
         tr = self.transaction()
 
@@ -918,7 +945,30 @@
             r = self.file(f)
             fp1 = m1.get(f, nullid)
             fp2 = m2.get(f, nullid)
+
+            # is the same revision on two branches of a merge?
+            if fp2 == fp1:
+                fp2 = nullid
+
+            if fp2 != nullid:
+                # is one parent an ancestor of the other?
+                fpa = r.ancestor(fp1, fp2)
+                if fpa == fp1:
+                    fp1, fp2 = fp2, nullid
+                elif fpa == fp2:
+                    fp2 = nullid
+
+                # is the file unmodified from the parent?
+                if not meta and t == r.read(fp1):
+                    # record the proper existing parent in manifest
+                    # no need to add a revision
+                    new[f] = fp1
+                    continue
+
             new[f] = r.add(t, meta, tr, linkrev, fp1, fp2)
+            # remember what we've added so that we can later calculate
+            # the files to pull from a set of changesets
+            changed.append(f)
 
         # update manifest
         m1.update(new)
@@ -933,16 +983,21 @@
         new.sort()
 
         if not text:
-            edittext = "\n" + "HG: manifest hash %s\n" % hex(mn)
-            edittext += "".join(["HG: changed %s\n" % f for f in new])
+            edittext = ""
+            if p2 != nullid:
+                edittext += "HG: branch merge\n"
+            edittext += "\n" + "HG: manifest hash %s\n" % hex(mn)
+            edittext += "".join(["HG: changed %s\n" % f for f in changed])
             edittext += "".join(["HG: removed %s\n" % f for f in remove])
+            if not changed and not remove:
+                edittext += "HG: no files changed\n"
             edittext = self.ui.edit(edittext)
             if not edittext.rstrip():
                 return None
             text = edittext
 
         user = user or self.ui.username()
-        n = self.changelog.add(mn, new, text, tr, p1, p2, user, date)
+        n = self.changelog.add(mn, changed, text, tr, p1, p2, user, date)
         tr.close()
 
         self.dirstate.setparents(n)
@@ -967,7 +1022,7 @@
 
         def fcmp(fn, mf):
             t1 = self.wfile(fn).read()
-            t2 = self.file(fn).revision(mf[fn])
+            t2 = self.file(fn).revision(mf.get(fn, nullid))
             return cmp(t1, t2)
 
         def mfmatches(node):
@@ -1574,7 +1629,6 @@
         merge = {}
         get = {}
         remove = []
-        mark = {}
 
         # construct a working dir manifest
         mw = m1.copy()
@@ -1607,7 +1661,6 @@
                     t1 = self.wfile(f).read()
                     t2 = self.file(f).revision(m2[f])
                     if cmp(t1, t2) == 0:
-                        mark[f] = 1
                         n = m2[f]
                     del t1, t2
 
@@ -1630,8 +1683,6 @@
                         self.ui.debug(" remote %s is newer, get\n" % f)
                         get[f] = m2[f]
                         s = 1
-                    else:
-                        mark[f] = 1
                 elif f in umap:
                     # this unknown file is the same as the checkout
                     get[f] = m2[f]
@@ -1646,7 +1697,6 @@
                         if mode != b:
                             self.ui.debug(" updating permissions for %s\n" % f)
                             util.set_exec(self.wjoin(f), mode)
-                            mark[f] = 1
                 del m2[f]
             elif f in ma:
                 if n != ma[f]:
@@ -1715,12 +1765,7 @@
                 self.ui.status("(use update -m to merge across branches" +
                                " or -C to lose changes)\n")
                 return 1
-            # we have to remember what files we needed to get/change
-            # because any file that's different from either one of its
-            # parents must be in the changeset
             mode = 'm'
-            if moddirstate:
-                self.dirstate.update(mark.keys(), "m")
 
         if moddirstate:
             self.dirstate.setparents(p1, p2)
@@ -1739,7 +1784,10 @@
                 self.wfile(f, "w").write(t)
             util.set_exec(self.wjoin(f), mf2[f])
             if moddirstate:
-                self.dirstate.update([f], mode)
+                if mode == 'm':
+                    self.dirstate.update([f], 'n', st_mtime=0)
+                else:
+                    self.dirstate.update([f], 'n')
 
         # merge the tricky bits
         files = merge.keys()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-filebranch	Mon Aug 22 13:06:43 2005 -0700
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+# This test makes sure that we don't mark a file as merged with its ancestor
+# when we do a merge.
+
+cat <<'EOF' > merge
+#!/bin/sh
+echo merging for `basename $1`
+EOF
+chmod +x merge
+
+echo creating base
+hg init a
+cd a
+echo 1 > foo
+echo 1 > bar
+echo 1 > baz
+echo 1 > quux
+hg add foo bar baz quux
+hg commit -m "base" -d "0 0"
+
+cd ..
+hg clone a b
+
+echo creating branch a
+cd a
+echo 2a > foo
+echo 2a > bar
+hg commit -m "branch a" -d "0 0"
+
+echo creating branch b
+
+cd ..
+cd b
+echo 2b > foo
+echo 2b > baz
+hg commit -m "branch b" -d "0 0"
+
+echo "we shouldn't have anything but n state here"
+hg debugstate | cut -b 1-16,35-
+
+echo merging
+hg pull ../a
+env HGMERGE=../merge hg update -vm --debug
+
+echo 2m > foo
+echo 2b > baz
+echo new > quux
+
+echo "we shouldn't have anything but foo in merge state here"
+hg debugstate | cut -b 1-16,35- | grep "^m"
+
+hg ci -m "merge" -d "0 0"
+
+echo "main: we should have a merge here"
+hg debugindex .hg/00changelog.i
+
+echo "foo: we should have a merge here"
+hg debugindex .hg/data/foo.i
+
+echo "bar: we shouldn't have a merge here"
+hg debugindex .hg/data/bar.i
+
+echo "baz: we shouldn't have a merge here"
+hg debugindex .hg/data/baz.i
+
+echo "quux: we shouldn't have a merge here"
+hg debugindex .hg/data/quux.i
+
+echo "everything should be clean now"
+hg status
+
+hg verify
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-filebranch.out	Mon Aug 22 13:06:43 2005 -0700
@@ -0,0 +1,58 @@
+creating base
+creating branch a
+creating branch b
+we shouldn't have anything but n state here
+n 644          2 bar
+n 644          3 baz
+n 644          3 foo
+n 644          2 quux
+merging
+pulling from ../a
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 2 changes to 2 files
+(run 'hg update' to get a working copy)
+merging for foo
+resolving manifests
+ force None allow 1 moddirstate True linear False
+ ancestor a0486579db29 local ef1b4dbe2193 remote 336d8406d617
+ remote bar is newer, get
+ foo versions differ, resolve
+getting bar
+merging foo
+resolving foo
+file foo: other 33d1fb69067a ancestor b8e02f643373
+we shouldn't have anything but foo in merge state here
+m 644          3 foo
+main: we should have a merge here
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0      73      0       0 cdca01651b96 000000000000 000000000000
+     1        73      68      1       1 f6718a9cb7f3 cdca01651b96 000000000000
+     2       141      68      2       2 bdd988058d16 cdca01651b96 000000000000
+     3       209      66      3       3 9da9fbd62226 f6718a9cb7f3 bdd988058d16
+foo: we should have a merge here
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0       3      0       0 b8e02f643373 000000000000 000000000000
+     1         3       4      1       1 2ffeddde1b65 b8e02f643373 000000000000
+     2         7       4      2       2 33d1fb69067a b8e02f643373 000000000000
+     3        11       4      3       3 aa27919ee430 2ffeddde1b65 33d1fb69067a
+bar: we shouldn't have a merge here
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0       3      0       0 b8e02f643373 000000000000 000000000000
+     1         3       4      1       2 33d1fb69067a b8e02f643373 000000000000
+baz: we shouldn't have a merge here
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0       3      0       0 b8e02f643373 000000000000 000000000000
+     1         3       4      1       1 2ffeddde1b65 b8e02f643373 000000000000
+quux: we shouldn't have a merge here
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0       3      0       0 b8e02f643373 000000000000 000000000000
+     1         3       5      1       3 6128c0f33108 b8e02f643373 000000000000
+everything should be clean now
+checking changesets
+checking manifests
+crosschecking files in changesets and manifests
+checking files
+4 files, 4 changesets, 10 total revisions
--- a/tests/test-merge6.out	Mon Aug 22 03:41:09 2005 -0700
+++ b/tests/test-merge6.out	Mon Aug 22 13:06:43 2005 -0700
@@ -6,7 +6,7 @@
 added 1 changesets with 1 changes to 1 files
 (run 'hg update' to get a working copy)
 bar should remain deleted.
-6b70e9e451a5a33faad7bbebe627e46b937b7364 644 foo
+f405ac83a5611071d6b54dd5eb26943b1fdc4460 644 foo
 pulling from ../A2
 searching for changes
 adding changesets
@@ -15,4 +15,4 @@
 added 1 changesets with 0 changes to 0 files
 (run 'hg update' to get a working copy)
 bar should remain deleted.
-6b70e9e451a5a33faad7bbebe627e46b937b7364 644 foo
+f9b0e817f6a48de3564c6b2957687c5e7297c5a0 644 foo
--- a/tests/test-push-warn.out	Mon Aug 22 03:41:09 2005 -0700
+++ b/tests/test-push-warn.out	Mon Aug 22 13:06:43 2005 -0700
@@ -18,4 +18,4 @@
 adding changesets
 adding manifests
 adding file changes
-added 2 changesets with 2 changes to 2 files
+added 2 changesets with 1 changes to 1 files
--- a/tests/test-tags.out	Mon Aug 22 03:41:09 2005 -0700
+++ b/tests/test-tags.out	Mon Aug 22 13:06:43 2005 -0700
@@ -10,6 +10,4 @@
 acb14030fe0a21b60322c440ad2d20cf7685a376+ first
 M a
 c8edf04160c7 tip
-c8edf04160c7+b9154636be93+ tip
-M .hgtags
-M a
+c8edf04160c7+b9154636be93 tip