Mercurial > public > mercurial-scm > hg
comparison mercurial/vfs.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | 66f2cc210a29 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
45 class abstractvfs(object): | 45 class abstractvfs(object): |
46 """Abstract base class; cannot be instantiated""" | 46 """Abstract base class; cannot be instantiated""" |
47 | 47 |
48 def __init__(self, *args, **kwargs): | 48 def __init__(self, *args, **kwargs): |
49 '''Prevent instantiation; don't call this from subclasses.''' | 49 '''Prevent instantiation; don't call this from subclasses.''' |
50 raise NotImplementedError('attempted instantiating ' + str(type(self))) | 50 raise NotImplementedError(b'attempted instantiating ' + str(type(self))) |
51 | 51 |
52 def _auditpath(self, path, mode): | 52 def _auditpath(self, path, mode): |
53 raise NotImplementedError | 53 raise NotImplementedError |
54 | 54 |
55 def tryread(self, path): | 55 def tryread(self, path): |
57 try: | 57 try: |
58 return self.read(path) | 58 return self.read(path) |
59 except IOError as inst: | 59 except IOError as inst: |
60 if inst.errno != errno.ENOENT: | 60 if inst.errno != errno.ENOENT: |
61 raise | 61 raise |
62 return "" | 62 return b"" |
63 | 63 |
64 def tryreadlines(self, path, mode='rb'): | 64 def tryreadlines(self, path, mode=b'rb'): |
65 '''gracefully return an empty array for missing files''' | 65 '''gracefully return an empty array for missing files''' |
66 try: | 66 try: |
67 return self.readlines(path, mode=mode) | 67 return self.readlines(path, mode=mode) |
68 except IOError as inst: | 68 except IOError as inst: |
69 if inst.errno != errno.ENOENT: | 69 if inst.errno != errno.ENOENT: |
79 for "write" mode access. | 79 for "write" mode access. |
80 ''' | 80 ''' |
81 return self.__call__ | 81 return self.__call__ |
82 | 82 |
83 def read(self, path): | 83 def read(self, path): |
84 with self(path, 'rb') as fp: | 84 with self(path, b'rb') as fp: |
85 return fp.read() | 85 return fp.read() |
86 | 86 |
87 def readlines(self, path, mode='rb'): | 87 def readlines(self, path, mode=b'rb'): |
88 with self(path, mode=mode) as fp: | 88 with self(path, mode=mode) as fp: |
89 return fp.readlines() | 89 return fp.readlines() |
90 | 90 |
91 def write(self, path, data, backgroundclose=False, **kwargs): | 91 def write(self, path, data, backgroundclose=False, **kwargs): |
92 with self(path, 'wb', backgroundclose=backgroundclose, **kwargs) as fp: | 92 with self(path, b'wb', backgroundclose=backgroundclose, **kwargs) as fp: |
93 return fp.write(data) | 93 return fp.write(data) |
94 | 94 |
95 def writelines(self, path, data, mode='wb', notindexed=False): | 95 def writelines(self, path, data, mode=b'wb', notindexed=False): |
96 with self(path, mode=mode, notindexed=notindexed) as fp: | 96 with self(path, mode=mode, notindexed=notindexed) as fp: |
97 return fp.writelines(data) | 97 return fp.writelines(data) |
98 | 98 |
99 def append(self, path, data): | 99 def append(self, path, data): |
100 with self(path, 'ab') as fp: | 100 with self(path, b'ab') as fp: |
101 return fp.write(data) | 101 return fp.write(data) |
102 | 102 |
103 def basename(self, path): | 103 def basename(self, path): |
104 """return base element of a path (as os.path.basename would do) | 104 """return base element of a path (as os.path.basename would do) |
105 | 105 |
173 return util.makelock(info, self.join(path)) | 173 return util.makelock(info, self.join(path)) |
174 | 174 |
175 def mkdir(self, path=None): | 175 def mkdir(self, path=None): |
176 return os.mkdir(self.join(path)) | 176 return os.mkdir(self.join(path)) |
177 | 177 |
178 def mkstemp(self, suffix='', prefix='tmp', dir=None): | 178 def mkstemp(self, suffix=b'', prefix=b'tmp', dir=None): |
179 fd, name = pycompat.mkstemp( | 179 fd, name = pycompat.mkstemp( |
180 suffix=suffix, prefix=prefix, dir=self.join(dir) | 180 suffix=suffix, prefix=prefix, dir=self.join(dir) |
181 ) | 181 ) |
182 dname, fname = util.split(name) | 182 dname, fname = util.split(name) |
183 if dir: | 183 if dir: |
201 To avoid file stat ambiguity forcibly, checkambig=True involves | 201 To avoid file stat ambiguity forcibly, checkambig=True involves |
202 copying ``src`` file, if it is owned by another. Therefore, use | 202 copying ``src`` file, if it is owned by another. Therefore, use |
203 checkambig=True only in limited cases (see also issue5418 and | 203 checkambig=True only in limited cases (see also issue5418 and |
204 issue5584 for detail). | 204 issue5584 for detail). |
205 """ | 205 """ |
206 self._auditpath(dst, 'w') | 206 self._auditpath(dst, b'w') |
207 srcpath = self.join(src) | 207 srcpath = self.join(src) |
208 dstpath = self.join(dst) | 208 dstpath = self.join(dst) |
209 oldstat = checkambig and util.filestat.frompath(dstpath) | 209 oldstat = checkambig and util.filestat.frompath(dstpath) |
210 if oldstat and oldstat.stat: | 210 if oldstat and oldstat.stat: |
211 ret = util.rename(srcpath, dstpath) | 211 ret = util.rename(srcpath, dstpath) |
300 yield | 300 yield |
301 return | 301 return |
302 vfs = getattr(self, 'vfs', self) | 302 vfs = getattr(self, 'vfs', self) |
303 if getattr(vfs, '_backgroundfilecloser', None): | 303 if getattr(vfs, '_backgroundfilecloser', None): |
304 raise error.Abort( | 304 raise error.Abort( |
305 _('can only have 1 active background file closer') | 305 _(b'can only have 1 active background file closer') |
306 ) | 306 ) |
307 | 307 |
308 with backgroundfilecloser(ui, expectedcount=expectedcount) as bfc: | 308 with backgroundfilecloser(ui, expectedcount=expectedcount) as bfc: |
309 try: | 309 try: |
310 vfs._backgroundfilecloser = bfc | 310 vfs._backgroundfilecloser = bfc |
363 if self._audit: | 363 if self._audit: |
364 if os.path.isabs(path) and path.startswith(self.base): | 364 if os.path.isabs(path) and path.startswith(self.base): |
365 path = os.path.relpath(path, self.base) | 365 path = os.path.relpath(path, self.base) |
366 r = util.checkosfilename(path) | 366 r = util.checkosfilename(path) |
367 if r: | 367 if r: |
368 raise error.Abort("%s: %r" % (r, path)) | 368 raise error.Abort(b"%s: %r" % (r, path)) |
369 self.audit(path, mode=mode) | 369 self.audit(path, mode=mode) |
370 | 370 |
371 def __call__( | 371 def __call__( |
372 self, | 372 self, |
373 path, | 373 path, |
374 mode="r", | 374 mode=b"r", |
375 atomictemp=False, | 375 atomictemp=False, |
376 notindexed=False, | 376 notindexed=False, |
377 backgroundclose=False, | 377 backgroundclose=False, |
378 checkambig=False, | 378 checkambig=False, |
379 auditpath=True, | 379 auditpath=True, |
411 ''' | 411 ''' |
412 if auditpath: | 412 if auditpath: |
413 self._auditpath(path, mode) | 413 self._auditpath(path, mode) |
414 f = self.join(path) | 414 f = self.join(path) |
415 | 415 |
416 if "b" not in mode: | 416 if b"b" not in mode: |
417 mode += "b" # for that other OS | 417 mode += b"b" # for that other OS |
418 | 418 |
419 nlink = -1 | 419 nlink = -1 |
420 if mode not in ('r', 'rb'): | 420 if mode not in (b'r', b'rb'): |
421 dirname, basename = util.split(f) | 421 dirname, basename = util.split(f) |
422 # If basename is empty, then the path is malformed because it points | 422 # If basename is empty, then the path is malformed because it points |
423 # to a directory. Let the posixfile() call below raise IOError. | 423 # to a directory. Let the posixfile() call below raise IOError. |
424 if basename: | 424 if basename: |
425 if atomictemp: | 425 if atomictemp: |
427 util.makedirs(dirname, self.createmode, notindexed) | 427 util.makedirs(dirname, self.createmode, notindexed) |
428 return util.atomictempfile( | 428 return util.atomictempfile( |
429 f, mode, self.createmode, checkambig=checkambig | 429 f, mode, self.createmode, checkambig=checkambig |
430 ) | 430 ) |
431 try: | 431 try: |
432 if 'w' in mode: | 432 if b'w' in mode: |
433 util.unlink(f) | 433 util.unlink(f) |
434 nlink = 0 | 434 nlink = 0 |
435 else: | 435 else: |
436 # nlinks() may behave differently for files on Windows | 436 # nlinks() may behave differently for files on Windows |
437 # shares if the file is open. | 437 # shares if the file is open. |
453 fp = util.posixfile(f, mode) | 453 fp = util.posixfile(f, mode) |
454 if nlink == 0: | 454 if nlink == 0: |
455 self._fixfilemode(f) | 455 self._fixfilemode(f) |
456 | 456 |
457 if checkambig: | 457 if checkambig: |
458 if mode in ('r', 'rb'): | 458 if mode in (b'r', b'rb'): |
459 raise error.Abort( | 459 raise error.Abort( |
460 _( | 460 _( |
461 'implementation error: mode %s is not' | 461 b'implementation error: mode %s is not' |
462 ' valid for checkambig=True' | 462 b' valid for checkambig=True' |
463 ) | 463 ) |
464 % mode | 464 % mode |
465 ) | 465 ) |
466 fp = checkambigatclosing(fp) | 466 fp = checkambigatclosing(fp) |
467 | 467 |
469 threading.currentThread(), threading._MainThread | 469 threading.currentThread(), threading._MainThread |
470 ): | 470 ): |
471 if not self._backgroundfilecloser: | 471 if not self._backgroundfilecloser: |
472 raise error.Abort( | 472 raise error.Abort( |
473 _( | 473 _( |
474 'backgroundclose can only be used when a ' | 474 b'backgroundclose can only be used when a ' |
475 'backgroundclosing context manager is active' | 475 b'backgroundclosing context manager is active' |
476 ) | 476 ) |
477 ) | 477 ) |
478 | 478 |
479 fp = delayclosedfile(fp, self._backgroundfilecloser) | 479 fp = delayclosedfile(fp, self._backgroundfilecloser) |
480 | 480 |
491 try: | 491 try: |
492 os.symlink(src, linkname) | 492 os.symlink(src, linkname) |
493 except OSError as err: | 493 except OSError as err: |
494 raise OSError( | 494 raise OSError( |
495 err.errno, | 495 err.errno, |
496 _('could not symlink to %r: %s') | 496 _(b'could not symlink to %r: %s') |
497 % (src, encoding.strtolocal(err.strerror)), | 497 % (src, encoding.strtolocal(err.strerror)), |
498 linkname, | 498 linkname, |
499 ) | 499 ) |
500 else: | 500 else: |
501 self.write(dst, src) | 501 self.write(dst, src) |
550 '''Wrapper vfs preventing any writing.''' | 550 '''Wrapper vfs preventing any writing.''' |
551 | 551 |
552 def __init__(self, vfs): | 552 def __init__(self, vfs): |
553 proxyvfs.__init__(self, vfs) | 553 proxyvfs.__init__(self, vfs) |
554 | 554 |
555 def __call__(self, path, mode='r', *args, **kw): | 555 def __call__(self, path, mode=b'r', *args, **kw): |
556 if mode not in ('r', 'rb'): | 556 if mode not in (b'r', b'rb'): |
557 raise error.Abort(_('this vfs is read only')) | 557 raise error.Abort(_(b'this vfs is read only')) |
558 return self.vfs(path, mode, *args, **kw) | 558 return self.vfs(path, mode, *args, **kw) |
559 | 559 |
560 def join(self, path, *insidef): | 560 def join(self, path, *insidef): |
561 return self.vfs.join(path, *insidef) | 561 return self.vfs.join(path, *insidef) |
562 | 562 |
582 def __enter__(self): | 582 def __enter__(self): |
583 self._origfh.__enter__() | 583 self._origfh.__enter__() |
584 return self | 584 return self |
585 | 585 |
586 def __exit__(self, exc_type, exc_value, exc_tb): | 586 def __exit__(self, exc_type, exc_value, exc_tb): |
587 raise NotImplementedError('attempted instantiating ' + str(type(self))) | 587 raise NotImplementedError(b'attempted instantiating ' + str(type(self))) |
588 | 588 |
589 def close(self): | 589 def close(self): |
590 raise NotImplementedError('attempted instantiating ' + str(type(self))) | 590 raise NotImplementedError(b'attempted instantiating ' + str(type(self))) |
591 | 591 |
592 | 592 |
593 class delayclosedfile(closewrapbase): | 593 class delayclosedfile(closewrapbase): |
594 """Proxy for a file object whose close is delayed. | 594 """Proxy for a file object whose close is delayed. |
595 | 595 |
617 self._threadexception = None | 617 self._threadexception = None |
618 | 618 |
619 # Only Windows/NTFS has slow file closing. So only enable by default | 619 # Only Windows/NTFS has slow file closing. So only enable by default |
620 # on that platform. But allow to be enabled elsewhere for testing. | 620 # on that platform. But allow to be enabled elsewhere for testing. |
621 defaultenabled = pycompat.iswindows | 621 defaultenabled = pycompat.iswindows |
622 enabled = ui.configbool('worker', 'backgroundclose', defaultenabled) | 622 enabled = ui.configbool(b'worker', b'backgroundclose', defaultenabled) |
623 | 623 |
624 if not enabled: | 624 if not enabled: |
625 return | 625 return |
626 | 626 |
627 # There is overhead to starting and stopping the background threads. | 627 # There is overhead to starting and stopping the background threads. |
628 # Don't do background processing unless the file count is large enough | 628 # Don't do background processing unless the file count is large enough |
629 # to justify it. | 629 # to justify it. |
630 minfilecount = ui.configint('worker', 'backgroundcloseminfilecount') | 630 minfilecount = ui.configint(b'worker', b'backgroundcloseminfilecount') |
631 # FUTURE dynamically start background threads after minfilecount closes. | 631 # FUTURE dynamically start background threads after minfilecount closes. |
632 # (We don't currently have any callers that don't know their file count) | 632 # (We don't currently have any callers that don't know their file count) |
633 if expectedcount > 0 and expectedcount < minfilecount: | 633 if expectedcount > 0 and expectedcount < minfilecount: |
634 return | 634 return |
635 | 635 |
636 maxqueue = ui.configint('worker', 'backgroundclosemaxqueue') | 636 maxqueue = ui.configint(b'worker', b'backgroundclosemaxqueue') |
637 threadcount = ui.configint('worker', 'backgroundclosethreadcount') | 637 threadcount = ui.configint(b'worker', b'backgroundclosethreadcount') |
638 | 638 |
639 ui.debug( | 639 ui.debug( |
640 'starting %d threads for background file closing\n' % threadcount | 640 b'starting %d threads for background file closing\n' % threadcount |
641 ) | 641 ) |
642 | 642 |
643 self._queue = pycompat.queue.Queue(maxsize=maxqueue) | 643 self._queue = pycompat.queue.Queue(maxsize=maxqueue) |
644 self._running = True | 644 self._running = True |
645 | 645 |
646 for i in range(threadcount): | 646 for i in range(threadcount): |
647 t = threading.Thread(target=self._worker, name='backgroundcloser') | 647 t = threading.Thread(target=self._worker, name=b'backgroundcloser') |
648 self._threads.append(t) | 648 self._threads.append(t) |
649 t.start() | 649 t.start() |
650 | 650 |
651 def __enter__(self): | 651 def __enter__(self): |
652 self._entered = True | 652 self._entered = True |
678 | 678 |
679 def close(self, fh): | 679 def close(self, fh): |
680 """Schedule a file for closing.""" | 680 """Schedule a file for closing.""" |
681 if not self._entered: | 681 if not self._entered: |
682 raise error.Abort( | 682 raise error.Abort( |
683 _('can only call close() when context manager ' 'active') | 683 _(b'can only call close() when context manager ' b'active') |
684 ) | 684 ) |
685 | 685 |
686 # If a background thread encountered an exception, raise now so we fail | 686 # If a background thread encountered an exception, raise now so we fail |
687 # fast. Otherwise we may potentially go on for minutes until the error | 687 # fast. Otherwise we may potentially go on for minutes until the error |
688 # is acted on. | 688 # is acted on. |