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")]) |