mercurial/hg.py
changeset 276 10e325db7347
parent 275 61d45b0ba8fb
child 277 79279550c8ff
equal deleted inserted replaced
275:61d45b0ba8fb 276:10e325db7347
     8 import sys, struct, os
     8 import sys, struct, os
     9 from revlog import *
     9 from revlog import *
    10 from demandload import *
    10 from demandload import *
    11 demandload(globals(), "re lock urllib urllib2 transaction time socket")
    11 demandload(globals(), "re lock urllib urllib2 transaction time socket")
    12 demandload(globals(), "tempfile byterange difflib")
    12 demandload(globals(), "tempfile byterange difflib")
       
    13 
       
    14 def is_exec(f):
       
    15     return (os.stat(f).st_mode & 0100 != 0)
       
    16 
       
    17 def set_exec(f, mode):
       
    18     s = os.stat(f).st_mode
       
    19     if (s & 0100 != 0) == mode:
       
    20         return
       
    21     os.chmod(f, s & 0666 | (mode * 0111))
    13 
    22 
    14 class filelog(revlog):
    23 class filelog(revlog):
    15     def __init__(self, opener, path):
    24     def __init__(self, opener, path):
    16         revlog.__init__(self, opener,
    25         revlog.__init__(self, opener,
    17                         os.path.join("data", path + ".i"),
    26                         os.path.join("data", path + ".i"),
    83     def read(self, node):
    92     def read(self, node):
    84         if self.mapcache and self.mapcache[0] == node:
    93         if self.mapcache and self.mapcache[0] == node:
    85             return self.mapcache[1].copy()
    94             return self.mapcache[1].copy()
    86         text = self.revision(node)
    95         text = self.revision(node)
    87         map = {}
    96         map = {}
       
    97         flag = {}
    88         self.listcache = (text, text.splitlines(1))
    98         self.listcache = (text, text.splitlines(1))
    89         for l in self.listcache[1]:
    99         for l in self.listcache[1]:
    90             (f, n) = l.split('\0')
   100             (f, n) = l.split('\0')
    91             map[f] = bin(n[:40])
   101             map[f] = bin(n[:40])
    92         self.mapcache = (node, map)
   102             flag[f] = (n[40:-1] == "x")
       
   103         self.mapcache = (node, map, flag)
    93         return map
   104         return map
       
   105 
       
   106     def readflags(self, node):
       
   107         if self.mapcache or self.mapcache[0] != node:
       
   108             self.read(node)
       
   109         return self.mapcache[2]
    94 
   110 
    95     def diff(self, a, b):
   111     def diff(self, a, b):
    96         # this is sneaky, as we're not actually using a and b
   112         # this is sneaky, as we're not actually using a and b
    97         if self.listcache and self.addlist and self.listcache[0] == a:
   113         if self.listcache and self.addlist and self.listcache[0] == a:
    98             d = mdiff.diff(self.listcache[1], self.addlist, 1)
   114             d = mdiff.diff(self.listcache[1], self.addlist, 1)
   101                 return mdiff.textdiff(a, b)
   117                 return mdiff.textdiff(a, b)
   102             return d
   118             return d
   103         else:
   119         else:
   104             return mdiff.textdiff(a, b)
   120             return mdiff.textdiff(a, b)
   105 
   121 
   106     def add(self, map, transaction, link, p1=None, p2=None):
   122     def add(self, map, flags, transaction, link, p1=None, p2=None):
   107         files = map.keys()
   123         files = map.keys()
   108         files.sort()
   124         files.sort()
   109 
   125 
   110         self.addlist = ["%s\000%s\n" % (f, hex(map[f])) for f in files]
   126         self.addlist = ["%s\000%s%s\n" %
       
   127                         (f, hex(map[f]), flags[f] and "x" or '')
       
   128                         for f in files]
   111         text = "".join(self.addlist)
   129         text = "".join(self.addlist)
   112 
   130 
   113         n = self.addrevision(text, transaction, link, p1, p2)
   131         n = self.addrevision(text, transaction, link, p1, p2)
   114         self.mapcache = (n, map)
   132         self.mapcache = (n, map)
   115         self.listcache = (text, self.addlist)
   133         self.listcache = (text, self.addlist)
   440 
   458 
   441         p1, p2 = self.dirstate.parents()
   459         p1, p2 = self.dirstate.parents()
   442         c1 = self.changelog.read(p1)
   460         c1 = self.changelog.read(p1)
   443         c2 = self.changelog.read(p2)
   461         c2 = self.changelog.read(p2)
   444         m1 = self.manifest.read(c1[0])
   462         m1 = self.manifest.read(c1[0])
       
   463         mf1 = self.manifest.readflags(c1[0])
   445         m2 = self.manifest.read(c2[0])
   464         m2 = self.manifest.read(c2[0])
   446         lock = self.lock()
   465         lock = self.lock()
   447         tr = self.transaction()
   466         tr = self.transaction()
   448 
   467 
   449         # check in files
   468         # check in files
   451         linkrev = self.changelog.count()
   470         linkrev = self.changelog.count()
   452         commit.sort()
   471         commit.sort()
   453         for f in commit:
   472         for f in commit:
   454             self.ui.note(f + "\n")
   473             self.ui.note(f + "\n")
   455             try:
   474             try:
   456                 t = file(self.wjoin(f)).read()
   475                 fp = self.wjoin(f)
       
   476                 mf1[f] = is_exec(fp)
       
   477                 t = file(fp).read()
   457             except IOError:
   478             except IOError:
   458                 self.warn("trouble committing %s!\n" % f)
   479                 self.warn("trouble committing %s!\n" % f)
   459                 raise
   480                 raise
   460 
   481 
   461             r = self.file(f)
   482             r = self.file(f)
   464             new[f] = r.add(t, tr, linkrev, fp1, fp2)
   485             new[f] = r.add(t, tr, linkrev, fp1, fp2)
   465 
   486 
   466         # update manifest
   487         # update manifest
   467         m1.update(new)
   488         m1.update(new)
   468         for f in remove: del m1[f]
   489         for f in remove: del m1[f]
   469         mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0])
   490         mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0])
   470 
   491 
   471         # add changeset
   492         # add changeset
   472         new = new.keys()
   493         new = new.keys()
   473         new.sort()
   494         new.sort()
   474 
   495 
   523                         changed.append(fn)
   544                         changed.append(fn)
   524                     elif c[0] == 'a':
   545                     elif c[0] == 'a':
   525                         added.append(fn)
   546                         added.append(fn)
   526                     elif c[0] == 'r':
   547                     elif c[0] == 'r':
   527                         unknown.append(fn)
   548                         unknown.append(fn)
   528                     elif c[2] != s.st_size:
   549                     elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100:
   529                         changed.append(fn)
   550                         changed.append(fn)
   530                     elif c[1] != s.st_mode or c[3] != s.st_mtime:
   551                     elif c[1] != s.st_mode or c[3] != s.st_mtime:
   531                         if fcmp(fn):
   552                         if fcmp(fn):
   532                             changed.append(fn)
   553                             changed.append(fn)
   533                 else:
   554                 else:
   844         p1, p2 = pl[0], node
   865         p1, p2 = pl[0], node
   845         m1n = self.changelog.read(p1)[0]
   866         m1n = self.changelog.read(p1)[0]
   846         m2n = self.changelog.read(p2)[0]
   867         m2n = self.changelog.read(p2)[0]
   847         man = self.manifest.ancestor(m1n, m2n)
   868         man = self.manifest.ancestor(m1n, m2n)
   848         m1 = self.manifest.read(m1n)
   869         m1 = self.manifest.read(m1n)
       
   870         mf1 = self.manifest.readflags(m1n)
   849         m2 = self.manifest.read(m2n)
   871         m2 = self.manifest.read(m2n)
       
   872         mf2 = self.manifest.readflags(m2n)
   850         ma = self.manifest.read(man)
   873         ma = self.manifest.read(man)
       
   874         mfa = self.manifest.readflags(m2n)
   851 
   875 
   852         (c, a, d, u) = self.diffdir(self.root)
   876         (c, a, d, u) = self.diffdir(self.root)
   853 
   877 
   854         # resolve the manifest to determine which files
   878         # resolve the manifest to determine which files
   855         # we care about merging
   879         # we care about merging
   861         get = {}
   885         get = {}
   862         remove = []
   886         remove = []
   863 
   887 
   864         # construct a working dir manifest
   888         # construct a working dir manifest
   865         mw = m1.copy()
   889         mw = m1.copy()
       
   890         mfw = mf1.copy()
   866         for f in a + c + u:
   891         for f in a + c + u:
   867             mw[f] = ""
   892             mw[f] = ""
       
   893             mfw[f] = is_exec(self.wjoin(f))
   868         for f in d:
   894         for f in d:
   869             if f in mw: del mw[f]
   895             if f in mw: del mw[f]
   870 
   896 
   871         for f, n in mw.iteritems():
   897         for f, n in mw.iteritems():
   872             if f in m2:
   898             if f in m2:
   873                 if n != m2[f]:
   899                 if n != m2[f]:
   874                     a = ma.get(f, nullid)
   900                     a = ma.get(f, nullid)
   875                     if n != a and m2[f] != a:
   901                     if n != a and m2[f] != a:
   876                         self.ui.debug(" %s versions differ, resolve\n" % f)
   902                         self.ui.debug(" %s versions differ, resolve\n" % f)
   877                         merge[f] = (m1.get(f, nullid), m2[f])
   903                         merge[f] = (m1.get(f, nullid), m2[f])
       
   904                         # merge executable bits
       
   905                         # "if we changed or they changed, change in merge"
       
   906                         a, b, c = mfa.get(f, 0), mfw[f], mf2[f]
       
   907                         mode = ((a^b) | (a^c)) ^ a
       
   908                         merge[f] = (m1.get(f, nullid), m2[f], mode)
   878                     elif m2[f] != a:
   909                     elif m2[f] != a:
   879                         self.ui.debug(" remote %s is newer, get\n" % f)
   910                         self.ui.debug(" remote %s is newer, get\n" % f)
   880                         get[f] = m2[f]
   911                         get[f] = m2[f]
   881                 del m2[f]
   912                 del m2[f]
   882             elif f in ma:
   913             elif f in ma:
   937         files = get.keys()
   968         files = get.keys()
   938         files.sort()
   969         files.sort()
   939         for f in files:
   970         for f in files:
   940             if f[0] == "/": continue
   971             if f[0] == "/": continue
   941             self.ui.note("getting %s\n" % f)
   972             self.ui.note("getting %s\n" % f)
   942             t = self.file(f).revision(get[f])
   973             t = self.file(f).read(get[f])
       
   974             wp = self.wjoin(f)
   943             try:
   975             try:
   944                 file(self.wjoin(f), "w").write(t)
   976                 file(wp, "w").write(t)
   945             except IOError:
   977             except IOError:
   946                 os.makedirs(os.path.dirname(f))
   978                 os.makedirs(os.path.dirname(wp))
   947                 file(self.wjoin(f), "w").write(t)
   979                 file(wp, "w").write(t)
       
   980             set_exec(wp, mf2[f])
   948             self.dirstate.update([f], mode)
   981             self.dirstate.update([f], mode)
   949 
   982 
   950         # merge the tricky bits
   983         # merge the tricky bits
   951         files = merge.keys()
   984         files = merge.keys()
   952         files.sort()
   985         files.sort()
   953         for f in files:
   986         for f in files:
   954             self.ui.status("merging %s\n" % f)
   987             self.ui.status("merging %s\n" % f)
   955             m, o = merge[f]
   988             m, o, flag = merge[f]
   956             self.merge3(f, m, o)
   989             self.merge3(f, m, o)
       
   990             set_exec(wp, flag)
   957             self.dirstate.update([f], 'm')
   991             self.dirstate.update([f], 'm')
   958 
   992 
   959         for f in remove:
   993         for f in remove:
   960             self.ui.note("removing %s\n" % f)
   994             self.ui.note("removing %s\n" % f)
   961             os.unlink(f)
   995             os.unlink(f)