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
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
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
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
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
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
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
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
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
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)
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
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
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
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
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
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)
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
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()
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
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
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
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
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
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
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
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
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()
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
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