unify checkout and resolve into update
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
unify checkout and resolve into update
This replaces checkout and resolve with a single command:
$ hg help co
hg update [node]
update or merge working directory
If there are no outstanding changes in the working directory and
there is a linear relationship between the current version and the
requested version, the result is the requested version.
Otherwise the result is a merge between the contents of the
current working directory and the requested version. Files that
changed between either parent are marked as changed for the next
commit and a commit must be performed before any further updates
are allowed.
manifest hash:
513d285d7fb775d0560de49387042a685ea062f7
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFComS7ywK+sNU5EO8RAmgRAJ96GA6qvHLy0Jp0fzUrR2os2azPuACePsdC
YBldZtA7yIuTnV2vIbn7OSE=
=QtM/
-----END PGP SIGNATURE-----
--- a/mercurial/commands.py Sat Jun 04 15:16:48 2005 -0800
+++ b/mercurial/commands.py Sat Jun 04 18:34:35 2005 -0800
@@ -164,18 +164,6 @@
if rev: n = r.lookup(rev)
sys.stdout.write(r.read(n))
-def checkout(ui, repo, changeset=None):
- '''checkout a given changeset or the current tip'''
- (c, a, d, u) = repo.diffdir(repo.root)
- if c or a or d:
- ui.warn("aborting (outstanding changes in working directory)\n")
- sys.exit(1)
-
- node = repo.changelog.tip()
- if changeset:
- node = repo.lookup(changeset)
- repo.checkout(node)
-
def commit(ui, repo, *files):
"""commit the specified files or all outstanding changes"""
repo.commit(relpath(repo, files))
@@ -405,14 +393,6 @@
"""remove the specified files on the next commit"""
repo.remove(relpath(repo, (file,) + files))
-def resolve(ui, repo, node=None):
- '''merge a given node or the current tip into the working dir'''
- if not node:
- node = repo.changelog.tip()
- else:
- node = repo.lookup(node)
- repo.resolve(node)
-
def serve(ui, repo, **opts):
from mercurial import hgweb
hgweb.server(repo.root, opts["name"], opts["templates"],
@@ -453,6 +433,22 @@
def undo(ui, repo):
repo.undo()
+def update(ui, repo, node=None):
+ '''update or merge working directory
+
+ If there are no outstanding changes in the working directory and
+ there is a linear relationship between the current version and the
+ requested version, the result is the requested version.
+
+ Otherwise the result is a merge between the contents of the
+ current working directory and the requested version. Files that
+ changed between either parent are marked as changed for the next
+ commit and a commit must be performed before any further updates
+ are allowed.
+ '''
+ node = node and repo.lookup(node) or repo.changelog.tip()
+ repo.update(node)
+
def verify(ui, repo):
"""verify the integrity of the repository"""
return repo.verify()
@@ -468,7 +464,6 @@
'hg annotate [-u] [-c] [-n] [-r id] [files]'),
"branch|clone": (branch, [], 'hg branch [path]'),
"cat|dump": (cat, [], 'hg cat <file> [rev]'),
- "checkout|co": (checkout, [], 'hg checkout [changeset]'),
"commit|ci": (commit, [], 'hg commit [files]'),
"debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
"debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
@@ -501,7 +496,6 @@
'hg rawcommit [options] [files]'),
"recover": (recover, [], "hg recover"),
"remove": (remove, [], "hg remove [files]"),
- "resolve": (resolve, [], 'hg resolve [node]'),
"serve": (serve, [('p', 'port', 8000, 'listen port'),
('a', 'address', '', 'interface address'),
('n', 'name', os.getcwd(), 'repository name'),
@@ -511,6 +505,7 @@
"tags": (tags, [], 'hg tags'),
"tip": (tip, [], 'hg tip'),
"undo": (undo, [], 'hg undo'),
+ "update|up|checkout|co|resolve": (update, [], 'hg update [node]'),
"verify": (verify, [], 'hg verify'),
}
--- a/mercurial/hg.py Sat Jun 04 15:16:48 2005 -0800
+++ b/mercurial/hg.py Sat Jun 04 18:34:35 2005 -0800
@@ -327,11 +327,17 @@
if self.tags is None:
self.tags = {}
try:
+ # read each head of the tags file, ending with the tip
+ # and add each tag found to the map, with "newer" ones
+ # taking precedence
fl = self.file(".hgtags")
- for l in fl.revision(fl.tip()).splitlines():
- if l:
- n, k = l.split(" ")
- self.tags[k] = bin(n)
+ h = fl.heads()
+ h.reverse()
+ for r in h:
+ for l in fl.revision(r).splitlines():
+ if l:
+ n, k = l.split(" ")
+ self.tags[k] = bin(n)
except KeyError: pass
try:
return self.tags[key]
@@ -476,27 +482,6 @@
self.dirstate.update(new, "n")
self.dirstate.forget(remove)
- def checkout(self, node):
- # checkout is really dumb at the moment
- # it ought to basically merge
- change = self.changelog.read(node)
- l = self.manifest.read(change[0]).items()
- l.sort()
-
- for f,n in l:
- if f[0] == "/": continue
- self.ui.note(f, "\n")
- t = self.file(f).revision(n)
- try:
- file(self.wjoin(f), "w").write(t)
- except IOError:
- os.makedirs(os.path.dirname(f))
- file(self.wjoin(f), "w").write(t)
-
- self.dirstate.setparents(node)
- self.dirstate.clear()
- self.dirstate.update([f for f,n in l], "n")
-
def diffdir(self, path, changeset = None):
changed = []
added = []
@@ -848,10 +833,10 @@
tr.close()
return
- def resolve(self, node):
+ def update(self, node):
pl = self.dirstate.parents()
if pl[1] != nullid:
- self.ui.warn("last merge not committed")
+ self.ui.warn("aborting: outstanding uncommitted merges\n")
return
p1, p2 = pl[0], node
@@ -866,7 +851,7 @@
# resolve the manifest to determine which files
# we care about merging
- self.ui.status("resolving manifests\n")
+ self.ui.note("resolving manifests\n")
self.ui.debug(" ancestor %s local %s remote %s\n" %
(short(man), short(m1n), short(m2n)))
@@ -876,16 +861,20 @@
# construct a working dir manifest
mw = m1.copy()
- for f in a + c:
- mw[f] = nullid
+ for f in a + c + u:
+ mw[f] = ""
for f in d:
- del mw[f]
+ if f in mw: del mw[f]
for f, n in mw.iteritems():
if f in m2:
if n != m2[f]:
- self.ui.debug(" %s versions differ, do resolve\n" % f)
- merge[f] = (m1.get(f, nullid), m2[f])
+ a = ma.get(f, nullid)
+ if n != a and m2[f] != a:
+ self.ui.debug(" %s versions differ, do resolve\n" % f)
+ merge[f] = (m1.get(f, nullid), m2[f])
+ else:
+ get[f] = m2[f]
del m2[f]
elif f in ma:
if n != ma[f]:
@@ -896,25 +885,36 @@
remove.append(f)
else:
self.ui.debug("other deleted %s\n" % f)
- pass # other deleted it
+ remove.append(f) # other deleted it
else:
- self.ui.debug("local created %s\n" %f)
+ if n == m1.get(f, nullid): # same as parent
+ self.ui.debug("remote deleted %s\n" % f)
+ remove.append(f)
+ else:
+ self.ui.debug("working dir created %s, keeping\n" % f)
for f, n in m2.iteritems():
- if f in ma:
- if n != ma[f]:
+ if f in ma and n != ma[f]:
r = self.ui.prompt(
("remote changed %s which local deleted\n" % f) +
"(k)eep or (d)elete?", "[kd]", "k")
if r == "d": remove.append(f)
- else:
- pass # probably safe
else:
- self.ui.debug("remote created %s, do resolve\n" % f)
+ self.ui.debug("remote created %s\n" % f)
get[f] = n
del mw, m1, m2, ma
+ if not merge:
+ # we don't need to do any magic, just jump to the new rev
+ mode = 'n'
+ p1, p2 = p2, nullid
+ else:
+ # 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'
+
self.dirstate.setparents(p1, p2)
# get the files we don't need to change
@@ -929,26 +929,24 @@
except IOError:
os.makedirs(os.path.dirname(f))
file(self.wjoin(f), "w").write(t)
-
- # 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
- self.dirstate.update(files, 'm')
+ self.dirstate.update([f], mode)
# merge the tricky bits
files = merge.keys()
files.sort()
for f in files:
+ self.status("mering %f\n" % f)
m, o = merge[f]
self.merge3(f, m, o)
-
- # same here
- self.dirstate.update(files, 'm')
+ self.dirstate.update([f], 'm')
for f in remove:
self.ui.note("removing %s\n" % f)
- #os.unlink(f)
- self.dirstate.update(remove, 'r')
+ os.unlink(f)
+ if mode == 'n':
+ self.dirstate.forget(remove)
+ else:
+ self.dirstate.update(remove, 'r')
def merge3(self, fn, my, other):
"""perform a 3-way merge in the working directory"""