def main(): available_repositories = utils.available_repositories() for item in os.listdir(cst.repos): repo_conf = os.path.join(cst.repos, item, cst.repo_file) if os.access(repo_conf, os.F_OK): with open(repo_conf) as data: data = conf.ReadConfig(data.read().splitlines(), delimiter="@") if item in available_repositories: out.normal("%s [%s]" % (item, out.color("enabled", "brightgreen"))) else: out.normal("%s [%s]" % (item, out.color("disabled", "brightred"))) out.notify("system name: %s" % item) if hasattr(data, "name"): out.notify("development name: %s" % data.name) else: out.warn("development name is not defined!") if hasattr(data, "summary"): out.notify("summary: %s" % data.summary) else: out.warn("summary is not defined!") if hasattr(data, "maintainer"): out.notify("maintainer: %s" % data.maintainer) else: out.warn("maintainer is not defined!") out.write("\n")
def main(self): out.normal("searching for %s\n" % self.keyword) for (repo, category, name, version, path) in self.search(): try: replace = re.compile("(%s)" % "|".join([self.keyword]), re.I) out.write( "%s/%s/%s-%s -- %s\n" % ( out.color(repo, "green"), out.color(category, "green"), out.color(name, "green"), out.color(version, "green"), replace.sub(out.color(r"\1", "brightred"), path), ) ) except: out.write( "%s/%s/%s-%s -- %s\n" % ( out.color(repo, "green"), out.color(category, "green"), out.color(name, "green"), out.color(version, "green"), path, ) )
def about(self): """ Shows application name and version and exits """ out.write("%s %s\n" % (__APP_NAME__, __VERSION__)) # Do nothing after after showing version information sys.exit(0)
def run_extract(self): # if the environment has no extract_plan variable, doesn't run extract function if not hasattr(self.environment, "extract_nevertheless" ) or not self.environment.extract_nevertheless: if not hasattr(self.environment, "extract_plan"): return target = os.path.dirname(self.environment.build_dir) extracted_file = os.path.join(os.path.dirname(target), ".extracted") if os.path.isfile(extracted_file): if self.environment.force_extract: shelltools.remove_file(extracted_file) else: out.write("%s %s/%s-%s had been already extracted.\n" % (out.color(">>", "brightyellow"), \ self.environment.category, self.environment.name, self.environment.version)) return True utils.xterm_title("lpms: extracting %s/%s/%s-%s" % (self.environment.repo, self.environment.category, \ self.environment.name, self.environment.version)) out.notify("extracting archive(s) to %s" % os.path.dirname(self.environment.build_dir)) # now, extract the archives self.run_stage("extract") out.notify("%s has been extracted." % self.environment.fullname) shelltools.touch(extracted_file) if self.environment.stage == "extract": lpms.terminate()
def initialize(): '''Initializes lpms package manager''' try: LPMSCore().initialize() except LpmsTerminate as err: # TODO: Parse these err variable when debug mode is enabled. out.write("Terminated.\n")
def system(cmd, show=False, stage=None, sandbox=None): cfg = conf.LPMSConfig() if sandbox is None: sandbox = True if cfg.sandbox else False # override 'sandbox' variable if the user wants to modifiy from cli if lpms.getopt("--enable-sandbox"): sandbox = True elif lpms.getopt("--disable-sandbox"): sandbox = False if lpms.getopt("--verbose"): ret, output, err = run_cmd(cmd, True) elif (not cfg.print_output or lpms.getopt("--quiet")) and not show: ret, output, err = run_cmd(cmd, show=False, enable_sandbox=sandbox) else: ret, output, err = run_cmd(cmd, show=True, enable_sandbox=sandbox) if ret != 0: if not conf.LPMSConfig().print_output or lpms.getopt("--quiet"): out.brightred("\n>> error messages:\n") out.write(err) out.warn("command failed: %s" % out.color(cmd, "red")) if stage and output and err: return False, output + err return False return True
def main(self): if not self.command_line: out.error("no command given.") return for command in self.command_line: if command == "list": self.list_news() return elif command == "read": id_index = self.command_line.index(command) + 1 try: self.cursor.get_all_news() news_id = self.command_line[id_index] self.read_news(news_id) return except IndexError: out.error("you must give a index number!") return elif command in ("--help", "-h"): self.usage() return elif command in ("--help", "-h"): out.write("lnews %s\n" % __version__) return else: out.error("invalid command: %s" % command) return
def system(cmd, show=False, stage=None, sandbox=None): cfg = conf.LPMSConfig() if sandbox is None: sandbox = True if cfg.sandbox else False # override 'sandbox' variable if the user wants to modifiy from cli if lpms.getopt('--enable-sandbox'): sandbox = True elif lpms.getopt('--disable-sandbox'): sandbox = False if lpms.getopt("--verbose"): ret, output, err = run_cmd(cmd, True) elif (not cfg.print_output or lpms.getopt("--quiet")) \ and not show: ret, output, err = run_cmd(cmd, show=False, enable_sandbox=sandbox) else: ret, output, err = run_cmd(cmd, show=True, enable_sandbox=sandbox) if ret != 0: if not conf.LPMSConfig().print_output or lpms.getopt("--quiet"): out.brightred("\n>> error messages:\n") out.write(err) out.warn("command failed: %s" % out.color(cmd, "red")) if stage and output and err: return False, output + err return False return True
def remove(self): try: api.remove_package(self.request.names, self.request.instruction) except PackageNotFound as err: out.write(">> %s could not be found.\n" % out.color(err.message, "red")) sys.exit(0)
def parse_traceback(exception_type=None): '''Parse exceptions and show nice and more readable error messages''' out.write( out.color(">>", "brightred") + " %s/%s/%s-%s\n" % (self.environment.repo, self.environment.category, self.environment.name, self.environment.version)) exc_type, exc_value, exc_traceback = sys.exc_info() formatted_lines = traceback.format_exception( exc_type, exc_value, exc_traceback) if not self.environment.debug: for item in formatted_lines: item = item.strip() if item.startswith("File"): regex = re.compile(r'(\w+)\S*$') regex = regex.search(item) if regex is None: continue if regex.group() in operation_order: line = re.compile(r'[^\d.]+') line = line.sub('', item) out.write("%s %s " % (out.color("on line %s:" % line, "red"), formatted_lines[-1])) break else: traceback.print_exc() out.error("an error occurred when running the %s function." % out.color(operation, "red")) return False
def perform_operation(self): utils.xterm_title("(%s/%s) lpms: merging %s/%s-%s from %s" % (self.environment.index, self.environment.count, self.environment.category, self.environment.name, self.environment.version, self.environment.repo)) # create $info_file_name.gz archive and remove info file self.create_info_archive() # merge the package self.merge_package() # clean the previous version if it is exists self.clean_obsolete_content() # write to database self.write_db() # create or update /usr/share/info/dir self.update_info_index() if self.backup: out.write("%s%s configuration file changed. Use %s to fix these files.\n" % (out.color(" > ", "green"), len(self.backup), \ out.color("merge-conf", "red"))) if shelltools.is_exists(cst.lock_file): shelltools.remove_file(cst.lock_file) return True, self.environment
def main(files): opr = Generate(os.getcwd(), files) if "--help" in files: usage() elif "--version" in files: out.write("%s-%s\n" % (app_name, app_version)) opr.check_repo_dir() opr.calculate_hashes()
def confirm(text): turns = 5 while turns: turns -= 1 out.warn(text+"["+out.color("yes", "green")+"/"+out.color("no", "red")+"]") answer = sys.stdin.readline().strip() if answer == "yes" or answer == "y" or answer == "": return True elif answer == "no" or answer == "n": return False out.write(out.color("Sorry, response " + answer + " not understood! yes/y or no/n\n", "red"))
def gnome2_icon_cache_update(*args, **kwargs): parameters = "-q -t -f" target = "/usr/share/icons/hicolor" if args: parameters = " ".join(args) if kwargs: if "target" in kwargs: target = kwargs["target"] out.notify("updating GTK+ icon cache...") if not shelltools.system("gtk-update-icon-cache %s %s" % (parameters, target), sandbox=False): out.write(out.color("\n\tFAILED\n", "red"))
def confirm(text): turns = 5 while turns: turns -= 1 out.warn(text + "[" + out.color("yes", "green") + "/" + out.color("no", "red") + "]") answer = sys.stdin.readline().strip() if answer == "yes" or answer == "y" or answer == "": return True elif answer == "no" or answer == "n": return False out.write( out.color( "Sorry, response " + answer + " not understood! yes/y or no/n\n", "red"))
def main(self): out.normal("searching for %s\n" % self.keyword) for (repo, category, name, version, path) in self.search(): try: replace = re.compile("(%s)" % '|'.join([self.keyword]), re.I) out.write( "%s/%s/%s-%s -- %s\n" % (out.color(repo, "green"), out.color(category, "green"), out.color(name, "green"), out.color(version, "green"), replace.sub(out.color(r"\1", "brightred"), path))) except: out.write( "%s/%s/%s-%s -- %s\n" % (out.color(repo, "green"), out.color( category, "green"), out.color( name, "green"), out.color(version, "green"), path))
def standard_extract(): """ Runs standard extract procedure """ target = os.path.dirname(build_dir) for url in extract_plan: out.write(" %s %s\n" % (out.color(">", "green"), \ os.path.join(cfg.LPMSConfig().src_cache, \ os.path.basename(url)))) archive_path = os.path.join(cfg.LPMSConfig().src_cache, \ os.path.basename(url)) try: partial = [atom.strip() for atom in partial.split(" ") if atom != "#"] archive.extract(str(archive_path), str(target), partial) except NameError: archive.extract(str(archive_path), str(target))
def select_pkgs(self): for pkg in self.instdb.get_all_packages(): self.repo, self.category, self.name, self.version, self.slot = pkg # catch packages which are from the outside if not self.repodb.find_package(package_name=self.name, \ package_category=self.category): if not (self.category, self.name) in self.notfound_pkg: self.notfound_pkg.append((self.category, self.name)) # get version data from repository database repository_items = self.repodb.find_package(package_name=self.name, \ package_category=self.category) if not repository_items: # if the installed package could not found in the repository database # add the item to not-founds list self.notfound_pkg.append((self.category, self.name)) continue # collect available package version by slot value available_versions = {} for item in repository_items: if item.slot in available_versions: available_versions[item.slot].append(item.version) else: available_versions[item.slot] = [item.version] # comparise versions for item in repository_items: if item.slot == self.slot: best_version = utils.best_version( available_versions[item.slot]) result = utils.vercmp(best_version, self.version) if result != 0: self.packages.append( os.path.join(self.category, self.name) + ":" + self.slot) break if self.notfound_pkg: out.write( "%s: the following packages were installed but they could not be found in the database:\n\n" % out.color("WARNING", "brightyellow")) for no_category, no_name, in self.notfound_pkg: out.notify("%s/%s" % (no_category, no_name)) out.write("\n")
def standard_extract(): """ Runs standard extract procedure """ target = os.path.dirname(build_dir) for url in extract_plan: out.write(" %s %s\n" % (out.color(">", "green"), \ os.path.join(cfg.LPMSConfig().src_cache, \ os.path.basename(url)))) archive_path = os.path.join(cfg.LPMSConfig().src_cache, \ os.path.basename(url)) try: partial = [ atom.strip() for atom in partial.split(" ") if atom != "#" ] archive.extract(str(archive_path), str(target), partial) except NameError: archive.extract(str(archive_path), str(target))
def read_news(self, news_id): try: news_id = int(news_id) repo, metadata, message = self.cursor.data[news_id] except ValueError: out.error("invalid id: %s" % news_id) return except IndexError: out.error("message found not found with this id: %d" % news_id) return out.write(out.color("from", "green")+": "+metadata["from"]+"\n") out.write(out.color("summary", "green")+": "+metadata["summary"]+"\n") out.write(out.color("date", "green")+": "+metadata["date"]+"\n") out.write(out.color("priority", "green")+": "+metadata["priority"]+"\n") out.write(message+"\n") self.cursor.mark_as_read("%s/%s" % (repo, metadata["summary"]))
def select_pkgs(self): for pkg in self.instdb.get_all_packages(): self.repo, self.category, self.name, self.version, self.slot = pkg # catch packages which are from the outside if not self.repodb.find_package(package_name=self.name, \ package_category=self.category): if not (self.category, self.name) in self.notfound_pkg: self.notfound_pkg.append((self.category, self.name)) # get version data from repository database repository_items = self.repodb.find_package(package_name=self.name, \ package_category=self.category) if not repository_items: # if the installed package could not found in the repository database # add the item to not-founds list self.notfound_pkg.append((self.category, self.name)) continue # collect available package version by slot value available_versions = {} for item in repository_items: if item.slot in available_versions: available_versions[item.slot].append(item.version) else: available_versions[item.slot] = [item.version] # comparise versions for item in repository_items: if item.slot == self.slot: best_version = utils.best_version(available_versions[item.slot]) result = utils.vercmp(best_version, self.version) if result != 0: self.packages.append(os.path.join(self.category, self.name)+":"+self.slot) break if self.notfound_pkg: out.write("%s: the following packages were installed but they could not be found in the database:\n\n" % out.color("WARNING", "brightyellow")) for no_category, no_name, in self.notfound_pkg: out.notify("%s/%s" % (no_category, no_name)) out.write("\n")
def read_news(self, news_id): try: news_id = int(news_id) repo, metadata, message = self.cursor.data[news_id] except ValueError: out.error("invalid id: %s" % news_id) return except IndexError: out.error("message found not found with this id: %d" % news_id) return out.write(out.color("from", "green") + ": " + metadata["from"] + "\n") out.write( out.color("summary", "green") + ": " + metadata["summary"] + "\n") out.write(out.color("date", "green") + ": " + metadata["date"] + "\n") out.write( out.color("priority", "green") + ": " + metadata["priority"] + "\n") out.write(message + "\n") self.cursor.mark_as_read("%s/%s" % (repo, metadata["summary"]))
def show_info(self, package): items = self.instdb.database.get_package_build_info(package.id) template = ( 'Start_Time', 'End Time', 'Requestor', 'Requestor ID', 'HOST', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS', 'JOBS', 'CC', 'CXX' ) out.normal("Build information for %s/%s/%s-%s {%s:%s}" % (package.repo, \ package.category, package.name, package.version, package.slot, package.arch)) for index, item in enumerate(template, 1): if index in (1, 2): out.write("%s: %s\n" % (out.color(item, "green"), \ datetime.datetime.fromtimestamp(items[index]).strftime('%Y-%m-%d %H:%M:%S'))) if index == 2: delta = datetime.datetime.fromtimestamp(items[2])-\ datetime.datetime.fromtimestamp(items[1]) operation_time = str(round(float(delta.seconds)/60, 1))+" minutes" if delta.seconds >= 60 \ else str(delta.seconds)+" seconds" out.write("%s: %s\n" % (out.color("Operation Time", "green"), operation_time)) continue out.write("%s: %s\n" % (out.color(item, "green"), items[index]))
def usage(): out.normal("A tool that creates \'hashes\' file for lpms packages.") out.green("General Usage:\n") out.write(" $ lhashgen <spec name>\n") out.write("\nIf you do not give any package name with command, it scans the directory and operates all valid specs\n") out.write("\nUse \'--version\' to see program's version\n") lpms.terminate()
def parse_traceback(exception_type=None): '''Parse exceptions and show nice and more readable error messages''' out.write(out.color(">>", "brightred")+" %s/%s/%s-%s\n" % (self.environment.repo, self.environment.category, self.environment.name, self.environment.version)) exc_type, exc_value, exc_traceback = sys.exc_info() formatted_lines = traceback.format_exception(exc_type, exc_value, exc_traceback) if not self.environment.debug: for item in formatted_lines: item = item.strip() if item.startswith("File"): regex = re.compile(r'(\w+)\S*$') regex = regex.search(item) if regex is None: continue if regex.group() in operation_order: line = re.compile(r'[^\d.]+') line = line.sub('', item) out.write("%s %s " % (out.color("on line %s:" % line, "red"), formatted_lines[-1])) break else: traceback.print_exc() out.error("an error occurred when running the %s function." % out.color(operation, "red")) return False
def usage(): out.normal("A tool that creates \'hashes\' file for lpms packages.") out.green("General Usage:\n") out.write(" $ lhashgen <spec name>\n") out.write( "\nIf you do not give any package name with command, it scans the directory and operates all valid specs\n" ) out.write("\nUse \'--version\' to see program's version\n") lpms.terminate()
def run_extract(self): # if the environment has no extract_plan variable, doesn't run extract function if not hasattr(self.environment, "extract_nevertheless") or not self.environment.extract_nevertheless: if not hasattr(self.environment, "extract_plan"): return target = os.path.dirname(self.environment.build_dir) extracted_file = os.path.join(os.path.dirname(target), ".extracted") if os.path.isfile(extracted_file): if self.environment.force_extract: shelltools.remove_file(extracted_file) else: out.write("%s %s/%s-%s had been already extracted.\n" % (out.color(">>", "brightyellow"), \ self.environment.category, self.environment.name, self.environment.version)) return True utils.xterm_title("lpms: extracting %s/%s/%s-%s" % (self.environment.repo, self.environment.category, \ self.environment.name, self.environment.version)) out.notify("extracting archive(s) to %s" % os.path.dirname(self.environment.build_dir)) # now, extract the archives self.run_stage("extract") out.notify("%s has been extracted." % self.environment.fullname) shelltools.touch(extracted_file) if self.environment.stage == "extract": lpms.terminate()
def usage(self): out.normal("Search given keywords in database") out.green("General Usage:\n") out.write(" $ lpms -s <keyword>\n") out.write("\nOther options:\n") for item in help_output: if len(item) == 2: out.write("%-28s: %s\n" % (out.color(item[0], "green"), item[1])) lpms.terminate()
def collision_check(): # TODO: This is a temporary solution. collision_check function # must be a reusable part for using in remove operation out.normal("checking file collisions...") lpms.logger.info("checking file collisions") collision_object = file_collisions.CollisionProtect( environment.category, environment.name, environment.slot, real_root=environment.real_root, source_dir=environment.install_dir) collision_object.handle_collisions() if collision_object.orphans: out.write( out.color(" > ", "brightyellow") + "these files are orphan. the package will adopt the files:\n" ) index = 0 for orphan in collision_object.orphans: out.notify(orphan) index += 1 if index > 100: # FIXME: the files must be logged out.write( out.color(" > ", "brightyellow") + "...and many others.") break if collision_object.collisions: out.write( out.color(" > ", "brightyellow") + "file collisions detected:\n") for item in collision_object.collisions: (category, name, slot, version), path = item out.write(out.color(" -- ", "red")+category+"/"+name+"-"\ +version+":"+slot+" -> "+path+"\n") if collision_object.collisions and self.config.collision_protect: if environment.force_file_collision: out.warn( "Disregarding these collisions, you have been warned!") else: return False return True
def main(self): parsed = self.pkgname.split("/") if len(parsed) == 3: repo, category, name = parsed name, version = utils.parse_pkgname(name) packages = self.instdb.find_package( package_repo=repo, package_category=category, package_name=name, package_version=version ) elif len(parsed) == 2: category, name = parsed name, version = utils.parse_pkgname(name) packages = self.instdb.find_package( package_category=category, package_name=name, package_version=version ) elif len(parsed) == 1: name, version = utils.parse_pkgname(self.pkgname) packages = self.instdb.find_package( package_name=name, package_version=version ) else: out.error("%s could not be recognized." % self.pkgname) lpms.terminate() if not packages: out.error("%s not installed." % self.pkgname) lpms.terminate() for package in packages: symdirs = {} out.normal("%s/%s/%s-%s" % (package.repo, package.category, \ package.name, package.version)) content = self.filesdb.get_paths_by_package(package.name, \ category=package.category, version=package.version) for item in content: item = item[0].encode('UTF-8') if os.path.islink(item): out.write("%s -> %s\n" % (out.color(item, "green"), os.readlink(item))) if os.path.isdir(os.path.realpath(item)): symdirs[os.path.realpath(item)+"/"] = item+"/" else: out.write(item+"\n") if symdirs: for symdir in symdirs: if item.startswith(symdir): out.write("%s -> %s\n" % (out.color(item.replace(symdir, \ symdirs[symdir]), "brightwhite"), out.color(item, "brightwhite")))
def main(self): parsed = self.pkgname.split("/") if len(parsed) == 3: repo, category, name = parsed name, version = utils.parse_pkgname(name) packages = self.instdb.find_package( package_repo=repo, package_category=category, package_name=name, package_version=version ) elif len(parsed) == 2: category, name = parsed name, version = utils.parse_pkgname(name) packages = self.instdb.find_package(package_category=category, package_name=name, package_version=version) elif len(parsed) == 1: name, version = utils.parse_pkgname(self.pkgname) packages = self.instdb.find_package(package_name=name, package_version=version) else: out.error("%s could not be recognized." % self.pkgname) lpms.terminate() if not packages: out.error("%s not installed." % self.pkgname) lpms.terminate() for package in packages: symdirs = {} out.normal("%s/%s/%s-%s" % (package.repo, package.category, package.name, package.version)) content = self.filesdb.get_paths_by_package( package.name, category=package.category, version=package.version ) for item in content: item = item[0].encode("UTF-8") if os.path.islink(item): out.write("%s -> %s\n" % (out.color(item, "green"), os.readlink(item))) if os.path.isdir(os.path.realpath(item)): symdirs[os.path.realpath(item) + "/"] = item + "/" else: out.write(item + "\n") if symdirs: for symdir in symdirs: if item.startswith(symdir): out.write( "%s -> %s\n" % ( out.color(item.replace(symdir, symdirs[symdir]), "brightwhite"), out.color(item, "brightwhite"), ) )
def list_news(self): self.cursor.get_all_news() i = 0 if not self.cursor.data: out.warn("no readable news.") return out.normal("readable messages listed:") out.write("index repo priority summary\n") out.write("===============================================\n") for news in self.cursor.data: repo, metadata = news[:-1] if not "%s/%s" % (repo, metadata["summary"]) in self.read_items: read = out.color("*", "brightgreen") else: read = "" out.write("[%s]%s\t%-15s\t%-12s %s\n" % (out.color(str(i), "green"), read, repo, \ metadata["priority"], metadata["summary"])) i += 1
def show_info(self, package): items = self.instdb.database.get_package_build_info(package.id) template = ( "Start_Time", "End Time", "Requestor", "Requestor ID", "HOST", "CFLAGS", "CXXFLAGS", "LDFLAGS", "JOBS", "CC", "CXX", ) out.normal( "Build information for %s/%s/%s-%s {%s:%s}" % (package.repo, package.category, package.name, package.version, package.slot, package.arch) ) for index, item in enumerate(template, 1): if index in (1, 2): out.write( "%s: %s\n" % ( out.color(item, "green"), datetime.datetime.fromtimestamp(items[index]).strftime("%Y-%m-%d %H:%M:%S"), ) ) if index == 2: delta = datetime.datetime.fromtimestamp(items[2]) - datetime.datetime.fromtimestamp(items[1]) operation_time = ( str(round(float(delta.seconds) / 60, 1)) + " minutes" if delta.seconds >= 60 else str(delta.seconds) + " seconds" ) out.write("%s: %s\n" % (out.color("Operation Time", "green"), operation_time)) continue out.write("%s: %s\n" % (out.color(item, "green"), items[index]))
def show_package(self, packages): package = packages.get(0) installed_packages = self.instdb.find_package(package_name=package.name, package_category=package.category) metadata = self.repodb.get_package_metadata(package_id=package.id) if installed_packages: installed_versions, available_versions, package_options = {}, {}, {} for package_item in packages: if package_item.arch in available_versions: available_versions[package_item.arch].add(package_item.version) else: available_versions[package_item.arch] = set([package_item.version]) for installed_package in installed_packages: if installed_package.arch in installed_versions: installed_versions[installed_package.arch].add(installed_package.version) else: installed_versions[installed_package.arch] = set([installed_package.version]) if installed_package.applied_options is None: continue for option in installed_package.options: if option in installed_package.applied_options: key = out.color( "{" + installed_package.slot + "} " + installed_package.repo + "::" + installed_package.version, "yellow", ) if not key in package_options: package_options[key] = [out.color(option, "red")] else: package_options[key].append(out.color(option, "red")) for option in installed_package.options: if not option in installed_package.applied_options: key = out.color( "{" + installed_package.slot + "} " + installed_package.repo + "::" + installed_package.version, "yellow", ) if not key in package_options: package_options[key] = [option] else: package_options[key].append(option) versions = "" for arch in available_versions: versions += out.color(arch, "yellow") + "(" + ", ".join(available_versions[arch]) + ") " installed_vers = "" for arch in installed_versions: installed_vers += out.color(arch, "yellow") + "(" + ", ".join(installed_versions[arch]) + ") " out.write( "[%s] %s/%s\n" % ( out.color("I", "backgroundgreen"), out.color(package.category, "brightgreen"), out.color(package.name, "brightgreen"), ) ) out.write(" %s %s\n" % (out.color("available versions:", "green"), versions)) out.write(" %s %s\n" % (out.color("installed versions:", "green"), installed_vers)) out.write(" %s %s\n" % (out.color("summary:", "green"), metadata.summary)) out.write(" %s %s\n" % (out.color("homepage:", "green"), metadata.homepage)) out.write(" %s %s\n" % (out.color("license:", "green"), metadata.license)) if package_options: out.write(" %s " % out.color("options:", "green")) for index, version in enumerate(package_options): if index == 0: out.write(" => %s" % version + "(" + ", ".join(package_options[version]) + ")") else: out.write( " => %s" % out.color(version, "brightblue") + "(" + ", ".join(package_options[version]) + ")" ) out.write("\n") else: available_versions, package_options = {}, {} for package_item in packages: if package_item.arch in available_versions: available_versions[package_item.arch].add(package_item.version) else: available_versions[package_item.arch] = set([package_item.version]) if package_item.options is not None: package_options[ "{" + package_item.slot + "} " + package_item.repo + "::" + package_item.version ] = package_item.options versions = "" for arch in available_versions: versions += out.color(arch, "yellow") + "(" + ", ".join(available_versions[arch]) + ") " out.write("%s %s/%s\n" % (out.color(" * ", "green"), package.category, out.color(package.name, "white"))) out.write(" %s %s\n" % (out.color("available versions:", "green"), versions)) out.write(" %s %s\n" % (out.color("summary:", "green"), metadata.summary)) out.write(" %s %s\n" % (out.color("homepage:", "green"), metadata.homepage)) out.write(" %s %s\n" % (out.color("license:", "green"), metadata.license)) if package_options: out.write(" %s " % out.color("options:", "green")) for index, version in enumerate(package_options): if index == 0: out.write( " => %s" % out.color(version, "brightblue") + "(" + ", ".join(package_options[version]) + ")" ) else: out.write( " => %s" % out.color(version, "brightblue") + "(" + ", ".join(package_options[version]) + ")" ) out.write("\n")
def usage(self): out.normal("Get information about given package") out.green("General Usage:\n") out.write(" $ lpms -i repo/category/pkgname\n") out.write("\nrepo and category keywords are optional.\n") lpms.terminate()
def usage(self): out.normal("news reader for lpms") out.write("Use 'list' command to list available messages. For reading these messages, use read <id>\n")
def ask(): for c, s in enumerate(sets): out.write(" "+out.color(str(c+1), "green")+") "+s+"\n") out.write("\nselect one of them:\n") out.write("to exit, press Q or q.\n")
def update_package(self, repo_path, category, my_pkg, my_version = None, update = False): dataset = LCollect() # Register some variables to use after self.env.repo = os.path.basename(repo_path) self.env.category = category dataset.repo = self.env.repo dataset.category = category os.chdir(os.path.join(repo_path, category, my_pkg)) for pkg in glob.glob("*"+cst.spec_suffix): script_path = os.path.join(repo_path, category, my_pkg, pkg) self.env.name, self.env.version = utils.parse_pkgname(pkg.split(cst.spec_suffix)[0]) dataset.name = self.env.name dataset.version = self.env.version # FIXME: We must develop a upper-class or environment to # use that cases to prevent code duplication # Begins code duplication interphase = re.search(r'-r[0-9][0-9]', self.env.version) if not interphase: interphase = re.search(r'-r[0-9]', self.env.version) self.env.raw_version = self.env.version self.env.revision = "" # Now, set real values of these variables if package revisioned. if interphase is not None and interphase.group(): self.env.raw_version = self.env.version.replace(interphase.group(), "") self.env.revision = interphase.group() # End of code duplication self.env.__dict__["fullname"] = self.env.name+"-"+self.env.version if not self.import_script(script_path): out.error("an error occured while processing the spec: %s" \ % out.color(script_path, "red")) out.error("please report the above error messages to the package maintainer.") continue metadata = utils.metadata_parser(self.env.metadata) metadata.update({"name": self.env.name, "version": self.env.version}) # This method checks metadata integrity. # It warn the user and pass the spec if a spec is broken self.check_metadata_integrity(metadata) # These values are optional if not "options" in metadata: metadata.update({"options": None}) if not "slot" in metadata: metadata.update({"slot": "0"}) if not "src_url" in metadata: metadata.update({"src_url": None}) if lpms.getopt("--verbose"): out.write(" %s-%s\n" % (self.env.name, self.env.version)) try: dataset.summary = metadata['summary'] dataset.homepage = metadata['homepage'] dataset.license = metadata['license'] dataset.src_uri = metadata['src_url'] if metadata['options'] is None: dataset.options = None else: dataset.options = metadata['options'].split(" ") dataset.slot = metadata['slot'] except KeyError as err: out.error("%s/%s/%s-%s: invalid metadata" % (repo_name, category, \ self.env.name, self.env.version)) out.warn("repository update was failed and the repository database was removed.") out.warn("you can run 'lpms --reload-previous-repodb' command to reload previous db version.") lpms.terminate("good luck!") if update: self.repodb.delete_package(package_repo=dataset.repo, package_category=dataset.category, \ package_name=self.env.name, package_version=self.env.version) static_depends_runtime = []; static_depends_build = []; static_depends_postmerge = []; static_depends_conflict = [] if 'depends' in self.env.__dict__.keys(): deps = utils.depends_parser(self.env.depends) if 'runtime' in deps: static_depends_runtime.extend(deps['runtime']) if 'build' in deps: static_depends_build.extend(deps['build']) if 'common' in deps: static_depends_runtime.extend(deps['common']) static_depends_build.extend(deps['common']) if 'postmerge' in deps: static_depends_postmerge.extend(deps['postmerge']) if 'conflict' in deps: static_depends_conflict.extend(deps['conflict']) optional_depends_runtime = []; optional_depends_build = []; optional_depends_postmerge = []; optional_depends_conflict = [] for opt in ('opt_common', 'opt_conflict', 'opt_postmerge', 'opt_runtime', 'opt_build'): try: deps = utils.parse_opt_deps(getattr(self.env, opt)) if opt.split("_")[1] == "runtime": optional_depends_runtime.append(deps) elif opt.split("_")[1] == "build": optional_depends_build.append(deps) elif opt.split("_")[1] == "common": optional_depends_build.append(deps) optional_depends_runtime.append(deps) elif opt.split("_")[1] == "postmerge": optional_depends_postmerge.append(deps) elif opt.split("_")[1] == "conflict": optional_depends_conflict.append(deps) del deps except AttributeError: continue dataset.optional_depends_runtime = optional_depends_runtime dataset.optional_depends_build = optional_depends_build dataset.optional_depends_postmerge = optional_depends_postmerge dataset.optional_depends_conflict = optional_depends_conflict dataset.static_depends_runtime = static_depends_runtime dataset.static_depends_build = static_depends_build dataset.static_depends_postmerge = static_depends_postmerge dataset.static_depends_conflict = static_depends_conflict if metadata['arch'] is not None: arches = metadata['arch'].split(" ") for arch in arches: dataset.arch = arch self.repodb.insert_package(dataset) else: dataset.arch = None self.repodb.insert_package(dataset) # remove optional keys for key in ('depends', 'options', 'opt_runtime', 'opt_build', \ 'opt_conflict', 'opt_common', 'opt_postmerge'): try: del self.env.__dict__[key] except KeyError: pass self.packages_num += 1
def main(params): # determine operation type repo_name = None if params: repo_name = params[0] # create operation object operation = Update() repo_num = 0 if repo_name is None: # firstly, lpms tries to create a copy of current repository database. db_backup() out.normal("updating repository database...") operation.repodb.database.begin_transaction() for repo_name in os.listdir(cst.repos): if not repo_name in utils.available_repositories(): continue if os.path.isfile(os.path.join(cst.repos, repo_name, "info/repo.conf")): out.write(out.color(" * ", "red") + repo_name+"\n") operation.update_repository(repo_name) repo_num += 1 operation.repodb.database.commit() out.normal("%s repository(ies) is/are updated." % repo_num) else: if repo_name == ".": current_path = os.getcwd() for repo_path in [os.path.join(cst.repos, item) \ for item in utils.available_repositories()]: if current_path == repo_path or len(current_path.split(repo_path)) == 2: # convert it a valid repo_name variable from the path repo_name = current_path.split(cst.repos)[1][1:] break if repo_name == ".": out.warn("%s does not seem a valid repository path." % \ out.color(current_path, "red")) lpms.terminate() if len(repo_name.split("/")) == 2: out.normal("updating %s" % repo_name) repo, category = repo_name.split("/") repo_path = os.path.join(cst.repos, repo) if not repo in utils.available_repositories(): out.error("%s is not a repository." % out.color(repo, "red")) lpms.terminate() operation.repodb.database.begin_transaction() for pkg in os.listdir(os.path.join(repo_path, category)): try: operation.update_package(repo_path, category, pkg, update=True) except IntegrityError: continue operation.repodb.database.commit() elif len(repo_name.split("/")) == 3: version = None repo, category, name = repo_name.split("/") if repo.startswith("="): repo = repo[1:] try: name, version = utils.parse_pkgname(name) except TypeError: out.error("you should give a version number") lpms.terminate() else: if utils.parse_pkgname(name) is not None and len(utils.parse_pkgname(name)) == 2: out.error("you must use %s" % (out.color("="+repo_name, "red"))) lpms.terminate() if not repo in utils.available_repositories(): out.error("%s is not a repository." % out.color(repo, "red")) lpms.terminate() repo_path = os.path.join(cst.repos, repo) out.normal("updating %s/%s/%s" % (repo, category, name)) operation.repodb.database.begin_transaction() operation.update_package(repo_path, category, name, my_version = version, update = True) operation.repodb.database.commit() else: if not repo_name in utils.available_repositories(): out.error("%s is not a repository." % out.color(repo_name, "red")) lpms.terminate() repo_dir = os.path.join(cst.repos, repo_name) if os.path.isdir(repo_dir): repo_path = os.path.join(repo_dir, cst.repo_file) if os.path.isfile(repo_path): operation.repodb.database.begin_transaction() out.normal("updating repository: %s" % out.color(repo_name, "green")) operation.update_repository(repo_name) operation.repodb.database.commit() else: lpms.terminate("repo.conf file could not found in %s" % repo_dir+"/info") else: lpms.terminate("repo.conf not found in %s" % os.path.join(cst.repos, repo_name)) out.normal("Total %s packages have been processed." % operation.packages_num) # Drop inactive repository from the database for name in operation.repodb.get_repository_names(): if not name in utils.available_repositories(): operation.repodb.delete_repository(name, commit=True) out.warn("%s dropped." % name) # Close the database connection operation.repodb.database.close()
def ask(): for c, s in enumerate(sets): out.write(" " + out.color(str(c + 1), "green") + ") " + s + "\n") out.write("\nselect one of them:\n") out.write("to exit, press Q or q.\n")
def usage(self): """ Prints available commands with their descriptions. """ out.normal("lpms -- %s Package Management System %s\n" % \ (out.color("L", "red"), out.color("v"+__VERSION__, "green"))) out.write("In order to build a package:\n\n") out.write(" # lpms <package-name> <extra-command>\n\n") out.write("To see extra commands use --help parameter.\n\n") out.write("Build related arguments:\n") for build_argument in self.build_arguments: if hasattr(build_argument, "short"): out.write(('%-29s %-10s : %s\n' % \ (out.color(build_argument.arg, 'green'), \ out.color(build_argument.short, 'green'), \ build_argument.description))) else: out.write(('%-32s : %s\n' % \ (out.color(build_argument.arg, 'green'), \ build_argument.description))) out.write("\nOther arguments:\n") for other_argument in self.other_arguments: if hasattr(other_argument, "short"): out.write(('%-29s %-10s : %s\n' % \ (out.color(other_argument.arg, 'green'), \ out.color(other_argument.short, 'green'), \ other_argument.description))) else: out.write(('%-32s : %s\n' % \ (out.color(other_argument.arg, 'green'), \ other_argument.description))) # Do nothing after showing help message sys.exit(0)
def show(packages, conflicts, options, installdb): '''Shows operation summary to the user''' # TODO: This can be splitted as a module for package in packages: status_bar = [' ', ' '] other_version = "" installed_packages = installdb.find_package( package_name=package.name, \ package_category=package.category) if not installed_packages: installed_package = None status_bar[0] = out.color("N", "brightgreen") else: if not [installed_package for installed_package in installed_packages \ if package.slot == installed_package.slot]: status_bar[1] = out.color("NS", "brightgreen") else: for installed_package in installed_packages: if installed_package.slot == package.slot: if package.version != installed_package.version: compare = utils.vercmp(package.version, \ installed_package.version) if compare == -1: status_bar[0] = out.color("D", "brightred") other_version = "[%s]" % out.color(\ installed_package.version, "brightred") elif compare == 1: status_bar[0] = out.color("U", "brightgreen") other_version = "[%s]" % out.color(\ installed_package.version, "green") elif package.version == installed_package.version: status_bar[0] = out.color("R", "brightyellow") class FormattedOptions(list): def __init__(self, data): super(FormattedOptions, self).extend(data) def append(self, item, color=None): self.remove(item) if color is not None: super(FormattedOptions, self).insert(0, out.color("*"+item, color)) else: super(FormattedOptions, self).insert(0, item) formatted_options = [] if package.options is not None: installed_package = None for item in installed_packages: if item.slot == package.slot: installed_package = item formatted_options = FormattedOptions(package.options) if package.id in options: if not status_bar[0].strip() or not status_bar[1].strip(): for applied_option in options[package.id]: if installed_package: if installed_package.applied_options is not None and not \ applied_option in installed_package.applied_options: formatted_options.append(applied_option, "brightgreen") continue elif installed_package.applied_options is None: formatted_options.append(applied_option, "brightgreen") continue formatted_options.append(applied_option, "red") if installed_package and installed_package.applied_options is not None: for applied_option in installed_package.applied_options: if not applied_option in options[package.id]: formatted_options.append(applied_option, "brightyellow") else: for option in package.options: if installed_package and installed_package.applied_options is not None and \ option in installed_package.applied_options: formatted_options.append(option, "brightyellow") else: formatted_options.append(option) else: if hasattr(installed_package, "applied_options") and installed_package.applied_options is not None: formatted_options = [out.color("%"+applied_option, "brightyellow") \ for applied_option in installed_package.applied_options] out.write(" [%s] %s/%s/%s {%s:%s} {%s} %s%s\n" % ( " ".join(status_bar), \ package.repo, \ package.category, \ package.name, \ out.color(package.slot, "yellow"),\ out.color(package.version, "green"),\ package.arch, \ other_version, \ " ("+", ".join(formatted_options)+")" if formatted_options else "" ) ) if package.id in conflicts: for conflict in conflicts[package.id]: category, name, slot = conflict.split("/") conflict = installdb.find_package(package_name=name, \ package_category=category, \ package_slot = slot).get(0) out.write("\t %s %s/%s/%s-%s" % (out.color(">> conflict:", "green"), \ conflict.repo,\ conflict.category, \ conflict.name, \ conflict.version ))
def get_convenient_package(self, package, instdb=False): def inline_options_management(inline_options): # TODO: inline_options variable must be a set # Check inline options, if an option is not available for the package, warn the user for inline_option in inline_options: if not inline_option in package.options: out.warn("%s option is not available for %s/%s/%s-%s. So that the option is removing..." % ( inline_option, package.repo, package.category, package.name, package.version )) inline_options.remove(inline_option) if inline_options: target = self.current_package.id if self.current_package is not \ None else self.parent_package.id my_package = package.category+"/"+package.name+"/"+package.slot if target in self.inline_option_targets: if my_package in self.inline_option_targets[target]: for option in inline_options: self.inline_option_targets[target][my_package].add(option) else: self.inline_option_targets[target][my_package] = set(inline_options) else: self.inline_option_targets[target] = {my_package: set(inline_options)} if package.id in self.inline_options: if not package.id in self.package_options: self.package_options[package.id] = set() for option in inline_options: if not option in self.inline_options[package.id]: self.inline_options[package.id].append(option) if package.id in self.package_options: self.package_options[package.id].add(option) else: self.inline_options[package.id] = inline_options if package.id in self.package_options: for inline_option in inline_options: self.package_options[package.id].add(inline_option) else: self.package_options[package.id] = set(inline_options) convenient_arches = utils.get_convenient_arches(self.conf.arch) current_package = self.parent_package if self.parent_package is not \ None else self.current_package result = LCollect() database = self.repodb if instdb is False else self.instdb slot = None gte, lte, lt, gt, et = False, False, False, False, False slot_parsed = package.split(":") if len(slot_parsed) == 2: data, slot = slot_parsed elif len(slot_parsed) > 2: out.error("%s invalid dependency in %s.py" % (data, self.current_package)) # Use and exception raise DependencyError else: data = package if ">=" == data[:2]: gte = True pkgname = data[2:] elif "<=" == data[:2]: lte = True pkgname = data[2:] elif "<" == data[:1]: lt = True pkgname = data[1:] elif ">" == data[:1]: gt = True pkgname = data[1:] elif "==" == data[:2]: et = True pkgname = data[2:] else: category, name = data.split("/") inline_options = self.parse_inline_options(name) if inline_options: name = name[:name.index("[")] if (category, name) in self.repository_cache: results = self.repository_cache[(category, name)] else: results = database.find_package(package_name=name, package_category=category) self.repository_cache[(category, name)] = results slot = self.get_convenient_slot(results, slot) if not results: if instdb: return current_package = current_package.repo+"/"+current_package.category+\ "/"+current_package.name+"-"+current_package.version+":"+current_package.slot out.error("unmet dependency: %s depends on %s" % (out.color(current_package, \ "red"), out.color(package, "red"))) raise DependencyError try: package = utils.get_convenient_package( results, self.locked_packages, self.custom_arch_requests, convenient_arches, self.instdb, slot ) except UnavailablePackage: for result in results: out.error("%s/%s/%s-%s:%s {%s} is unavailable for your arch(%s)." % (result.repo, result.category, \ result.name, result.version, result.slot, result.arch, self.conf.arch)) out.write("\n") out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) raise DependencyError except LockedPackage: out.error("these package(s) is/are locked by the system administrator:") for result in results: out.error_notify("%s/%s/%s-%s:%s {%s}" % (result.repo, result.category, \ result.name, result.version, result.slot, result.arch)) out.write("\n") out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) raise DependencyError # Set some variables to manage inline options inline_options_management(inline_options) return package category, name = pkgname.split("/") inline_options = self.parse_inline_options(name) if inline_options: name = name[:name.index("[")] name, version = utils.parse_pkgname(name) if (category, name) in self.repository_cache: results = self.repository_cache[(category, name)] else: results = database.find_package(package_name=name, package_category=category) self.repository_cache[(category, name)] = results slot = self.get_convenient_slot(results, slot) packages = [] decision_point = {} owner_package = current_package.repo+"/"+current_package.category+\ "/"+current_package.name+"-"+current_package.version if gte: decision_point = {"type": ">=", "version": version, \ "owner_package": owner_package, "owner_id": current_package.id} for result in results: comparison = utils.vercmp(result.version, version) if comparison == 1 or comparison == 0: packages.append(result) elif lte: decision_point = {"type": "<=", "version": version, \ "owner_package": owner_package, "owner_id": current_package.id} for result in results: comparison = utils.vercmp(result.version, version) if comparison == -1 or comparison == 0: packages.append(result) elif lt: decision_point = {"type": "<", "version": version, \ "owner_package": owner_package, "owner_id": current_package.id} for result in results: comparison = utils.vercmp(result.version, version) if comparison == -1: packages.append(result) elif gt: decision_point = {"type": ">", "version": version, \ "owner_package": owner_package, "owner_id": current_package.id} for result in results: comparison = utils.vercmp(result.version, version) if comparison == 1: packages.append(result) elif et: decision_point = {"type": "==", "version": version, \ "owner_package": owner_package, "owner_id": current_package.id} for result in results: comparison = utils.vercmp(result.version, version) if comparison == 0: packages.append(result) if not packages: out.error("unmet dependency: %s/%s/%s-%s:%s {%s} depends on %s" % \ (current_package.repo, \ current_package.category, \ current_package.name, \ current_package.version, \ current_package.slot, \ current_package.arch, \ out.color(package, "red"))) raise DependencyError try: package = utils.get_convenient_package( results if not packages else packages, self.locked_packages, self.custom_arch_requests, convenient_arches, self.instdb, slot ) except UnavailablePackage: for result in results: out.error("%s/%s/%s-%s:%s {%s}is unavailable for your arch(%s)." % (result.repo, result.category, \ result.name, result.version, result.slot, result.arch, self.conf.arch)) out.write("\n") out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) raise DependencyError except LockedPackage: out.error("these package(s) is/are locked by the system administrator:") for result in results: out.error_notify("%s/%s/%s-%s:%s {%s}" % (result.repo, result.category, \ result.name, result.version, result.slot, result.arch)) out.write("\n") out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \ current_package.category, current_package.name, current_package.version, \ current_package.slot, current_package.arch)) raise DependencyError # Set some variables to manage inline options inline_options_management(inline_options) if package.id in self.conditional_packages: self.conditional_packages[package.id].append(decision_point) else: self.conditional_packages[package.id] = [decision_point] return package
import sys from lpms import out from lpms import utils from lpms import shelltools from lpms.db import dbapi filesdb = dbapi.FilesDB() installdb = dbapi.InstallDB() cmdline = sys.argv if "--help" in cmdline: out.normal("A tool that to create reverse depends database from scratch.") out.write("To hide outputs use '--quiet' parameter.\n") if "--quiet" in cmdline: out.normal("creating reverse depends database...") if os.path.exists("/var/db/lpms/reverse_depends.db"): shelltools.remove_file("/var/db/lpms/reverse_depends.db") reversedb = dbapi.ReverseDependsDB() for package in installdb.get_all_names(): reverse_repo, reverse_category, reverse_name = package versions = [] map( lambda ver: versions.extend(ver), installdb.get_version(reverse_name,
def write(msg): out.write(msg)
def remove_package(pkgnames, instruction): '''Triggers remove operation for given packages''' if instruction.like: # handle shortened package names database = dbapi.InstallDB() for item in instruction.like: query = database.db.cursor.execute( "SELECT name FROM package where name LIKE ?", (item, )) results = query.fetchall() if results: for result in results: pkgnames.append(result[0]) del database file_relationsdb = dbapi.FileRelationsDB() #try: packages = [ GetPackage(pkgname, installdb=True).select() for pkgname in pkgnames ] #except PackageNotFound as package_name: # out.error("%s seems not installed." % package_name) # lpms.terminate() instruction.count = len(packages) index = 0 # FIXME: I must create a new reverse dependency handler implementation #if instruct["show-reverse-depends"]: # instruct["ask"] = True # # WARNING: the mechanism only shows directly reverse dependencies # # supposing that if A is a reverse dependency of B and C is depends on A. # # when the user removes B, A and C will be broken. But lpms will warn the user about A. # broken_packages = [] # reversedb = dbapi.ReverseDependsDB() # out.normal("resolving primary reverse dependencies...\n") # for package in packages: # category, name, version = package[1:] # if lpms.getopt("--use-file-relations"): # broken_packages.extend(file_relations.get_packages(category, name, version)) # else: # broken_packages.extend(reversedb.get_reverse_depends(category, name)) # if broken_packages: # out.warn("the following packages will be broken:\n") # for broken_package in broken_packages: # broken_repo, broken_category, broken_name, broken_version = broken_package # out.write(" %s %s/%s/%s-%s\n" % (out.color(">", "brightred"), broken_repo, broken_category, \ # broken_name, broken_version)) # else: # out.warn("no reverse dependency found.") if instruction.ask: out.write("\n") for package in packages: out.write( " %s %s/%s/%s-%s\n" % (out.color( ">", "brightgreen"), out.color(package.repo, "green"), out.color(package.category, "green"), out.color(package.name, "green"), out.color(package.version, "green"))) utils.xterm_title("lpms: confirmation request") out.write("\nTotal %s package will be removed.\n\n" % out.color(str(instruction.count), "green")) if not utils.confirm("Would you like to continue?"): out.write("quitting...\n") utils.xterm_title_reset() lpms.terminate() realroot = instruction.new_root if instruction.new_root else cst.root config = conf.LPMSConfig() for package in packages: fdb = file_collisions.CollisionProtect(package.category, package.name, \ package.slot, version=package.version, real_root=realroot) fdb.handle_collisions() if fdb.collisions: out.write(out.color(" > ", "brightyellow")+"file collisions detected while removing %s/%s/%s-%s\n\n" \ % (package.repo, package.category, package.name, package.version)) for (c_package, c_path) in fdb.collisions: c_category, c_name, c_slot, c_version = c_package out.write(out.color(" -- ", "red")+c_category+"/"+c_name+"-"\ +c_version+":"+c_slot+" -> "+c_path+"\n") if fdb.collisions and config.collision_protect and not \ lpms.getopt('--force-file-collision'): out.write( "\nquitting... use '--force-file-collision' to continue.\n" ) lpms.terminate() index += 1 instruction.index = index if not initpreter.InitializeInterpreter( package, instruction, ['remove'], remove=True).initialize(): out.warn("an error occured during remove operation: %s/%s/%s-%s" % (package.repo, package.category, \ package.name, package.version)) else: file_relationsdb.delete_item_by_pkgdata(package.category, package.name, package.version, commit=True)
def create_operation_plan(self): '''Resolve dependencies and prepares a convenient operation plan''' single_packages = PackageItem() for package in self.packages: self.parent_package = package self.current_package = None self.package_heap[package.id] = package dependencies = [] package_dependencies = self.collect_dependencies(package) if not package_dependencies: single_packages.add(package) continue # Create a list that consists of parent and child items for dependency in package_dependencies: dependency.parent = package.category+"/"+package.name+"/"+package.slot dependencies.append((package.id, dependency)) while True: buff = [] for parent, dependency in dependencies: self.current_package = dependency self.parent_package = None self.package_query.append((dependency.id, parent)) if dependency.id in self.processed: if self.processed[dependency.id] == self.package_options.get(dependency.id, None): # This package was processed and it has no option changes continue # Keep the package options to prevent extra transaction self.processed[dependency.id] = self.package_options.get(dependency.id, None) # Keep the package information for the next operations. # We don't want to create a new transaction for it. self.package_heap[dependency.id] = dependency # Get its dependencies package_collection = self.collect_dependencies(dependency) if not package_collection: # The item has no dependency continue # Create a list that consists of parent and child items for item in package_collection: item.parent = package.category+"/"+package.name+"/"+package.slot buff.append((dependency.id, item)) if not buff: # End of the node break dependencies = buff try: # Sort packages for building operation plan = sorter.topsort(self.package_query) except sorter.CycleError as err: answer, num_parents, children = err out.brightred("Circular dependency detected:\n") for items in sorter.find_cycles(parent_children=children): for item in items: package = self.repodb.find_package(package_id=item).get(0) out.write(package.repo+"/"+package.category+"/"+package.name+"-"\ +package.version+":"+package.slot+" ") out.write("\n") raise DependencyError # This part detects inline option conflicts removed = {} option_conflict = set() for package_id in self.inline_option_targets: for target in self.inline_option_targets[package_id]: for option in self.inline_option_targets[package_id][target]: if option.startswith("-"): if option in removed: removed[option].add((package_id, target)) else: removed[option] = set([(package_id, target)]) else: if "-"+option in removed: for (my_pkg_id, my_target) in removed["-"+option]: if my_target == target: option_conflict.add((my_target, \ self.package_heap[package_id], \ self.package_heap[my_pkg_id],\ option)) if option_conflict: out.error("option conflict detected:\n") for (pkg, add, remove, option)in option_conflict: out.error(out.color(option, "red")+" option on "+pkg+"\n") out.warn("%s/%s/%s/%s adds the option." % (add.repo, add.category, \ add.name, add.version)) out.warn("%s/%s/%s/%s removes the option." % (remove.repo, remove.category, \ remove.name, remove.version)) lpms.terminate() self.conditional_versions = {} for (key, values) in self.conditional_packages.items(): for value in values: target_package = self.package_heap[key] my_item = { "type": value["type"], "version": value["version"], "target": target_package.category+"/"+target_package.name+\ "/"+target_package.slot, } if not value["owner_id"] in self.conditional_versions: self.conditional_versions[value["owner_id"]] = [my_item] else: self.conditional_versions[value["owner_id"]].append(my_item) # TODO: I think I must use most professional way for ignore-depends feature. if lpms.getopt("--ignore-deps"): result = LCollect() result.packages = self.packages result.dependencies = self.package_dependencies result.options = self.package_options result.inline_option_targets = self.inline_option_targets result.conditional_versions = self.conditional_versions result.conflicts = self.conflicts return result # Workaround for postmerge dependencies for (id_dependency, id_package) in self.postmerge_dependencies: plan.remove(id_dependency) plan.insert(plan.index(id_package)+1, id_dependency) final_plan = PackageItem() required_package_ids = [package.id for package in self.packages] for package_id in plan: package = self.package_heap[package_id] continue_conditional = False # If a package has a conditional decision point, # we should consider the condition if package.id not in self.conditional_packages: for c_package_id in self.conditional_packages: c_package = self.package_heap[c_package_id] if package.pk == c_package.pk: continue_conditional = True if package_id in required_package_ids: final_plan.add_by_pk(c_package) break if package_id in required_package_ids: if continue_conditional is False: final_plan.add_by_pk(package) if continue_conditional: continue installed_package = self.instdb.find_package( package_category=package.category, package_name=package.name, package_slot=package.slot ) if installed_package: if package.id in self.inline_options: if installed_package.get(0).applied_options is None: final_plan.add_by_pk(package) continue continue_inline = False for inline_option in self.inline_options[package.id]: if not inline_option in installed_package.get(0).applied_options: final_plan.add_by_pk(package) continue_inline = True break if continue_inline: continue try: conditional_versions_query = self.instdb.find_conditional_versions( target=package.category+"/"+package.name+"/"+package.slot) if conditional_versions_query: for item in conditional_versions_query: item.decision_point["package_id"]=item.package_id if package.id in self.conditional_packages: if not item.decision_point in self.conditional_packages[package.id]: self.conditional_packages[package.id].append(item.decision_point) else: self.conditional_packages[package.id] = [item.decision_point] if package.id in self.conditional_packages: decision_points = self.conditional_packages[package.id] for decision_point in decision_points: comparison = utils.vercmp(installed_package.get(0).version, \ decision_point["version"]) if decision_point["type"] == ">=": if self.handle_condition_conflict(decision_point, final_plan, \ package.pk, ("<", ">"), (0, 1)) is False: continue if not comparison in (1, 0) or package.id in required_package_ids: final_plan.add_by_pk(package) elif decision_point["type"] == "<": if self.handle_condition_conflict(decision_point, final_plan, \ package.pk, (">", "<"), (0, -1)) is False: continue if comparison != -1: final_plan.add_by_pk(package) elif decision_point["type"] == ">": if self.handle_condition_conflict(decision_point, final_plan, \ package.pk, ("<", ">"), (0, 1)) is False: continue if comparison != 1 or package.id in required_package_ids: final_plan.add_by_pk(package) elif decision_point["type"] == "<=": if self.handle_condition_conflict(decision_point, final_plan, \ package.pk, (">", "<"), (0, -1)) is False: continue if not comparison in (-1, 0) or package.id in required_package_ids: final_plan.add_by_pk(package) elif decision_point["type"] == "==": if comparison != 0 or package.id in required_package_ids: final_plan.add_by_pk(package) except ConditionConflict: if not "owner_package" in decision_point: conflict_package = self.instdb.find_package(package_id=\ decision_point["package_id"]).get(0) decision_point["owner_package"] = conflict_package.repo+"/"+ \ conflict_package.category+"/"+ \ conflict_package.name+"/"+ \ conflict_package.version out.error("while selecting a convenient version of %s, a conflict detected:\n" % \ out.color(package.pk, "red")) out.notify(decision_point["owner_package"]+" wants "+\ decision_point["type"]+decision_point["version"]) out.notify(self.conflict_point["owner_package"]+" wants "+\ self.conflict_point["type"]+self.conflict_point["version"]) lpms.terminate("\nplease contact the package maintainers.") # Use new options if the package is effected if self.use_new_options and not package in final_plan: if package.id in self.package_options: for option in self.package_options[package.id]: if not option in installed_package.get(0).applied_options: final_plan.add_by_pk(package) break else: final_plan.add_by_pk(package) # Oh my god! Some packages have no dependency. if single_packages: for single_package in single_packages: for item_id in plan: if self.package_heap[item_id].pk == single_package.pk: single_packages.remove(single_package) break for single_package in single_packages: final_plan.insert_into(0, single_package) # Create LCollect object to manage package dependency data operation_plan = LCollect() operation_plan.packages = final_plan operation_plan.dependencies = self.package_dependencies operation_plan.options = self.package_options operation_plan.inline_option_targets = self.inline_option_targets operation_plan.conditional_versions = self.conditional_versions operation_plan.conflicts = self.conflicts return operation_plan
import sys from lpms import out from lpms import utils from lpms import shelltools from lpms.db import dbapi filesdb = dbapi.FilesDB() installdb = dbapi.InstallDB() cmdline = sys.argv if "--help" in cmdline: out.normal("A tool that to create reverse depends database from scratch.") out.write("To hide outputs use '--quiet' parameter.\n") if "--quiet" in cmdline: out.normal("creating reverse depends database...") if os.path.exists("/var/db/lpms/reverse_depends.db"): shelltools.remove_file("/var/db/lpms/reverse_depends.db") reversedb = dbapi.ReverseDependsDB() for package in installdb.get_all_names(): reverse_repo, reverse_category, reverse_name = package versions = [] map(lambda ver: versions.extend(ver), installdb.get_version(reverse_name, pkg_category=reverse_category).values()) for reverse_version in versions: depends = installdb.get_depends(reverse_repo, reverse_category, reverse_name, reverse_version)
def package_mangler(self, **kwargs): def collision_check(): # TODO: This is a temporary solution. collision_check function # must be a reusable part for using in remove operation out.normal("checking file collisions...") lpms.logger.info("checking file collisions") collision_object = file_collisions.CollisionProtect( environment.category, environment.name, environment.slot, real_root=environment.real_root, source_dir=environment.install_dir) collision_object.handle_collisions() if collision_object.orphans: out.write( out.color(" > ", "brightyellow") + "these files are orphan. the package will adopt the files:\n" ) index = 0 for orphan in collision_object.orphans: out.notify(orphan) index += 1 if index > 100: # FIXME: the files must be logged out.write( out.color(" > ", "brightyellow") + "...and many others.") break if collision_object.collisions: out.write( out.color(" > ", "brightyellow") + "file collisions detected:\n") for item in collision_object.collisions: (category, name, slot, version), path = item out.write(out.color(" -- ", "red")+category+"/"+name+"-"\ +version+":"+slot+" -> "+path+"\n") if collision_object.collisions and self.config.collision_protect: if environment.force_file_collision: out.warn( "Disregarding these collisions, you have been warned!") else: return False return True names = kwargs.get("names", self.request.names) # Prepare build environment out.normal("resolving dependencies") targets = api.resolve_dependencies(names, self.request.instruction) if self.request.instruction.pretend: out.write("\n") out.normal("these packages will be merged, respectively:\n") showplan.show(targets.packages, targets.conflicts, targets.options, installdb=dbapi.InstallDB()) out.write("\ntotal %s package(s) listed.\n\n" \ % out.color(str(len(targets.packages)), "green")) raise LpmsTerminate if self.request.instruction.ask: out.write("\n") out.normal("these packages will be merged, respectively:\n") showplan.show(targets.packages, targets.conflicts, targets.options, installdb=dbapi.InstallDB()) utils.xterm_title("lpms: confirmation request") out.write("\ntotal %s package(s) will be merged.\n\n" \ % out.color(str(len(targets.packages)), "green")) if not utils.confirm("Would you like to continue?"): # Reset terminal title and terminate lpms. utils.xterm_title_reset() raise LpmsTerminate self.request.instruction.count = len(targets.packages) for index, package in enumerate(targets.packages, 1): self.request.instruction.index = index retval, environment = api.prepare_environment( package, self.request.instruction, dependencies=targets.dependencies[package.id] if package.id in \ targets.dependencies else None, options=targets.options[package.id] if package.id in \ targets.options else None, conditional_versions=targets.conditional_versions[package.id] \ if package.id in targets.conditional_versions else None, conflicts=targets.conflicts[package.id] if package.id \ in targets.conflicts else None, inline_option_targets=targets.inline_option_targets[package.id] \ if package.id in targets.inline_option_targets else None ) if not retval: out.error( "There are some errors while preparing environment to build FOO." ) out.error( "So you should submit a bug report to fix the issue.") raise LpmsTerminate("thanks to flying with lpms.") # Now, run package script(spec) for configuring, building and install retval, environment = self.interpreter.initialize(environment) if retval is False: out.error( "There are some errors while building FOO from source.") out.error("Error messages should be seen above.") out.error( "If you want to submit a bug report, please attatch BAR or send above messages in a proper way." ) raise LpmsTerminate("thanks to flying with lpms.") elif retval is None: raise LpmsTerminate if not collision_check(): out.error( "File collisions detected. If you want to overwrite these files," ) out.error( "You have to use --force-file-collisions parameter or disable collision_protect in configuration file." ) raise LpmsTerminate("thanks to flying with lpms.") # Merge package to livefs if environment.not_merge: raise LpmsTerminate("not merging...") retval, environment = merge.Merge(environment).perform_operation() if not retval: raise LpmsTerminate("Some errors occured while merging %s" % environment.fullname) lpms.logger.info("finished %s/%s/%s-%s" % (package.repo, package.category, package.name, package.version)) utils.xterm_title("lpms: %s/%s finished" % (package.category, package.name)) out.normal("Cleaning build directory") shelltools.remove_dir(os.path.dirname(environment.install_dir)) catdir = os.path.dirname(os.path.dirname(environment.install_dir)) if not os.listdir(catdir): shelltools.remove_dir(catdir) # There is no error, exitting... out.normal("Completed.")