mercurial/util.py
changeset 1584 b3e94785ab69
parent 1583 32a4e6802864
parent 1566 8befbb4e30b2
child 1585 d7c4b9bfcc94
equal deleted inserted replaced
1583:32a4e6802864 1584:b3e94785ab69
   103 class Abort(Exception):
   103 class Abort(Exception):
   104     """Raised if a command needs to print an error and exit."""
   104     """Raised if a command needs to print an error and exit."""
   105 
   105 
   106 def always(fn): return True
   106 def always(fn): return True
   107 def never(fn): return False
   107 def never(fn): return False
       
   108 
       
   109 def patkind(name, dflt_pat='glob'):
       
   110     """Split a string into an optional pattern kind prefix and the
       
   111     actual pattern."""
       
   112     for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
       
   113         if name.startswith(prefix + ':'): return name.split(':', 1)
       
   114     return dflt_pat, name
   108 
   115 
   109 def globre(pat, head='^', tail='$'):
   116 def globre(pat, head='^', tail='$'):
   110     "convert a glob pattern into a regexp"
   117     "convert a glob pattern into a regexp"
   111     i, n = 0, len(pat)
   118     i, n = 0, len(pat)
   112     res = ''
   119     res = ''
   156 def pathto(n1, n2):
   163 def pathto(n1, n2):
   157     '''return the relative path from one place to another.
   164     '''return the relative path from one place to another.
   158     this returns a path in the form used by the local filesystem, not hg.'''
   165     this returns a path in the form used by the local filesystem, not hg.'''
   159     if not n1: return localpath(n2)
   166     if not n1: return localpath(n2)
   160     a, b = n1.split('/'), n2.split('/')
   167     a, b = n1.split('/'), n2.split('/')
   161     a.reverse(), b.reverse()
   168     a.reverse()
       
   169     b.reverse()
   162     while a and b and a[-1] == b[-1]:
   170     while a and b and a[-1] == b[-1]:
   163         a.pop(), b.pop()
   171         a.pop()
       
   172         b.pop()
   164     b.reverse()
   173     b.reverse()
   165     return os.sep.join((['..'] * len(a)) + b)
   174     return os.sep.join((['..'] * len(a)) + b)
   166 
   175 
   167 def canonpath(root, cwd, myname):
   176 def canonpath(root, cwd, myname):
   168     """return the canonical path of myname, given cwd and root"""
   177     """return the canonical path of myname, given cwd and root"""
   169     rootsep = root + os.sep
   178     if root == os.sep:
       
   179         rootsep = os.sep
       
   180     else:
       
   181     	rootsep = root + os.sep
   170     name = myname
   182     name = myname
   171     if not name.startswith(os.sep):
   183     if not name.startswith(os.sep):
   172         name = os.path.join(root, cwd, name)
   184         name = os.path.join(root, cwd, name)
   173     name = os.path.normpath(name)
   185     name = os.path.normpath(name)
   174     if name.startswith(rootsep):
   186     if name.startswith(rootsep):
   215     - a bool indicating if any patterns were passed in
   227     - a bool indicating if any patterns were passed in
   216 
   228 
   217     todo:
   229     todo:
   218     make head regex a rooted bool
   230     make head regex a rooted bool
   219     """
   231     """
   220 
       
   221     def patkind(name, dflt_pat='glob'):
       
   222         for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
       
   223             if name.startswith(prefix + ':'): return name.split(':', 1)
       
   224         return dflt_pat, name
       
   225 
   232 
   226     def contains_glob(name):
   233     def contains_glob(name):
   227         for c in name:
   234         for c in name:
   228             if c in _globchars: return True
   235             if c in _globchars: return True
   229         return False
   236         return False
   251         matches = []
   258         matches = []
   252         for k, p in pats:
   259         for k, p in pats:
   253             try:
   260             try:
   254                 pat = '(?:%s)' % regex(k, p, tail)
   261                 pat = '(?:%s)' % regex(k, p, tail)
   255                 matches.append(re.compile(pat).match)
   262                 matches.append(re.compile(pat).match)
   256             except re.error, inst:
   263             except re.error:
   257                 raise Abort("invalid pattern: %s:%s" % (k, p))
   264                 raise Abort("invalid pattern: %s:%s" % (k, p))
   258 
   265 
   259         def buildfn(text):
   266         def buildfn(text):
   260             for m in matches:
   267             for m in matches:
   261                 r = m(text)
   268                 r = m(text)
   360 
   367 
   361     this function is used to hide the details of COW semantics and
   368     this function is used to hide the details of COW semantics and
   362     remote file access from higher level code.
   369     remote file access from higher level code.
   363     """
   370     """
   364     p = base
   371     p = base
   365     def o(path, mode="r", text=False):
   372 
       
   373     def mktempcopy(name):
       
   374         d, fn = os.path.split(name)
       
   375         fd, temp = tempfile.mkstemp(prefix=fn, dir=d)
       
   376         fp = os.fdopen(fd, "wb")
       
   377         try:
       
   378             fp.write(file(name, "rb").read())
       
   379         except:
       
   380             try: os.unlink(temp)
       
   381             except: pass
       
   382             raise
       
   383         fp.close()
       
   384         st = os.lstat(name)
       
   385         os.chmod(temp, st.st_mode)
       
   386         return temp
       
   387 
       
   388     class atomicfile(file):
       
   389         """the file will only be copied on close"""
       
   390         def __init__(self, name, mode, atomic=False):
       
   391             self.__name = name
       
   392             self.temp = mktempcopy(name)
       
   393             file.__init__(self, self.temp, mode)
       
   394         def close(self):
       
   395             if not self.closed:
       
   396                 file.close(self)
       
   397                 rename(self.temp, self.__name)
       
   398         def __del__(self):
       
   399             self.close()
       
   400 
       
   401     def o(path, mode="r", text=False, atomic=False):
   366         f = os.path.join(p, path)
   402         f = os.path.join(p, path)
   367 
   403 
   368         if not text:
   404         if not text:
   369             mode += "b" # for that other OS
   405             mode += "b" # for that other OS
   370 
   406 
   374             except OSError:
   410             except OSError:
   375                 d = os.path.dirname(f)
   411                 d = os.path.dirname(f)
   376                 if not os.path.isdir(d):
   412                 if not os.path.isdir(d):
   377                     os.makedirs(d)
   413                     os.makedirs(d)
   378             else:
   414             else:
       
   415                 if atomic:
       
   416                     return atomicfile(f, mode)
   379                 if nlink > 1:
   417                 if nlink > 1:
   380                     d, fn = os.path.split(f)
   418                     rename(mktempcopy(f), f)
   381                     fd, temp = tempfile.mkstemp(prefix=fn, dir=d)
       
   382                     fp = os.fdopen(fd, "wb")
       
   383                     try:
       
   384                         fp.write(file(f, "rb").read())
       
   385                     except:
       
   386                         try: os.unlink(temp)
       
   387                         except: pass
       
   388                         raise
       
   389                     fp.close()
       
   390                     rename(temp, f)
       
   391 
       
   392         return file(f, mode)
   419         return file(f, mode)
   393 
   420 
   394     return o
   421     return o
   395 
   422 
   396 def _makelock_file(info, pathname):
   423 def _makelock_file(info, pathname):
   482 
   509 
   483 else:
   510 else:
   484     nulldev = '/dev/null'
   511     nulldev = '/dev/null'
   485 
   512 
   486     def rcfiles(path):
   513     def rcfiles(path):
       
   514         print 'checking', path
   487         rcs = [os.path.join(path, 'hgrc')]
   515         rcs = [os.path.join(path, 'hgrc')]
   488         rcdir = os.path.join(path, 'hgrc.d')
   516         rcdir = os.path.join(path, 'hgrc.d')
   489         try:
   517         try:
   490             rcs.extend([os.path.join(rcdir, f) for f in os.listdir(rcdir)
   518             rcs.extend([os.path.join(rcdir, f) for f in os.listdir(rcdir)
   491                         if f.endswith(".rc")])
   519                         if f.endswith(".rc")])