Esempio n. 1
0
    def verify(self) -> bool:
        """
        This method runs several checks to ensure bzr commands can proceed. It is automatically
        executed at package initialisation. This includes:

        * checks if all expected keys are present in the configuration file
        * checks if the `bzr` binary is installed and can be found on the system

        Returns:
            bool:   verification success
        """

        logger = KtrLogger(LOG_PREFIX)

        success = True

        # check if the configuration file is valid
        expected_keys = ["branch", "keep", "keep_repo", "orig", "revno"]

        for key in expected_keys:
            if key not in self.spkg.conf["bzr"]:
                logger.err("The [bzr] section in the package's .conf file doesn't set the '" +
                           key +
                           "' key.")
                success = False

        # check if bzr is installed
        try:
            subprocess.check_output(["which", "bzr"]).decode().rstrip("\n")
        except subprocess.CalledProcessError:
            logger.log("Install bzr to use the specified source.")
            success = False

        return success
Esempio n. 2
0
    def get(self) -> bool:
        """
        This method attempts to copy the specified source from the location specified in the package
        configuration file to the determined destination. If the destination file already exists,
        nothing will be done.

        Returns:
            bool:   *True* if source was copied successfully, *False* if not
        """

        logger = KtrLogger(LOG_PREFIX)

        # check if $KTR_BASE_DIR/sources/$PACKAGE exists and create if not
        if not os.access(self.sdir, os.W_OK):
            os.makedirs(self.sdir)

        # if source seems to already exist, return False
        if os.access(self.dest, os.R_OK):
            logger.log("Sources already present.", 1)
            return False

        # copy file from origin to destination
        shutil.copy2(self.get_orig(), self.dest)

        return True
Esempio n. 3
0
    def verify(self) -> bool:
        """
        This method runs several checks to ensure copr uploads can proceed. It is automatically
        executed at package initialisation. This includes:

        * checks if all expected keys are present in the configuration file
        * checks if the `copr-cli` binary is installed and can be found on the system

        Returns:
            bool:   verification success
        """

        logger = KtrLogger(LOG_PREFIX)

        success = True

        # check if the configuration file is valid
        expected_keys = ["active", "dists", "keep", "repo", "wait"]

        for key in expected_keys:
            if key not in self.upkg.conf["copr"]:
                logger.err("The [copr] section in the package's .conf file doesn't set the '" +
                           key +
                           "' key.")
                success = False

        # check if copr is installed
        try:
            subprocess.check_output(["which", "copr-cli"])
        except subprocess.CalledProcessError:
            logger.log("Install copr-cli to use the specified builder.")
            success = False

        return success
Esempio n. 4
0
def ktr_mkdirp(path: str) -> bool:
    """
    This function checks for directory existence and the ability to write to it. If the directory
    does not exist, it will be created.

    Arguments:
        str path:   path of directory to check and create

    Returns:
        bool:       success (or not)
    """

    logger = KtrLogger(LOG_PREFIX)

    if os.path.exists(path):
        if os.access(path, os.W_OK):
            return True
        else:
            logger.err(path + " can't be written to.")
            return False
    else:
        logger.log(path + " directory doesn't exist and will be created.")
        try:
            os.makedirs(path)
        except OSError:
            logger.err(path + " directory could not be created.")
            return False
        return True
Esempio n. 5
0
    def update(self) -> bool:
        """
        This method executes a git repository update as specified in the package configuration file.
        If a specific commit has been set in the config file, this method will not attempt to
        execute an update.

        Returns:
            bool: *True* if update available and successful, *False* if not
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        # if specific commit is requested, do not pull updates (obviously)
        if self.get_commit() == "HEAD":
            return False

        # check for connectivity to server
        if not is_connected(self.get_orig()):
            logger.log("No connection to remote host detected. Cancelling source update.", 2)
            return False

        # construct git command
        cmd = ["git", "pull", "--rebase"]

        # add --verbose or --quiet depending on settings
        if (ktr.verby == 2) and not ktr.debug:
            cmd.append("--quiet")
        if (ktr.verby == 0) or ktr.debug:
            cmd.append("--verbose")

        # check if source directory exists before going there
        if not os.access(self.dest, os.W_OK):
            logger.err("Sources need to be get before an update can be run.")
            return False

        # get old commit ID
        rev_old = self.commit()

        # change to git repository directory
        prev_dir = os.getcwd()
        os.chdir(self.dest)

        # get updates
        logger.log_command(cmd, 1)
        subprocess.call(cmd)

        # go back to previous dir
        os.chdir(prev_dir)

        # get new commit ID
        rev_new = self.commit()
        self.date()

        # return True if update found, False if not
        return rev_new != rev_old
Esempio n. 6
0
    def upload(self) -> bool:
        """
        This method executes the upload of the newest SRPM package found in the package directory.
        The invocation of `copr-cli` also includes the chroot settings set in the package
        configuration file.

        Returns:
            bool:       returns *False* if anything goes wrong, *True* otherwise
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        package_dir = os.path.join(ktr.conf.get_packdir(), self.upkg.get_conf_name())

        # get all srpms in the package directory
        srpms = glob.glob(os.path.join(package_dir, self.upkg.get_name() + "*.src.rpm"))

        if not srpms:
            logger.log("No source packages were found. Construct them first.")
            return False

        # figure out which srpm to build
        srpms.sort(reverse=True)
        srpm = srpms[0]

        # construct copr-cli command
        cmd = ["copr-cli", "build", self.get_repo()]

        # append chroots (dists)
        for dist in self.get_dists():
            cmd.append("--chroot")
            cmd.append(dist)

        # append --nowait if wait=False
        if not self.get_wait():
            cmd.append("--nowait")

        # append package
        cmd.append(srpm)

        # check for connectivity to server
        if not is_connected(self.remote):
            logger.log("No connection to remote host detected. Cancelling upload.", 2)
            return False

        logger.log_command(cmd, 1)
        subprocess.call(cmd)

        # TODO: error handling

        # remove source package if keep=False is specified
        if not self.get_keep():
            os.remove(srpm)

        return True
Esempio n. 7
0
    def verify(self) -> bool:
        """
        This method runs several checks to ensure mock builds can proceed. It is automatically
        executed at package initialisation. This includes:

        * checks if all expected keys are present in the configuration file
        * checks if the `mock` binary is installed and can be found on the system
        * checks if the current user is allowed to run builds with mock
        * checks if the current user is root (building as root is strongly discouraged)

        Returns:
            bool:   verification success
        """

        logger = KtrLogger(LOG_PREFIX)

        success = True

        # check if the configuration file is valid
        expected_keys = ["active", "dists", "export", "keep"]

        for key in expected_keys:
            if key not in self.bpkg.conf["mock"]:
                logger.err("The [mock] section in the package's .conf file doesn't set the '" +
                           key +
                           "' key.")
                success = False

        # check if mock is installed
        try:
            subprocess.check_output(["which", "mock"]).decode().rstrip("\n")
        except subprocess.CalledProcessError:
            logger.log("Install mock to use the specified builder.")
            success = False

        # check if the user is in the "mock" group or is root
        mock_group = grp.getgrnam("mock")
        mock_user = os.getenv("USER")

        if mock_user not in mock_group.gr_mem:
            logger.err("The current user is not allowed to use mock.")
            logger.err("Add yourself to the 'mock' group, log out and back in.")
            success = False

        if mock_user == "root":
            logger.err("Don't attempt to run mock as root.")
            success = False

        return success
Esempio n. 8
0
    def verify(self) -> bool:
        """
        This method runs several checks to ensure srpm builds can proceed. It is automatically
        executed at package initialisation. This includes:

        * checks if all expected keys are present in the configuration file
        * checks if the `mock` binary is installed and can be found on the system
        * checks if the current user is allowed to run builds with mock
        * checks if the current user is root (building as root is strongly discouraged)
        * checks if the .spec file is present at the expected location

        Returns:
            bool:   verification success
        """

        logger = KtrLogger(LOG_PREFIX)

        success = True

        # check if the configuration file is valid
        expected_keys = []

        for key in expected_keys:
            if key not in self.cpkg.conf["srpm"]:
                logger.err("The [srpm] section in the package's .conf file doesn't set the '" +
                           key +
                           "' key.")
                success = False

        # check for .spec file presence
        if not os.path.exists(self.path):
            logger.err("Spec file has not been found at the expected location:")
            logger.err(self.path)
            success = False

        # check if rpmbuild and rpmdev-bumpspec are installed
        try:
            subprocess.check_output(["which", "rpmbuild"]).decode().rstrip("\n")
        except subprocess.CalledProcessError:
            logger.log("Install rpm-build to use the srpm constructor.")
            success = False

        try:
            subprocess.check_output(["which", "rpmdev-bumpspec"]).decode().rstrip("\n")
        except subprocess.CalledProcessError:
            logger.log("Install rpmdevtools to use the srpm constructor.")
            success = False

        return success
Esempio n. 9
0
    def execute(self) -> bool:
        logger = KtrLogger(LOG_PREFIX)

        success = self.build()

        if not success:
            logger.log("Binary package building unsuccessful, aborting action.")
            return False

        success = self.export()

        if not success:
            logger.log("Binary package exporting unsuccessful, aborting action.")
            return False

        return success
Esempio n. 10
0
    def export(self):
        """
        This method copies the assembled source packages from `rpmbuild/SRPMS` to the directory for
        built packages as specified in the kentauros configuration. If multiple SRPM packages are
        found, they all are copied.
        """

        logger = KtrLogger(LOG_PREFIX)

        srpms = glob.glob(os.path.join(self.srpmdir, "*.src.rpm"))

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

        for srpm in srpms:
            shutil.copy2(srpm, self.pdir)
            logger.log("File copied: " + srpm, 0)
Esempio n. 11
0
    def get(self) -> bool:
        """
        This method executes the download of the file specified by the URL to the package source
        directory.

        Returns:
            bool:  *True* if successful, *False* if not or source already exists
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        # check if $KTR_BASE_DIR/sources/$PACKAGE exists and create if not
        if not os.access(self.sdir, os.W_OK):
            os.makedirs(self.sdir)

        # if source seems to already exist, return False
        if os.access(self.dest, os.R_OK):
            logger.log("Sources already downloaded.", 1)
            return False

        # check for connectivity to server
        if not is_connected(self.get_orig()):
            logger.log("No connection to remote host detected. Cancelling source download.", 2)
            return False

        # construct wget commands
        cmd = ["wget"]

        # add --verbose or --quiet depending on settings
        if (ktr.verby == 2) and not ktr.debug:
            cmd.append("--quiet")
        if (ktr.verby == 0) or ktr.debug:
            cmd.append("--verbose")

        # set origin and destination
        cmd.append(self.get_orig())
        cmd.append("-O")
        cmd.append(self.dest)

        # wget source from origin to destination
        logger.log_command(cmd, 1)
        subprocess.call(cmd)

        return True
Esempio n. 12
0
    def verify(self) -> bool:
        """
        This method runs several checks to ensure git commands can proceed. It is automatically
        executed at package initialisation. This includes:

        * checks if all expected keys are present in the configuration file
        * checks that the configuration file is consistent (i.e. shallow clone and commit checkout
          are not compatible)
        * checks if the `git` binary is installed and can be found on the system

        Returns:
            bool:   verification success
        """

        logger = KtrLogger(LOG_PREFIX)

        success = True

        # check if the configuration file is valid
        expected_keys = ["branch", "commit", "keep", "keep_repo", "orig", "shallow"]

        for key in expected_keys:
            if key not in self.spkg.conf["git"]:
                logger.err("The [git] section in the package's .conf file doesn't set the '" +
                           key +
                           "' key.")
                success = False

        # shallow clones and checking out a specific commit is not supported
        if (self.get_commit() != "HEAD") and self.get_shallow():
            logger.err("Shallow clones are not compatible with specifying a specific commit.")
            success = False

        # check if git is installed
        try:
            subprocess.check_output(["which", "git"]).decode().rstrip("\n")
        except subprocess.CalledProcessError:
            logger.log("Install git to use the specified source.")
            success = False

        return success
Esempio n. 13
0
    def execute(self) -> bool:
        """
        This method executes the :py:meth:`Source.prepare()` method to execute source preparation.
        This includes downloading or copying to destination, updating if necessary, and exporting to
        tarball if necessary.

        Returns:
            bool:           *True* when successful, *False* if sub-action fails
        """

        logger = KtrLogger(LOGPREFIX)

        source = self.kpkg.get_module("source")

        if source is None:
            logger.log("This package doesn't define a source module. Aborting.")
            return True

        success = source.execute()

        self.update_status()

        if success:
            logger.log(self.kpkg.get_conf_name() + ": Success!")
        else:
            logger.log(self.kpkg.get_conf_name() + ": Not successful.")

        return success
Esempio n. 14
0
    def execute(self) -> bool:
        """
        This method executes the :py:meth:`Uploader.upload()` method to execute the source upload,
        if possible - this only has effect for packages with a valid uploader specified in the
        package configuration file.

        Returns:
            bool:           always *True*, future error checking still missing
        """

        logger = KtrLogger(LOGPREFIX)

        uploader = self.kpkg.get_module("uploader")

        if uploader is None:
            logger.log("This package doesn't define an uploader module. Aborting.")
            return True

        success = uploader.execute()

        self.update_status()

        if success:
            logger.log(self.kpkg.get_conf_name() + ": Success!")
        else:
            logger.log(self.kpkg.get_conf_name() + ": Not successful.")

        return success
Esempio n. 15
0
    def execute(self) -> bool:
        """
        This method cleans up the sources of to the package specified at initialisation. It executes
        the :py:meth:`Source.clean()` method of the :py:class:`Source` instance in the specified
        package.

        Returns:
            bool:           always ``True`` at the moment
        """

        logger = KtrLogger(LOGPREFIX)

        success = True

        for module in self.kpkg.get_modules():
            cleanup = module.clean()

            if not cleanup:
                logger.log("Module '" + str(module) + "' did not clean up successfully.")

            success = success and cleanup

        if success:
            logger.log(self.kpkg.get_conf_name() + ": Success!")
        else:
            logger.log(self.kpkg.get_conf_name() + ": Not successful.")

        return success
Esempio n. 16
0
    def init(self):
        """
        This method creates a temporary directory (which is then set to `$HOME` in the
        :py:meth:`SrpmConstructor.build()` method) and other necessary sub-directories (here:
        `SOURCES`, `SRPMS`, `SPECS`).
        """

        logger = KtrLogger(LOG_PREFIX)

        # make sure to finally call self.clean()!
        self.tempdir = tempfile.mkdtemp()

        logger.log("Temporary directory " + self.tempdir + " created.", 1)

        self.rpmbdir = os.path.join(self.tempdir, "rpmbuild")
        self.specdir = os.path.join(self.tempdir, "rpmbuild", "SPECS")
        self.srpmdir = os.path.join(self.tempdir, "rpmbuild", "SRPMS")
        self.srcsdir = os.path.join(self.tempdir, "rpmbuild", "SOURCES")

        # create $TEMPDIR/rpmbuild
        if not os.path.exists(self.rpmbdir):
            os.mkdir(self.rpmbdir)

        logger.log("Temporary rpmbuild directory created: " + self.tempdir, 1)

        # create $TEMPDIR/rpmbuild/{SPECS,SRPMS,SOURCES}
        for directory in [self.specdir, self.srpmdir, self.srcsdir]:
            if not os.path.exists(directory):
                os.mkdir(directory)

        logger.log("Temporary 'SOURCES', 'SPECS', 'SRPMS' directories created.", 1)
Esempio n. 17
0
def get_mock_cmd() -> str:
    """
    This function tries to determine the correct mock binary path. If something is messing with the
    `$PATH` environment variable, it will try to account for that. If mock is not installed (or
    cannot be found within `$PATH`, this function will raise an Exception.

    Raises:
        subprocess.CalledProcessError

    Returns:
        str:    path to the mock binary
    """
    logger = KtrLogger(LOG_PREFIX)

    mock_cmd = subprocess.check_output(["which", "mock"]).decode().rstrip("\n")

    # check if the right binary is used or if something is messing up $PATH
    if mock_cmd == "/usr/sbin/mock":
        logger.log("Something is messing with your $PATH variable.", 2)
        mock_cmd = "/usr/bin/mock"

    return mock_cmd
Esempio n. 18
0
def print_parameters():
    """
    This function prints the general execution parameters.
    """

    ktr = Kentauros()
    logger = KtrLogger(LOG_PREFIX)

    print_flush()

    logger.log("Debugging:                          " + str(ktr.debug), 0)
    logger.log("Logger Verbosity:                   " + str(ktr.verby) + "/2", 1)

    print_flush()

    logger.dbg("Base directory:                     " + ktr.conf.basedir)
    logger.dbg("Package configuration directory:    " + ktr.conf.get_confdir())
    logger.dbg("Package sources directory:          " + ktr.conf.get_datadir())
    logger.dbg("Binary package directory:           " + ktr.conf.get_expodir())
    logger.dbg("Source package directory:           " + ktr.conf.get_packdir())
    logger.dbg("Package specification directory:    " + ktr.conf.get_specdir())

    print_flush()
Esempio n. 19
0
    def clean(self) -> bool:
        """
        This method cleans up all of a package's sources - excluding other files in the packages's
        source directory, which may include patches or other, additional files - they are preserved.

        Returns:
            bool:   *True* if successful
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        if not os.path.exists(self.sdir):
            logger.log("Nothing here to be cleaned.", 0)
            return True

        # try to be careful with "rm -r"
        assert os.path.isabs(self.dest)
        assert ktr.conf.get_datadir() in self.dest

        # remove source destination first

        # if destination is a file (tarball):
        if os.path.isfile(self.dest):
            os.remove(self.dest)

        # if destination is a directory (VCS repo):
        elif os.path.isdir(self.dest):
            shutil.rmtree(self.dest)

        # if source directory is empty now (no patches, additional files, etc. left):
        # remove whole directory
        if not os.listdir(self.sdir):
            os.rmdir(self.sdir)

        return True
Esempio n. 20
0
    def build(self):
        """
        This method starts the mock build (and waits for already running builds with the same
        chroot to finish before that).

        Returns:
            int:    return code of the subprocess call
        """

        logger = KtrLogger(LOG_PREFIX)

        dist_path = os.path.join("/var/lib/mock/", self.dist)
        lock_path = os.path.join(dist_path, "buildroot.lock")

        # wait 2 minutes for builds occupying the specified build chroot
        if os.path.isdir(dist_path):
            build_wait = True

            while build_wait:
                lock_file = open(lock_path, "a+")

                try:
                    fcntl.lockf(lock_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
                except IOError:
                    logger.log("The specified build chroot is busy, waiting.", 2)
                    time.sleep(120)
                else:
                    build_wait = False
                finally:
                    lock_file.close()

        cmd = self.get_command()
        logger.log_command(cmd)

        ret = subprocess.call(cmd)
        return ret
Esempio n. 21
0
    def execute(self) -> bool:
        logger = KtrLogger(LOGPREFIX)

        constructor = self.kpkg.get_module("constructor")

        if constructor is None:
            logger.log("This package doesn't define a constructor module. Aborting.")
            return True

        success = constructor.execute()

        self.update_status()

        if success:
            logger.log(self.kpkg.get_conf_name() + ": Success!")
        else:
            logger.log(self.kpkg.get_conf_name() + ": Not successful.")

        return success
Esempio n. 22
0
    def execute(self) -> bool:
        """
        This method runs the "chain reaction" corresponding to the package specified at
        initialisation, with the configuration from the package configuration file.

        Returns:
            bool:   ``True`` if chain went all the way through, ``False`` if not
        """

        ktr = Kentauros()
        logger = KtrLogger(LOGPREFIX)
        force = ktr.cli.get_force()

        success = True

        for module in self.kpkg.get_modules():
            succeeded = module.execute()

            if not succeeded:
                logger.err("Execution of module '" + str(module) + "' wasn't successful.")

                if force:
                    logger.log("Execution is forced to continue.")
                    success = success and succeeded
                    continue
                else:
                    success = False
                    break

        self.update_status()

        if success:
            logger.log(self.kpkg.get_conf_name() + ": Success!")
        else:
            logger.log(self.kpkg.get_conf_name() + ": Not successful.")

        return success
Esempio n. 23
0
    def export(self) -> bool:
        """
        This method executes the export from the package source repository to a tarball with pretty
        file name. It also respects the `git.keep=False` setting in the package configuration file -
        the git repository will be deleted from disk after the export if this flag is set.

        Returns:
            bool:   *True* if successful or already done, *False* at failure
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        def remove_not_keep():
            """
            This local function removes the git repository and is called after source export, if
            not keeping the repository around was specified in the configuration file.
            """

            if not self.get_keep():
                # try to be careful with "rm -r"
                assert os.path.isabs(self.dest)
                assert ktr.conf.get_datadir() in self.dest
                shutil.rmtree(self.dest)
                logger.log("git repository has been deleted after exporting to tarball.", 1)

        # construct git command to export HEAD or specified commit
        cmd = ["git", "archive", self.get_commit()]

        # check if git repo exists
        if not os.access(self.dest, os.R_OK):
            logger.err("Sources need to be get before they can be exported.")
            return False

        version = self.formatver()
        name_version = self.spkg.get_name() + "-" + version

        # add prefix
        cmd.append("--prefix=" + name_version + "/")

        file_name = os.path.join(self.sdir, name_version + ".tar.gz")

        cmd.append("--output")
        cmd.append(file_name)

        # check if file has already been exported
        if os.path.exists(file_name):
            logger.log("Tarball has already been exported.", 1)
            # remove git repo if keep is False
            remove_not_keep()
            return True

        # remember previous directory
        prev_dir = os.getcwd()

        # change to git repository directory
        os.chdir(self.dest)

        # export tar.gz to $KTR_DATA_DIR/$PACKAGE/*.tar.gz
        logger.log_command(cmd, 1)
        subprocess.call(cmd)

        # update saved rev and date
        self.commit()
        self.date()

        # remove git repo if keep is False
        remove_not_keep()

        os.chdir(prev_dir)
        return True
Esempio n. 24
0
    def prepare(self) -> bool:
        """
        This method prepares all files necessary for source package assembly.

        This includes

        - copying every file (not directories) from package source directory to `rpmbuild/SOURCES`,
        - removing the latest tarball from the package source directory if it should not be kept,
        - copying the package configuration file to `rpmbuild/SOURCES`
        - preparing the `package.spec` file in `rpmbuild/SPECS` from the file in the spec directory,
        - defining macros for git and bzr version string additions,
        - setting `Version:` and `Release:` tags according to configuration,
        - appending a changelog entry automatically for every different build,
        - copying back the modified spec file to preserve added changelog entries.

        Returns:
            bool:           returns `True` if the preparation was successful.
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        spec = RPMSpec(self.path, self.cpkg.get_module("source"))

        if not os.path.exists(self.rpmbdir):
            warnings.warn("Make sure to call Constructor.init() before .prepare()!", Warning)
            self.init()

        # copy sources to rpmbuild/SOURCES
        for entry in os.listdir(self.cpkg.get_module("source").sdir):
            entry_path = os.path.join(self.cpkg.get_module("source").sdir, entry)
            if os.path.isfile(entry_path):
                shutil.copy2(entry_path, self.srcsdir)
                logger.log("File copied to SOURCES: " + entry_path, 1)

        # remove tarballs if they should not be kept
        if not self.cpkg.get_module("source").get_keep():

            # if source is a tarball (or similar) from the beginning:
            if os.path.isfile(self.cpkg.get_module("source").dest):
                os.remove(self.cpkg.get_module("source").dest)

            # otherwise it is in kentauros' standard .tar.gz format:
            else:
                tarballs = glob.glob(os.path.join(self.cpkg.get_module("source").sdir,
                                                  self.cpkg.get_name()) + "*.tar.gz")
                # remove only the newest one to be safe
                tarballs.sort(reverse=True)
                if os.path.isfile(tarballs[0]):
                    assert self.cpkg.get_module("source").sdir in tarballs[0]
                    os.remove(tarballs[0])
                    logger.log("Tarball removed: " + tarballs[0], 1)

        # copy package.conf to rpmbuild/SOURCES
        shutil.copy2(self.cpkg.file, self.srcsdir)
        logger.log("Package configuration copied to SOURCES: " + self.cpkg.file, 1)

        # construct preamble and new version string
        old_version = self._get_last_version(spec)
        old_release = self._get_last_release(spec)
        new_version = self.cpkg.get_version()

        # TODO: check if release resetting / incrementing logic works now

        spec.set_version()
        spec.set_source()

        # if old version and new version are different, force release reset to 0
        rel_reset = (new_version != old_version)

        # start constructing release string from old release string
        if rel_reset:
            spec.do_release_reset()

        # write preamble to new spec file
        preamble = spec.build_preamble_string()

        # calculate absolute path of new spec file and copy it over
        new_spec_path = os.path.join(self.specdir, self.cpkg.get_name() + ".spec")
        spec.export_to_file(new_spec_path)

        # use "rpmdev-bumpspec" to increment release number and create changelog entries
        force = ktr.cli.get_force()

        logger.dbg("Old Version: " + old_version)
        logger.dbg("New Version: " + new_version)
        logger.dbg("Old Release: " + old_release)

        # if major version has changed, put it into the changelog
        if (old_version != new_version) or (old_release[0] == "0"):
            do_release_bump(new_spec_path,
                            "Update to version " + self.cpkg.get_version() + ".")
            new_rpm_spec = RPMSpec(new_spec_path, self.cpkg.get_module("source"))

        # else if nothing changed but "force" was set (packaging changes)
        # old_version =!= new_version, rel_reset !=!= True
        elif force:
            message = ktr.cli.get_message()
            if message is None:
                do_release_bump(new_spec_path, "Update for packaging changes.")
            else:
                do_release_bump(new_spec_path, message)

            new_rpm_spec = RPMSpec(new_spec_path, self.cpkg.get_module("source"))

        # else if version has not changed, but snapshot has been updated:
        # old_version =!= new_version
        elif rel_reset:
            new_rpm_spec = RPMSpec(new_spec_path, self.cpkg.get_module("source"))
            new_rpm_spec.do_release_reset()
            do_release_bump(new_spec_path, "Update to latest snapshot.")
            new_rpm_spec = RPMSpec(new_spec_path, self.cpkg.get_module("source"))

        else:
            logger.err("Something went wrong.")
            return False

        self.last_release = new_rpm_spec.get_release()
        self.last_version = new_rpm_spec.get_version()

        # copy new spec file back to ktr/specdir to preserve version tracking,
        # release number and changelog consistency (keep old version once as backup)
        # BUT: remove preamble again, it would break things otherwise

        new_rpm_spec.contents = new_rpm_spec.contents.replace(preamble, "")
        shutil.copy2(self.path, self.path + ".old")
        new_rpm_spec.export_to_file(self.path)

        return True
Esempio n. 25
0
    def build(self) -> bool:
        """
        This method constructs the :py:class:`MockBuilder` instances, which contain the commands
        for executing the builds, and executes them in turn. It also checks if the executing user is
        allowed to execute a mock build by checking if ``$USER`` is "root" or if the user is in the
        "mock" group.

        If no source packages are found in the specified directory (``PACKDIR``), the build
        terminates without executing mock. If SRPM packages are found, only the most recent
        (biggest version number, determined just by sorting!) is built, for all specified chroots.

        After the last mock invocation, a list of successful and unsuccessful builds is printed.

        Returns:
            bool:   ``True`` if all builds succeeded, ``False`` if not
        """

        if not self.get_active():
            return True

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        package_dir = os.path.join(ktr.conf.get_packdir(), self.bpkg.get_conf_name())

        # get all srpms in the package directory
        srpms = glob.glob(os.path.join(package_dir, self.bpkg.get_name() + "*.src.rpm"))

        if not srpms:
            logger.log("No source packages were found. Construct them first.", 2)
            return False

        # figure out which srpm to build
        srpms.sort(reverse=True)
        srpm = srpms[0]

        logger.log_list("Specified chroots", self.get_dists())

        # generate build queue
        build_queue = list()

        mock_cmd = get_mock_cmd()

        for dist in self.get_dists():
            build_queue.append(MockBuild(mock_cmd, srpm, dist))

        # run builds in queue
        builds_success = list()
        builds_failure = list()

        for build in build_queue:
            ret = build.build()
            if ret:
                builds_failure.append((build.path, build.dist))
            else:
                builds_success.append((build.path, build.dist))

        # remove source package if keep=False is specified
        if not self.get_keep():
            os.remove(srpm)

        if builds_success:
            logger.log_list("Build successes", builds_success)

        if builds_failure:
            logger.log_list("Build failures", builds_failure)

        return not builds_failure
Esempio n. 26
0
    def get(self) -> bool:
        """
        This method executes the git repository download to the package source directory. This
        respects the branch and commit set in the package configuration file.

        Returns:
            bool: *True* if successful, *False* if not or source pre-exists
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        # check if $KTR_BASE_DIR/sources/$PACKAGE exists and create if not
        if not os.access(self.sdir, os.W_OK):
            os.makedirs(self.sdir)

        # if source directory seems to already exist, return False
        if os.access(self.dest, os.R_OK):
            rev = self.commit()
            logger.log("Sources already downloaded. Latest commit id:", 2)
            logger.log(rev, 2)
            return False

        # check for connectivity to server
        if not is_connected(self.get_orig()):
            logger.log("No connection to remote host detected. Cancelling source checkout.", 2)
            return False

        # construct clone command
        cmd_clone = ["git", "clone"]

        # add --verbose or --quiet depending on settings
        if (ktr.verby == 2) and not ktr.debug:
            cmd_clone.append("--quiet")
        if (ktr.verby == 0) or ktr.debug:
            cmd_clone.append("--verbose")

        # set --depth==1 if shallow is specified
        if self.get_shallow():
            cmd_clone.append("--depth=1")

        # set branch if specified
        if self.get_branch():
            cmd_clone.append("--branch")
            cmd_clone.append(self.get_branch())

        # set origin and destination
        cmd_clone.append(self.get_orig())
        cmd_clone.append(self.dest)

        # clone git repo from origin to destination
        logger.log_command(cmd_clone, 1)
        subprocess.call(cmd_clone)

        # if commit is specified: checkout commit
        if self.get_commit():
            # construct checkout command
            cmd_checkout = ["git", "checkout", self.get_commit()]

            # go to git repo and remember old cwd
            prev_dir = os.getcwd()
            os.chdir(self.dest)

            # checkout commit
            logger.log_command(cmd_checkout, 1)
            subprocess.call(cmd_checkout)

            # go to previous dir
            os.chdir(prev_dir)

        # get commit ID
        rev = self.commit()
        self.date()

        # check if checkout worked
        if self.get_commit() != "HEAD":
            if self.get_commit() != rev:
                logger.err("Something went wrong, requested commit not checked out.")
                return False

        # return True if successful
        return True
Esempio n. 27
0
def run():
    """
    This function is corresponding to (one of) the "main" function of the `kentauros` package and is
    the entry point used by the `ktr.py` script from git and the script installed at installation.
    """

    ktr = Kentauros()
    logger = KtrLogger(LOG_PREFIX)

    print_parameters()

    # if no action is specified: exit
    if ktr.cli.get_action() is None:
        logger.log("No action specified. Exiting.")
        logger.log("Use 'ktr --help' for more information.")
        print_flush()
        return

    if not ktr_bootstrap():
        raise SystemExit()

    packages = list()

    # if only specified packages are to be processed: process packages from CLI only
    if not ktr.cli.get_packages_all():
        packages = ktr.cli.get_packages().copy()

        for pkg in packages:
            pkg_conf_path = os.path.join(ktr.conf.get_confdir(), pkg + ".conf")

            if not os.path.exists(pkg_conf_path):
                logger.err("Package configuration for '" + pkg + "' could not be found.")
                packages.remove(pkg)

    # if all package are to be processed: get package configs present in the package configuration
    # directory
    else:
        pkg_conf_paths = glob.glob(os.path.join(ktr.conf.get_confdir(), "*.conf"))

        for pkg_conf_path in pkg_conf_paths:
            packages.append(os.path.basename(pkg_conf_path).replace(".conf", ""))

    if not packages:
        logger.log("No packages have been specified or found. Exiting.")
        print_flush()
        raise SystemExit()

    packages.sort()

    # log list of found packages
    logger.log_list("Packages", packages)
    print_flush()

    # generate package objects
    for name in packages:
        assert isinstance(name, str)

        try:
            pkg = Package(name)
            ktr.add_package(name, pkg)
        except PackageError:
            logger.log("Package with configuration file '" + name + "' is invalid, skipping.")
            continue

    actions_success = list()
    actions_failure = list()

    # run action for every specified package
    for name in ktr.get_package_names():
        assert isinstance(name, str)

        if ktr.state_read(name) is None:
            logger.log("Importing new package into the database.")
            import_action = ImportAction(name)
            import_action.execute()

        action_type = ktr.cli.get_action()
        action = ACTION_DICT[action_type](name)
        success = action.execute()

        if success:
            actions_success.append(name)
        else:
            actions_failure.append(name)

    print_flush()

    if actions_success:
        logger.log_list("Successful actions", actions_success)

    if actions_failure:
        logger.log_list("Failed actions", actions_failure)

    print_flush()

    raise SystemExit()
Esempio n. 28
0
    def get(self) -> bool:
        """
        This method executes the bzr repository download to the package source directory. This
        respects the branch and revision set in the package configuration file.

        Returns:
            bool:  `True` if successful, `False` if not or source already exists
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        # check if $KTR_BASE_DIR/sources/$PACKAGE exists and create if not
        if not os.access(self.sdir, os.W_OK):
            os.makedirs(self.sdir)

        # if source directory seems to already exist, return False
        if os.access(self.dest, os.R_OK):
            rev = self.rev()
            logger.log("Sources already downloaded. Latest revision: " + str(rev), 1)
            return False

        # check for connectivity to server
        if not is_connected(self.remote):
            logger.log("No connection to remote host detected. Cancelling source checkout.", 2)
            return False

        # construct bzr command
        cmd = ["bzr", "branch"]

        # add --verbose or --quiet depending on settings
        if (ktr.verby == 2) and not ktr.debug:
            cmd.append("--quiet")
        if (ktr.verby == 0) or ktr.debug:
            cmd.append("--verbose")

        # set origin
        if not self.get_branch():
            cmd.append(self.get_orig())
        else:
            cmd.append(self.get_orig() + "/" + self.get_branch())

        # set revision is specified
        if self.get_revno():
            cmd.append("--revision")
            cmd.append(self.get_revno())

        # set destination
        cmd.append(self.dest)

        # branch bzr repo from origin to destination
        logger.log_command(cmd, 1)
        subprocess.call(cmd)

        # get commit ID
        rev = self.rev()

        # check if checkout worked
        if self.get_revno():
            if self.get_revno() != rev:
                logger.err("Something went wrong, requested commit not available.")
                return False

        # return True if successful
        return True
Esempio n. 29
0
    def export(self) -> bool:
        """
        This method executes the export from the package source repository to a tarball with pretty
        file name. It also respects the `bzr.keep=False` setting in the package configuration file -
        the bzr repository will be deleted from disk after the export if this flag is set.

        Returns:
            bool:       `True` if successful, `False` if not or already exported
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        def remove_not_keep():
            """
            This local function removes the bzr repository and is called after source export, if
            not keeping the repository around was specified in the configuration file.
            """

            if not self.get_keep_repo():
                # try to be careful with "rm -r"
                assert os.path.isabs(self.dest)
                assert ktr.conf.get_datadir() in self.dest
                shutil.rmtree(self.dest)
                logger.log("bzr repository deleted after export to tarball", 1)

        # construct bzr command
        cmd = ["bzr", "export"]

        # add --verbose or --quiet depending on settings
        if (ktr.verby == 2) and not ktr.debug:
            cmd.append("--quiet")
        if (ktr.verby == 0) or ktr.debug:
            cmd.append("--verbose")

        # export HEAD or specified commit
        if self.get_revno():
            cmd.append("--revision")
            cmd.append(self.get_revno())

        # check if bzr repo exists
        if not os.access(self.dest, os.R_OK):
            logger.err("Sources need to be get before they can be exported.")
            return False

        version = self.formatver()
        name_version = self.spkg.get_name() + "-" + version

        file_name = os.path.join(self.sdir, name_version + ".tar.gz")

        cmd.append(file_name)

        # check if file has already been exported
        if os.path.exists(file_name):
            logger.log("Tarball has already been exported.", 1)
            # remove bzr repo if keep is False
            remove_not_keep()
            return False

        # remember previous directory
        prev_dir = os.getcwd()

        # change to git repository directory
        os.chdir(self.dest)

        # export tar.gz to $KTR_DATA_DIR/$PACKAGE/*.tar.gz
        logger.log_command(cmd, 1)
        subprocess.call(cmd)

        # update saved rev
        self.rev()

        # remove bzr repo if keep is False
        remove_not_keep()

        os.chdir(prev_dir)
        return True