Beispiel #1
0
    def test_config_env_dedup(self):
        """Regression test for LP: #1767625.
        Verify that the use of after with multiple parts does not produce
        duplicate exports.
        """
        snapcraft_yaml = dedent("""\
            name: test
            base: core18
            version: "1"
            summary: test
            description: test
            confinement: strict
            grade: stable

            parts:
              main:
                plugin: nil
                after: [part1, part2, part3]
              part1:
                plugin: nil
              part2:
                plugin: nil
              part3:
                plugin: nil
        """)
        project_config = self.make_snapcraft_project(snapcraft_yaml)
        part = project_config.parts.get_part("main")
        environment = project_config.parts.build_env_for_part(part,
                                                              root_part=True)
        # We sort here for equality checking but they should not be sorted
        # for a real case scenario.
        environment.sort()
        self.assertThat(
            environment,
            Equals([
                ('PATH="{0}/parts/main/install/usr/sbin:'
                 "{0}/parts/main/install/usr/bin:"
                 "{0}/parts/main/install/sbin:"
                 '{0}/parts/main/install/bin:$PATH"').format(self.path),
                ('PATH="{0}/stage/usr/sbin:'
                 "{0}/stage/usr/bin:"
                 "{0}/stage/sbin:"
                 '{0}/stage/bin:$PATH"').format(self.path),
                'PERL5LIB="{0}/stage/usr/share/perl5/"'.format(self.path),
                'SNAPCRAFT_ARCH_TRIPLET="{}"'.format(
                    project_config.project.arch_triplet),
                'SNAPCRAFT_EXTENSIONS_DIR="{}"'.format(
                    common.get_extensionsdir()),
                'SNAPCRAFT_PARALLEL_BUILD_COUNT="2"',
                'SNAPCRAFT_PART_BUILD="{}/parts/main/build"'.format(self.path),
                'SNAPCRAFT_PART_INSTALL="{}/parts/main/install"'.format(
                    self.path),
                'SNAPCRAFT_PART_SRC="{}/parts/main/src"'.format(self.path),
                'SNAPCRAFT_PRIME="{}/prime"'.format(self.path),
                'SNAPCRAFT_PROJECT_GRADE="stable"',
                'SNAPCRAFT_PROJECT_NAME="test"',
                'SNAPCRAFT_PROJECT_VERSION="1"',
                'SNAPCRAFT_STAGE="{}/stage"'.format(self.path),
            ]),
        )
Beispiel #2
0
def snapcraft_global_environment(project: project.Project) -> Dict[str, str]:
    if project.info.name:
        name = project.info.name
    else:
        name = ""

    if project.info.version:
        version = project.info.version
    else:
        version = ""

    if project.info.grade:
        grade = project.info.grade
    else:
        grade = ""

    return {
        "SNAPCRAFT_ARCH_TRIPLET": project.arch_triplet,
        "SNAPCRAFT_PARALLEL_BUILD_COUNT": str(project.parallel_build_count),
        "SNAPCRAFT_PROJECT_NAME": name,
        "SNAPCRAFT_PROJECT_VERSION": version,
        "SNAPCRAFT_PROJECT_DIR": project._project_dir,
        "SNAPCRAFT_PROJECT_GRADE": grade,
        "SNAPCRAFT_STAGE": project.stage_dir,
        "SNAPCRAFT_PRIME": project.prime_dir,
        "SNAPCRAFT_EXTENSIONS_DIR": common.get_extensionsdir(),
    }
Beispiel #3
0
def get_snapcraft_global_environment(project: "Project") -> Dict[str, str]:
    # The triple check is mostly for unit tests support until we completely
    # get rid of project.info.
    if project._snap_meta.name:
        name = project._snap_meta.name
    elif project.info is not None and project.info.name:
        name = project.info.name
    else:
        name = ""

    if project._snap_meta.version:
        version = project._snap_meta.version
    elif project.info is not None and project.info.version:
        version = project.info.version
    else:
        version = ""

    if project._snap_meta.grade:
        grade = project._snap_meta.grade
    elif project.info is not None and project.info.grade:
        grade = project.info.grade
    else:
        grade = ""

    return {
        "SNAPCRAFT_ARCH_TRIPLET": project.arch_triplet,
        "SNAPCRAFT_PARALLEL_BUILD_COUNT": str(project.parallel_build_count),
        "SNAPCRAFT_PROJECT_NAME": name,
        "SNAPCRAFT_PROJECT_VERSION": version,
        "SNAPCRAFT_PROJECT_DIR": project._project_dir,
        "SNAPCRAFT_PROJECT_GRADE": grade,
        "SNAPCRAFT_STAGE": project.stage_dir,
        "SNAPCRAFT_PRIME": project.prime_dir,
        "SNAPCRAFT_EXTENSIONS_DIR": common.get_extensionsdir(),
    }
Beispiel #4
0
def setup_dirs() -> None:
    """
    Ensure that snapcraft.common plugindir is setup correctly
    and support running out of a development snapshot
    """
    from snapcraft.internal import common

    topdir = os.path.abspath(os.path.join(__file__, "..", "..", ".."))

    # Only change the default if we are running from a checkout or from the
    # snap, or in Windows.
    if os.path.exists(os.path.join(topdir, "setup.py")):
        common.set_plugindir(os.path.join(topdir, "snapcraft", "plugins"))
        common.set_schemadir(os.path.join(topdir, "schema"))
        common.set_extensionsdir(os.path.join(topdir, "extensions"))
        common.set_keyringsdir(os.path.join(topdir, "keyrings"))

    # The default paths are relative to sys.prefix, which works well for
    # Snapcraft as a deb or in a venv. However, the Python plugin installs
    # packages into $SNAP/ as a prefix, while Python itself is contained in
    # $SNAP/usr/. As a result, using sys.prefix (which is '/usr') to find these
    # files won't work in the snap.
    elif common.is_snap():
        snap_path = os.environ.get("SNAP")
        if snap_path is None:
            # Shouldn't happen, but it is certainly an error if it does.
            raise RuntimeError("SNAP not defined, but SNAP_NAME is?")

        parent_dir = os.path.join(snap_path, "share", "snapcraft")
        common.set_plugindir(os.path.join(parent_dir, "plugins"))
        common.set_schemadir(os.path.join(parent_dir, "schema"))
        common.set_extensionsdir(os.path.join(parent_dir, "extensions"))
        common.set_keyringsdir(os.path.join(parent_dir, "keyrings"))
        common.set_legacy_snapcraft_dir(
            os.path.join(snap_path, "legacy_snapcraft"))

    elif sys.platform == "win32":
        common.set_plugindir(os.path.join(topdir, "snapcraft", "plugins"))

        data_dir = _find_windows_data_dir(topdir)
        common.set_schemadir(os.path.join(data_dir, "schema"))
        common.set_extensionsdir(os.path.join(data_dir, "extensions"))
        common.set_keyringsdir(os.path.join(data_dir, "keyrings"))

    else:
        # Make sure required data directories exist in the default locations.
        # Plugins and legacy snapcraft directory are not required.
        for d in [
                common.get_schemadir(),
                common.get_extensionsdir(),
                common.get_keyringsdir(),
        ]:
            if not os.path.exists(d):
                raise snapcraft.internal.errors.SnapcraftDataDirectoryMissingError(
                )
Beispiel #5
0
def get_snapcraft_global_environment(
    project: "Project", include_prime: bool = True
) -> Dict[str, str]:
    """
    Return a global environment for a part.

    include_prime defaults to True for behaviour not to change when using
    core and core18 bases.

    :param Project project: the Snapcraft project instance.
    :param bool include_prime: whether to include the prime directory in
                               the results.
    :returns: a dictionary with environment variables to apply.
    :rtype: dict
    """
    # The triple check is mostly for unit tests support until we completely
    # get rid of project.info.
    if project._snap_meta.name:
        name = project._snap_meta.name
    elif project.info is not None and project.info.name:
        name = project.info.name
    else:
        name = ""

    if project._snap_meta.version:
        version = project._snap_meta.version
    elif project.info is not None and project.info.version:
        version = project.info.version
    else:
        version = ""

    if project._snap_meta.grade:
        grade = project._snap_meta.grade
    elif project.info is not None and project.info.grade:
        grade = project.info.grade
    else:
        grade = ""

    return {
        "SNAPCRAFT_ARCH_TRIPLET": project.arch_triplet,
        "SNAPCRAFT_EXTENSIONS_DIR": common.get_extensionsdir(),
        "SNAPCRAFT_PARALLEL_BUILD_COUNT": str(project.parallel_build_count),
        "SNAPCRAFT_PRIME": project.prime_dir,
        "SNAPCRAFT_PROJECT_NAME": name,
        "SNAPCRAFT_PROJECT_VERSION": version,
        "SNAPCRAFT_PROJECT_DIR": project._project_dir,
        "SNAPCRAFT_PROJECT_GRADE": grade,
        "SNAPCRAFT_STAGE": project.stage_dir,
        "SNAPCRAFT_TARGET_ARCH": project.target_arch,
    }
Beispiel #6
0
    def setUp(self):
        super().setUp()
        temp_cwd_fixture = fixture_setup.TempCWD()
        self.useFixture(temp_cwd_fixture)
        self.path = temp_cwd_fixture.path

        # Use a separate path for XDG dirs, or changes there may be detected as
        # source changes.
        self.xdg_path = self.useFixture(fixtures.TempDir()).path
        self.useFixture(fixture_setup.TempXDG(self.xdg_path))
        self.fake_terminal = fixture_setup.FakeTerminal()
        self.useFixture(self.fake_terminal)
        # Some tests will directly or indirectly change the plugindir, which
        # is a module variable. Make sure that it is returned to the original
        # value when a test ends.
        self.addCleanup(common.set_plugindir, common.get_plugindir())
        self.addCleanup(common.set_schemadir, common.get_schemadir())
        self.addCleanup(common.set_extensionsdir, common.get_extensionsdir())
        self.addCleanup(common.set_keyringsdir, common.get_keyringsdir())
        self.addCleanup(common.reset_env)
        common.set_schemadir(os.path.join(get_snapcraft_path(), "schema"))
        self.fake_logger = fixtures.FakeLogger(level=logging.ERROR)
        self.useFixture(self.fake_logger)

        # Some tests will change the apt Dir::Etc::Trusted and
        # Dir::Etc::TrustedParts directories. Make sure they're properly reset.
        self.addCleanup(
            apt.apt_pkg.config.set,
            "Dir::Etc::Trusted",
            apt.apt_pkg.config.find_file("Dir::Etc::Trusted"),
        )
        self.addCleanup(
            apt.apt_pkg.config.set,
            "Dir::Etc::TrustedParts",
            apt.apt_pkg.config.find_file("Dir::Etc::TrustedParts"),
        )

        patcher = mock.patch("os.sched_getaffinity")
        self.cpu_count = patcher.start()
        self.cpu_count.return_value = {1, 2}
        self.addCleanup(patcher.stop)

        # We do not want the paths to affect every test we have.
        patcher = mock.patch(
            "snapcraft.file_utils.get_snap_tool_path", side_effect=lambda x: x
        )
        patcher.start()
        self.addCleanup(patcher.stop)

        patcher = mock.patch(
            "snapcraft.internal.indicators.ProgressBar", new=SilentProgressBar
        )
        patcher.start()
        self.addCleanup(patcher.stop)

        # These are what we expect by default
        self.snap_dir = os.path.join(os.getcwd(), "snap")
        self.prime_dir = os.path.join(os.getcwd(), "prime")
        self.stage_dir = os.path.join(os.getcwd(), "stage")
        self.parts_dir = os.path.join(os.getcwd(), "parts")
        self.local_plugins_dir = os.path.join(self.snap_dir, "plugins")

        # Use this host to run through the lifecycle tests
        self.useFixture(
            fixtures.EnvironmentVariable("SNAPCRAFT_BUILD_ENVIRONMENT", "host")
        )

        # Make sure snap installation does the right thing
        self.fake_snapd.installed_snaps = [
            dict(name="core16", channel="stable", revision="10"),
            dict(name="core18", channel="stable", revision="10"),
        ]
        self.fake_snapd.snaps_result = [
            dict(name="core16", channel="stable", revision="10"),
            dict(name="core18", channel="stable", revision="10"),
        ]
        self.fake_snapd.find_result = [
            dict(
                core16=dict(
                    channel="stable",
                    channels={"latest/stable": dict(confinement="strict")},
                )
            ),
            dict(
                core18=dict(
                    channel="stable",
                    channels={"latest/stable": dict(confinement="strict")},
                )
            ),
        ]
        self.fake_snapd.snap_details_func = None

        self.fake_snap_command = fixture_setup.FakeSnapCommand()
        self.useFixture(self.fake_snap_command)

        # Avoid installing patchelf in the tests
        self.useFixture(fixtures.EnvironmentVariable("SNAPCRAFT_NO_PATCHELF", "1"))

        # Disable Sentry reporting for tests, otherwise they'll hang waiting
        # for input
        self.useFixture(
            fixtures.EnvironmentVariable("SNAPCRAFT_ENABLE_ERROR_REPORTING", "false")
        )

        # Don't let the managed host variable leak into tests
        self.useFixture(fixtures.EnvironmentVariable("SNAPCRAFT_MANAGED_HOST"))

        machine = os.environ.get("SNAPCRAFT_TEST_MOCK_MACHINE", None)
        self.base_environment = fixture_setup.FakeBaseEnvironment(machine=machine)
        self.useFixture(self.base_environment)

        # Make sure "SNAPCRAFT_ENABLE_DEVELOPER_DEBUG" is reset between tests
        self.useFixture(
            fixtures.EnvironmentVariable("SNAPCRAFT_ENABLE_DEVELOPER_DEBUG")
        )
        self.useFixture(fixture_setup.FakeSnapcraftctl())

        # Don't let host SNAPCRAFT_BUILD_INFO variable leak into tests
        self.useFixture(fixtures.EnvironmentVariable("SNAPCRAFT_BUILD_INFO"))
Beispiel #7
0
    def setUp(self):
        super().setUp()
        temp_cwd_fixture = fixture_setup.TempCWD()
        self.useFixture(temp_cwd_fixture)
        self.path = temp_cwd_fixture.path

        # Use a separate path for XDG dirs, or changes there may be detected as
        # source changes.
        self.xdg_path = self.useFixture(fixtures.TempDir()).path
        self.useFixture(fixture_setup.TempXDG(self.xdg_path))
        self.fake_terminal = fixture_setup.FakeTerminal()
        self.useFixture(self.fake_terminal)
        self.useFixture(fixture_setup.SilentSnapProgress())
        # Some tests will directly or indirectly change the plugindir, which
        # is a module variable. Make sure that it is returned to the original
        # value when a test ends.
        self.addCleanup(common.set_plugindir, common.get_plugindir())
        self.addCleanup(common.set_schemadir, common.get_schemadir())
        self.addCleanup(common.set_librariesdir, common.get_librariesdir())
        self.addCleanup(common.set_extensionsdir, common.get_extensionsdir())
        self.addCleanup(common.reset_env)
        common.set_schemadir(os.path.join(get_snapcraft_path(), "schema"))
        self.fake_logger = fixtures.FakeLogger(level=logging.ERROR)
        self.useFixture(self.fake_logger)

        patcher = mock.patch("multiprocessing.cpu_count")
        self.cpu_count = patcher.start()
        self.cpu_count.return_value = 2
        self.addCleanup(patcher.stop)

        # We do not want the paths to affect every test we have.
        patcher = mock.patch("snapcraft.file_utils.get_tool_path",
                             side_effect=lambda x: x)
        patcher.start()
        self.addCleanup(patcher.stop)

        patcher = mock.patch("snapcraft.internal.indicators.ProgressBar",
                             new=SilentProgressBar)
        patcher.start()
        self.addCleanup(patcher.stop)

        # These are what we expect by default
        self.snap_dir = os.path.join(os.getcwd(), "snap")
        self.prime_dir = os.path.join(os.getcwd(), "prime")
        self.stage_dir = os.path.join(os.getcwd(), "stage")
        self.parts_dir = os.path.join(os.getcwd(), "parts")
        self.local_plugins_dir = os.path.join(self.snap_dir, "plugins")

        # Avoid installing patchelf in the tests
        self.useFixture(
            fixtures.EnvironmentVariable("SNAPCRAFT_NO_PATCHELF", "1"))

        # Disable Sentry reporting for tests, otherwise they'll hang waiting
        # for input
        self.useFixture(
            fixtures.EnvironmentVariable("SNAPCRAFT_ENABLE_ERROR_REPORTING",
                                         "false"))

        # Don't let the managed host variable leak into tests
        self.useFixture(fixtures.EnvironmentVariable("SNAPCRAFT_MANAGED_HOST"))

        machine = os.environ.get("SNAPCRAFT_TEST_MOCK_MACHINE", None)
        self.base_environment = fixture_setup.FakeBaseEnvironment(
            machine=machine)
        self.useFixture(self.base_environment)

        # Make sure "SNAPCRAFT_ENABLE_DEVELOPER_DEBUG" is reset between tests
        self.useFixture(
            fixtures.EnvironmentVariable("SNAPCRAFT_ENABLE_DEVELOPER_DEBUG"))
        self.useFixture(fixture_setup.FakeSnapcraftctl())