Unverified Commit c467b34c authored by Sébastien Eustace's avatar Sébastien Eustace
Browse files

Add hash check when installing/updating packages

parent 15f31faa
Loading
Loading
Loading
Loading
+7 −0
Changes for CHANGELOG.md: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Change Log


## [Unreleased]

### Changed

- Added hashes check when installing packages.


## [0.4.2] - 2018-03-10

### Fixed
+55 −10
Changes for poetry/installation/pip_installer.py: 55 added lines, 10 removed lines.
Original line number Diff line number Diff line
import os
import tempfile

from subprocess import CalledProcessError

from poetry.utils.venv import Venv

from .base_installer import BaseInstaller
@@ -9,29 +14,69 @@ class PipInstaller(BaseInstaller):
        self._venv = venv
        self._io = io

    def install(self, package):
        args = ['install', self.requirement(package), '--no-deps']
    def install(self, package, update=False):
        args = ['install', '--no-deps']

        if package.source_type == 'legacy' and package.source_url:
            args += ['--index-url', package.source_url]

        if update:
            args.append('-U')

        if package.hashes and not package.source_type:
            # Format as a requirements.txt
            # We need to create a requirements.txt file
            # for each package in order to check hashes.
            # This is far from optimal but we do not have any
            # other choice since this is the only way for pip
            # to verify hashes.
            req = self.create_temporary_requirement(package)
            args += ['-r', req]

            try:
                self.run(*args)
            finally:
                os.unlink(req)
        else:
            args.append(self.requirement(package))

    def update(self, source, target):
        args = ['install', self.requirement(target), '--no-deps', '-U']
        if target.source_type == 'legacy' and target.source_url:
            args += ['--index-url', target.source_url]
            self.run(*args)

        self.run('install', self.requirement(target), '--no-deps', '-U')
    def update(self, _, target):
        self.install(target, update=True)

    def remove(self, package):
        try:
            self.run('uninstall', package.name, '-y')
        except CalledProcessError as e:
            if 'not installed' in str(e):
                return

            raise

    def run(self, *args) -> str:
        return self._venv.run('pip', *args)
    def run(self, *args, **kwargs) -> str:
        return self._venv.run('pip', *args, **kwargs)

    def requirement(self, package, formatted=False) -> str:
        if formatted and not package.source_type == 'git':
            req = f'{package.name}=={package.version}'
            for h in package.hashes:
                req += f' --hash sha256:{h}'

            req += '\n'

            return req

    def requirement(self, package) -> str:
        if package.source_type == 'git':
            return f'git+{package.source_url}@{package.source_reference}' \
                   f'#egg={package.name}'

        return f'{package.name}=={package.version}'

    def create_temporary_requirement(self, package):
        fd, name = tempfile.mkstemp('reqs.txt', f'{package.name}-{package.version}')

        with open(fd, 'w') as f:
            f.write(self.requirement(package, formatted=True))

        return name
+6 −2
Changes for poetry/utils/venv.py: 6 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -73,12 +73,16 @@ class Venv:
        """
        return self._bin('pip')

    def run(self, bin: str, *args) -> str:
    def run(self, bin: str, *args, **kwargs) -> str:
        """
        Run a command inside the virtual env.
        """
        cmd = [self._bin(bin)] + list(args)
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)

        output = subprocess.check_output(
            cmd, stderr=subprocess.STDOUT,
            **kwargs
        )

        return output.decode()