示例#1
0
 def _build(self, component, manifest):
     """
     Worker method for building a single component.
     """
     
     # Store the major / minor / release values
     major = manifest['major']
     minor = manifest['minor']
     release = manifest['release']
     
     print('Preparing to package component: %s' % component)
     print('Generating new release: %s.%s-%s -> %s.%s-%s' % (major, minor, release, major, minor, (release + 1)))
 
     # Update the manifest release value
     manifest['release'] = release + 1
     
     # Construct the package build root
     build_root = 'tmp/%s_%s.%s-%s' % (component, major, minor, manifest['release'])
     self._build_pkg_root(build_root, manifest['source'])
 
     # Generate the control file
     self._create_control_file(component, build_root, manifest)
 
     # Copy any extra scripts
     self._copy_scripts(component, build_root)
 
     # Build the package
     build_package(build_root, copy_files=False, repository='output')
 
     print('Successfully built component "%s" package: %s_%s.%s-%s.deb' % (component, component, major, minor, manifest['release']))
 
     # Update the manifest
     print('Updating release in manifest')
     with open('manifest/%s' % component, 'w') as handle:
         json.dump(manifest, handle)
示例#2
0
 def build(self):
     """
     Ref: https://linuxconfig.org/easy-way-to-create-a-debian-package-and-local-package-repository
     """
     configdir = join(self.config.config_dir(), self.pkgtype)
     makedirs(configdir + '/DEBIAN', exist_ok=True)
     self.control(configdir)
     self.layout(configdir)
     return build_package(configdir)
示例#3
0
 def build(self):
     """
     Ref: https://linuxconfig.org/easy-way-to-create-a-debian-package-and-local-package-repository
     """
     configdir = self.config.config_dir()
     makedirs(configdir + '/DEBIAN', exist_ok=True)
     with open(configdir + '/DEBIAN/control', 'w') as f:
         content = [
             'Package: %s\n' % self.config.name,
             'Version: %s\n' % self.config.version, 'Section: Custom\n',
             'Priority: optional\n', 'Architecture: all\n',
             'Essential: no\n',
             'Maintainer: %s\n' % self.config.maintainers,
             'Description: %s\n' % self.config.description
         ]
         f.writelines(content)
     return build_package(configdir)
示例#4
0
 def _build_deb(self, temp_dir, outputdir, *args, **kwargs):
     os.makedirs(outputdir, exist_ok=True)
     build_package(temp_dir, outputdir)
示例#5
0
    def convert(self):
        """
        Convert current package from Python package to Debian package.

        :returns: The pathname of the generated ``*.deb`` archive.
        """
        with TemporaryDirectory(prefix='py2deb-build-') as build_directory:

            # Prepare the absolute pathname of the Python interpreter on the
            # target system. This pathname will be embedded in the first line
            # of executable scripts (including the post-installation and
            # pre-removal scripts).
            python_executable = '/usr/bin/%s' % python_version()

            # Unpack the binary distribution archive provided by pip-accel inside our build directory.
            build_install_prefix = os.path.join(
                build_directory, self.converter.install_prefix.lstrip('/'))
            self.converter.pip_accel.bdists.install_binary_dist(
                members=self.transform_binary_dist(python_executable),
                prefix=build_install_prefix,
                python=python_executable,
                virtualenv_compatible=False,
            )

            # Determine the directory (at build time) where the *.py files for
            # Python modules are located (the site-packages equivalent).
            if self.has_custom_install_prefix:
                build_modules_directory = os.path.join(build_install_prefix,
                                                       'lib')
            else:
                # The /py*/ pattern below is intended to match both /pythonX.Y/ and /pypyX.Y/.
                dist_packages_directories = glob.glob(
                    os.path.join(build_install_prefix,
                                 'lib/py*/dist-packages'))
                if len(dist_packages_directories) != 1:
                    msg = "Expected to find a single 'dist-packages' directory inside converted package!"
                    raise Exception(msg)
                build_modules_directory = dist_packages_directories[0]

            # Determine the directory (at installation time) where the *.py
            # files for Python modules are located.
            install_modules_directory = os.path.join(
                '/', os.path.relpath(build_modules_directory, build_directory))

            # Execute a user defined command inside the directory where the Python modules are installed.
            command = self.converter.scripts.get(self.python_name.lower())
            if command:
                execute(command,
                        directory=build_modules_directory,
                        logger=logger)

            # Determine the package's dependencies, starting with the currently
            # running version of Python and the Python requirements converted
            # to Debian packages.
            dependencies = [python_version()] + self.debian_dependencies

            # Check if the converted package contains any compiled *.so files.
            object_files = find_object_files(build_directory)
            if object_files:
                # Strip debugging symbols from the object files.
                strip_object_files(object_files)
                # Determine system dependencies by analyzing the linkage of the
                # *.so file(s) found in the converted package.
                dependencies += find_system_dependencies(object_files)

            # Make up some control file fields ... :-)
            architecture = self.determine_package_architecture(object_files)
            control_fields = unparse_control_fields(
                dict(package=self.debian_name,
                     version=self.debian_version,
                     maintainer=self.debian_maintainer,
                     description=self.debian_description,
                     architecture=architecture,
                     depends=dependencies,
                     priority='optional',
                     section='python'))

            # Automatically add the Mercurial global revision id when available.
            if self.vcs_revision:
                control_fields['Vcs-Hg'] = self.vcs_revision

            # Apply user defined control field overrides from `stdeb.cfg'.
            control_fields = self.load_control_field_overrides(control_fields)

            # Create the DEBIAN directory.
            debian_directory = os.path.join(build_directory, 'DEBIAN')
            os.mkdir(debian_directory)

            # Generate the DEBIAN/control file.
            control_file = os.path.join(debian_directory, 'control')
            logger.debug("Saving control file fields to %s: %s", control_file,
                         control_fields)
            with open(control_file, 'wb') as handle:
                control_fields.dump(handle)

            # Lintian is a useful tool to find mistakes in Debian binary
            # packages however Lintian checks from the perspective of a package
            # included in the official Debian repositories. Because py2deb
            # doesn't and probably never will generate such packages some
            # messages emitted by Lintian are useless (they merely point out
            # how the internals of py2deb work). Because of this we silence
            # `known to be irrelevant' messages from Lintian using overrides.
            if self.converter.lintian_ignore:
                overrides_directory = os.path.join(
                    build_directory,
                    'usr',
                    'share',
                    'lintian',
                    'overrides',
                )
                overrides_file = os.path.join(overrides_directory,
                                              self.debian_name)
                os.makedirs(overrides_directory)
                with open(overrides_file, 'w') as handle:
                    for tag in self.converter.lintian_ignore:
                        handle.write('%s: %s\n' % (self.debian_name, tag))

            # Find the alternatives relevant to the package we're building.
            alternatives = set(
                (link, path) for link, path in self.converter.alternatives
                if os.path.isfile(
                    os.path.join(build_directory, path.lstrip('/'))))

            # Generate post-installation and pre-removal maintainer scripts.
            self.generate_maintainer_script(
                filename=os.path.join(debian_directory, 'postinst'),
                python_executable=python_executable,
                function='post_installation_hook',
                package_name=self.debian_name,
                alternatives=alternatives,
                modules_directory=install_modules_directory,
                namespaces=self.namespaces)
            self.generate_maintainer_script(
                filename=os.path.join(debian_directory, 'prerm'),
                python_executable=python_executable,
                function='pre_removal_hook',
                package_name=self.debian_name,
                alternatives=alternatives,
                modules_directory=install_modules_directory,
                namespaces=self.namespaces)

            # Enable a user defined Python callback to manipulate the resulting
            # binary package before it's turned into a *.deb archive (e.g.
            # manipulate the contents or change the package metadata).
            if self.converter.python_callback:
                logger.debug("Invoking user defined Python callback ..")
                self.converter.python_callback(self.converter, self,
                                               build_directory)
                logger.debug("User defined Python callback finished!")

            return build_package(directory=build_directory,
                                 check_package=self.converter.lintian_enabled,
                                 copy_files=False)
示例#6
0
    def convert(self):
        """
        Convert current package from Python package to Debian package.

        :returns: The pathname of the generated ``*.deb`` archive.
        """
        with TemporaryDirectory(prefix='py2deb-build-') as build_directory:

            # Prepare the absolute pathname of the Python interpreter on the
            # target system. This pathname will be embedded in the first line
            # of executable scripts (including the post-installation and
            # pre-removal scripts).
            python_executable = '/usr/bin/%s' % python_version()

            # Unpack the binary distribution archive provided by pip-accel inside our build directory.
            build_install_prefix = os.path.join(build_directory, self.converter.install_prefix.lstrip('/'))
            self.converter.pip_accel.bdists.install_binary_dist(
                members=self.transform_binary_dist(),
                prefix=build_install_prefix,
                python=python_executable,
                virtualenv_compatible=False,
            )

            # Determine the directory (at build time) where the *.py files for
            # Python modules are located (the site-packages equivalent).
            if self.has_custom_install_prefix:
                build_modules_directory = os.path.join(build_install_prefix, 'lib')
            else:
                dist_packages_directories = glob.glob(os.path.join(build_install_prefix, 'lib/python*/dist-packages'))
                if len(dist_packages_directories) != 1:
                    msg = "Expected to find a single 'dist-packages' directory inside converted package!"
                    raise Exception(msg)
                build_modules_directory = dist_packages_directories[0]

            # Determine the directory (at installation time) where the *.py
            # files for Python modules are located.
            install_modules_directory = os.path.join('/', os.path.relpath(build_modules_directory, build_directory))

            # Execute a user defined command inside the directory where the Python modules are installed.
            command = self.converter.scripts.get(self.python_name.lower())
            if command:
                execute(command, directory=build_modules_directory, logger=logger)

            # Determine the package's dependencies, starting with the currently
            # running version of Python and the Python requirements converted
            # to Debian packages.
            dependencies = [python_version()] + self.debian_dependencies

            # Check if the converted package contains any compiled *.so files.
            shared_object_files = self.find_shared_object_files(build_directory)
            if shared_object_files:
                # Determine system dependencies by analyzing the linkage of the
                # *.so file(s) found in the converted package.
                dependencies += self.find_system_dependencies(shared_object_files)

            # Make up some control file fields ... :-)
            architecture = self.determine_package_architecture(shared_object_files)
            control_fields = unparse_control_fields(dict(package=self.debian_name,
                                                         version=self.debian_version,
                                                         maintainer=self.debian_maintainer,
                                                         description=self.debian_description,
                                                         architecture=architecture,
                                                         depends=dependencies,
                                                         priority='optional',
                                                         section='python'))

            # Automatically add the Mercurial global revision id when available.
            if self.vcs_revision:
                control_fields['Vcs-Hg'] = self.vcs_revision

            # Apply user defined control field overrides from `stdeb.cfg'.
            control_fields = self.load_control_field_overrides(control_fields)

            # Create the DEBIAN directory.
            debian_directory = os.path.join(build_directory, 'DEBIAN')
            os.mkdir(debian_directory)

            # Generate the DEBIAN/control file.
            control_file = os.path.join(debian_directory, 'control')
            logger.debug("Saving control file fields to %s: %s", control_file, control_fields)
            with open(control_file, 'wb') as handle:
                control_fields.dump(handle)

            # Lintian is a useful tool to find mistakes in Debian binary
            # packages however Lintian checks from the perspective of a package
            # included in the official Debian repositories. Because py2deb
            # doesn't and probably never will generate such packages some
            # messages emitted by Lintian are useless (they merely point out
            # how the internals of py2deb work). Because of this we silence
            # `known to be irrelevant' messages from Lintian using overrides.
            overrides_directory = os.path.join(build_directory, 'usr', 'share',
                                               'lintian', 'overrides')
            overrides_file = os.path.join(overrides_directory, self.debian_name)
            os.makedirs(overrides_directory)
            with open(overrides_file, 'w') as handle:
                for tag in ['debian-changelog-file-missing',
                            'embedded-javascript-library',
                            'extra-license-file',
                            'unknown-control-interpreter',
                            'vcs-field-uses-unknown-uri-format']:
                    handle.write('%s: %s\n' % (self.debian_name, tag))

            # Find the alternatives relevant to the package we're building.
            alternatives = set((link, path) for link, path in self.converter.alternatives
                               if os.path.isfile(os.path.join(build_directory, path.lstrip('/'))))

            # Generate post-installation and pre-removal maintainer scripts.
            self.generate_maintainer_script(filename=os.path.join(debian_directory, 'postinst'),
                                            python_executable=python_executable,
                                            function='post_installation_hook',
                                            package_name=self.debian_name,
                                            alternatives=alternatives,
                                            modules_directory=install_modules_directory,
                                            namespaces=self.namespaces)
            self.generate_maintainer_script(filename=os.path.join(debian_directory, 'prerm'),
                                            python_executable=python_executable,
                                            function='pre_removal_hook',
                                            package_name=self.debian_name,
                                            alternatives=alternatives,
                                            modules_directory=install_modules_directory,
                                            namespaces=self.namespaces)

            # Enable a user defined Python callback to manipulate the resulting
            # binary package before it's turned into a *.deb archive (e.g.
            # manipulate the contents or change the package metadata).
            if self.converter.python_callback:
                logger.debug("Invoking user defined Python callback ..")
                self.converter.python_callback(self.converter, self, build_directory)
                logger.debug("User defined Python callback finished!")

            return build_package(directory=build_directory,
                                 check_package=self.converter.lintian_enabled,
                                 copy_files=False)