comparison mercurial/hg.py @ 254:c03f58e5fd2d

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-----
author mpm@selenic.com
date Sat, 04 Jun 2005 18:34:35 -0800
parents 2da0a56aa1fd
children 649ed23e4661
comparison
equal deleted inserted replaced
253:2da0a56aa1fd 254:c03f58e5fd2d
325 325
326 def lookup(self, key): 326 def lookup(self, key):
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]
338 except KeyError: 344 except KeyError:
339 return self.changelog.lookup(key) 345 return self.changelog.lookup(key)
473 tr.close() 479 tr.close()
474 480
475 self.dirstate.setparents(n) 481 self.dirstate.setparents(n)
476 self.dirstate.update(new, "n") 482 self.dirstate.update(new, "n")
477 self.dirstate.forget(remove) 483 self.dirstate.forget(remove)
478
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 484
500 def diffdir(self, path, changeset = None): 485 def diffdir(self, path, changeset = None):
501 changed = [] 486 changed = []
502 added = [] 487 added = []
503 unknown = [] 488 unknown = []
846 % (files, changesets, revisions)) 831 % (files, changesets, revisions))
847 832
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
858 m1n = self.changelog.read(p1)[0] 843 m1n = self.changelog.read(p1)[0]
859 m2n = self.changelog.read(p2)[0] 844 m2n = self.changelog.read(p2)[0]
864 849
865 (c, a, d, u) = self.diffdir(self.root) 850 (c, a, d, u) = self.diffdir(self.root)
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
873 merge = {} 858 merge = {}
874 get = {} 859 get = {}
875 remove = [] 860 remove = []
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]:
892 r = self.ui.prompt( 881 r = self.ui.prompt(
893 (" local changed %s which remote deleted\n" % f) + 882 (" local changed %s which remote deleted\n" % f) +
894 "(k)eep or (d)elete?", "[kd]", "k") 883 "(k)eep or (d)elete?", "[kd]", "k")
895 if r == "d": 884 if r == "d":
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
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 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
921 files = get.keys() 921 files = get.keys()
927 try: 927 try:
928 file(self.wjoin(f), "w").write(t) 928 file(self.wjoin(f), "w").write(t)
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"""
955 953
956 import tempfile 954 import tempfile