##// END OF EJS Templates
Catch hgrc interpolation errors nicely.
Catch hgrc interpolation errors nicely.

File last commit:

r1835:bdfb524d default
r1876:2e0fd785 default
Show More
util.py
715 lines | 21.6 KiB | text/x-python | PythonLexer
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """
util.py - Mercurial utility functions and platform specfic implementations
Copyright 2005 K. Thananchayan <thananck@yahoo.com>
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
This contains helper routines that are independent of the SCM core and hide
platform-specific details from the core.
"""
mpm@selenic.com
[PATCH] file seperator handling for the other 'OS'...
r419
Thomas Arendsen Hein
Make makelock and readlock work on filesystems without symlink support....
r704 import os, errno
Benoit Boissinot
i18n first part: make '_' available for files who need it
r1400 from i18n import gettext as _
Bryan O'Sullivan
Get add and locate to use new repo and dirstate walk code....
r724 from demandload import *
Vadim Gelfer
eliminate backtrace when piping output on windows....
r1609 demandload(globals(), "cStringIO errno popen2 re shutil sys tempfile")
demandload(globals(), "threading time")
mpm@selenic.com
Add file encoding/decoding support
r1258
Bryan O'Sullivan
Enhance the file filtering capabilities....
r1293 def pipefilter(s, cmd):
'''filter string S through command CMD, returning its output'''
mpm@selenic.com
Add file encoding/decoding support
r1258 (pout, pin) = popen2.popen2(cmd, -1, 'b')
def writer():
pin.write(s)
pin.close()
# we should use select instead on UNIX, but this will work on most
# systems, including Windows
w = threading.Thread(target=writer)
w.start()
f = pout.read()
pout.close()
w.join()
return f
mpm@selenic.com
[PATCH] file seperator handling for the other 'OS'...
r419
Bryan O'Sullivan
Enhance the file filtering capabilities....
r1293 def tempfilter(s, cmd):
'''filter string S through a pair of temporary files with CMD.
CMD is used as a template to create the real command to be run,
with the strings INFILE and OUTFILE replaced by the real names of
the temporary files generated.'''
inname, outname = None, None
try:
infd, inname = tempfile.mkstemp(prefix='hgfin')
fp = os.fdopen(infd, 'wb')
fp.write(s)
fp.close()
outfd, outname = tempfile.mkstemp(prefix='hgfout')
os.close(outfd)
cmd = cmd.replace('INFILE', inname)
cmd = cmd.replace('OUTFILE', outname)
code = os.system(cmd)
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 if code: raise Abort(_("command '%s' failed: %s") %
Bryan O'Sullivan
Enhance the file filtering capabilities....
r1293 (cmd, explain_exit(code)))
return open(outname, 'rb').read()
finally:
try:
if inname: os.unlink(inname)
except: pass
try:
if outname: os.unlink(outname)
except: pass
filtertable = {
'tempfile:': tempfilter,
'pipe:': pipefilter,
}
def filter(s, cmd):
"filter a string through a command that transforms its input to its output"
for name, fn in filtertable.iteritems():
if cmd.startswith(name):
return fn(s, cmd[len(name):].lstrip())
return pipefilter(s, cmd)
Volker Kleinfeld
Make 'hg import' platform independent....
r1285 def patch(strip, patchname, ui):
"""apply the patch <patchname> to the working directory.
a list of patched files is returned"""
fp = os.popen('patch -p%d < "%s"' % (strip, patchname))
files = {}
for line in fp:
line = line.rstrip()
ui.status("%s\n" % line)
if line.startswith('patching file '):
pf = parse_patch_output(line)
files.setdefault(pf, 1)
code = fp.close()
if code:
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 raise Abort(_("patch command failed: %s") % explain_exit(code)[0])
Volker Kleinfeld
Make 'hg import' platform independent....
r1285 return files.keys()
Thomas Arendsen Hein
Cleanup of tabs and trailing spaces.
r1308
mpm@selenic.com
Add automatic binary file detection to diff and export...
r1015 def binary(s):
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """return true if a string is binary data using diff's heuristic"""
mpm@selenic.com
Add automatic binary file detection to diff and export...
r1015 if s and '\0' in s[:4096]:
return True
return False
mpm@selenic.com
Move dirstate.uniq to util.unique...
r556 def unique(g):
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """return the uniq elements of iterable g"""
mpm@selenic.com
Move dirstate.uniq to util.unique...
r556 seen = {}
for f in g:
if f not in seen:
seen[f] = 1
yield f
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 class Abort(Exception):
"""Raised if a command needs to print an error and exit."""
mpm@selenic.com
[PATCH] Harden os.system...
r508
Bryan O'Sullivan
Get add and locate to use new repo and dirstate walk code....
r724 def always(fn): return True
def never(fn): return False
Robin Farine
export patkind() from util
r1563 def patkind(name, dflt_pat='glob'):
"""Split a string into an optional pattern kind prefix and the
actual pattern."""
for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
if name.startswith(prefix + ':'): return name.split(':', 1)
return dflt_pat, name
benoit.boissinot@ens-lyon.fr
pep-0008 cleanup...
r1062 def globre(pat, head='^', tail='$'):
Bryan O'Sullivan
Get add and locate to use new repo and dirstate walk code....
r724 "convert a glob pattern into a regexp"
i, n = 0, len(pat)
res = ''
group = False
def peek(): return i < n and pat[i]
while i < n:
c = pat[i]
i = i+1
if c == '*':
if peek() == '*':
i += 1
res += '.*'
else:
res += '[^/]*'
elif c == '?':
res += '.'
elif c == '[':
j = i
if j < n and pat[j] in '!]':
j += 1
while j < n and pat[j] != ']':
j += 1
if j >= n:
res += '\\['
else:
stuff = pat[i:j].replace('\\','\\\\')
i = j + 1
if stuff[0] == '!':
stuff = '^' + stuff[1:]
elif stuff[0] == '^':
stuff = '\\' + stuff
res = '%s[%s]' % (res, stuff)
elif c == '{':
group = True
res += '(?:'
elif c == '}' and group:
res += ')'
group = False
elif c == ',' and group:
res += '|'
else:
res += re.escape(c)
return head + res + tail
Bryan O'Sullivan
Reduce the amount of stat traffic generated by a walk....
r812 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
Bryan O'Sullivan
Fix walk code for files that do not exist anywhere, and unhandled types....
r884 def pathto(n1, n2):
Bryan O'Sullivan
Fix walk path handling on Windows
r886 '''return the relative path from one place to another.
this returns a path in the form used by the local filesystem, not hg.'''
if not n1: return localpath(n2)
a, b = n1.split('/'), n2.split('/')
twaldmann@thinkmo.de
fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
r1541 a.reverse()
b.reverse()
Bryan O'Sullivan
Fix walk code for files that do not exist anywhere, and unhandled types....
r884 while a and b and a[-1] == b[-1]:
twaldmann@thinkmo.de
fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
r1541 a.pop()
b.pop()
Bryan O'Sullivan
Fix walk code for files that do not exist anywhere, and unhandled types....
r884 b.reverse()
return os.sep.join((['..'] * len(a)) + b)
mpm@selenic.com
Change canonpath to not know about repo objects...
r1081 def canonpath(root, cwd, myname):
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """return the canonical path of myname, given cwd and root"""
Arun Sharma
Handle hg under /
r1566 if root == os.sep:
rootsep = os.sep
else:
Thomas Arendsen Hein
Whitespace, tab and formatting cleanups, mainly in mq.py
r1810 rootsep = root + os.sep
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 name = myname
if not name.startswith(os.sep):
mpm@selenic.com
Change canonpath to not know about repo objects...
r1081 name = os.path.join(root, cwd, name)
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 name = os.path.normpath(name)
if name.startswith(rootsep):
Bryan O'Sullivan
Fix walk path handling on Windows
r886 return pconvert(name[len(rootsep):])
mpm@selenic.com
Change canonpath to not know about repo objects...
r1081 elif name == root:
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 return ''
else:
mpm@selenic.com
Change canonpath to not know about repo objects...
r1081 raise Abort('%s not under root' % myname)
mpm@selenic.com
Fix bug with empty inc and exc...
r897
Vadim Gelfer
if hgignore contains errors, print message that is not confusing.
r1610 def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
return _matcher(canonroot, cwd, names, inc, exc, head, 'glob', src)
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413
Vadim Gelfer
if hgignore contains errors, print message that is not confusing.
r1610 def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413 if os.name == 'nt':
dflt_pat = 'glob'
else:
dflt_pat = 'relpath'
Vadim Gelfer
if hgignore contains errors, print message that is not confusing.
r1610 return _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src)
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413
Vadim Gelfer
if hgignore contains errors, print message that is not confusing.
r1610 def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src):
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """build a function to match a set of file patterns
arguments:
canonroot - the canonical root of the tree you're matching against
cwd - the current working directory, if relevant
names - patterns to find
inc - patterns to include
exc - patterns to exclude
head - a regex to prepend to patterns to control whether a match is rooted
a pattern is one of:
Bryan O'Sullivan
Switch to new syntax for .hgignore files....
r1270 'glob:<rooted glob>'
're:<rooted regexp>'
'path:<rooted path>'
'relglob:<relative glob>'
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 'relpath:<relative path>'
Bryan O'Sullivan
Switch to new syntax for .hgignore files....
r1270 'relre:<relative regexp>'
'<rooted path or regexp>'
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082
returns:
a 3-tuple containing
- list of explicit non-pattern names passed in
- a bool match(filename) function
- a bool indicating if any patterns were passed in
todo:
make head regex a rooted bool
"""
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413 def contains_glob(name):
Bryan O'Sullivan
Reduce the amount of stat traffic generated by a walk....
r812 for c in name:
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413 if c in _globchars: return True
return False
Bryan O'Sullivan
Clean up walk and changes code to use normalised names properly....
r820
Bryan O'Sullivan
Fix up handling of regexp paths.
r888 def regex(kind, name, tail):
mpm@selenic.com
Refactor matchpats and walk...
r742 '''convert a pattern into a regular expression'''
Bryan O'Sullivan
Clean up walk and changes code to use normalised names properly....
r820 if kind == 're':
return name
elif kind == 'path':
Bryan O'Sullivan
Fix up handling of regexp paths.
r888 return '^' + re.escape(name) + '(?:/|$)'
Bryan O'Sullivan
Switch to new syntax for .hgignore files....
r1270 elif kind == 'relglob':
return head + globre(name, '(?:|.*/)', tail)
Bryan O'Sullivan
Fix up handling of regexp paths.
r888 elif kind == 'relpath':
return head + re.escape(name) + tail
Bryan O'Sullivan
Switch to new syntax for .hgignore files....
r1270 elif kind == 'relre':
if name.startswith('^'):
return name
return '.*' + name
mpm@selenic.com
Refactor matchpats and walk...
r742 return head + globre(name, '', tail)
def matchfn(pats, tail):
"""build a matching function from a set of patterns"""
Benoit Boissinot
further fix traceback on invalid .hgignore patterns...
r1454 if not pats:
return
Benoit Boissinot
abort on invalid pattern in matcher
r1446 matches = []
for k, p in pats:
try:
pat = '(?:%s)' % regex(k, p, tail)
matches.append(re.compile(pat).match)
twaldmann@thinkmo.de
fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
r1541 except re.error:
Vadim Gelfer
make invalid pattern message not confusing.
r1611 if src: raise Abort("%s: invalid pattern (%s): %s" % (src, k, p))
else: raise Abort("invalid pattern (%s): %s" % (k, p))
Benoit Boissinot
abort on invalid pattern in matcher
r1446
def buildfn(text):
for m in matches:
r = m(text)
if r:
return r
return buildfn
mpm@selenic.com
Refactor matchpats and walk...
r742
Bryan O'Sullivan
Clean up walk and changes code to use normalised names properly....
r820 def globprefix(pat):
'''return the non-glob prefix of a path, e.g. foo/* -> foo'''
root = []
for p in pat.split(os.sep):
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413 if contains_glob(p): break
Bryan O'Sullivan
Clean up walk and changes code to use normalised names properly....
r820 root.append(p)
Bryan O'Sullivan
Fix walk path handling on Windows
r886 return '/'.join(root)
Bryan O'Sullivan
Clean up walk and changes code to use normalised names properly....
r820
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 pats = []
files = []
roots = []
Benoit Boissinot
Do not use 'glob' expansion by default on OS != 'nt'
r1413 for kind, name in [patkind(p, dflt_pat) for p in names]:
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 if kind in ('glob', 'relpath'):
mpm@selenic.com
Change canonpath to not know about repo objects...
r1081 name = canonpath(canonroot, cwd, name)
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 if name == '':
kind, name = 'glob', '**'
Bryan O'Sullivan
Fix up handling of regexp paths.
r888 if kind in ('glob', 'path', 're'):
pats.append((kind, name))
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 if kind == 'glob':
root = globprefix(name)
if root: roots.append(root)
elif kind == 'relpath':
Bryan O'Sullivan
Fix up handling of regexp paths.
r888 files.append((kind, name))
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 roots.append(name)
mpm@selenic.com
Fix bug with empty inc and exc...
r897
Bryan O'Sullivan
Clean up walk and changes code to use normalised names properly....
r820 patmatch = matchfn(pats, '$') or always
filematch = matchfn(files, '(?:/|$)') or always
mpm@selenic.com
Fix bug with empty inc and exc...
r897 incmatch = always
if inc:
incmatch = matchfn(map(patkind, inc), '(?:/|$)')
excmatch = lambda fn: False
if exc:
excmatch = matchfn(map(patkind, exc), '(?:/|$)')
mpm@selenic.com
Refactor matchpats and walk...
r742
Bryan O'Sullivan
Rewrite log command. New version is faster and more featureful....
r1031 return (roots,
lambda fn: (incmatch(fn) and not excmatch(fn) and
(fn.endswith('/') or
(not pats and not files) or
(pats and patmatch(fn)) or
(files and filematch(fn)))),
(inc or exc or (pats and pats != [('glob', '**')])) and True)
mpm@selenic.com
Refactor matchpats and walk...
r742
mpm@selenic.com
[PATCH] Fix use of util.CommandError...
r521 def system(cmd, errprefix=None):
mpm@selenic.com
[PATCH] Harden os.system...
r508 """execute a shell command that must succeed"""
rc = os.system(cmd)
if rc:
mpm@selenic.com
[PATCH] Fix use of util.CommandError...
r521 errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
explain_exit(rc)[0])
if errprefix:
errmsg = "%s: %s" % (errprefix, errmsg)
Bryan O'Sullivan
Teach walk code about absolute paths....
r870 raise Abort(errmsg)
mpm@selenic.com
[PATCH] Harden os.system...
r508
mpm@selenic.com
[PATCH] rename under the other OS...
r421 def rename(src, dst):
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """forcibly rename a file"""
mpm@selenic.com
[PATCH] rename under the other OS...
r421 try:
os.rename(src, dst)
except:
os.unlink(dst)
os.rename(src, dst)
Benoit Boissinot
refactor some unlink/remove code and make sure we prune empty dir
r1415 def unlink(f):
"""unlink and remove the directory if it is empty"""
os.unlink(f)
# try removing directories that might now be empty
try: os.removedirs(os.path.dirname(f))
except: pass
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 def copyfiles(src, dst, hardlink=None):
"""Copy a directory tree using hardlinks if possible"""
if hardlink is None:
hardlink = (os.stat(src).st_dev ==
os.stat(os.path.dirname(dst)).st_dev)
Thomas Arendsen Hein
Use python function instead of external 'cp' command when cloning repos....
r698
mpm@selenic.com
Rewrite copytree as copyfiles...
r1207 if os.path.isdir(src):
os.mkdir(dst)
for name in os.listdir(src):
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 copyfiles(srcname, dstname, hardlink)
mpm@selenic.com
Rewrite copytree as copyfiles...
r1207 else:
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 if hardlink:
try:
os_link(src, dst)
except:
hardlink = False
Benoit Boissinot
do not copy atime and mtime in util.copyfiles...
r1591 shutil.copy(src, dst)
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 else:
Benoit Boissinot
do not copy atime and mtime in util.copyfiles...
r1591 shutil.copy(src, dst)
Thomas Arendsen Hein
Use python function instead of external 'cp' command when cloning repos....
r698
Thomas Arendsen Hein
Validate paths before reading or writing files in repository or working dir....
r1835 def audit_path(path):
"""Abort if path contains dangerous components"""
parts = os.path.normcase(path).split(os.sep)
if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '')
or os.pardir in parts):
raise Abort(_("path contains illegal component: %s\n") % path)
def opener(base, audit=True):
mpm@selenic.com
Move opener to utils...
r1090 """
return a function that opens files relative to base
this function is used to hide the details of COW semantics and
remote file access from higher level code.
"""
p = base
Thomas Arendsen Hein
Validate paths before reading or writing files in repository or working dir....
r1835 audit_p = audit
Benoit Boissinot
add an atomic argument to util.opener...
r1528
def mktempcopy(name):
d, fn = os.path.split(name)
fd, temp = tempfile.mkstemp(prefix=fn, dir=d)
fp = os.fdopen(fd, "wb")
try:
fp.write(file(name, "rb").read())
except:
try: os.unlink(temp)
except: pass
raise
fp.close()
st = os.lstat(name)
os.chmod(temp, st.st_mode)
return temp
class atomicfile(file):
"""the file will only be copied on close"""
def __init__(self, name, mode, atomic=False):
self.__name = name
self.temp = mktempcopy(name)
file.__init__(self, self.temp, mode)
def close(self):
if not self.closed:
Benoit Boissinot
close file before renaming it (since it doesn't work the other way on windows)
r1546 file.close(self)
Benoit Boissinot
add an atomic argument to util.opener...
r1528 rename(self.temp, self.__name)
def __del__(self):
self.close()
def o(path, mode="r", text=False, atomic=False):
Thomas Arendsen Hein
Validate paths before reading or writing files in repository or working dir....
r1835 if audit_p:
audit_path(path)
mpm@selenic.com
Move opener to utils...
r1090 f = os.path.join(p, path)
Bryan O'Sullivan
Allow files to be opened in text mode, even on Windows.
r1329 if not text:
mode += "b" # for that other OS
mpm@selenic.com
Move opener to utils...
r1090
if mode[0] != "r":
try:
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 nlink = nlinks(f)
mpm@selenic.com
Move opener to utils...
r1090 except OSError:
d = os.path.dirname(f)
if not os.path.isdir(d):
os.makedirs(d)
else:
Benoit Boissinot
add an atomic argument to util.opener...
r1528 if atomic:
return atomicfile(f, mode)
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 if nlink > 1:
Benoit Boissinot
add an atomic argument to util.opener...
r1528 rename(mktempcopy(f), f)
mpm@selenic.com
Move opener to utils...
r1090 return file(f, mode)
return o
Thomas Arendsen Hein
Make makelock and readlock work on filesystems without symlink support....
r704 def _makelock_file(info, pathname):
ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
os.write(ld, info)
os.close(ld)
def _readlock_file(pathname):
return file(pathname).read()
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 def nlinks(pathname):
"""Return number of hardlinks for the given file."""
return os.stat(pathname).st_nlink
if hasattr(os, 'link'):
os_link = os.link
else:
def os_link(src, dst):
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 raise OSError(0, _("Hardlinks not supported"))
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 # Platform specific variants
mpm@selenic.com
[PATCH] file seperator handling for the other 'OS'...
r419 if os.name == 'nt':
olivier.maquelin@intel.com
Avoid insertion/deletion of CRs on stdio during hg serve
r1420 demandload(globals(), "msvcrt")
mpm@selenic.com
[PATCH] /dev/null for other OS...
r461 nulldev = 'NUL:'
Vadim Gelfer
eliminate backtrace when piping output on windows....
r1609
class winstdout:
'''stdout on windows misbehaves if sent through a pipe'''
def __init__(self, fp):
self.fp = fp
def __getattr__(self, key):
return getattr(self.fp, key)
def close(self):
try:
self.fp.close()
except: pass
def write(self, s):
try:
return self.fp.write(s)
except IOError, inst:
if inst.errno != 0: raise
self.close()
raise IOError(errno.EPIPE, 'Broken pipe')
sys.stdout = winstdout(sys.stdout)
Zbynek Winkler
Try to use ini-file in the same directory as the exe as the default on NT.
r1399 try:
import win32api, win32process
filename = win32process.GetModuleFileNameEx(win32api.GetCurrentProcess(), 0)
systemrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
Vadim Gelfer
eliminate backtrace when piping output on windows....
r1609
Zbynek Winkler
Try to use ini-file in the same directory as the exe as the default on NT.
r1399 except ImportError:
systemrc = r'c:\mercurial\mercurial.ini'
pass
mpm@selenic.com
[PATCH] /dev/null for other OS...
r461
Zbynek Winkler
Try to use ini-file in the same directory as the exe as the default on NT.
r1399 rcpath = (systemrc,
Bryan O'Sullivan
Use platform-appropriate rc file names.
r1292 os.path.join(os.path.expanduser('~'), 'mercurial.ini'))
Volker Kleinfeld
Make 'hg import' platform independent....
r1285 def parse_patch_output(output_line):
"""parses the output produced by patch and returns the file name"""
pf = output_line[14:]
if pf[0] == '`':
pf = pf[1:-1] # Remove the quotes
return pf
Stephen Darnell
Add support for cloning with hardlinks on windows....
r1241 try: # ActivePython can create hard links using win32file module
import win32file
def os_link(src, dst): # NB will only succeed on NTFS
win32file.CreateHardLink(dst, src)
def nlinks(pathname):
"""Return number of hardlinks for the given file."""
try:
fh = win32file.CreateFile(pathname,
win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
None, win32file.OPEN_EXISTING, 0, None)
res = win32file.GetFileInformationByHandle(fh)
fh.Close()
return res[7]
except:
return os.stat(pathname).st_nlink
except ImportError:
pass
mpm@selenic.com
Permission handling for the other OS...
r441 def is_exec(f, last):
return last
def set_exec(f, mode):
pass
mpm@selenic.com
Whitespace cleanups...
r515
olivier.maquelin@intel.com
Avoid insertion/deletion of CRs on stdio during hg serve
r1420 def set_binary(fd):
msvcrt.setmode(fd.fileno(), os.O_BINARY)
mpm@selenic.com
[PATCH] file seperator handling for the other 'OS'...
r419 def pconvert(path):
return path.replace("\\", "/")
mpm@selenic.com
[PATCH] Enables lock work under the other 'OS'...
r422
Bryan O'Sullivan
Fix walk path handling on Windows
r886 def localpath(path):
return path.replace('/', '\\')
def normpath(path):
return pconvert(os.path.normpath(path))
Thomas Arendsen Hein
Make makelock and readlock work on filesystems without symlink support....
r704 makelock = _makelock_file
readlock = _readlock_file
mpm@selenic.com
[PATCH] /dev/null for other OS...
r461
thananck@yahoo.com
Provided platform dependent implementations for explain_exit...
r782 def explain_exit(code):
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 return _("exited with status %d") % code, code
thananck@yahoo.com
Provided platform dependent implementations for explain_exit...
r782
mpm@selenic.com
[PATCH] file seperator handling for the other 'OS'...
r419 else:
mpm@selenic.com
[PATCH] /dev/null for other OS...
r461 nulldev = '/dev/null'
Vadim Gelfer
make mercurial look in more places for config files....
r1583 def rcfiles(path):
rcs = [os.path.join(path, 'hgrc')]
rcdir = os.path.join(path, 'hgrc.d')
try:
rcs.extend([os.path.join(rcdir, f) for f in os.listdir(rcdir)
if f.endswith(".rc")])
except OSError, inst: pass
return rcs
efiring@manini.soest.hawaii.edu
Fix rcpath for hgwebdir case (sys.argv is empty)
r1635 rcpath = []
if len(sys.argv) > 0:
rcpath.extend(rcfiles(os.path.dirname(sys.argv[0]) + '/../etc/mercurial'))
Vadim Gelfer
make mercurial look in more places for config files....
r1583 rcpath.extend(rcfiles('/etc/mercurial'))
rcpath.append(os.path.expanduser('~/.hgrc'))
rcpath = [os.path.normpath(f) for f in rcpath]
Bryan O'Sullivan
Use platform-appropriate rc file names.
r1292
Volker Kleinfeld
Make 'hg import' platform independent....
r1285 def parse_patch_output(output_line):
"""parses the output produced by patch and returns the file name"""
Benoit Boissinot
if a filename contains spaces, patch adds quote around it
r1593 pf = output_line[14:]
if pf.startswith("'") and pf.endswith("'") and pf.find(" ") >= 0:
pf = pf[1:-1] # Remove the quotes
return pf
Volker Kleinfeld
Make 'hg import' platform independent....
r1285
mpm@selenic.com
Permission handling for the other OS...
r441 def is_exec(f, last):
mpm@selenic.com
Update util.py docstrings, fix walk test
r1082 """check whether a file is executable"""
mpm@selenic.com
Permission handling for the other OS...
r441 return (os.stat(f).st_mode & 0100 != 0)
def set_exec(f, mode):
s = os.stat(f).st_mode
if (s & 0100 != 0) == mode:
return
if mode:
# Turn on +x for every +r bit when making a file executable
# and obey umask.
umask = os.umask(0)
os.umask(umask)
os.chmod(f, s | (s & 0444) >> 2 & ~umask)
else:
os.chmod(f, s & 0666)
olivier.maquelin@intel.com
Avoid insertion/deletion of CRs on stdio during hg serve
r1420 def set_binary(fd):
pass
mpm@selenic.com
[PATCH] file seperator handling for the other 'OS'...
r419 def pconvert(path):
return path
Bryan O'Sullivan
Fix walk path handling on Windows
r886 def localpath(path):
return path
normpath = os.path.normpath
mpm@selenic.com
[PATCH] Enables lock work under the other 'OS'...
r422 def makelock(info, pathname):
Thomas Arendsen Hein
Make makelock and readlock work on filesystems without symlink support....
r704 try:
os.symlink(info, pathname)
except OSError, why:
if why.errno == errno.EEXIST:
raise
else:
_makelock_file(info, pathname)
mpm@selenic.com
[PATCH] Enables lock work under the other 'OS'...
r422
def readlock(pathname):
Thomas Arendsen Hein
Make makelock and readlock work on filesystems without symlink support....
r704 try:
return os.readlink(pathname)
except OSError, why:
if why.errno == errno.EINVAL:
return _readlock_file(pathname)
else:
raise
thananck@yahoo.com
Provided platform dependent implementations for explain_exit...
r782
def explain_exit(code):
"""return a 2-tuple (desc, code) describing a process's status"""
if os.WIFEXITED(code):
val = os.WEXITSTATUS(code)
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 return _("exited with status %d") % val, val
thananck@yahoo.com
Provided platform dependent implementations for explain_exit...
r782 elif os.WIFSIGNALED(code):
val = os.WTERMSIG(code)
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 return _("killed by signal %d") % val, val
thananck@yahoo.com
Provided platform dependent implementations for explain_exit...
r782 elif os.WIFSTOPPED(code):
mark.williamson@cl.cam.ac.uk
Minor tweak: os.STOPSIG -> os.WSTOPSIG. Pychecker spotted this one.
r912 val = os.WSTOPSIG(code)
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 return _("stopped by signal %d") % val, val
raise ValueError(_("invalid exit code"))
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199
class chunkbuffer(object):
"""Allow arbitrary sized chunks of data to be efficiently read from an
iterator over chunks of arbitrary size."""
Bryan O'Sullivan
Minor cleanups.
r1200
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 def __init__(self, in_iter, targetsize = 2**16):
"""in_iter is the iterator that's iterating over the input chunks.
targetsize is how big a buffer to try to maintain."""
self.in_iter = iter(in_iter)
self.buf = ''
self.targetsize = int(targetsize)
Bryan O'Sullivan
Minor cleanups.
r1200 if self.targetsize <= 0:
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 raise ValueError(_("targetsize must be greater than 0, was %d") %
Bryan O'Sullivan
Minor cleanups.
r1200 targetsize)
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 self.iterempty = False
Bryan O'Sullivan
Minor cleanups.
r1200
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 def fillbuf(self):
Bryan O'Sullivan
Minor cleanups.
r1200 """Ignore target size; read every chunk from iterator until empty."""
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 if not self.iterempty:
collector = cStringIO.StringIO()
collector.write(self.buf)
for ch in self.in_iter:
collector.write(ch)
self.buf = collector.getvalue()
self.iterempty = True
def read(self, l):
Bryan O'Sullivan
Minor cleanups.
r1200 """Read L bytes of data from the iterator of chunks of data.
Thomas Arendsen Hein
Cleanup of tabs and trailing spaces.
r1308 Returns less than L bytes if the iterator runs dry."""
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 if l > len(self.buf) and not self.iterempty:
# Clamp to a multiple of self.targetsize
targetsize = self.targetsize * ((l // self.targetsize) + 1)
collector = cStringIO.StringIO()
collector.write(self.buf)
collected = len(self.buf)
for chunk in self.in_iter:
collector.write(chunk)
collected += len(chunk)
if collected >= targetsize:
break
if collected < targetsize:
self.iterempty = True
self.buf = collector.getvalue()
Bryan O'Sullivan
Minor cleanups.
r1200 s, self.buf = self.buf[:l], buffer(self.buf, l)
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 return s
def filechunkiter(f, size = 65536):
Bryan O'Sullivan
Minor cleanups.
r1200 """Create a generator that produces all the data in the file size
(default 65536) bytes at a time. Chunks may be less than size
bytes if the chunk is the last chunk in the file, or the file is a
socket or some other type of file that sometimes reads less data
than is requested."""
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 s = f.read(size)
Eric Hopper
Fixed a bug in my changes to httprepo.py
r1377 while len(s) > 0:
Eric Hopper
Created a class in util called chunkbuffer that buffers reads from an...
r1199 yield s
s = f.read(size)
Bryan O'Sullivan
Fix up representation of dates in hgweb....
r1320
Bryan O'Sullivan
Clean up date and timezone handling....
r1321 def makedate():
Benoit Boissinot
fix handling of daylight saving time
r1482 lt = time.localtime()
if lt[8] == 1 and time.daylight:
tz = time.altzone
else:
tz = time.timezone
return time.mktime(lt), tz
Bryan O'Sullivan
Allow files to be opened in text mode, even on Windows.
r1329
Bryan O'Sullivan
Clean up date and timezone handling....
r1321 def datestr(date=None, format='%c'):
"""represent a (unixtime, offset) tuple as a localized time.
unixtime is seconds since the epoch, and offset is the time zone's
number of seconds away from UTC."""
t, tz = date or makedate()
Bryan O'Sullivan
Fix up representation of dates in hgweb....
r1320 return ("%s %+03d%02d" %
(time.strftime(format, time.gmtime(float(t) - tz)),
-tz / 3600,
((-tz % 3600) / 60)))
Vadim Gelfer
hgwebdir: export collections of repos...
r1829
def walkrepos(path):
'''yield every hg repository under path, recursively.'''
def errhandler(err):
if err.filename == path:
raise err
for root, dirs, files in os.walk(path, onerror=errhandler):
for d in dirs:
if d == '.hg':
yield root
dirs[:] = []
break