##// END OF EJS Templates
unify checkout and resolve into update...
mpm@selenic.com -
r254:c03f58e5 default
parent child Browse files
Show More
@@ -164,18 +164,6 b' def cat(ui, repo, file, rev = []):'
164 if rev: n = r.lookup(rev)
164 if rev: n = r.lookup(rev)
165 sys.stdout.write(r.read(n))
165 sys.stdout.write(r.read(n))
166
166
167 def checkout(ui, repo, changeset=None):
168 '''checkout a given changeset or the current tip'''
169 (c, a, d, u) = repo.diffdir(repo.root)
170 if c or a or d:
171 ui.warn("aborting (outstanding changes in working directory)\n")
172 sys.exit(1)
173
174 node = repo.changelog.tip()
175 if changeset:
176 node = repo.lookup(changeset)
177 repo.checkout(node)
178
179 def commit(ui, repo, *files):
167 def commit(ui, repo, *files):
180 """commit the specified files or all outstanding changes"""
168 """commit the specified files or all outstanding changes"""
181 repo.commit(relpath(repo, files))
169 repo.commit(relpath(repo, files))
@@ -405,14 +393,6 b' def remove(ui, repo, file, *files):'
405 """remove the specified files on the next commit"""
393 """remove the specified files on the next commit"""
406 repo.remove(relpath(repo, (file,) + files))
394 repo.remove(relpath(repo, (file,) + files))
407
395
408 def resolve(ui, repo, node=None):
409 '''merge a given node or the current tip into the working dir'''
410 if not node:
411 node = repo.changelog.tip()
412 else:
413 node = repo.lookup(node)
414 repo.resolve(node)
415
416 def serve(ui, repo, **opts):
396 def serve(ui, repo, **opts):
417 from mercurial import hgweb
397 from mercurial import hgweb
418 hgweb.server(repo.root, opts["name"], opts["templates"],
398 hgweb.server(repo.root, opts["name"], opts["templates"],
@@ -453,6 +433,22 b' def tip(ui, repo):'
453 def undo(ui, repo):
433 def undo(ui, repo):
454 repo.undo()
434 repo.undo()
455
435
436 def update(ui, repo, node=None):
437 '''update or merge working directory
438
439 If there are no outstanding changes in the working directory and
440 there is a linear relationship between the current version and the
441 requested version, the result is the requested version.
442
443 Otherwise the result is a merge between the contents of the
444 current working directory and the requested version. Files that
445 changed between either parent are marked as changed for the next
446 commit and a commit must be performed before any further updates
447 are allowed.
448 '''
449 node = node and repo.lookup(node) or repo.changelog.tip()
450 repo.update(node)
451
456 def verify(ui, repo):
452 def verify(ui, repo):
457 """verify the integrity of the repository"""
453 """verify the integrity of the repository"""
458 return repo.verify()
454 return repo.verify()
@@ -468,7 +464,6 b' table = {'
468 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
464 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
469 "branch|clone": (branch, [], 'hg branch [path]'),
465 "branch|clone": (branch, [], 'hg branch [path]'),
470 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
466 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
471 "checkout|co": (checkout, [], 'hg checkout [changeset]'),
472 "commit|ci": (commit, [], 'hg commit [files]'),
467 "commit|ci": (commit, [], 'hg commit [files]'),
473 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
468 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
474 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
469 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
@@ -501,7 +496,6 b' table = {'
501 'hg rawcommit [options] [files]'),
496 'hg rawcommit [options] [files]'),
502 "recover": (recover, [], "hg recover"),
497 "recover": (recover, [], "hg recover"),
503 "remove": (remove, [], "hg remove [files]"),
498 "remove": (remove, [], "hg remove [files]"),
504 "resolve": (resolve, [], 'hg resolve [node]'),
505 "serve": (serve, [('p', 'port', 8000, 'listen port'),
499 "serve": (serve, [('p', 'port', 8000, 'listen port'),
506 ('a', 'address', '', 'interface address'),
500 ('a', 'address', '', 'interface address'),
507 ('n', 'name', os.getcwd(), 'repository name'),
501 ('n', 'name', os.getcwd(), 'repository name'),
@@ -511,6 +505,7 b' table = {'
511 "tags": (tags, [], 'hg tags'),
505 "tags": (tags, [], 'hg tags'),
512 "tip": (tip, [], 'hg tip'),
506 "tip": (tip, [], 'hg tip'),
513 "undo": (undo, [], 'hg undo'),
507 "undo": (undo, [], 'hg undo'),
508 "update|up|checkout|co|resolve": (update, [], 'hg update [node]'),
514 "verify": (verify, [], 'hg verify'),
509 "verify": (verify, [], 'hg verify'),
515 }
510 }
516
511
@@ -327,11 +327,17 b' class localrepository:'
327 if self.tags is None:
327 if self.tags is None:
328 self.tags = {}
328 self.tags = {}
329 try:
329 try:
330 # read each head of the tags file, ending with the tip
331 # and add each tag found to the map, with "newer" ones
332 # taking precedence
330 fl = self.file(".hgtags")
333 fl = self.file(".hgtags")
331 for l in fl.revision(fl.tip()).splitlines():
334 h = fl.heads()
332 if l:
335 h.reverse()
333 n, k = l.split(" ")
336 for r in h:
334 self.tags[k] = bin(n)
337 for l in fl.revision(r).splitlines():
338 if l:
339 n, k = l.split(" ")
340 self.tags[k] = bin(n)
335 except KeyError: pass
341 except KeyError: pass
336 try:
342 try:
337 return self.tags[key]
343 return self.tags[key]
@@ -476,27 +482,6 b' class localrepository:'
476 self.dirstate.update(new, "n")
482 self.dirstate.update(new, "n")
477 self.dirstate.forget(remove)
483 self.dirstate.forget(remove)
478
484
479 def checkout(self, node):
480 # checkout is really dumb at the moment
481 # it ought to basically merge
482 change = self.changelog.read(node)
483 l = self.manifest.read(change[0]).items()
484 l.sort()
485
486 for f,n in l:
487 if f[0] == "/": continue
488 self.ui.note(f, "\n")
489 t = self.file(f).revision(n)
490 try:
491 file(self.wjoin(f), "w").write(t)
492 except IOError:
493 os.makedirs(os.path.dirname(f))
494 file(self.wjoin(f), "w").write(t)
495
496 self.dirstate.setparents(node)
497 self.dirstate.clear()
498 self.dirstate.update([f for f,n in l], "n")
499
500 def diffdir(self, path, changeset = None):
485 def diffdir(self, path, changeset = None):
501 changed = []
486 changed = []
502 added = []
487 added = []
@@ -848,10 +833,10 b' class localrepository:'
848 tr.close()
833 tr.close()
849 return
834 return
850
835
851 def resolve(self, node):
836 def update(self, node):
852 pl = self.dirstate.parents()
837 pl = self.dirstate.parents()
853 if pl[1] != nullid:
838 if pl[1] != nullid:
854 self.ui.warn("last merge not committed")
839 self.ui.warn("aborting: outstanding uncommitted merges\n")
855 return
840 return
856
841
857 p1, p2 = pl[0], node
842 p1, p2 = pl[0], node
@@ -866,7 +851,7 b' class localrepository:'
866
851
867 # resolve the manifest to determine which files
852 # resolve the manifest to determine which files
868 # we care about merging
853 # we care about merging
869 self.ui.status("resolving manifests\n")
854 self.ui.note("resolving manifests\n")
870 self.ui.debug(" ancestor %s local %s remote %s\n" %
855 self.ui.debug(" ancestor %s local %s remote %s\n" %
871 (short(man), short(m1n), short(m2n)))
856 (short(man), short(m1n), short(m2n)))
872
857
@@ -876,16 +861,20 b' class localrepository:'
876
861
877 # construct a working dir manifest
862 # construct a working dir manifest
878 mw = m1.copy()
863 mw = m1.copy()
879 for f in a + c:
864 for f in a + c + u:
880 mw[f] = nullid
865 mw[f] = ""
881 for f in d:
866 for f in d:
882 del mw[f]
867 if f in mw: del mw[f]
883
868
884 for f, n in mw.iteritems():
869 for f, n in mw.iteritems():
885 if f in m2:
870 if f in m2:
886 if n != m2[f]:
871 if n != m2[f]:
887 self.ui.debug(" %s versions differ, do resolve\n" % f)
872 a = ma.get(f, nullid)
888 merge[f] = (m1.get(f, nullid), m2[f])
873 if n != a and m2[f] != a:
874 self.ui.debug(" %s versions differ, do resolve\n" % f)
875 merge[f] = (m1.get(f, nullid), m2[f])
876 else:
877 get[f] = m2[f]
889 del m2[f]
878 del m2[f]
890 elif f in ma:
879 elif f in ma:
891 if n != ma[f]:
880 if n != ma[f]:
@@ -896,25 +885,36 b' class localrepository:'
896 remove.append(f)
885 remove.append(f)
897 else:
886 else:
898 self.ui.debug("other deleted %s\n" % f)
887 self.ui.debug("other deleted %s\n" % f)
899 pass # other deleted it
888 remove.append(f) # other deleted it
900 else:
889 else:
901 self.ui.debug("local created %s\n" %f)
890 if n == m1.get(f, nullid): # same as parent
891 self.ui.debug("remote deleted %s\n" % f)
892 remove.append(f)
893 else:
894 self.ui.debug("working dir created %s, keeping\n" % f)
902
895
903 for f, n in m2.iteritems():
896 for f, n in m2.iteritems():
904 if f in ma:
897 if f in ma and n != ma[f]:
905 if n != ma[f]:
906 r = self.ui.prompt(
898 r = self.ui.prompt(
907 ("remote changed %s which local deleted\n" % f) +
899 ("remote changed %s which local deleted\n" % f) +
908 "(k)eep or (d)elete?", "[kd]", "k")
900 "(k)eep or (d)elete?", "[kd]", "k")
909 if r == "d": remove.append(f)
901 if r == "d": remove.append(f)
910 else:
911 pass # probably safe
912 else:
902 else:
913 self.ui.debug("remote created %s, do resolve\n" % f)
903 self.ui.debug("remote created %s\n" % f)
914 get[f] = n
904 get[f] = n
915
905
916 del mw, m1, m2, ma
906 del mw, m1, m2, ma
917
907
908 if not merge:
909 # we don't need to do any magic, just jump to the new rev
910 mode = 'n'
911 p1, p2 = p2, nullid
912 else:
913 # we have to remember what files we needed to get/change
914 # because any file that's different from either one of its
915 # parents must be in the changeset
916 mode = 'm'
917
918 self.dirstate.setparents(p1, p2)
918 self.dirstate.setparents(p1, p2)
919
919
920 # get the files we don't need to change
920 # get the files we don't need to change
@@ -929,26 +929,24 b' class localrepository:'
929 except IOError:
929 except IOError:
930 os.makedirs(os.path.dirname(f))
930 os.makedirs(os.path.dirname(f))
931 file(self.wjoin(f), "w").write(t)
931 file(self.wjoin(f), "w").write(t)
932
932 self.dirstate.update([f], mode)
933 # we have to remember what files we needed to get/change
934 # because any file that's different from either one of its
935 # parents must be in the changeset
936 self.dirstate.update(files, 'm')
937
933
938 # merge the tricky bits
934 # merge the tricky bits
939 files = merge.keys()
935 files = merge.keys()
940 files.sort()
936 files.sort()
941 for f in files:
937 for f in files:
938 self.status("mering %f\n" % f)
942 m, o = merge[f]
939 m, o = merge[f]
943 self.merge3(f, m, o)
940 self.merge3(f, m, o)
944
941 self.dirstate.update([f], 'm')
945 # same here
946 self.dirstate.update(files, 'm')
947
942
948 for f in remove:
943 for f in remove:
949 self.ui.note("removing %s\n" % f)
944 self.ui.note("removing %s\n" % f)
950 #os.unlink(f)
945 os.unlink(f)
951 self.dirstate.update(remove, 'r')
946 if mode == 'n':
947 self.dirstate.forget(remove)
948 else:
949 self.dirstate.update(remove, 'r')
952
950
953 def merge3(self, fn, my, other):
951 def merge3(self, fn, my, other):
954 """perform a 3-way merge in the working directory"""
952 """perform a 3-way merge in the working directory"""
General Comments 0
You need to be logged in to leave comments. Login now