Show More
@@ -556,28 +556,55 b' def _filterfull(entry, copy, vfsmap):' | |||||
556 | return (src, name, ftype, copy(vfsmap[src].join(name))) |
|
556 | return (src, name, ftype, copy(vfsmap[src].join(name))) | |
557 |
|
557 | |||
558 |
|
558 | |||
559 | @contextlib.contextmanager |
|
559 | class TempCopyManager: | |
560 | def maketempcopies(): |
|
560 | """Manage temporary backup of volatile file during stream clone | |
561 | """return a function to temporary copy file""" |
|
561 | ||
|
562 | This should be used as a Python context, the copies will be discarded when | |||
|
563 | exiting the context. | |||
|
564 | ||||
|
565 | A copy can be done by calling the object on the real path (encoded full | |||
|
566 | path) | |||
562 |
|
|
567 | ||
563 | files = [] |
|
568 | The backup path can be retrieved using the __getitem__ protocol, obj[path]. | |
564 | dst_dir = pycompat.mkdtemp(prefix=b'hg-clone-') |
|
569 | On file without backup, it will return the unmodified path. (equivalent to | |
565 | try: |
|
570 | `dict.get(x, x)`) | |
|
571 | """ | |||
|
572 | ||||
|
573 | def __init__(self): | |||
|
574 | self._copies = None | |||
|
575 | self._dst_dir = None | |||
566 |
|
576 | |||
567 | def copy(src): |
|
577 | def __enter__(self): | |
568 | fd, dst = pycompat.mkstemp( |
|
578 | if self._copies is not None: | |
569 | prefix=os.path.basename(src), dir=dst_dir |
|
579 | msg = "Copies context already open" | |
570 | ) |
|
580 | raise error.ProgrammingError(msg) | |
571 | os.close(fd) |
|
581 | self._copies = {} | |
572 | files.append(dst) |
|
582 | self._dst_dir = pycompat.mkdtemp(prefix=b'hg-clone-') | |
573 | util.copyfiles(src, dst, hardlink=True) |
|
583 | return self | |
574 | return dst |
|
|||
575 |
|
584 | |||
576 | yield copy |
|
585 | def __call__(self, src): | |
577 | finally: |
|
586 | """create a backup of the file at src""" | |
578 | for tmp in files: |
|
587 | prefix = os.path.basename(src) | |
|
588 | fd, dst = pycompat.mkstemp(prefix=prefix, dir=self._dst_dir) | |||
|
589 | os.close(fd) | |||
|
590 | self._copies[src] = dst | |||
|
591 | util.copyfiles(src, dst, hardlink=True) | |||
|
592 | return dst | |||
|
593 | ||||
|
594 | def __getitem__(self, src): | |||
|
595 | """return the path to a valid version of `src` | |||
|
596 | ||||
|
597 | If the file has no backup, the path of the file is returned | |||
|
598 | unmodified.""" | |||
|
599 | return self._copies.get(src, src) | |||
|
600 | ||||
|
601 | def __exit__(self, *args, **kwars): | |||
|
602 | """discard all backups""" | |||
|
603 | for tmp in self._copies.values(): | |||
579 | util.tryunlink(tmp) |
|
604 | util.tryunlink(tmp) | |
580 | util.tryrmdir(dst_dir) |
|
605 | util.tryrmdir(self._dst_dir) | |
|
606 | self._copies = None | |||
|
607 | self._dst_dir = None | |||
581 |
|
608 | |||
582 |
|
609 | |||
583 | def _makemap(repo): |
|
610 | def _makemap(repo): | |
@@ -610,7 +637,7 b' def _emit2(repo, entries, totalfilesize)' | |||||
610 | _(b'bundle'), total=totalfilesize, unit=_(b'bytes') |
|
637 | _(b'bundle'), total=totalfilesize, unit=_(b'bytes') | |
611 | ) |
|
638 | ) | |
612 | progress.update(0) |
|
639 | progress.update(0) | |
613 |
with |
|
640 | with TempCopyManager() as copy, progress: | |
614 | # copy is delayed until we are in the try |
|
641 | # copy is delayed until we are in the try | |
615 | entries = [_filterfull(e, copy, vfsmap) for e in entries] |
|
642 | entries = [_filterfull(e, copy, vfsmap) for e in entries] | |
616 | yield None # this release the lock on the repository |
|
643 | yield None # this release the lock on the repository |
General Comments 0
You need to be logged in to leave comments.
Login now