comparison mercurial/util.py @ 896:01215ad04283

Merge with BOS
author mpm@selenic.com
date Sat, 13 Aug 2005 19:43:42 -0800
parents 9c918287d10b 77b52b864249
children fe30f5434b51
comparison
equal deleted inserted replaced
867:0cd2ee61b10a 896:01215ad04283
14 for f in g: 14 for f in g:
15 if f not in seen: 15 if f not in seen:
16 seen[f] = 1 16 seen[f] = 1
17 yield f 17 yield f
18 18
19 class CommandError(Exception): pass 19 class Abort(Exception):
20 """Raised if a command needs to print an error and exit."""
20 21
21 def always(fn): return True 22 def always(fn): return True
22 def never(fn): return False 23 def never(fn): return False
23 24
24 def globre(pat, head = '^', tail = '$'): 25 def globre(pat, head = '^', tail = '$'):
66 res += re.escape(c) 67 res += re.escape(c)
67 return head + res + tail 68 return head + res + tail
68 69
69 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} 70 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
70 71
71 def matcher(cwd, names, inc, exc, head = ''): 72 def pathto(n1, n2):
73 '''return the relative path from one place to another.
74 this returns a path in the form used by the local filesystem, not hg.'''
75 if not n1: return localpath(n2)
76 a, b = n1.split('/'), n2.split('/')
77 a.reverse(), b.reverse()
78 while a and b and a[-1] == b[-1]:
79 a.pop(), b.pop()
80 b.reverse()
81 return os.sep.join((['..'] * len(a)) + b)
82
83 def canonpath(repo, cwd, myname):
84 rootsep = repo.root + os.sep
85 name = myname
86 if not name.startswith(os.sep):
87 name = os.path.join(repo.root, cwd, name)
88 name = os.path.normpath(name)
89 if name.startswith(rootsep):
90 return pconvert(name[len(rootsep):])
91 elif name == repo.root:
92 return ''
93 else:
94 raise Abort('%s not under repository root' % myname)
95
96 def matcher(repo, cwd, names, inc, exc, head = ''):
72 def patkind(name): 97 def patkind(name):
73 for prefix in 're:', 'glob:', 'path:': 98 for prefix in 're:', 'glob:', 'path:', 'relpath:':
74 if name.startswith(prefix): return name.split(':', 1) 99 if name.startswith(prefix): return name.split(':', 1)
75 for c in name: 100 for c in name:
76 if c in _globchars: return 'glob', name 101 if c in _globchars: return 'glob', name
77 return 'relpath', name 102 return 'relpath', name
78 103
79 cwdsep = cwd + os.sep 104 def regex(kind, name, tail):
80
81 def regex(name, tail):
82 '''convert a pattern into a regular expression''' 105 '''convert a pattern into a regular expression'''
83 kind, name = patkind(name)
84 if kind == 're': 106 if kind == 're':
85 return name 107 return name
86 elif kind == 'path': 108 elif kind == 'path':
87 return '^' + re.escape(name) + '$' 109 return '^' + re.escape(name) + '(?:/|$)'
88 if cwd: name = os.path.join(cwdsep, name) 110 elif kind == 'relpath':
89 name = os.path.normpath(name) 111 return head + re.escape(name) + tail
90 if name == '.': name = '**'
91 return head + globre(name, '', tail) 112 return head + globre(name, '', tail)
92
93 def under(fn):
94 """check if fn is under our cwd"""
95 return not cwd or fn.startswith(cwdsep)
96 113
97 def matchfn(pats, tail): 114 def matchfn(pats, tail):
98 """build a matching function from a set of patterns""" 115 """build a matching function from a set of patterns"""
99 if pats: 116 if pats:
100 pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats]) 117 pat = '(?:%s)' % '|'.join([regex(k, p, tail) for (k, p) in pats])
101 return re.compile(pat).match 118 return re.compile(pat).match
102 119
103 def globprefix(pat): 120 def globprefix(pat):
104 '''return the non-glob prefix of a path, e.g. foo/* -> foo''' 121 '''return the non-glob prefix of a path, e.g. foo/* -> foo'''
105 root = [] 122 root = []
106 for p in pat.split(os.sep): 123 for p in pat.split(os.sep):
107 if patkind(p)[0] == 'glob': break 124 if patkind(p)[0] == 'glob': break
108 root.append(p) 125 root.append(p)
109 return os.sep.join(root) 126 return '/'.join(root)
110 127
111 patkinds = map(patkind, names) 128 pats = []
112 pats = [name for (kind, name) in patkinds if kind != 'relpath'] 129 files = []
113 files = [name for (kind, name) in patkinds if kind == 'relpath'] 130 roots = []
114 roots = filter(None, map(globprefix, pats)) + files 131 for kind, name in map(patkind, names):
115 if cwd: roots = [cwdsep + r for r in roots] 132 if kind in ('glob', 'relpath'):
133 name = canonpath(repo, cwd, name)
134 if name == '':
135 kind, name = 'glob', '**'
136 if kind in ('glob', 'path', 're'):
137 pats.append((kind, name))
138 if kind == 'glob':
139 root = globprefix(name)
140 if root: roots.append(root)
141 elif kind == 'relpath':
142 files.append((kind, name))
143 roots.append(name)
116 144
117 patmatch = matchfn(pats, '$') or always 145 patmatch = matchfn(pats, '$') or always
118 filematch = matchfn(files, '(?:/|$)') or always 146 filematch = matchfn(files, '(?:/|$)') or always
119 incmatch = matchfn(inc, '(?:/|$)') or always 147 incmatch = matchfn(map(patkind, inc), '(?:/|$)') or always
120 excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) 148 excmatch = matchfn(map(patkind, exc), '(?:/|$)') or (lambda fn: False)
121 149
122 return roots, lambda fn: (incmatch(fn) and not excmatch(fn) and 150 return roots, lambda fn: (incmatch(fn) and not excmatch(fn) and
123 (fn.endswith('/') or 151 (fn.endswith('/') or
124 (not pats and not files) or 152 (not pats and not files) or
125 (pats and patmatch(fn)) or 153 (pats and patmatch(fn)) or
131 if rc: 159 if rc:
132 errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]), 160 errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
133 explain_exit(rc)[0]) 161 explain_exit(rc)[0])
134 if errprefix: 162 if errprefix:
135 errmsg = "%s: %s" % (errprefix, errmsg) 163 errmsg = "%s: %s" % (errprefix, errmsg)
136 raise CommandError(errmsg) 164 raise Abort(errmsg)
137 165
138 def rename(src, dst): 166 def rename(src, dst):
139 try: 167 try:
140 os.rename(src, dst) 168 os.rename(src, dst)
141 except: 169 except:
175 def set_exec(f, mode): 203 def set_exec(f, mode):
176 pass 204 pass
177 205
178 def pconvert(path): 206 def pconvert(path):
179 return path.replace("\\", "/") 207 return path.replace("\\", "/")
208
209 def localpath(path):
210 return path.replace('/', '\\')
211
212 def normpath(path):
213 return pconvert(os.path.normpath(path))
180 214
181 makelock = _makelock_file 215 makelock = _makelock_file
182 readlock = _readlock_file 216 readlock = _readlock_file
183 217
184 def explain_exit(code): 218 def explain_exit(code):
204 os.chmod(f, s & 0666) 238 os.chmod(f, s & 0666)
205 239
206 def pconvert(path): 240 def pconvert(path):
207 return path 241 return path
208 242
243 def localpath(path):
244 return path
245
246 normpath = os.path.normpath
247
209 def makelock(info, pathname): 248 def makelock(info, pathname):
210 try: 249 try:
211 os.symlink(info, pathname) 250 os.symlink(info, pathname)
212 except OSError, why: 251 except OSError, why:
213 if why.errno == errno.EEXIST: 252 if why.errno == errno.EEXIST: