def execute(self, options_dict, non_option_args): if len(non_option_args) < 1: self.usage() return False plist = [] yum = self.yum() for dep in non_option_args: if yum.returnInstalledPackagesByDep (dep): continue try: pkg = yum.returnPackageByDep(dep) plist.append(pkg.name) except: rucktalk.error("Unable to satisfy requirement '%s'" % dep) return False installs, updates = self.find_available_packages(plist) if not installs and not updates: rucktalk.message("Requirements are already met on the system."); return True for i in installs: yum.install(i) for u in updates: exactmatches, matches, unmatched = self.find_packages([u.name], installed=True) yum.tsInfo.addUpdate(u, exactmatches[0]) self.start_transaction(dryrun=options_dict.has_key('dry-run'))
def usage_full(): rucktalk.message("Usage: ruck <command> <options> ...") rucktalk.message("") rucktalk.message("The following options are understood by all commands:") ruckformat.opt_table(default_opt_table) keys = command_dict.keys() if keys: command_list = [] for k in keys: description, constructor, aliases, hidden, basic, category = command_dict[k] if not hidden: command_list.append([k, aliases, description, category]) print_command_list(command_list, with_categories=1) rucktalk.message("") rucktalk.message("For more detailed information about a specific command,") rucktalk.message("run 'ruck <command name> --help'.") rucktalk.message("") else: rucktalk.error("<< No commands found --- something is wrong! >>")
def execute(self, options_dict, non_option_args): size = len(non_option_args) if size < 1: self.usage() return False table_rows = [] yum = self.yum() for file in non_option_args: if not os.access (file, os.F_OK): rucktalk.error("File %s does not exist" % file) continue matches = yum.rpmdb.searchFiles (file); if not matches: rucktalk.message("No package owns file %s" % file) continue for pkg in matches: row = ruckformat.package_to_row(yum, pkg, False, ["name", "version"]) if size > 1: row.insert (0, file) table_rows.append (row) if len(table_rows): if size == 1: ruckformat.tabular(["Name", "Version"], table_rows) else: ruckformat.tabular(["File", "Name", "Version"], table_rows)
def execute(self, options_dict, non_option_args): if len(non_option_args) != 1: self.usage() return False locks = rucklocks.get_locks() i = int(non_option_args[0]) - 1 if i >= len(locks): rucktalk.error("Invalid lock %s" % str(i + 1)) return False rucklocks.remove_lock(i) rucktalk.message("--- Lock successfully removed ---")
def execute(self, options_dict, non_option_args): if len(non_option_args) != 2: self.usage() return False repoid = non_option_args[0] url = non_option_args[1] if not self.check_url(url): rucktalk.error("Invalid url '%s'" % url) return False if self.find_repo_file(repoid) != None: rucktalk.error("Repository '%s' already exists" % repoid) return False yum = self.yum(repos=False) repopath = os.path.join(yum.conf.reposdir[0], repoid + ".repo") if not os.path.exists(os.path.dirname(repopath)): os.makedirs(os.path.dirname(repopath)) parser = ConfigParser() parser.add_section(repoid) name = repoid if options_dict.has_key('name'): name = options_dict['name'] parser.set(repoid, "name", name) if options_dict.has_key('mirrorlist'): parser.set(repoid, "mirrorlist", url) else: parser.set(repoid, "baseurl", url) parser.set(repoid, "enabled", "1") gpgval = "0" if options_dict.has_key('check-signatures'): gpgval = "1" parser.set(repoid, "gpgcheck", gpgval) parser.write(file(repopath, "w+")) rucktalk.message("--- Successfully added '%s' ---" % repoid)
def gpgsigcheck(self, pkgs): yum = self.yum() for p in pkgs: result, errmsg = yum.sigCheckPkg(p) if result == 0: # woo! pass elif result == 1: # FIXME: need to download gpg rucktalk.error("Ignoring missing gpg key.") pass else: yumtalk.error(errmsg) return False return True
def execute(self, options_dict, non_option_args): if len(non_option_args) < 1 or (options_dict.has_key('uninstalled-only') and options_dict.has_key('installed-only')): self.usage() return False table_rows = [] yum = self.yum() dtype = self.dep_type(); plist = [] unmatched1 = None unmatched2 = None if not options_dict.has_key('uninstalled-only'): exactmatches, matches, unmatched1 = self.find_packages (non_option_args, installed=True) plist = exactmatches + matches if not options_dict.has_key('installed-only'): exactmatches, matches, unmatched2 = self.find_packages (non_option_args, installed=False) plist += exactmatches plist += matches if (unmatched1 is None or len(unmatched1) > 0) and (unmatched2 is None or len(unmatched2)) > 0: if unmatched1 != None: arg = unmatched1[0] else: arg = unmatched2[0] rucktalk.error("Could not find package '%s'" % arg) return False for p in plist: rucktalk.message("--- %s ---" % ruckformat.package_to_str(p)) deps = p.returnPrco(dtype) if len(deps) == 0: rucktalk.message("\nNo %s found\n" % dtype) else: for dep in deps: #FIXME: piece of crap prcoPrintable sometimes chokes try: rucktalk.message(p.prcoPrintable(dep)) except: pass rucktalk.message('')
def execute(self, options_dict, non_option_args): if len(non_option_args) < 1: self.usage() return 1 yum = self.yum() exactmatches, matches, unmatched = self.find_packages(non_option_args, installed=1) if len(unmatched) > 0: rucktalk.error("Could not find package '%s'" % unmatched[0]) return False plist = exactmatches + matches for p in plist: yum.remove(p) self.start_transaction(dryrun=options_dict.has_key('dry-run'))
def execute(self, options_dict, non_option_args): if len(non_option_args) != 1: self.usage() return False repoid = non_option_args[0] repopath = self.find_repo_file(repoid) if repopath == None: rucktalk.error("Repository '%s' does not exist" % repoid) return False parser = ConfigParser() parser.read(repopath) parser.remove_section(repoid) if len(parser.sections()) == 0: os.unlink(repopath) else: parser.write(file(repopath, 'w+')) rucktalk.message("--- Successfully removed '%s' ---" % repoid)
def execute(self, options_dict, non_option_args): if len(non_option_args) < 1: self.usage() return 1 pk = self.pkcon() for arg in non_option_args: if os.path.exists(arg): rucktalk.error("This hasn't been implemented yet") # FIXME else: installs, removals = self.separate_args(non_option_args) pkids = pk.resolve(installs) if len(pkids) > 0: pk.install_packages(pkids) else: rucktalk.error("No packages found") return 1 if len(removals) > 0: pk.remove_packages(removals)
def usage_basic(): rucktalk.message("Usage: ruck <command> <options> ...") rucktalk.message("") keys = command_dict.keys() if keys: keys.sort() command_list = [] for k in keys: description, constructor, aliases, hidden, basic, category = command_dict[k] if not hidden and basic: command_list.append([k, aliases, description, category]) rucktalk.message("Some basic commands are:") print_command_list(command_list) rucktalk.message("") rucktalk.message("For a more complete list of commands and important options,") rucktalk.message("run \"ruck help\".") rucktalk.message("") else: rucktalk.error("<< No commands found --- something is wrong! >>")
def show_exception(e): if rucktalk.show_verbose: trace = "" exception = "" exc_list = traceback.format_exception_only(sys.exc_type, sys.exc_value) for entry in exc_list: exception += entry tb_list = traceback.format_tb(sys.exc_info()[2]) for entry in tb_list: trace += entry rucktalk.error(str(e)) rucktalk.error(trace) else: rucktalk.error(str(e))
def register(constructor): obj = constructor() name = obj.name() aliases = obj.aliases() hidden = obj.is_hidden() basic = obj.is_basic() description = obj.description_short() or "<No Description Available>" category = obj.category() if command_dict.has_key(name): rucktalk.error("Command name collision: '"+name+"'") else: command_dict[name] = (description, constructor, aliases, hidden, basic, category) for a in aliases: al = string.lower(a) if command_dict.has_key(al): rucktalk.error("Command/alias collision: '"+a+"'") elif alias_dict.has_key(al): rucktalk.error("Alias collision: '"+a+"'") else: alias_dict[al] = name
def start_transaction(self, dryrun=False, download_only=False): yum = self.yum() if not download_only: (rescode, resmsgs) = self.resolve_deps() if rescode != 2: for resmsg in resmsgs: rucktalk.error(resmsg) return False self.show_ts_packages() if self.tsInfo_is_empty(yum.tsInfo): rucktalk.warning("Nothing to do.") return False downloadpkgs = self.get_pkgs_to_download() if len(downloadpkgs) > 0: total_size = 0 for p in downloadpkgs: try: size = int(p.size()) total_size += size except: pass if total_size > 0: rucktalk.message("\nTotal download size: %s\n" % (ruckformat.bytes_to_str(total_size))) if self.need_prompt(): answer = raw_input('\nProceed with transaction? (y/N) ') if len(answer) != 1 or answer[0] != 'y': rucktalk.message('Transaction Canceled') return False problems = yum.downloadPkgs(downloadpkgs) if len(problems.keys()) > 0: rucktalk.error("Error downloading packages:") for key in problems.keys(): for error in unique(problems[key]): rucktalk.message(" %s: %s" % (key, error)) return False if download_only: for pkg in downloadpkgs: dest = ruckformat.package_to_str(pkg, repo=False) + ".rpm" shutil.move(pkg.localpath, dest) rucktalk.message ("Downloaded '%s'" % dest) return True # Check GPG signatures if not self.gpgsigcheck(downloadpkgs): return False tsConf = {} for feature in ['diskspacecheck']: # more to come, I'm sure tsConf[feature] = getattr(yum.conf, feature) if dryrun: testcb = ruckyum.RPMInstallCallback(output=1) testcb.tsInfo = yum.tsInfo # clean out the ts b/c we have to give it new paths to the rpms del yum.ts yum.initActionTs() yum.populateTs(keepold=0) # sigh tserrors = yum.ts.test(testcb, conf=tsConf) del testcb if len(tserrors) > 0: errstring = '' for descr in tserrors: errstring += ' %s\n' % descr rucktalk.error(errstring) return False else: rucktalk.message('Running Transaction Test') testcb = ruckyum.RPMInstallCallback(output=0) testcb.tsInfo = yum.tsInfo # clean out the ts b/c we have to give it new paths to the rpms del yum.ts yum.initActionTs() # save our dsCallback out dscb = yum.dsCallback yum.dsCallback = None # dumb, dumb dumb dumb! yum.populateTs(keepold=0) # sigh tserrors = yum.ts.test(testcb, conf=tsConf) del testcb if len(tserrors) > 0: errstring = 'Transaction Check Error: ' for descr in tserrors: errstring += ' %s\n' % descr rucktalk.error(errstring) return False rucktalk.message('Transaction Test Succeeded\n') del yum.ts yum.initActionTs() # make a new, blank ts to populate yum.populateTs(keepold=0) # populate the ts yum.ts.check() #required for ordering yum.ts.order() # order # put back our depcheck callback yum.dsCallback = dscb cb = ruckyum.RPMInstallCallback(output=1) cb.tsInfo = yum.tsInfo yum.runTransaction(cb=cb) rucktalk.message('\nTransaction Finished') return True
def expand_synthetic_args(argv): ### ### First, walk across our argument list and find any --read-from-file ### options. For each, read the arguments from the file and insert ### them directly after the --read-from-file option. ### i = 0 is_file_to_read_from = 0 while i < len(argv): arg = argv[i] file_to_read = None if is_file_to_read_from: file_to_read = arg is_file_to_read_from = 0 if arg == "--read-from-file": is_file_to_read_from = 1 elif string.find(arg, "--read-from-file=") == 0: file_to_read = arg[len("--read-from-file="):] is_file_to_read_from = 0 if file_to_read: lines = [] try: f = open(file_to_read, "r") lines = map(string.strip, f.readlines()) except IOError: rucktalk.error("Couldn't open file '%s' to read arguments" % file_to_read) sys.exit(1) argv = argv[:i] + lines + argv[i+1:] i = i + len(lines) i = i + 1 ### ### Next, look for --read-from-stdin options. If there is more than ### one on the command line, we split our list of options on blank ### lines. ### rfs_count = argv.count("--read-from-stdin") if rfs_count > 0: lines = map(string.strip, sys.stdin.readlines()) i = 0 # position in argv j = 0 # position in lines while i < len(argv): if argv[i] == "--read-from-stdin": if j < len(lines): if rfs_count > 1 and "" in lines[j:]: j1 = j + lines[j:].index("") argv = argv[:i+1] + lines[j:j1] + argv[i+1:] j = j1+1 else: argv = argv[:i+1] + \ filter(lambda x:x!="", lines[j:]) + \ argv[i+1:] j = len(lines) rfs_count = rfs_count - 1 i = i + 1 ### ### Finally, we filter our all of those --read-from-* arguments ### that we left lying around in argv. ### argv = filter(lambda x: \ string.find(x,"--read-from-file") != 0 \ and x != "--read-from-stdin", argv) return argv
def errorlog(self, level, message): rucktalk.error(message)
def execute(self, server, options_dict, non_option_args): rucktalk.error("Execute not implemented!") sys.exit(1)
def main(ver, ruck_dir): global local global ruck_version ruck_version = ver if os.environ.has_key("RUCK_DEBUG"): rucktalk.show_debug = 1 import rucklocks rucklocks.init() import_commands(ruck_dir) ### ### Grab the option list and extract the first non-option argument that ### looks like a command. This could get weird if someone passes the name ### of a command as the argument to an option. ### argv = sys.argv[1:] argv = ruckcommand.expand_synthetic_args(argv) if "--version" in argv: print print ruck_name + " " + ruck_version print ruck_copyright print sys.exit(0) command = ruckcommand.extract_command_from_argv(argv) if "-?" in argv or "--help" in argv: command.usage() sys.exit(0) # A hack to suppress extra whitespace when dumping. if command.name() == "dump": rucktalk.be_terse = 1 argv = ruckcommand.get_user_default_args(argv, command) opt_dict, args = command.process_argv(argv) ### ### Control verbosity ### if opt_dict.has_key("terse"): rucktalk.be_terse = 1 if opt_dict.has_key("quiet"): rucktalk.show_messages = 0 rucktalk.show_warnings = 0 if opt_dict.has_key("verbose"): rucktalk.show_verbose = 1 ### Whitespace is nice, so we always print a blank line before ### executing the command if not rucktalk.be_terse: rucktalk.message("") if opt_dict.has_key("cache-only") or os.getuid() != 0: command.cache_only = True elif opt_dict.has_key("no-plugins"): command.no_plugins = True try: command.execute(opt_dict, args) except IOError, e: if e.errno == 13: rucktalk.error("You must be root to execute this command") else: show_exception(e) sys.exit(1)
def process_argv(self, argv): ### ### Expand our synthetic args. ### Then compile our list of arguments into something that getopt can ### understand. Finally, call getopt on argv and massage the results ### in something easy-to-use. ### argv = get_user_default_args(argv, self.name()) opt_table = self.opt_table() short_opt_getopt = "" long_opt_getopt = [] short2long_dict = {} for o in opt_table: short_opt = o[0] long_opt = o[1] opt_desc = o[2] if short_opt: if short2long_dict.has_key(short_opt): rucktalk.error("Short option collision!") rucktalk.error("-" + short_opt + ", --" + long_opt) rucktalk.error(" vs.") rucktalk.error("-" + short_opt + ", --" + short2long_dict[short_opt]) sys.exit(1) short2long_dict[short_opt] = long_opt short_opt_getopt = short_opt_getopt + short_opt if opt_desc: short_opt_getopt = short_opt_getopt + ":" if opt_desc: long_opt_getopt.append(long_opt + "=") else: long_opt_getopt.append(long_opt) try: optlist, args = getopt.getopt(argv, short_opt_getopt, long_opt_getopt) except getopt.error: did_something = 0 for a in argv: if string.find(a,"--") == 0: if not a[2:] in map(lambda x:x[1], opt_table): rucktalk.error("Invalid argument " + a) did_something = 1 elif string.find(a, "-") == 0: if not a[1:] in map(lambda x:x[0], opt_table): rucktalk.error("Invalid argument " + a) did_something = 1 # Just in case something strange went wrong and we weren't # able to describe quite why the options parsing failed, # we print a catch-all error message. if not did_something: rucktalk.error("Invalid arguments") self.usage() sys.exit(1) ### ### Walk through our list of options and replace short options with the ### corresponding long option. ### i = 0 while i < len(optlist): key = optlist[i][0] if key[0:2] != "--": optlist[i] = ("--" + short2long_dict[key[1:]], optlist[i][1]) i = i + 1 ### ### Get the list of "orthogonal" options for this command and, if our ### list of options contains orthogonal elements, remove all but the ### last such option. ### (i.e. if we are handed --quiet --verbose, we drop the --quiet) ### optlist.reverse() for oo_list in self.orthogonal_opts(): i = 0 seen_oo = 0 while i < len(optlist): key = optlist[i][0] if key[2:] in oo_list: if seen_oo: del optlist[i] i = i - 1 seen_oo = 1 i = i + 1 optlist.reverse() ### ### Store our options in a dictionary ### opt_dict = {} for key, value in optlist: opt_dict[key[2:]] = value return opt_dict, args