示例#1
0
    def write_snap_directory(self):
        # First migrate the snap directory. It will overwrite any conflicting
        # files.
        for root, directories, files in os.walk('snap'):
            for directory in directories:
                source = os.path.join(root, directory)
                destination = os.path.join(self._snap_dir, source)
                file_utils.create_similar_directory(source, destination)

            for file_path in files:
                source = os.path.join(root, file_path)
                destination = os.path.join(self._snap_dir, source)
                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)
                file_utils.link_or_copy(source, destination)

        # Now copy the hooks contained within the snap directory directly into
        # meta (they don't get wrappers like the ones that come from parts).
        snap_hooks_dir = os.path.join('snap', 'hooks')
        hooks_dir = os.path.join(self._snap_dir, 'meta', 'hooks')
        if os.path.isdir(snap_hooks_dir):
            os.makedirs(hooks_dir, exist_ok=True)
            for hook_name in os.listdir(snap_hooks_dir):
                source = os.path.join(snap_hooks_dir, hook_name)
                destination = os.path.join(hooks_dir, hook_name)

                # First, verify that the hook is actually executable
                if not os.stat(source).st_mode & stat.S_IEXEC:
                    raise CommandError('hook {!r} is not executable'.format(
                        hook_name))

                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)

                file_utils.link_or_copy(source, destination)
示例#2
0
    def _get(self, apt_cache):
        # Ideally we'd use apt.Cache().fetch_archives() here, but it seems to
        # mangle some package names on disk such that we can't match it up to
        # the archive later. We could get around this a few different ways:
        #
        # 1. Store each stage package in the cache named by a hash instead of
        #    its name from the archive.
        # 2. Download packages in a different manner.
        #
        # In the end, (2) was chosen for minimal overhead and a simpler cache
        # implementation. So we're using fetch_binary() here instead.
        # Downloading each package individually has the drawback of witholding
        # any clue of how long the whole pulling process will take, but that's
        # something we'll have to live with.
        pkg_list = []
        for package in apt_cache.get_changes():
            pkg_list.append(str(package.candidate))
            source = package.candidate.fetch_binary(
                self._cache.packages_dir, progress=self._apt.progress)
            destination = os.path.join(
                self._downloaddir, os.path.basename(source))
            with contextlib.suppress(FileNotFoundError):
                os.remove(destination)
            file_utils.link_or_copy(source, destination)

        return pkg_list
示例#3
0
def _migrate_files(snap_files, snap_dirs, srcdir, dstdir, missing_ok=False,
                   follow_symlinks=False, fixup_func=lambda *args: None):

    for directory in snap_dirs:
        src = os.path.join(srcdir, directory)
        dst = os.path.join(dstdir, directory)

        snapcraft.file_utils.create_similar_directory(src, dst)

    for snap_file in snap_files:
        src = os.path.join(srcdir, snap_file)
        dst = os.path.join(dstdir, snap_file)

        snapcraft.file_utils.create_similar_directory(os.path.dirname(src),
                                                      os.path.dirname(dst))

        if missing_ok and not os.path.exists(src):
            continue

        # If the file is already here and it's a symlink, leave it alone.
        if os.path.islink(dst):
            continue

        # Otherwise, remove and re-link it.
        if os.path.exists(dst):
            os.remove(dst)

        if src.endswith('.pc'):
            shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
        else:
            file_utils.link_or_copy(src, dst, follow_symlinks=follow_symlinks)

        fixup_func(dst)
示例#4
0
文件: repo.py 项目: 3v1n0/snapcraft
 def _restore_cached_packages(self, apt_changes,
                              package_cache_dir, download_dir):
     for pkg in apt_changes:
         src = os.path.join(package_cache_dir, pkg.name)
         dst = os.path.join(download_dir, pkg.name)
         if os.path.exists(src):
             file_utils.link_or_copy(src, dst)
示例#5
0
    def test_link_file_ioerror(self):
        orig_link = os.link

        def link_and_ioerror(a, b, **kwargs):
            orig_link(a, b)
            raise IOError()
        with mock.patch('os.link') as mock_link:
            mock_link.side_effect = link_and_ioerror
            file_utils.link_or_copy('1', 'foo/1')
示例#6
0
    def _ensure_snapcraft_yaml(self):
        source = project_loader.get_snapcraft_yaml()
        destination = os.path.join(self._snap_dir, 'snap', 'snapcraft.yaml')

        with contextlib.suppress(FileNotFoundError):
            os.remove(destination)

        os.makedirs(os.path.dirname(destination), exist_ok=True)
        file_utils.link_or_copy(source, destination)
示例#7
0
    def wheel(self, packages, *, setup_py_dir=None, constraints=None,
              requirements=None, process_dependency_links=False):
        """Build wheels of packages in the cache.

        The packages should have already been downloaded via `download()`.

        :param iterable packages: Packages in cache for which to build wheels.
        :param str setup_py_dir: Directory containing setup.py.
        :param iterable constraints: Collection of paths to constraints files.
        :param iterable requirements: Collection of paths to requirements
                                      files.
        :param boolean process_dependency_links: Enable the processing of
                                                 dependency links.

        :return: List of paths to each wheel that was built.
        :rtype: list
        """
        args = _process_common_args(
            process_dependency_links=process_dependency_links,
            packages=packages, constraints=constraints,
            requirements=requirements)

        cwd = None
        if setup_py_dir:
            args.append('.')
            cwd = setup_py_dir

        if not args:
            return  # No operation was requested

        wheels = []
        with tempfile.TemporaryDirectory() as temp_dir:

            # Using pip with a few special parameters:
            #
            # --no-index: Don't hit pypi, assume the packages are already
            #             downloaded (i.e. by using `self.download()`)
            # --find-links: Provide the directory into which the packages
            #               should have already been fetched
            # --wheel-dir: Build wheels into a temporary working area rather
            #              rather than cwd. We'll copy them over. FIXME: We can
            #              probably get away just building them in the package
            #              dir. Try that once this refactor has been validated.
            self._run(['wheel', '--no-index', '--find-links',
                       self._python_package_dir, '--wheel-dir',
                       temp_dir] + args, cwd=cwd)
            wheels = os.listdir(temp_dir)
            for wheel in wheels:
                file_utils.link_or_copy(
                    os.path.join(temp_dir, wheel),
                    os.path.join(self._python_package_dir, wheel))

        return [os.path.join(self._python_package_dir, wheel)
                for wheel in wheels]
示例#8
0
文件: repo.py 项目: 3v1n0/snapcraft
 def _store_cached_packages(self, package_cache_dir, download_dir):
     os.makedirs(package_cache_dir, exist_ok=True)
     for pkg in os.listdir(download_dir):
         if not pkg.endswith('.deb'):
             continue
         src = os.path.join(download_dir, pkg)
         dst = os.path.join(package_cache_dir, pkg)
         # The dst may be an incomplete or broken so let's update
         # just in case.
         if os.path.exists(dst):
             os.unlink(dst)
         file_utils.link_or_copy(src, dst)
示例#9
0
文件: _snap.py 项目: 3v1n0/snapcraft
    def cache(self, snap_filename, revision):
        """Cache snap revision in XDG cache.

        :returns: path to cached revision.
        """
        cached_snap = _rewrite_snap_filename_with_revision(
            snap_filename,
            revision)
        cached_snap_path = os.path.join(self.snap_cache_dir, cached_snap)
        try:
            link_or_copy(snap_filename, cached_snap_path)
        except OSError:
            logger.warning(
                'Unable to cache snap {}.'.format(cached_snap))
        return cached_snap_path
示例#10
0
    def write_snap_directory(self) -> None:
        # First migrate the snap directory. It will overwrite any conflicting
        # files.
        for root, directories, files in os.walk("snap"):
            with contextlib.suppress(ValueError):
                directories.remove(".snapcraft")
            with contextlib.suppress(ValueError):
                # The snapcraft.yaml is migrated later
                files.remove("snapcraft.yaml")

            for directory in directories:
                source = os.path.join(root, directory)
                destination = os.path.join(self._prime_dir, source)
                file_utils.create_similar_directory(source, destination)

            for file_path in files:
                source = os.path.join(root, file_path)
                destination = os.path.join(self._prime_dir, source)
                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)
                file_utils.link_or_copy(source, destination)

        # Now copy the assets contained within the snap directory directly into
        # meta.
        for origin in ["gui", "hooks"]:
            src_dir = os.path.join("snap", origin)
            dst_dir = os.path.join(self.meta_dir, origin)
            if os.path.isdir(src_dir):
                os.makedirs(dst_dir, exist_ok=True)
                for asset in os.listdir(src_dir):
                    source = os.path.join(src_dir, asset)
                    destination = os.path.join(dst_dir, asset)

                    # First, verify that the hook is actually executable
                    if origin == "hooks":
                        _validate_hook(source)

                    with contextlib.suppress(FileNotFoundError):
                        os.remove(destination)

                    file_utils.link_or_copy(source, destination)

        self._record_manifest_and_source_snapcraft_yaml()
示例#11
0
    def write_snap_directory(self) -> None:
        # First migrate the snap directory. It will overwrite any conflicting
        # files.
        for root, directories, files in os.walk("snap"):
            with contextlib.suppress(ValueError):
                directories.remove(".snapcraft")
            with contextlib.suppress(ValueError):
                # The snapcraft.yaml is migrated later
                files.remove("snapcraft.yaml")

            for directory in directories:
                source = os.path.join(root, directory)
                destination = os.path.join(self._prime_dir, source)
                file_utils.create_similar_directory(source, destination)

            for file_path in files:
                source = os.path.join(root, file_path)
                destination = os.path.join(self._prime_dir, source)
                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)
                file_utils.link_or_copy(source, destination)

        # Now copy the assets contained within the snap directory directly into
        # meta.
        for origin in ["gui", "hooks"]:
            src_dir = os.path.join("snap", origin)
            dst_dir = os.path.join(self.meta_dir, origin)
            if os.path.isdir(src_dir):
                os.makedirs(dst_dir, exist_ok=True)
                for asset in os.listdir(src_dir):
                    source = os.path.join(src_dir, asset)
                    destination = os.path.join(dst_dir, asset)

                    # First, verify that the hook is actually executable
                    if origin == "hooks":
                        _validate_hook(source)

                    with contextlib.suppress(FileNotFoundError):
                        os.remove(destination)

                    file_utils.link_or_copy(source, destination)

        self._record_manifest_and_source_snapcraft_yaml()
示例#12
0
    def build(self):
        super().build()

        self._maven_tar.provision(self._maven_dir,
                                  clean_target=False,
                                  keep_tarball=True)

        mvn_cmd = ["mvn", "package"]
        if self._use_proxy():
            settings_path = os.path.join(self.partdir, "m2", "settings.xml")
            _create_settings(settings_path)
            mvn_cmd += ["-s", settings_path]

        self.run(mvn_cmd + self.options.maven_options, rootdir=self.builddir)

        for f in self.options.maven_targets:
            src = os.path.join(self.builddir, f, "target")
            jarfiles = glob(os.path.join(src, "*.jar"))
            warfiles = glob(os.path.join(src, "*.war"))
            arfiles = glob(os.path.join(src, "*.[jw]ar"))

            if len(arfiles) == 0:
                raise RuntimeError(
                    "Could not find any built jar files for part")
            if len(jarfiles) > 0 and len(f) == 0:
                basedir = "jar"
            elif len(warfiles) > 0 and len(f) == 0:
                basedir = "war"
            else:
                basedir = f

            targetdir = os.path.join(self.installdir, basedir)
            os.makedirs(targetdir, exist_ok=True)
            for src in arfiles:
                # Make rebuilding easier when enabled
                base = os.path.basename(src)
                dst = os.path.join(targetdir, base)
                if os.path.exists(dst):
                    os.unlink(dst)
                file_utils.link_or_copy(src, dst)

        self._create_symlinks()
示例#13
0
def _migrate_files(
    snap_files,
    snap_dirs,
    srcdir,
    dstdir,
    missing_ok=False,
    follow_symlinks=False,
    fixup_func=lambda *args: None,
):

    for directory in snap_dirs:
        src = os.path.join(srcdir, directory)
        dst = os.path.join(dstdir, directory)

        snapcraft.file_utils.create_similar_directory(src, dst)

    for snap_file in snap_files:
        src = os.path.join(srcdir, snap_file)
        dst = os.path.join(dstdir, snap_file)

        snapcraft.file_utils.create_similar_directory(
            os.path.dirname(src), os.path.dirname(dst)
        )

        if missing_ok and not os.path.exists(src):
            continue

        # If the file is already here and it's a symlink, leave it alone.
        if os.path.islink(dst):
            continue

        # Otherwise, remove and re-link it.
        if os.path.exists(dst):
            os.remove(dst)

        if src.endswith(".pc"):
            shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
        else:
            file_utils.link_or_copy(src, dst, follow_symlinks=follow_symlinks)

        fixup_func(dst)
示例#14
0
    def write_snap_directory(self):
        # First migrate the snap directory. It will overwrite any conflicting
        # files.
        for root, directories, files in os.walk('snap'):
            for directory in directories:
                source = os.path.join(root, directory)
                destination = os.path.join(self._snap_dir, source)
                file_utils.create_similar_directory(source, destination)

            for file_path in files:
                source = os.path.join(root, file_path)
                destination = os.path.join(self._snap_dir, source)
                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)
                file_utils.link_or_copy(source, destination)

        # Now copy the assets contained within the snap directory directly into
        # meta.
        for origin in ['gui', 'hooks']:
            src_dir = os.path.join('snap', origin)
            dst_dir = os.path.join(self.meta_dir, origin)
            if os.path.isdir(src_dir):
                os.makedirs(dst_dir, exist_ok=True)
                for asset in os.listdir(src_dir):
                    source = os.path.join(src_dir, asset)
                    destination = os.path.join(dst_dir, asset)

                    # First, verify that the hook is actually executable
                    if origin == 'hooks':
                        _validate_hook(source)

                    with contextlib.suppress(FileNotFoundError):
                        os.remove(destination)

                    file_utils.link_or_copy(source, destination)

        # FIXME hide this functionality behind a feature flag for now
        if os.environ.get('SNAPCRAFT_BUILD_INFO'):
            self._ensure_snapcraft_yaml()
        else:
            self._ensure_no_build_artifacts()
示例#15
0
    def write_snap_directory(self):
        # First migrate the snap directory. It will overwrite any conflicting
        # files.
        for root, directories, files in os.walk('snap'):
            for directory in directories:
                source = os.path.join(root, directory)
                destination = os.path.join(self._snap_dir, source)
                file_utils.create_similar_directory(source, destination)

            for file_path in files:
                source = os.path.join(root, file_path)
                destination = os.path.join(self._snap_dir, source)
                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)
                file_utils.link_or_copy(source, destination)

        # Now copy the assets contained within the snap directory directly into
        # meta.
        for origin in ['gui', 'hooks']:
            src_dir = os.path.join('snap', origin)
            dst_dir = os.path.join(self.meta_dir, origin)
            if os.path.isdir(src_dir):
                os.makedirs(dst_dir, exist_ok=True)
                for asset in os.listdir(src_dir):
                    source = os.path.join(src_dir, asset)
                    destination = os.path.join(dst_dir, asset)

                    # First, verify that the hook is actually executable
                    if origin == 'hooks':
                        _validate_hook(source)

                    with contextlib.suppress(FileNotFoundError):
                        os.remove(destination)

                    file_utils.link_or_copy(source, destination)

        # FIXME hide this functionality behind a feature flag for now
        if os.environ.get('SNAPCRAFT_BUILD_INFO'):
            self._ensure_snapcraft_yaml()
        else:
            self._ensure_no_build_artifacts()
示例#16
0
    def build(self):
        super().build()

        self.run(["shards", "install", "--production"], self.builddir)
        self.run(["shards", "build", "--production"], self.builddir)

        output_bin = os.path.join(self.builddir, "bin")
        if not os.path.exists(output_bin):
            raise errors.SnapcraftEnvironmentError(
                "No binaries were built. Ensure the shards.yaml contains valid targets."
            )

        install_bin_path = os.path.join(self.installdir, "bin")

        bin_paths = (os.path.join(output_bin, b)
                     for b in os.listdir(output_bin))
        elf_files = (elf.ElfFile(path=b) for b in bin_paths
                     if elf.ElfFile.is_elf(b))

        os.makedirs(install_bin_path, exist_ok=True)

        for elf_file in elf_files:
            shutil.copy2(
                elf_file.path,
                os.path.join(install_bin_path,
                             os.path.basename(elf_file.path)),
            )

            elf_dependencies_path = elf_file.load_dependencies(
                root_path=self.installdir,
                core_base_path=common.get_core_path(
                    self.project.info.get_build_base()),
            )
            for elf_dependency_path in elf_dependencies_path:
                lib_install_path = os.path.join(self.installdir,
                                                elf_dependency_path[1:])
                os.makedirs(os.path.dirname(lib_install_path), exist_ok=True)
                if not os.path.exists(lib_install_path):
                    file_utils.link_or_copy(elf_dependency_path,
                                            lib_install_path,
                                            follow_symlinks=True)
示例#17
0
    def setup_assets(self) -> None:
        # We do _setup_from_setup first since it is legacy and let the
        # declarative items take over.
        self._setup_gui()

        if "icon" in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            icon_ext = self._config_data["icon"].split(os.path.extsep)[-1]
            icon_dir = os.path.join(self.meta_dir, "gui")
            icon_path = os.path.join(icon_dir, "icon.{}".format(icon_ext))
            if not os.path.exists(icon_dir):
                os.mkdir(icon_dir)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            file_utils.link_or_copy(self._config_data["icon"], icon_path)

        if self._config_data.get("type", "") == "gadget":
            if not os.path.exists("gadget.yaml"):
                raise errors.MissingGadgetError()
            file_utils.link_or_copy("gadget.yaml",
                                    os.path.join(self.meta_dir, "gadget.yaml"))
示例#18
0
    def fetch_stage_packages(cls, *, package_names: List[str], base: str,
                             stage_packages_path: pathlib.Path) -> List[str]:
        logger.debug(f"Requested stage-packages: {sorted(package_names)!r}")

        installed: Set[str] = set()

        stage_packages_path.mkdir(exist_ok=True)
        with AptCache(stage_cache=_STAGE_CACHE_DIR) as apt_cache:
            filter_packages = set(get_packages_in_base(base=base))
            apt_cache.update()
            apt_cache.mark_packages(set(package_names))
            apt_cache.unmark_packages(required_names=set(package_names),
                                      filtered_names=filter_packages)
            for pkg_name, pkg_version, dl_path in apt_cache.fetch_archives(
                    _DEB_CACHE_DIR):
                logger.debug(f"Extracting stage package: {pkg_name}")
                installed.add(f"{pkg_name}={pkg_version}")
                file_utils.link_or_copy(
                    str(dl_path), str(stage_packages_path / dl_path.name))

        return sorted(installed)
示例#19
0
    def setup_assets(self):
        # We do _setup_from_setup first since it is legacy and let the
        # declarative items take over.
        self._setup_gui()

        if 'icon' in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            icon_ext = self._config_data['icon'].split(os.path.extsep)[-1]
            icon_dir = os.path.join(self.meta_dir, 'gui')
            icon_path = os.path.join(icon_dir, 'icon.{}'.format(icon_ext))
            if not os.path.exists(icon_dir):
                os.mkdir(icon_dir)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            os.link(self._config_data['icon'], icon_path)

        if self._config_data.get('type', '') == 'gadget':
            if not os.path.exists('gadget.yaml'):
                raise errors.MissingGadgetError()
            file_utils.link_or_copy(
                'gadget.yaml', os.path.join(self.meta_dir, 'gadget.yaml'))
示例#20
0
    def setup_assets(self) -> None:
        # We do _setup_from_setup first since it is legacy and let the
        # declarative items take over.
        self._setup_gui()

        if 'icon' in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            icon_ext = self._config_data['icon'].split(os.path.extsep)[-1]
            icon_dir = os.path.join(self.meta_dir, 'gui')
            icon_path = os.path.join(icon_dir, 'icon.{}'.format(icon_ext))
            if not os.path.exists(icon_dir):
                os.mkdir(icon_dir)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            os.link(self._config_data['icon'], icon_path)

        if self._config_data.get('type', '') == 'gadget':
            if not os.path.exists('gadget.yaml'):
                raise errors.MissingGadgetError()
            file_utils.link_or_copy('gadget.yaml',
                                    os.path.join(self.meta_dir, 'gadget.yaml'))
示例#21
0
    def wheel(self, args, **kwargs):
        cmd = [
            *self._runnable, 'wheel',
            '--disable-pip-version-check', '--no-index',
            '--find-links', self._package_dir,
        ]
        cmd.extend(self._extra_pip_args)

        os.makedirs(self._package_dir, exist_ok=True)

        wheels = []
        with tempfile.TemporaryDirectory() as temp_dir:
            cmd.extend(['--wheel-dir', temp_dir])
            cmd.extend(args)
            self._exec_func(cmd, env=self._env, **kwargs)
            wheels = os.listdir(temp_dir)
            for wheel in wheels:
                file_utils.link_or_copy(
                    os.path.join(temp_dir, wheel),
                    os.path.join(self._package_dir, wheel))

        return [os.path.join(self._package_dir, wheel) for wheel in wheels]
示例#22
0
    def setup_assets(self) -> None:
        # We do _setup_from_setup first since it is legacy and let the
        # declarative items take over.
        self._setup_gui()

        if "icon" in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            icon_ext = self._config_data["icon"].split(os.path.extsep)[-1]
            icon_dir = os.path.join(self.meta_dir, "gui")
            icon_path = os.path.join(icon_dir, "icon.{}".format(icon_ext))
            if not os.path.exists(icon_dir):
                os.mkdir(icon_dir)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            os.link(self._config_data["icon"], icon_path)

        if self._config_data.get("type", "") == "gadget":
            if not os.path.exists("gadget.yaml"):
                raise errors.MissingGadgetError()
            file_utils.link_or_copy(
                "gadget.yaml", os.path.join(self.meta_dir, "gadget.yaml")
            )
示例#23
0
    def write_snap_directory(self):
        # First migrate the snap directory. It will overwrite any conflicting
        # files.
        for root, directories, files in os.walk('snap'):
            if '.snapcraft' in directories:
                directories.remove('.snapcraft')
            for directory in directories:
                source = os.path.join(root, directory)
                destination = os.path.join(self._prime_dir, source)
                file_utils.create_similar_directory(source, destination)

            for file_path in files:
                source = os.path.join(root, file_path)
                destination = os.path.join(self._prime_dir, source)
                with contextlib.suppress(FileNotFoundError):
                    os.remove(destination)
                file_utils.link_or_copy(source, destination)

        # Now copy the assets contained within the snap directory directly into
        # meta.
        for origin in ['gui', 'hooks']:
            src_dir = os.path.join('snap', origin)
            dst_dir = os.path.join(self.meta_dir, origin)
            if os.path.isdir(src_dir):
                os.makedirs(dst_dir, exist_ok=True)
                for asset in os.listdir(src_dir):
                    source = os.path.join(src_dir, asset)
                    destination = os.path.join(dst_dir, asset)

                    # First, verify that the hook is actually executable
                    if origin == 'hooks':
                        _validate_hook(source)

                    with contextlib.suppress(FileNotFoundError):
                        os.remove(destination)

                    file_utils.link_or_copy(source, destination)

        self._record_snapcraft()
示例#24
0
    def wheel(self, args, **kwargs):
        cmd = [
            *self._runnable, 'wheel',
            '--disable-pip-version-check', '--no-index',
            '--find-links', self._package_dir,
        ]
        cmd.extend(self._extra_pip_args)

        os.makedirs(self._package_dir, exist_ok=True)

        wheels = []
        with tempfile.TemporaryDirectory() as temp_dir:
            cmd.extend(['--wheel-dir', temp_dir])
            cmd.extend(args)
            self._exec_func(cmd, env=self._env, **kwargs)
            wheels = os.listdir(temp_dir)
            for wheel in wheels:
                file_utils.link_or_copy(
                    os.path.join(temp_dir, wheel),
                    os.path.join(self._package_dir, wheel))

        return [os.path.join(self._package_dir, wheel) for wheel in wheels]
示例#25
0
    def setup_assets(self) -> None:
        # We do _setup_from_setup first since it is legacy and let the
        # declarative items take over.
        self._setup_gui()

        # Extracted metadata (e.g. from the AppStream) can override the
        # icon location.
        if self._extracted_metadata:
            icon_path = self._extracted_metadata.get_icon()
        else:
            icon_path = None

        snap_name = self._project_config.project.info.name
        for app_name, app in self._snap_meta.apps.items():
            app.write_command_wrappers(prime_dir=self._prime_dir)
            app.write_application_desktop_file(
                snap_name=snap_name,
                prime_dir=self._prime_dir,
                gui_dir=self.meta_gui_dir,
                icon_path=icon_path,
            )
            app.validate_command_chain_executables(self._prime_dir)

        if "icon" in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            icon_ext = self._config_data["icon"].split(os.path.extsep)[-1]
            icon_path = os.path.join(self.meta_gui_dir,
                                     "icon.{}".format(icon_ext))
            os.makedirs(self.meta_gui_dir, exist_ok=True)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            file_utils.link_or_copy(self._config_data["icon"], icon_path)

        if self._config_data.get("type", "") == "gadget":
            if not os.path.exists("gadget.yaml"):
                raise errors.MissingGadgetError()
            file_utils.link_or_copy("gadget.yaml",
                                    os.path.join(self.meta_dir, "gadget.yaml"))
示例#26
0
    def setup_assets(self):
        if 'icon' in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            logger.warning(
                "DEPRECATED: 'icon' defined in snapcraft.yaml. Look at "
                "https://github.com/snapcore/snapcraft/blob/master/docs/"
                "metadata.md#snap-icon for more information")
            icon_ext = self._config_data['icon'].split(os.path.extsep)[1]
            icon_dir = os.path.join(self.meta_dir, 'gui')
            icon_path = os.path.join(icon_dir, 'icon.{}'.format(icon_ext))
            if not os.path.exists(icon_dir):
                os.mkdir(icon_dir)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            os.link(self._config_data['icon'], icon_path)

        self._setup_from_setup()

        if self._config_data.get('type', '') == 'gadget':
            if not os.path.exists('gadget.yaml'):
                raise MissingGadgetError()
            file_utils.link_or_copy(
                'gadget.yaml', os.path.join(self.meta_dir, 'gadget.yaml'))
示例#27
0
    def setup_assets(self):
        if 'icon' in self._config_data:
            # TODO: use developer.ubuntu.com once it has updated documentation.
            logger.warning(
                "DEPRECATED: 'icon' defined in snapcraft.yaml. Look at "
                "https://github.com/snapcore/snapcraft/blob/master/docs/"
                "metadata.md#snap-icon for more information")
            icon_ext = self._config_data['icon'].split(os.path.extsep)[1]
            icon_dir = os.path.join(self.meta_dir, 'gui')
            icon_path = os.path.join(icon_dir, 'icon.{}'.format(icon_ext))
            if not os.path.exists(icon_dir):
                os.mkdir(icon_dir)
            if os.path.exists(icon_path):
                os.unlink(icon_path)
            os.link(self._config_data['icon'], icon_path)

        self._setup_from_setup()

        if self._config_data.get('type', '') == 'gadget':
            if not os.path.exists('gadget.yaml'):
                raise MissingGadgetError()
            file_utils.link_or_copy('gadget.yaml',
                                    os.path.join(self.meta_dir, 'gadget.yaml'))
示例#28
0
    def write_snap_directory(self) -> None:
        """Record manifest and copy assets found under $SNAPCRAFT_PROJECT_ROOT/snap.

        These assets have priority over any code generated assets and include:
        - hooks
        - gui
        """
        snap_assets_dir = self._project_config.project._get_snapcraft_assets_dir(
        )
        prime_snap_dir = os.path.join(self._prime_dir, "snap")

        snap_dir_iter = itertools.product([prime_snap_dir], ["hooks"])
        meta_dir_iter = itertools.product([self.meta_dir], ["hooks", "gui"])

        for origin in itertools.chain(snap_dir_iter, meta_dir_iter):
            src_dir = os.path.join(snap_assets_dir, origin[1])
            dst_dir = os.path.join(origin[0], origin[1])
            if os.path.isdir(src_dir):
                os.makedirs(dst_dir, exist_ok=True)
                for asset in os.listdir(src_dir):
                    source = os.path.join(src_dir, asset)
                    destination = os.path.join(dst_dir, asset)

                    with contextlib.suppress(FileNotFoundError):
                        os.remove(destination)

                    file_utils.link_or_copy(source,
                                            destination,
                                            follow_symlinks=True)

                    # Ensure that the hook is executable in meta/hooks, this is a moot
                    # point considering the prior link_or_copy call, but is technically
                    # correct and allows for this operation to take place only once.
                    if origin[0] == self.meta_dir and origin[1] == "hooks":
                        _prepare_hook(destination)

        self._record_manifest_and_source_snapcraft_yaml()
示例#29
0
    def build(self):
        super().build()

        if self._using_gradlew():
            gradle_cmd = ["./gradlew"]
        else:
            self._gradle_tar.provision(self._gradle_dir, keep_zip=True)
            gradle_cmd = ["gradle"]
        self.run(
            gradle_cmd + self._get_proxy_options() +
            self.options.gradle_options +
            (["jar"] if self.options.gradle_build_jar else []),
            rootdir=self.builddir,
        )

        src = os.path.join(self.builddir, self.options.gradle_output_dir)
        basedir = "java"
        if self.options.gradle_build_jar:
            jarfiles = glob(os.path.join(src, "*.jar"))
            warfiles = glob(os.path.join(src, "*.war"))

            if len(jarfiles) > 0:
                basedir = "jar"
            elif len(warfiles) > 0:
                basedir = "war"
                jarfiles = warfiles
            else:
                raise RuntimeError(
                    "Could not find any built jar files for part")

        file_utils.link_or_copy_tree(
            src,
            os.path.join(self.installdir, basedir),
            copy_function=lambda src, dst: file_utils.link_or_copy(
                src, dst, self.installdir),
        )

        self._create_symlinks()
示例#30
0
 def test_copy_nested_file(self):
     file_utils.link_or_copy("foo/bar/baz/4", "foo2/bar/baz/4")
     self.assertTrue(os.path.isfile("foo2/bar/baz/4"))
示例#31
0
    def wheel(self,
              packages,
              *,
              setup_py_dir=None,
              constraints=None,
              requirements=None,
              process_dependency_links=False):
        """Build wheels of packages in the cache.

        The packages should have already been downloaded via `download()`.

        :param iterable packages: Packages in cache for which to build wheels.
        :param str setup_py_dir: Directory containing setup.py.
        :param iterable constraints: Collection of paths to constraints files.
        :param iterable requirements: Collection of paths to requirements
                                      files.
        :param boolean process_dependency_links: Enable the processing of
                                                 dependency links.

        :return: List of paths to each wheel that was built.
        :rtype: list
        """
        args = _process_common_args(
            process_dependency_links=process_dependency_links,
            packages=packages,
            constraints=constraints,
            requirements=requirements)

        cwd = None
        if setup_py_dir:
            args.append('.')
            cwd = setup_py_dir

        if not args:
            return  # No operation was requested

        wheels = []
        with tempfile.TemporaryDirectory() as temp_dir:

            # Using pip with a few special parameters:
            #
            # --no-index: Don't hit pypi, assume the packages are already
            #             downloaded (i.e. by using `self.download()`)
            # --find-links: Provide the directory into which the packages
            #               should have already been fetched
            # --wheel-dir: Build wheels into a temporary working area rather
            #              rather than cwd. We'll copy them over. FIXME: We can
            #              probably get away just building them in the package
            #              dir. Try that once this refactor has been validated.
            self._run([
                'wheel', '--no-index', '--find-links',
                self._python_package_dir, '--wheel-dir', temp_dir
            ] + args,
                      cwd=cwd)
            wheels = os.listdir(temp_dir)
            for wheel in wheels:
                file_utils.link_or_copy(
                    os.path.join(temp_dir, wheel),
                    os.path.join(self._python_package_dir, wheel))

        return [
            os.path.join(self._python_package_dir, wheel) for wheel in wheels
        ]
示例#32
0
 def test_copy_nested_file(self):
     file_utils.link_or_copy('foo/bar/baz/4', 'foo2/bar/baz/4')
     self.assertTrue(os.path.isfile('foo2/bar/baz/4'))
示例#33
0
 def test_copy_nested_file(self):
     file_utils.link_or_copy('foo/bar/baz/4', 'foo2/bar/baz/4')
     self.assertTrue(os.path.isfile('foo2/bar/baz/4'))
示例#34
0
def handle_glibc_mismatch(*,
                          elf_files: FrozenSet[elf.ElfFile],
                          root_path: str,
                          core_base_path: str,
                          snap_base_path: str,
                          preferred_patchelf_path=None) -> None:
    """Copy over libc6 libraries from the host and patch necessary elf files.

    If no newer glibc version is detected in elf_files, this function returns.

    :param snapcraft.internal.elf.ElfFile elf_files:
        set of candidate elf files to patch if a newer libc6 is required.
    :param str root_path: the root path of a snap tree.
    :param str core_base_path: the path to the base snap.
    :param str snap_base_path: absolute path to the snap once installed to
                               setup proper rpaths.
    :param str preferred_patchelf_path: patch the necessary elf_files with
                                        this patchelf.
    """
    formatted_list = list()  # type: List[str]
    patch_elf_files = list()  # type: List[elf.ElfFile]
    for elf_file in elf_files:
        required_glibc = elf_file.get_required_glibc()
        if not required_glibc:
            continue

        # We need to verify now that the GLIBC version would be compatible
        # with that of the base.
        # TODO the linker version depends on the chosen base, but that
        # base may not be installed so we cannot depend on
        # get_core_dynamic_linker to resolve the final path for which
        # we resort to our only working base 16, ld-2.23.so.
        if not elf_file.is_linker_compatible(linker='ld-2.23.so'):
            formatted_list.append('- {} -> GLIBC {}'.format(
                elf_file.path, required_glibc))
            patch_elf_files.append(elf_file)

    if not patch_elf_files:
        return

    logger.warning('The primed files will not work with the current '
                   'base given the GLIBC mismatch of the primed '
                   'files and the linker version (2.23) used in the '
                   'base. These are the GLIBC versions required by '
                   'the primed files that do not match and will be '
                   'patched:\n {}\n'
                   'To work around this, the newer libc will be '
                   'migrated into the snap, and these files will be '
                   'patched to use it.'.format('\n'.join(formatted_list)))
    # We assume the current system will satisfy the GLIBC requirement,
    # get the current libc6 libraries (which includes the linker)
    libc6_libraries = repo.Repo.get_package_libraries('libc6')
    libc6_path = os.path.join('snap', 'libc6')

    # Before doing anything else, verify there's a dynamic linker we can use.
    dynamic_linker_path = os.path.join(snap_base_path, libc6_path,
                                       _get_dynamic_linker(libc6_libraries))

    dest_dir = os.path.join(root_path, libc6_path)
    os.makedirs(dest_dir, exist_ok=True)

    for src in libc6_libraries:
        dst = os.path.join(dest_dir, os.path.basename(src))
        # follow_symlinks is set to True for elf crawling to work.
        file_utils.link_or_copy(src, dst, follow_symlinks=True)

    elf_patcher = elf.Patcher(dynamic_linker=dynamic_linker_path,
                              root_path=root_path,
                              preferred_patchelf_path=preferred_patchelf_path)
    for elf_file in patch_elf_files:
        # Search for dependencies again now that the new libc6 is
        # migrated.
        elf_file.load_dependencies(root_path=root_path,
                                   core_base_path=core_base_path)
        elf_patcher.patch(elf_file=elf_file)
示例#35
0
 def test_copy_nested_file(self):
     file_utils.link_or_copy("foo/bar/baz/4", "foo2/bar/baz/4")
     self.assertTrue(os.path.isfile("foo2/bar/baz/4"))