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): |