mercurial/hg.py
changeset 896 01215ad04283
parent 866 6d6095823b82
parent 895 77b52b864249
child 898 3616c0d7ab88
equal deleted inserted replaced
867:0cd2ee61b10a 896:01215ad04283
     8 import sys, struct, os
     8 import sys, struct, os
     9 import util
     9 import util
    10 from revlog import *
    10 from revlog import *
    11 from demandload import *
    11 from demandload import *
    12 demandload(globals(), "re lock urllib urllib2 transaction time socket")
    12 demandload(globals(), "re lock urllib urllib2 transaction time socket")
    13 demandload(globals(), "tempfile httprangereader bdiff urlparse stat")
    13 demandload(globals(), "tempfile httprangereader bdiff urlparse")
    14 demandload(globals(), "bisect select")
    14 demandload(globals(), "bisect errno select stat")
    15 
    15 
    16 class filelog(revlog):
    16 class filelog(revlog):
    17     def __init__(self, opener, path):
    17     def __init__(self, opener, path):
    18         revlog.__init__(self, opener,
    18         revlog.__init__(self, opener,
    19                         os.path.join("data", self.encodedir(path + ".i")),
    19                         os.path.join("data", self.encodedir(path + ".i")),
   298         self.ignorefunc = None
   298         self.ignorefunc = None
   299 
   299 
   300     def wjoin(self, f):
   300     def wjoin(self, f):
   301         return os.path.join(self.root, f)
   301         return os.path.join(self.root, f)
   302 
   302 
       
   303     def getcwd(self):
       
   304         cwd = os.getcwd()
       
   305         if cwd == self.root: return ''
       
   306         return cwd[len(self.root) + 1:]
       
   307 
   303     def ignore(self, f):
   308     def ignore(self, f):
   304         if not self.ignorefunc:
   309         if not self.ignorefunc:
   305             bigpat = []
   310             bigpat = []
   306             try:
   311             try:
   307                 l = file(self.wjoin(".hgignore"))
   312                 l = file(self.wjoin(".hgignore"))
   308                 for pat in l:
   313                 for pat in l:
   309                     if pat != "\n":
   314                     if pat != "\n":
   310                         p = util.pconvert(pat[:-1])
   315 			p = pat[:-1]
   311                         try:
   316                         try:
   312                             r = re.compile(p)
   317                             re.compile(p)
   313                         except:
   318                         except:
   314                             self.ui.warn("ignoring invalid ignore"
   319                             self.ui.warn("ignoring invalid ignore"
   315                                          + " regular expression '%s'\n" % p)
   320                                          + " regular expression '%s'\n" % p)
   316                         else:
   321                         else:
   317                             bigpat.append(util.pconvert(pat[:-1]))
   322                             bigpat.append(p)
   318             except IOError: pass
   323             except IOError: pass
   319 
   324 
   320             if bigpat:
   325             if bigpat:
   321                 s = "(?:%s)" % (")|(?:".join(bigpat))
   326                 s = "(?:%s)" % (")|(?:".join(bigpat))
   322                 r = re.compile(s)
   327                 r = re.compile(s)
   435                 f = f + "\0" + c
   440                 f = f + "\0" + c
   436             e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
   441             e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
   437             st.write(e + f)
   442             st.write(e + f)
   438         self.dirty = 0
   443         self.dirty = 0
   439 
   444 
   440     def walk(self, files = None, match = util.always):
   445     def filterfiles(self, files):
       
   446         ret = {}
       
   447         unknown = []
       
   448 
       
   449         for x in files:
       
   450             if x is '.':
       
   451                 return self.map.copy()
       
   452             if x not in self.map:
       
   453                 unknown.append(x)
       
   454             else:
       
   455                 ret[x] = self.map[x]
       
   456                 
       
   457         if not unknown:
       
   458             return ret
       
   459 
       
   460         b = self.map.keys()
       
   461         b.sort()
       
   462         blen = len(b)
       
   463 
       
   464         for x in unknown:
       
   465             bs = bisect.bisect(b, x)
       
   466             if bs != 0 and  b[bs-1] == x: 
       
   467                 ret[x] = self.map[x]
       
   468                 continue
       
   469             while bs < blen:
       
   470                 s = b[bs]
       
   471                 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/':
       
   472                     ret[s] = self.map[s]
       
   473                 else:
       
   474                     break
       
   475                 bs += 1
       
   476         return ret
       
   477 
       
   478     def walk(self, files = None, match = util.always, dc=None):
   441         self.read()
   479         self.read()
   442         dc = self.map.copy()
   480 
   443         # walk all files by default
   481         # walk all files by default
   444         if not files: files = [self.root]
   482         if not files:
       
   483             files = [self.root]
       
   484             if not dc:
       
   485                 dc = self.map.copy()
       
   486         elif not dc:
       
   487             dc = self.filterfiles(files)
       
   488                     
   445         known = {'.hg': 1}
   489         known = {'.hg': 1}
   446         def seen(fn):
   490         def seen(fn):
   447             if fn in known: return True
   491             if fn in known: return True
   448             known[fn] = 1
   492             known[fn] = 1
   449         def traverse():
   493         def traverse():
   450             for f in util.unique(files):
   494             for ff in util.unique(files):
   451                 f = os.path.join(self.root, f)
   495                 f = os.path.join(self.root, ff)
   452                 if os.path.isdir(f):
   496                 try:
       
   497                     st = os.stat(f)
       
   498                 except OSError, inst:
       
   499                     if ff not in dc: self.ui.warn('%s: %s\n' % (
       
   500                         util.pathto(self.getcwd(), ff),
       
   501                         inst.strerror))
       
   502                     continue
       
   503                 if stat.S_ISDIR(st.st_mode):
   453                     for dir, subdirs, fl in os.walk(f):
   504                     for dir, subdirs, fl in os.walk(f):
   454                         d = dir[len(self.root) + 1:]
   505                         d = dir[len(self.root) + 1:]
   455                         nd = os.path.normpath(d)
   506                         nd = util.normpath(d)
       
   507                         if nd == '.': nd = ''
   456                         if seen(nd):
   508                         if seen(nd):
   457                             subdirs[:] = []
   509                             subdirs[:] = []
   458                             continue
   510                             continue
   459                         for sd in subdirs:
   511                         for sd in subdirs:
   460                             ds = os.path.join(nd, sd +'/')
   512                             ds = os.path.join(nd, sd +'/')
   463                         subdirs.sort()
   515                         subdirs.sort()
   464                         fl.sort()
   516                         fl.sort()
   465                         for fn in fl:
   517                         for fn in fl:
   466                             fn = util.pconvert(os.path.join(d, fn))
   518                             fn = util.pconvert(os.path.join(d, fn))
   467                             yield 'f', fn
   519                             yield 'f', fn
       
   520                 elif stat.S_ISREG(st.st_mode):
       
   521                     yield 'f', ff
   468                 else:
   522                 else:
   469                     yield 'f', f[len(self.root) + 1:]
   523                     kind = 'unknown'
       
   524                     if stat.S_ISCHR(st.st_mode): kind = 'character device'
       
   525                     elif stat.S_ISBLK(st.st_mode): kind = 'block device'
       
   526                     elif stat.S_ISFIFO(st.st_mode): kind = 'fifo'
       
   527                     elif stat.S_ISLNK(st.st_mode): kind = 'symbolic link'
       
   528                     elif stat.S_ISSOCK(st.st_mode): kind = 'socket'
       
   529                     self.ui.warn('%s: unsupported file type (type is %s)\n' % (
       
   530                         util.pathto(self.getcwd(), ff),
       
   531                         kind))
   470 
   532 
   471             ks = dc.keys()
   533             ks = dc.keys()
   472             ks.sort()
   534             ks.sort()
   473             for k in ks:
   535             for k in ks:
   474                 yield 'm', k
   536                 yield 'm', k
   475 
   537 
   476         # yield only files that match: all in dirstate, others only if
   538         # yield only files that match: all in dirstate, others only if
   477         # not in .hgignore
   539         # not in .hgignore
   478 
   540 
   479         for src, fn in util.unique(traverse()):
   541         for src, fn in util.unique(traverse()):
   480             fn = os.path.normpath(fn)
   542             fn = util.normpath(fn)
   481             if seen(fn): continue
   543             if seen(fn): continue
   482             if fn in dc:
   544             if fn not in dc and self.ignore(fn):
   483                 del dc[fn]
       
   484             elif self.ignore(fn):
       
   485                 continue
   545                 continue
   486             if match(fn):
   546             if match(fn):
   487                 yield src, fn
   547                 yield src, fn
   488 
   548 
   489     def changes(self, files=None, match=util.always):
   549     def changes(self, files=None, match=util.always):
   490         self.read()
   550         self.read()
   491         dc = self.map.copy()
   551         if not files:
       
   552             dc = self.map.copy()
       
   553         else:
       
   554             dc = self.filterfiles(files)
   492         lookup, modified, added, unknown = [], [], [], []
   555         lookup, modified, added, unknown = [], [], [], []
   493         removed, deleted = [], []
   556         removed, deleted = [], []
   494 
   557 
   495         for src, fn in self.walk(files, match):
   558         for src, fn in self.walk(files, match, dc=dc):
   496             try:
   559             try:
   497                 s = os.stat(os.path.join(self.root, fn))
   560                 s = os.stat(os.path.join(self.root, fn))
   498             except OSError:
   561             except OSError:
   499                 continue
   562                 continue
   500             if not stat.S_ISREG(s.st_mode):
   563             if not stat.S_ISREG(s.st_mode):
   695     def file(self, f):
   758     def file(self, f):
   696         if f[0] == '/': f = f[1:]
   759         if f[0] == '/': f = f[1:]
   697         return filelog(self.opener, f)
   760         return filelog(self.opener, f)
   698 
   761 
   699     def getcwd(self):
   762     def getcwd(self):
   700         cwd = os.getcwd()
   763         return self.dirstate.getcwd()
   701         if cwd == self.root: return ''
       
   702         return cwd[len(self.root) + 1:]
       
   703 
   764 
   704     def wfile(self, f, mode='r'):
   765     def wfile(self, f, mode='r'):
   705         return self.wopener(f, mode)
   766         return self.wopener(f, mode)
   706 
   767 
   707     def transaction(self):
   768     def transaction(self):