mercurial/hg.py
changeset 254 c03f58e5fd2d
parent 253 2da0a56aa1fd
child 256 649ed23e4661
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