--- a/mercurial/hg.py Wed May 18 15:24:18 2005 -0800
+++ b/mercurial/hg.py Wed May 18 16:29:39 2005 -0800
@@ -30,42 +30,6 @@
def add(self, text, transaction, link, p1=None, p2=None):
return self.addrevision(text, transaction, link, p1, p2)
- def resolvedag(self, old, new, transaction, link):
- """resolve unmerged heads in our DAG"""
- if old == new: return None
- a = self.ancestor(old, new)
- if old == a: return None
- return self.merge3(old, new, a, transaction, link)
-
- def merge3(self, my, other, base, transaction, link):
- """perform a 3-way merge and append the result"""
- def temp(prefix, node):
- (fd, name) = tempfile.mkstemp(prefix)
- f = os.fdopen(fd, "w")
- f.write(self.revision(node))
- f.close()
- return name
-
- a = temp("local", my)
- b = temp("remote", other)
- c = temp("parent", base)
-
- cmd = os.environ["HGMERGE"]
- r = os.system("%s %s %s %s" % (cmd, a, b, c))
- if r:
- raise "Merge failed, implement rollback!"
-
- t = open(a).read()
- os.unlink(a)
- os.unlink(b)
- os.unlink(c)
- return self.addrevision(t, transaction, link, my, other)
-
- def merge(self, other, transaction, linkseq, link):
- """perform a merge and resolve resulting heads"""
- (o, n) = self.mergedag(other, transaction, linkseq)
- return self.resolvedag(o, n, transaction, link)
-
def annotate(self, node):
revs = []
while node != nullid:
@@ -160,9 +124,6 @@
text = "\n".join(l)
return self.addrevision(text, transaction, self.count(), p1, p2)
- def merge3(self, my, other, base):
- pass
-
class dircache:
def __init__(self, opener, ui):
self.opener = opener
@@ -335,122 +296,6 @@
def transaction(self):
return transaction(self.opener, self.join("journal"))
- def merge(self, other):
- tr = self.transaction()
- changed = {}
- new = {}
- seqrev = self.changelog.count()
- # some magic to allow fiddling in nested scope
- nextrev = [seqrev]
-
- # helpers for back-linking file revisions to local changeset
- # revisions so we can immediately get to changeset from annotate
- def accumulate(text):
- # track which files are added in which changeset and the
- # corresponding _local_ changeset revision
- files = self.changelog.extract(text)[3]
- for f in files:
- changed.setdefault(f, []).append(nextrev[0])
- nextrev[0] += 1
-
- def seq(start):
- while 1:
- yield start
- start += 1
-
- def lseq(l):
- for r in l:
- yield r
-
- # begin the import/merge of changesets
- self.ui.status("merging new changesets\n")
- (co, cn) = self.changelog.mergedag(other.changelog, tr,
- seq(seqrev), accumulate)
- resolverev = self.changelog.count()
-
- # is there anything to do?
- if co == cn:
- tr.close()
- return
-
- # do we need to resolve?
- simple = (co == self.changelog.ancestor(co, cn))
-
- # merge all files changed by the changesets,
- # keeping track of the new tips
- changelist = changed.keys()
- changelist.sort()
- for f in changelist:
- sys.stdout.write(".")
- sys.stdout.flush()
- r = self.file(f)
- node = r.merge(other.file(f), tr, lseq(changed[f]), resolverev)
- if node:
- new[f] = node
- sys.stdout.write("\n")
-
- # begin the merge of the manifest
- self.ui.status("merging manifests\n")
- (mm, mo) = self.manifest.mergedag(other.manifest, tr, seq(seqrev))
-
- # For simple merges, we don't need to resolve manifests or changesets
- if simple:
- tr.close()
- return
-
- ma = self.manifest.ancestor(mm, mo)
-
- # resolve the manifest to point to all the merged files
- self.ui.status("resolving manifests\n")
- omap = self.manifest.read(mo) # other
- amap = self.manifest.read(ma) # ancestor
- mmap = self.manifest.read(mm) # mine
- nmap = {}
-
- for f, mid in mmap.iteritems():
- if f in omap:
- if mid != omap[f]:
- nmap[f] = new.get(f, mid) # use merged version
- else:
- nmap[f] = new.get(f, mid) # they're the same
- del omap[f]
- elif f in amap:
- if mid != amap[f]:
- pass # we should prompt here
- else:
- pass # other deleted it
- else:
- nmap[f] = new.get(f, mid) # we created it
-
- del mmap
-
- for f, oid in omap.iteritems():
- if f in amap:
- if oid != amap[f]:
- pass # this is the nasty case, we should prompt
- else:
- pass # probably safe
- else:
- nmap[f] = new.get(f, oid) # remote created it
-
- del omap
- del amap
-
- node = self.manifest.add(nmap, tr, resolverev, mm, mo)
-
- # Now all files and manifests are merged, we add the changed files
- # and manifest id to the changelog
- self.ui.status("committing merge changeset\n")
- new = new.keys()
- new.sort()
- if co == cn: cn = -1
-
- edittext = "\n"+"".join(["HG: changed %s\n" % f for f in new])
- edittext = self.ui.edit(edittext)
- n = self.changelog.add(node, new, edittext, tr, co, cn)
-
- tr.close()
-
def commit(self, parent, update = None, text = ""):
tr = self.transaction()
@@ -640,19 +485,26 @@
def newer(self, nodes):
m = {}
nl = []
+ pm = {}
cl = self.changelog
t = l = cl.count()
+
+ # find the lowest numbered node
for n in nodes:
l = min(l, cl.rev(n))
- for p in cl.parents(n):
- m[p] = 1
+ m[n] = 1
for i in xrange(l, t):
n = cl.node(i)
+ if n in m: # explicitly listed
+ pm[n] = 1
+ nl.append(n)
+ continue
for p in cl.parents(n):
- if p in m and n not in m:
- m[n] = 1
+ if p in pm: # parent listed
+ pm[n] = 1
nl.append(n)
+ break
return nl
@@ -676,13 +528,14 @@
self.ui.debug("found incomplete branch %s\n" % short(n[1]))
search.append(n) # schedule branch range for scanning
else:
+ if n[2] in m and n[3] in m:
+ if n[1] not in fetch:
+ self.ui.debug("found new changeset %s\n" %
+ short(n[1]))
+ fetch.append(n[1]) # earliest unknown
+ continue
for b in remote.branches([n[2], n[3]]):
- if b[0] in m:
- if n[1] not in fetch:
- self.ui.debug("found new changeset %s\n" %
- short(n[1]))
- fetch.append(n[1]) # earliest unknown
- else:
+ if b[0] not in m:
unknown.append(b)
while search:
@@ -707,7 +560,7 @@
if f in m:
raise "already have", short(f[:4])
- self.ui.note("merging new changesets starting at " +
+ self.ui.note("adding new changesets starting at " +
" ".join([short(f) for f in fetch]) + "\n")
return remote.changegroup(fetch)
@@ -767,13 +620,17 @@
tr = self.transaction()
simple = True
- self.ui.status("merging changesets\n")
+ self.ui.status("adding changesets\n")
# pull off the changeset group
+ def report(x):
+ self.ui.debug("add changeset %s\n" % short(x))
+ return self.changelog.count()
+
csg = getchunk()
co = self.changelog.tip()
- cn = self.changelog.addgroup(csg, lambda x: self.changelog.count(), tr)
+ cn = self.changelog.addgroup(csg, report, tr)
- self.ui.status("merging manifests\n")
+ self.ui.status("adding manifests\n")
# pull off the manifest group
mfg = getchunk()
mm = self.manifest.tip()
@@ -785,21 +642,21 @@
resolverev = self.changelog.count()
# process the files
- self.ui.status("merging files\n")
+ self.ui.status("adding files\n")
new = {}
while 1:
f = getchunk(4)
if not f: break
fg = getchunk()
-
+ self.ui.debug("adding %s revisions\n" % f)
fl = self.file(f)
o = fl.tip()
n = fl.addgroup(fg, lambda x: self.changelog.rev(x), tr)
if not simple:
- nn = fl.resolvedag(o, n, tr, resolverev)
- if nn:
- self.ui.note("merged %s\n", f)
- new[f] = nn
+ if o == n: continue
+ # this file has changed between branches, so it must be
+ # represented in the merge changeset
+ new[f] = self.merge3(fl, f, o, n, tr, resolverev)
# For simple merges, we don't need to resolve manifests or changesets
if simple:
@@ -821,8 +678,9 @@
if f in omap:
if mid != omap[f]:
self.ui.debug("%s versions differ\n" % f)
- if f in new: self.ui.note("%s updated in resolve\n" % f)
- nmap[f] = new.get(f, mid) # use merged version
+ if f in new: self.ui.debug("%s updated in resolve\n" % f)
+ # use merged version or local version
+ nmap[f] = new.get(f, mid)
else:
nmap[f] = mid # keep ours
del omap[f]