Example #1
0
    def commit(self) -> str:
        """
        This method provides an easy way of getting the commit hash of the requested commit. It
        also stores the latest commit hash between method invocations, if the source goes away and
        the hash is needed again.

        Returns:
            str:        commit hash
        """

        logger = KtrLogger(LOG_PREFIX)

        # if sources are not accessible (anymore), return None or last saved rev
        if not os.access(self.dest, os.R_OK):
            if self.saved_commit is None:
                logger.dbg("Sources need to be get before commit hash can be read.")
                return None
            else:
                return self.saved_commit

        cmd = ["git", "rev-parse", "HEAD"]

        prev_dir = os.getcwd()
        os.chdir(self.dest)

        logger.log_command(cmd, 1)
        rev = subprocess.check_output(cmd).decode().rstrip("\n")

        os.chdir(prev_dir)

        self.saved_commit = rev
        return rev
Example #2
0
    def build(self):
        """
        This method executes the actual SRPM package assembly. It sets `$HOME` to the created
        temporary directory and executes `rpmbuild -bs` with the copy of the package spec file in
        `rpmbuild/SPECS`. After that, `$HOME` is reset to the old value.
        """

        ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        old_home = os.environ['HOME']
        os.environ['HOME'] = self.tempdir

        # construct rpmbuild command
        cmd = ["rpmbuild"]

        # 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")

        cmd.append("-bs")
        cmd.append(os.path.join(self.specdir, self.cpkg.get_name() + ".spec"))

        logger.log_command(cmd)

        try:
            subprocess.call(cmd)
        finally:
            os.environ['HOME'] = old_home
Example #3
0
    def rev(self) -> str:
        """
        This method determines which revision the bzr repository associated with this
        :py:class:`BzrSource` currently is at and returns it as a string. Once run, it saves the
        last processed revision number in `self.saved_rev`, in case the revision needs to be
        determined when bzr repository might not be accessible anymore (e.g. if `bzr.keep=False` is
        set in configuration, so the repository is not kept after export to tarball).

        Returns:
            str: either revision string from repo, last stored rev string or `""` when unsuccessful
        """

        # ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        # if sources are not accessible (anymore), return "" or last saved rev
        if not os.access(self.dest, os.R_OK):
            if self.saved_rev is None:
                logger.dbg("Sources need to be get before rev can be determined.")
                return ""
            else:
                return self.saved_rev

        cmd = ["bzr", "revno"]

        prev_dir = os.getcwd()
        os.chdir(self.dest)

        logger.log_command(cmd, 0)
        rev = subprocess.check_output(cmd).decode().rstrip("\n")

        os.chdir(prev_dir)

        self.saved_rev = rev
        return rev
Example #4
0
def do_release_bump(path: str, comment: str=None):
    """
    This function calls `rpmdev-bumpspec` with the specified arguments to bump the release number
    and create a changelog entry with a given comment.

    Arguments:
        str comment:    comment to be added to the changelog entry
    """

    ktr = Kentauros()
    logger = KtrLogger(LOG_PREFIX)

    if not os.path.exists(path):
        raise FileNotFoundError()

    if comment is None:
        comment = "Automatic build by kentauros."

    # construct rpmdev-bumpspec command
    cmd = ["rpmdev-bumpspec"]

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

    cmd.append(path)
    cmd.append('--comment="' + comment + '"')

    logger.log_command(cmd)
    subprocess.call(cmd)
Example #5
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
Example #6
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
Example #7
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
Example #8
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
Example #9
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
Example #10
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
Example #11
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
Example #12
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
Example #13
0
    def date(self) -> str:
        """
        This method provides an easy way of getting the date and time of the requested commit in a
        standardised format (``YYMMDD.HHmmSS``). It also stores the latest parsed date between
        method invocations, if the source goes away and the commit datetime string is needed again.

        Returns:
            str:        commit date.time string (``YYMMDD.HHmmSS``)
        """

        def prepend_zero(string):
            """
            This local function prepends '0' to one-digit time value strings.
            """

            if len(string) == 1:
                return "0" + string
            else:
                return string

        def date_str_from_raw(raw_date: str):
            """
            This local function parses a datetime object and returns a simple string.
            """

            assert isinstance(raw_date, str)

            date_obj = dateutil.parser.parse(raw_date)

            year_str = str(date_obj.year)[2:]
            month_str = prepend_zero(str(date_obj.month))
            day_str = prepend_zero(str(date_obj.day))

            hour_str = prepend_zero(str(date_obj.hour))
            minute_str = prepend_zero(str(date_obj.minute))
            second_str = prepend_zero(str(date_obj.second))

            date_str = year_str + month_str + day_str + "." + hour_str + minute_str + second_str

            return date_str

        # ktr = Kentauros()
        logger = KtrLogger(LOG_PREFIX)

        # if sources are not accessible (anymore), return None or last saved rev
        if not os.access(self.dest, os.R_OK):
            if self.saved_date is None:
                logger.dbg("Sources need to be get before their age can be read.")
                return None
            else:
                return self.saved_date

        cmd = ["git", "show", "-s", "--date=short", "--format=%cI"]

        prev_dir = os.getcwd()
        os.chdir(self.dest)

        logger.log_command(cmd, 1)
        date_raw = subprocess.check_output(cmd).decode().rstrip('\r\n')

        os.chdir(prev_dir)

        date = date_str_from_raw(date_raw)

        self.saved_date = date
        # ktr.state_write(self.spkg.get_conf_name(), dict(git_last_date=date))

        return date