A chroot of files overlaid from one directory to another directory. Files may be tagged when added in order to keep track of multiple overlays in the chroot.
| 654 | |
| 655 | |
| 656 | class Chroot(object): |
| 657 | """A chroot of files overlaid from one directory to another directory. |
| 658 | |
| 659 | Files may be tagged when added in order to keep track of multiple overlays in the chroot. |
| 660 | """ |
| 661 | |
| 662 | class Error(Exception): |
| 663 | pass |
| 664 | |
| 665 | class ChrootTaggingException(Error): |
| 666 | pass |
| 667 | |
| 668 | def __init__(self, chroot_base): |
| 669 | # type: (str) -> None |
| 670 | """Create the chroot. |
| 671 | |
| 672 | :chroot_base Directory for the creation of the target chroot. |
| 673 | """ |
| 674 | try: |
| 675 | safe_mkdir(chroot_base) |
| 676 | except OSError as e: |
| 677 | raise self.Error("Unable to create chroot in %s: %s" % (chroot_base, e)) |
| 678 | self.chroot = chroot_base # type: str |
| 679 | self.filesets = defaultdict(set) # type: DefaultDict[Optional[str], Set[str]] |
| 680 | self._compress_by_file = {} # type: Dict[str, bool] |
| 681 | self._file_index = {} # type: Dict[str, Optional[str]] |
| 682 | |
| 683 | def path(self): |
| 684 | # type: () -> str |
| 685 | """The path of the chroot.""" |
| 686 | return self.chroot |
| 687 | |
| 688 | def _normalize(self, dst): |
| 689 | # type: (str) -> str |
| 690 | dst = os.path.normpath(dst) |
| 691 | if dst.startswith(os.sep) or dst.startswith(".."): |
| 692 | raise self.Error("Destination path is not a relative path!") |
| 693 | return dst |
| 694 | |
| 695 | def _check_tag( |
| 696 | self, |
| 697 | fn, # type: str |
| 698 | label, # type: Optional[str] |
| 699 | compress=True, # type: bool |
| 700 | ): |
| 701 | # type: (...) -> None |
| 702 | """Raises ChrootTaggingException if a file was added under more than one label.""" |
| 703 | existing_label = self._file_index.setdefault(fn, label) |
| 704 | if label != existing_label: |
| 705 | raise self.ChrootTaggingException( |
| 706 | "Trying to add {file} to fileset({new_tag}) but already in " |
| 707 | "fileset({orig_tag})!".format(file=fn, new_tag=label, orig_tag=existing_label) |
| 708 | ) |
| 709 | existing_compress = self._compress_by_file.setdefault(fn, compress) |
| 710 | if compress != existing_compress: |
| 711 | raise self.ChrootTaggingException( |
| 712 | "Trying to add {file} to fileset({tag}) with compress {new_compress} but already " |
| 713 | "added with compress {orig_compress}!".format( |
no outgoing calls