Exemplo n.º 1
0
def test_renaming_based_on_include(tmpdir):
    """Targets should be renameable based on the include capture group."""
    temp_dir = Path(tmpdir)

    file1 = temp_dir / 'file1'
    file1.touch()

    file2 = temp_dir / 'file2'
    file2.touch()

    recursive_dir = temp_dir / 'recursive'
    recursive_dir.mkdir()

    file3 = temp_dir / 'recursive' / 'file3'
    file3.touch()

    targets = resolve_targets(
        content=temp_dir,
        target=Path('/a/b'),
        include=r'.+(\d)',
    )
    assert targets == {
        file1: Path('/a/b/1'),
        file2: Path('/a/b/2'),
        file3: Path('/a/b/recursive/3'),
    }
Exemplo n.º 2
0
def test_resolving_content_directory(tmpdir):
    """Directory hierarchy should be preserved at target."""
    temp_dir = Path(tmpdir)

    file1 = temp_dir / 'file1'
    file1.touch()

    file2 = temp_dir / 'file2'
    file2.touch()

    recursive_dir = temp_dir / 'recursive'
    recursive_dir.mkdir()

    file3 = temp_dir / 'recursive' / 'file3'
    file3.touch()

    targets = resolve_targets(
        content=temp_dir,
        target=Path('/a/b'),
        include=r'.*',
    )
    assert targets == {
        file1: Path('/a/b/file1'),
        file2: Path('/a/b/file2'),
        file3: Path('/a/b/recursive/file3'),
    }
Exemplo n.º 3
0
    def execute(self, dry_run: bool = False) -> Dict[Path, Path]:
        """
        Copy from `content` path to `target` path.

        :param dry_run: If True, skip and log copy creation(s).
        :return: Dictionary with content keys and copy values.
        """
        if self.null_object:
            return {}

        content = self.option(key='content', path=True)
        target = self.option(key='target', path=True)
        include = self.option(key='include', default=r'(.+)')
        permissions = self.option(key='permissions', default=None)

        copies = utils.resolve_targets(
            content=content,
            target=target,
            include=include,
        )
        logger = logging.getLogger(__name__)
        for content, copy in copies.items():
            self.copied_files[content].add(copy)

            log_msg = f'[copy] Content: "{content}" -> Target: "{target}".'
            if dry_run:
                logger.info('SKIPPED: ' + log_msg)
                continue

            logger.info(log_msg)
            self.creation_store.mkdir(copy.parent)
            self.creation_store.backup(path=copy)
            utils.copy(
                source=content,
                destination=copy,
                follow_symlinks=False,
            )
            self.creation_store.insert_creation(
                content=content,
                target=copy,
                method=persistence.CreationMethod.COPY,
            )

        if permissions and not dry_run:
            for copy in copies.values():
                result = utils.run_shell(
                    command=f'chmod {permissions} "{copy}"',
                    timeout=1,
                    fallback=False,
                )

                if result is False:
                    logger = logging.getLogger(__name__)
                    logger.error(
                        f'Could not set "{permissions}" '
                        f'permissions for copy "{target}"',
                    )

        return copies
Exemplo n.º 4
0
def test_resolving_non_existent_file():
    """When `content` does not exist, no targets should be returned."""
    targets = resolve_targets(
        content=Path('/does/not/exist'),
        target=Path('/'),
        include=r'.*',
    )
    assert targets == {}
Exemplo n.º 5
0
def test_resolving_target_file_to_directory():
    """When content is a file, but target is a directory, keep filename."""
    targets = resolve_targets(
        content=Path(__file__),
        target=Path('/tmp'),
        include=r'.*',
    )
    assert targets == {Path(__file__): Path('/tmp/test_resolve_targets.py')}
Exemplo n.º 6
0
def test_resolving_target_of_content_file():
    """When `content` is a file, the target root is used."""
    targets = resolve_targets(
        content=Path(__file__),
        target=Path('/does/not/exist'),
        include=r'.*',
    )
    assert targets == {Path(__file__): Path('/does/not/exist')}
Exemplo n.º 7
0
    def execute(self, dry_run: bool = False) -> Dict[Path, Path]:
        """
        Compile template source to target destination.

        :param dry_run: If True, skip and log compilation(s).
        :return: Dictionary with template content keys and target path values.
        """
        if self.null_object:
            # Null objects do nothing
            return {}
        elif 'target' not in self._options:
            # If no target is specified, we create a deterministic target.
            template = self.option(key='content', path=True)
            target = self.create_compilation_target(template=template)
            self._options['target'] = str(target)

        # These might either be file paths or directory paths
        template_source = self.option(key='content', path=True)
        target_source = self.option(key='target', path=True)
        if not template_source.exists():
            logger = logging.getLogger(__name__)
            logger.error(
                f'Could not compile template "{template_source}" '
                f'to target "{target_source}". No such path!', )
            return {}

        compile_pairs = utils.resolve_targets(
            content=template_source,
            target=target_source,
            include=self.option(key='include', default=r'(.+)'),
        )
        permissions = self.option(key='permissions')

        for content_file, target_file in compile_pairs.items():
            if dry_run:
                logger = logging.getLogger(__name__)
                logger.info(
                    f'SKIPPED: '
                    f'[Compiling] Template: "{content_file}" '
                    f'-> Target: "{target_file}"', )
            else:
                self.creation_store.backup(path=target_file)
                compiler.compile_template(
                    template=content_file,
                    target=target_file,
                    context=self.context_store,
                    shell_command_working_directory=self.directory,
                    permissions=permissions,
                )
                self.creation_store.insert_creation(
                    content=content_file,
                    target=target_file,
                    method=persistence.CreationMethod.COMPILE,
                )

            self._performed_compilations[content_file].add(target_file)

        return compile_pairs
Exemplo n.º 8
0
    def execute(self, dry_run: bool = False) -> Dict[Path, Path]:
        """
        Symlink to `content` path from `target` path.

        :param dry_run: If True, skip and log symlink creation(s).
        :return: Dictionary with content keys and symlink values.
        """
        if self.null_object:
            return {}

        content = self.option(key='content', path=True)
        target = self.option(key='target', path=True)
        include = self.option(key='include', default=r'(.+)')
        links = utils.resolve_targets(
            content=content,
            target=target,
            include=include,
        )

        logger = logging.getLogger(__name__)
        for content, symlink in links.items():
            self.symlinked_files[content].add(symlink)
            log_msg = f'[symlink] Content "{content}" -> Target: "{symlink}".'

            if symlink.resolve() == content.resolve():
                continue

            if dry_run:
                logger.info('SKIPPED: ' + log_msg)
                continue

            logger.info(log_msg)
            symlink.parent.mkdir(parents=True, exist_ok=True)

            self.creation_store.backup(path=symlink)
            symlink.symlink_to(content)
            self.creation_store.insert_creation(
                content=content,
                target=symlink,
                method=persistence.CreationMethod.SYMLINK,
            )

        return links
Exemplo n.º 9
0
def test_filtering_based_on_include(tmpdir):
    """Only files that match the regex should be included."""
    temp_dir = Path(tmpdir)

    file1 = temp_dir / 'file1'
    file1.touch()

    file2 = temp_dir / 'file2'
    file2.touch()

    recursive_dir = temp_dir / 'recursive'
    recursive_dir.mkdir()

    file3 = temp_dir / 'recursive' / 'file3'
    file3.touch()

    targets = resolve_targets(
        content=temp_dir,
        target=Path('/a/b'),
        include=r'.+3',
    )
    assert targets == {
        file3: Path('/a/b/recursive/file3'),
    }