def handle(config, options, args): """@type config: L{zeroinstall.injector.config.Config} @type args: [str]""" if len(args) == 0: from zeroinstall import helpers if helpers.get_selections_gui(None, [], use_gui = options.gui) == helpers.DontUseGUI: for key, setting_type in settings.items(): value = getattr(config, key) print(key, "=", setting_type.format(value)) # (else we displayed the preferences dialog in the GUI) return elif len(args) > 2: raise UsageError() option = args[0] if option not in settings: raise SafeException(_('Unknown option "%s"') % option) if len(args) == 1: value = getattr(config, option) print(settings[option].format(value)) else: value = settings[option].parse(args[1]) if option == 'network_use' and value not in model.network_levels: raise SafeException(_("Must be one of %s") % list(model.network_levels)) setattr(config, option, value) config.save_globals()
def handle(config, options, args): if len(args) == 0: from zeroinstall import helpers if helpers.get_selections_gui(None, [], use_gui = options.gui) == helpers.DontUseGUI: for key, setting_type in settings.items(): value = getattr(config, key) print(key, "=", setting_type.format(value)) # (else we displayed the preferences dialog in the GUI) return elif len(args) > 2: raise UsageError() option = args[0] if option not in settings: raise SafeException(_('Unknown option "%s"') % option) if len(args) == 1: value = getattr(config, option) print(settings[option].format(value)) else: value = settings[option].parse(args[1]) if option == 'network_use' and value not in model.network_levels: raise SafeException(_("Must be one of %s") % list(model.network_levels)) setattr(config, option, value) config.save_globals()
def handle(config, options, args): if len(args) == 0: if options.gui is None and os.environ.get('DISPLAY', None): options.gui = True if options.gui: from zeroinstall import helpers return helpers.get_selections_gui(None, []) else: for key, setting_type in settings.iteritems(): value = getattr(config, key) print key, "=", setting_type.format(value) return elif len(args) > 2: raise UsageError() option = args[0] if option not in settings: raise SafeException(_('Unknown option "%s"') % option) if len(args) == 1: value = getattr(config, option) print settings[option].format(value) else: value = settings[option].parse(args[1]) if option == 'network_use' and value not in model.network_levels: raise SafeException(_("Must be one of %s") % list(model.network_levels)) setattr(config, option, value) config.save_globals()
def do_get_selections_gui(config, args): reqs, opts = args use_gui = opts['use_gui'] if use_gui == "yes": use_gui = True elif use_gui == "no": use_gui = False elif use_gui == "maybe": use_gui = None else: assert 0, use_gui gui_args = [] if opts['refresh']: gui_args += ['--refresh'] if opts['systray']: gui_args += ['--systray'] if opts['action'] == 'for-select': gui_args += ['--select-only'] elif opts['action'] == 'for-download': gui_args += ['--download-only'] elif opts['action'] != 'for-run': assert 0, opts reqs = reqs_from_json(reqs) gui_args += reqs.get_as_options() from zeroinstall import helpers sels = helpers.get_selections_gui(reqs.interface_uri, gui_args, use_gui = use_gui) if sels == helpers.DontUseGUI: return ["dont-use-gui"] if not sels: return ["aborted-by-user"] return ["ok", sels.toDOM().toxml()]
def handle(config, options, args): if len(args) == 0: if options.gui is None and os.environ.get('DISPLAY', None): options.gui = True if options.gui: from zeroinstall import helpers return helpers.get_selections_gui(None, []) else: for key, setting_type in settings.iteritems(): value = getattr(config, key) print(key, "=", setting_type.format(value)) return elif len(args) > 2: raise UsageError() option = args[0] if option not in settings: raise SafeException(_('Unknown option "%s"') % option) if len(args) == 1: value = getattr(config, option) print(settings[option].format(value)) else: value = settings[option].parse(args[1]) if option == 'network_use' and value not in model.network_levels: raise SafeException( _("Must be one of %s") % list(model.network_levels)) setattr(config, option, value) config.save_globals()
def do_get_selections_gui(config, args): reqs, opts = args use_gui = opts['use_gui'] if use_gui == "yes": use_gui = True elif use_gui == "no": use_gui = False elif use_gui == "maybe": use_gui = None else: assert 0, use_gui gui_args = [] if opts['refresh']: gui_args += ['--refresh'] if opts['systray']: gui_args += ['--systray'] if opts['action'] == 'for-select': gui_args += ['--select-only'] elif opts['action'] == 'for-download': gui_args += ['--download-only'] elif opts['action'] != 'for-run': assert 0, opts reqs = reqs_from_json(reqs) gui_args += reqs.get_as_options() from zeroinstall import helpers sels = helpers.get_selections_gui(reqs.interface_uri, gui_args, use_gui=use_gui) if sels == helpers.DontUseGUI: return ["dont-use-gui"] if not sels: return ["aborted-by-user"] return ["ok", sels.toDOM().toxml()]
def _foreground_update(self, driver, use_gui): """We can't run with saved selections or solved selections without downloading. Try to open the GUI for a blocking download. If we can't do that, download without the GUI. @type driver: L{zeroinstall.injector.driver.Driver} @rtype: L{zeroinstall.injector.selections.Selections}""" from zeroinstall import helpers from zeroinstall.support import tasks gui_args = driver.requirements.get_as_options() + [ '--download-only', '--refresh' ] sels = helpers.get_selections_gui(driver.requirements.interface_uri, gui_args, test_callback=None, use_gui=use_gui) if sels is None: raise SafeException("Aborted by user") if sels is helpers.DontUseGUI: downloaded = driver.solve_and_download_impls(refresh=True) if downloaded: tasks.wait_for_blocker(downloaded) sels = driver.solver.selections self.set_selections(sels, set_last_checked=True) return sels
def _fork_gui(iface_uri, gui_args, prog_args, options = None): """Run the GUI to get the selections. prog_args and options are used only if the GUI requests a test. """ from zeroinstall import helpers def test_callback(sels): from zeroinstall.injector import run return run.test_selections(sels, prog_args, bool(options and options.dry_run), options and options.main) return helpers.get_selections_gui(iface_uri, gui_args, test_callback)
def _foreground_update(self, driver, use_gui): """We can't run with saved selections or solved selections without downloading. Try to open the GUI for a blocking download. If we can't do that, download without the GUI.""" from zeroinstall import helpers from zeroinstall.support import tasks gui_args = driver.requirements.get_as_options() + ['--download-only', '--refresh'] sels = helpers.get_selections_gui(driver.requirements.interface_uri, gui_args, test_callback = None, use_gui = use_gui) if sels is None: raise SafeException("Aborted by user") if sels is helpers.DontUseGUI: downloaded = driver.solve_and_download_impls(refresh = True) if downloaded: tasks.wait_for_blocker(downloaded) sels = driver.solver.selections self.set_selections(sels, set_last_checked = True) return sels
def main(command_args, config=None): """Act as if 0launch was run with the given arguments. @arg command_args: array of arguments (e.g. C{sys.argv[1:]}) @type command_args: [str] """ # Ensure stdin, stdout and stderr FDs exist, to avoid confusion for std in (0, 1, 2): try: os.fstat(std) except OSError: fd = os.open('/dev/null', os.O_RDONLY) if fd != std: os.dup2(fd, std) os.close(fd) parser = OptionParser( usage=_("usage: %prog [options] interface [args]\n" " %prog --list [search-term]\n" " %prog --import [signed-interface-files]\n" " %prog --feed [interface]")) parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION') parser.add_option("", "--command", help=_("command to select"), metavar='COMMAND') parser.add_option("-c", "--console", help=_("never use GUI"), action='store_false', dest='gui') parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU') parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true') parser.add_option("-D", "--dry-run", help=_("just print actions"), action='store_true') parser.add_option("-f", "--feed", help=_("add or remove a feed"), action='store_true') parser.add_option("", "--get-selections", help=_("write selected versions as XML"), action='store_true', dest='xml') parser.add_option("-g", "--gui", help=_("show graphical policy editor"), action='store_true') parser.add_option("-i", "--import", help=_("import from files, not from the network"), action='store_true') parser.add_option("-l", "--list", help=_("list all known interfaces"), action='store_true') parser.add_option("-m", "--main", help=_("name of the file to execute")) parser.add_option("", "--message", help=_("message to display when interacting with user")) parser.add_option("", "--not-before", help=_("minimum version to choose"), metavar='VERSION') parser.add_option("", "--os", help=_("target operation system type"), metavar='OS') parser.add_option("-o", "--offline", help=_("try to avoid using the network"), action='store_true') parser.add_option("-r", "--refresh", help=_("refresh all used interfaces"), action='store_true') parser.add_option("", "--select-only", help=_("only download the feeds"), action='store_true') parser.add_option("", "--set-selections", help=_("run versions specified in XML file"), metavar='FILE') parser.add_option("", "--show", help=_("show where components are installed"), action='store_true') parser.add_option("-s", "--source", help=_("select source code"), action='store_true') parser.add_option("-v", "--verbose", help=_("more verbose output"), action='count') parser.add_option("-V", "--version", help=_("display version information"), action='store_true') parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR') parser.add_option("-w", "--wrapper", help=_("execute program using a debugger, etc"), metavar='COMMAND') parser.disable_interspersed_args() (options, args) = parser.parse_args(command_args) if options.verbose: logger = logging.getLogger() if options.verbose == 1: logger.setLevel(logging.INFO) else: logger.setLevel(logging.DEBUG) import zeroinstall logging.info( _("Running 0launch %(version)s %(args)s; Python %(python_version)s" ), { 'version': zeroinstall.version, 'args': repr(args), 'python_version': sys.version }) if options.select_only or options.show: options.download_only = True if config is None: config = load_config() config.handler.dry_run = bool(options.dry_run) if options.with_store: from zeroinstall import zerostore for x in options.with_store: config.stores.stores.append(zerostore.Store(os.path.abspath(x))) logging.info(_("Stores search path is now %s"), config.stores.stores) if options.set_selections: args = [options.set_selections] + args try: if options.list: from zeroinstall.cmd import list list.handle(config, options, args) elif options.version: import zeroinstall print("0launch (zero-install) " + zeroinstall.version) print("Copyright (C) 2010 Thomas Leonard") print( _("This program comes with ABSOLUTELY NO WARRANTY," "\nto the extent permitted by law." "\nYou may redistribute copies of this program" "\nunder the terms of the GNU Lesser General Public License." "\nFor more information about these matters, see the file named COPYING." )) elif getattr(options, 'import'): # (import is a keyword) cmd = __import__('zeroinstall.cmd.import', globals(), locals(), ["import"], 0) cmd.handle(config, options, args) elif options.feed: from zeroinstall.cmd import add_feed add_feed.handle(config, options, args, add_ok=True, remove_ok=True) elif options.select_only: from zeroinstall.cmd import select if not options.show: options.quiet = True select.handle(config, options, args) elif options.download_only or options.xml or options.show: from zeroinstall.cmd import download download.handle(config, options, args) else: if len(args) < 1: if options.gui: from zeroinstall import helpers return helpers.get_selections_gui(None, []) else: raise UsageError() else: from zeroinstall.cmd import run run.handle(config, options, args) except NeedDownload as ex: # This only happens for dry runs print(ex) except KeyboardInterrupt: logging.info("KeyboardInterrupt") sys.exit(1) except UsageError: parser.print_help() sys.exit(1) except SafeException as ex: if options.verbose: raise try: print(unicode(ex), file=sys.stderr) except: print(repr(ex), file=sys.stderr) sys.exit(1)
def _check_for_updates(requirements, verbose, app): """@type requirements: L{zeroinstall.injector.requirements.Requirements} @type verbose: bool @type app: L{zeroinstall.apps.App}""" if app is not None: old_sels = app.get_selections() from zeroinstall.injector.driver import Driver from zeroinstall.injector.config import load_config background_handler = BackgroundHandler(requirements.interface_uri, requirements.interface_uri) background_config = load_config(background_handler) root_iface = background_config.iface_cache.get_interface( requirements.interface_uri).get_name() background_handler.title = root_iface driver = Driver(config=background_config, requirements=requirements) logger.info(_("Checking for updates to '%s' in a background process"), root_iface) if verbose: background_handler.notify("Zero Install", _("Checking for updates to '%s'...") % root_iface, timeout=1) network_state = background_handler.get_network_state() if network_state not in (_NetworkState.NM_STATE_CONNECTED_SITE, _NetworkState.NM_STATE_CONNECTED_GLOBAL): logger.info( _("Not yet connected to network (status = %d). Sleeping for a bit..." ), network_state) import time time.sleep(120) if network_state in (_NetworkState.NM_STATE_DISCONNECTED, _NetworkState.NM_STATE_ASLEEP): logger.info(_("Still not connected to network. Giving up.")) sys.exit(1) else: logger.info(_("NetworkManager says we're on-line. Good!")) background_config.freshness = 0 # Don't bother trying to refresh when getting the interface refresh = driver.solve_with_downloads( force=True) # (causes confusing log messages) tasks.wait_for_blocker(refresh) if background_handler.need_gui or not driver.solver.ready or driver.get_uncached_implementations( ): if verbose: background_handler.notify( "Zero Install", _("Updates ready to download for '%s'.") % root_iface, timeout=1) # Run the GUI if possible... from zeroinstall import helpers gui_args = ['--refresh', '--systray', '--download' ] + requirements.get_as_options() new_sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, use_gui=None) if new_sels is None: sys.exit(0) # Cancelled by user elif new_sels is helpers.DontUseGUI: if not driver.solver.ready: background_handler.notify("Zero Install", _("Can't update '%s'") % root_iface) sys.exit(1) tasks.wait_for_blocker(driver.download_uncached_implementations()) new_sels = driver.solver.selections if app is None: background_handler.notify( "Zero Install", _("{name} updated.").format(name=root_iface), timeout=1) else: if verbose: background_handler.notify("Zero Install", _("No updates to download."), timeout=1) new_sels = driver.solver.selections if app is not None: assert driver.solver.ready from zeroinstall.support import xmltools if not xmltools.nodes_equal(new_sels.toDOM(), old_sels.toDOM()): app.set_selections(new_sels) background_handler.notify( "Zero Install", _("{app} updated.").format(app=app.get_name()), timeout=1) app.set_last_checked() sys.exit(0)
def _normal_mode(options, args): from zeroinstall.injector import handler if len(args) < 1: if options.gui: from zeroinstall import helpers return helpers.get_selections_gui(None, []) else: raise UsageError() iface_uri = model.canonical_iface_uri(args[0]) root_iface = iface_cache.get_interface(iface_uri) if os.isatty(1): h = handler.ConsoleHandler() else: h = handler.Handler() h.dry_run = bool(options.dry_run) policy = autopolicy.AutoPolicy(iface_uri, handler = h, download_only = bool(options.download_only), src = options.source) if options.before or options.not_before: policy.solver.extra_restrictions[root_iface] = [model.VersionRangeRestriction(model.parse_version(options.before), model.parse_version(options.not_before))] if options.os or options.cpu: from zeroinstall.injector import arch policy.target_arch = arch.get_architecture(options.os, options.cpu) if options.offline: policy.network_use = model.network_offline if options.get_selections: if len(args) > 1: raise SafeException(_("Can't use arguments with --get-selections")) if options.main: raise SafeException(_("Can't use --main with --get-selections")) # Note that need_download() triggers a solve if options.refresh or options.gui: # We could run immediately, but the user asked us not to can_run_immediately = False else: can_run_immediately = (not policy.need_download()) and policy.ready stale_feeds = [feed for feed in policy.solver.feeds_used if policy.is_stale(iface_cache.get_feed(feed))] if options.download_only and stale_feeds: can_run_immediately = False if can_run_immediately: if stale_feeds: if policy.network_use == model.network_offline: logging.debug(_("No doing background update because we are in off-line mode.")) else: # There are feeds we should update, but we can run without them. # Do the update in the background while the program is running. import background background.spawn_background_update(policy, options.verbose > 0) if options.get_selections: _get_selections(policy) else: if not options.download_only: from zeroinstall.injector import run run.execute(policy, args[1:], dry_run = options.dry_run, main = options.main, wrapper = options.wrapper) else: logging.info(_("Downloads done (download-only mode)")) assert options.dry_run or options.download_only return # If the user didn't say whether to use the GUI, choose for them. if options.gui is None and os.environ.get('DISPLAY', None): options.gui = True # If we need to download anything, we might as well # refresh all the interfaces first. Also, this triggers # the 'checking for updates' box, which is non-interactive # when there are no changes to the selection. options.refresh = True logging.info(_("Switching to GUI mode... (use --console to disable)")) prog_args = args[1:] try: from zeroinstall.injector import run if options.gui: gui_args = [] if options.download_only: # Just changes the button's label gui_args.append('--download-only') if options.refresh: gui_args.append('--refresh') if options.systray: gui_args.append('--systray') if options.not_before: gui_args.insert(0, options.not_before) gui_args.insert(0, '--not-before') if options.before: gui_args.insert(0, options.before) gui_args.insert(0, '--before') if options.source: gui_args.insert(0, '--source') if options.message: gui_args.insert(0, options.message) gui_args.insert(0, '--message') if options.verbose: gui_args.insert(0, '--verbose') if options.verbose > 1: gui_args.insert(0, '--verbose') if options.cpu: gui_args.insert(0, options.cpu) gui_args.insert(0, '--cpu') if options.os: gui_args.insert(0, options.os) gui_args.insert(0, '--os') if options.with_store: for x in options.with_store: gui_args += ['--with-store', x] sels = _fork_gui(iface_uri, gui_args, prog_args, options) if not sels: sys.exit(1) # Aborted else: #program_log('download_and_execute ' + iface_uri) downloaded = policy.solve_and_download_impls(refresh = bool(options.refresh)) if downloaded: policy.handler.wait_for_blocker(downloaded) sels = selections.Selections(policy) if options.get_selections: doc = sels.toDOM() doc.writexml(sys.stdout) sys.stdout.write('\n') elif not options.download_only: run.execute_selections(sels, prog_args, options.dry_run, options.main, options.wrapper) except NeedDownload, ex: # This only happens for dry runs print ex
def get_selections(config, options, iface_uri, select_only, download_only, test_callback): """Get selections for iface_uri, according to the options passed. Will switch to GUI mode if necessary. @param options: options from OptionParser @param iface_uri: canonical URI of the interface @param select_only: return immediately even if the selected versions aren't cached @param download_only: wait for stale feeds, and display GUI button as Download, not Run @return: the selected versions, or None if the user cancels @rtype: L{selections.Selections} | None """ if options.offline: config.network_use = model.network_offline # Try to load it as a feed. If it is a feed, it'll get cached. If not, it's a # selections document and we return immediately. maybe_selections = config.iface_cache.get_feed(iface_uri, selections_ok = True) if isinstance(maybe_selections, selections.Selections): if not select_only: blocker = maybe_selections.download_missing(config) if blocker: logging.info(_("Waiting for selected implementations to be downloaded...")) config.handler.wait_for_blocker(blocker) return maybe_selections r = requirements.Requirements(iface_uri) r.parse_options(options) policy = Policy(config = config, requirements = r) # Note that need_download() triggers a solve if options.refresh or options.gui: # We could run immediately, but the user asked us not to can_run_immediately = False else: if select_only: # --select-only: we only care that we've made a selection, not that we've cached the implementations policy.need_download() can_run_immediately = policy.ready else: can_run_immediately = not policy.need_download() stale_feeds = [feed for feed in policy.solver.feeds_used if not feed.startswith('distribution:') and # Ignore (memory-only) PackageKit feeds policy.is_stale(config.iface_cache.get_feed(feed))] if download_only and stale_feeds: can_run_immediately = False if can_run_immediately: if stale_feeds: if policy.network_use == model.network_offline: logging.debug(_("No doing background update because we are in off-line mode.")) else: # There are feeds we should update, but we can run without them. # Do the update in the background while the program is running. from zeroinstall.injector import background background.spawn_background_update(policy, options.verbose > 0) return policy.solver.selections # If the user didn't say whether to use the GUI, choose for them. if options.gui is None and os.environ.get('DISPLAY', None): options.gui = True # If we need to download anything, we might as well # refresh all the feeds first. options.refresh = True logging.info(_("Switching to GUI mode... (use --console to disable)")) if options.gui: gui_args = policy.requirements.get_as_options() if download_only: # Just changes the button's label gui_args.append('--download-only') if options.refresh: gui_args.append('--refresh') if options.verbose: gui_args.insert(0, '--verbose') if options.verbose > 1: gui_args.insert(0, '--verbose') if options.with_store: for x in options.with_store: gui_args += ['--with-store', x] if select_only: gui_args.append('--select-only') from zeroinstall import helpers sels = helpers.get_selections_gui(iface_uri, gui_args, test_callback) if not sels: return None # Aborted else: # Note: --download-only also makes us stop and download stale feeds first. downloaded = policy.solve_and_download_impls(refresh = options.refresh or download_only or False, select_only = select_only) if downloaded: config.handler.wait_for_blocker(downloaded) sels = selections.Selections(policy) return sels
def get_selections(config, options, iface_uri, select_only, download_only, test_callback): """Get selections for iface_uri, according to the options passed. Will switch to GUI mode if necessary. @param options: options from OptionParser @param iface_uri: canonical URI of the interface @param select_only: return immediately even if the selected versions aren't cached @param download_only: wait for stale feeds, and display GUI button as Download, not Run @return: the selected versions, or None if the user cancels @rtype: L{selections.Selections} | None """ if options.offline: config.network_use = model.network_offline iface_cache = config.iface_cache # Try to load it as a feed. If it is a feed, it'll get cached. If not, it's a # selections document and we return immediately. maybe_selections = iface_cache.get_feed(iface_uri, selections_ok = True) if isinstance(maybe_selections, selections.Selections): if not select_only: blocker = maybe_selections.download_missing(config) if blocker: logging.info(_("Waiting for selected implementations to be downloaded...")) tasks.wait_for_blocker(blocker) return maybe_selections r = requirements.Requirements(iface_uri) r.parse_options(options) policy = Policy(config = config, requirements = r) # Note that need_download() triggers a solve if options.refresh or options.gui: # We could run immediately, but the user asked us not to can_run_immediately = False else: if select_only: # --select-only: we only care that we've made a selection, not that we've cached the implementations policy.need_download() can_run_immediately = policy.ready else: can_run_immediately = not policy.need_download() stale_feeds = [feed for feed in policy.solver.feeds_used if not os.path.isabs(feed) and # Ignore local feeds (note: file might be missing too) not feed.startswith('distribution:') and # Ignore (memory-only) PackageKit feeds iface_cache.is_stale(iface_cache.get_feed(feed), config.freshness)] if download_only and stale_feeds: can_run_immediately = False if can_run_immediately: if stale_feeds: if policy.network_use == model.network_offline: logging.debug(_("No doing background update because we are in off-line mode.")) else: # There are feeds we should update, but we can run without them. # Do the update in the background while the program is running. from zeroinstall.injector import background background.spawn_background_update(policy, options.verbose > 0) return policy.solver.selections # If the user didn't say whether to use the GUI, choose for them. if options.gui is None and os.environ.get('DISPLAY', None): options.gui = True # If we need to download anything, we might as well # refresh all the feeds first. options.refresh = True logging.info(_("Switching to GUI mode... (use --console to disable)")) if options.gui: gui_args = policy.requirements.get_as_options() if download_only: # Just changes the button's label gui_args.append('--download-only') if options.refresh: gui_args.append('--refresh') if options.verbose: gui_args.insert(0, '--verbose') if options.verbose > 1: gui_args.insert(0, '--verbose') if options.with_store: for x in options.with_store: gui_args += ['--with-store', x] if select_only: gui_args.append('--select-only') from zeroinstall import helpers sels = helpers.get_selections_gui(iface_uri, gui_args, test_callback) if not sels: return None # Aborted else: # Note: --download-only also makes us stop and download stale feeds first. downloaded = policy.solve_and_download_impls(refresh = options.refresh or download_only or False, select_only = select_only) if downloaded: tasks.wait_for_blocker(downloaded) sels = selections.Selections(policy) return sels
def get_selections_for(requirements, config, options, select_only, download_only, test_callback): """Get selections for given requirements. @since: 1.9""" if options.offline: config.network_use = model.network_offline iface_cache = config.iface_cache driver = Driver(config = config, requirements = requirements) # Note that need_download() triggers a solve if options.refresh or options.gui: # We could run immediately, but the user asked us not to can_run_immediately = False else: if select_only: # --select-only: we only care that we've made a selection, not that we've cached the implementations driver.need_download() can_run_immediately = driver.solver.ready else: can_run_immediately = not driver.need_download() stale_feeds = [feed for feed in driver.solver.feeds_used if not feed.startswith('distribution:') and # Ignore (memory-only) PackageKit feeds iface_cache.is_stale(feed, config.freshness)] if download_only and stale_feeds: can_run_immediately = False if can_run_immediately: if stale_feeds: if config.network_use == model.network_offline: logger.debug(_("No doing background update because we are in off-line mode.")) else: # There are feeds we should update, but we can run without them. # Do the update in the background while the program is running. from zeroinstall.injector import background background.spawn_background_update(driver, options.verbose) return driver.solver.selections # If we need to download anything, we might as well # refresh all the feeds first. options.refresh = True if options.gui != False: # If the user didn't say whether to use the GUI, choose for them. gui_args = driver.requirements.get_as_options() if download_only: # Just changes the button's label gui_args.append('--download-only') if options.refresh: gui_args.append('--refresh') if options.verbose: gui_args.insert(0, '--verbose') if options.verbose > 1: gui_args.insert(0, '--verbose') if options.with_store: for x in options.with_store: gui_args += ['--with-store', x] if select_only: gui_args.append('--select-only') from zeroinstall import helpers sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, test_callback, use_gui = options.gui) if not sels: return None # Aborted elif sels is helpers.DontUseGUI: sels = None else: sels = None if sels is None: # Note: --download-only also makes us stop and download stale feeds first. downloaded = driver.solve_and_download_impls(refresh = options.refresh or download_only or False, select_only = select_only) if downloaded: tasks.wait_for_blocker(downloaded) sels = driver.solver.selections return sels
def get_selections_for(requirements, config, options, select_only, download_only, test_callback): """Get selections for given requirements. @since: 1.9""" if options.offline: config.network_use = model.network_offline iface_cache = config.iface_cache driver = Driver(config=config, requirements=requirements) # Note that need_download() triggers a solve if options.refresh or options.gui: # We could run immediately, but the user asked us not to can_run_immediately = False else: if select_only: # --select-only: we only care that we've made a selection, not that we've cached the implementations driver.need_download() can_run_immediately = driver.solver.ready else: can_run_immediately = not driver.need_download() stale_feeds = [ feed for feed in driver.solver.feeds_used if not feed.startswith('distribution:') and # Ignore (memory-only) PackageKit feeds iface_cache.is_stale(feed, config.freshness) ] if download_only and stale_feeds: can_run_immediately = False if can_run_immediately: if stale_feeds: if config.network_use == model.network_offline: logger.debug( _("No doing background update because we are in off-line mode." )) else: # There are feeds we should update, but we can run without them. # Do the update in the background while the program is running. from zeroinstall.injector import background background.spawn_background_update(driver, options.verbose) return driver.solver.selections # If we need to download anything, we might as well # refresh all the feeds first. options.refresh = True if options.gui != False: # If the user didn't say whether to use the GUI, choose for them. gui_args = driver.requirements.get_as_options() if download_only: # Just changes the button's label gui_args.append('--download-only') if options.refresh: gui_args.append('--refresh') if options.verbose: gui_args.insert(0, '--verbose') if options.verbose > 1: gui_args.insert(0, '--verbose') if options.with_store: for x in options.with_store: gui_args += ['--with-store', x] if select_only: gui_args.append('--select-only') from zeroinstall import helpers sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, test_callback, use_gui=options.gui) if not sels: return None # Aborted elif sels is helpers.DontUseGUI: sels = None else: sels = None if sels is None: # Note: --download-only also makes us stop and download stale feeds first. downloaded = driver.solve_and_download_impls(refresh=options.refresh or download_only or False, select_only=select_only) if downloaded: tasks.wait_for_blocker(downloaded) sels = driver.solver.selections return sels
def main(command_args, config = None): """Act as if 0launch was run with the given arguments. @arg command_args: array of arguments (e.g. C{sys.argv[1:]}) @type command_args: [str] """ # Ensure stdin, stdout and stderr FDs exist, to avoid confusion for std in (0, 1, 2): try: os.fstat(std) except OSError: fd = os.open(os.devnull, os.O_RDONLY) if fd != std: os.dup2(fd, std) os.close(fd) parser = OptionParser(usage=_("usage: %prog [options] interface [args]\n" " %prog --list [search-term]\n" " %prog --import [signed-interface-files]\n" " %prog --feed [interface]")) parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION') parser.add_option("", "--command", help=_("command to select"), metavar='COMMAND') parser.add_option("-c", "--console", help=_("never use GUI"), action='store_false', dest='gui') parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU') parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true') parser.add_option("-D", "--dry-run", help=_("just print actions"), action='store_true') parser.add_option("-f", "--feed", help=_("add or remove a feed"), action='store_true') parser.add_option("", "--get-selections", help=_("write selected versions as XML"), action='store_true', dest='xml') parser.add_option("-g", "--gui", help=_("show graphical policy editor"), action='store_true') parser.add_option("-i", "--import", help=_("import from files, not from the network"), action='store_true') parser.add_option("-l", "--list", help=_("list all known interfaces"), action='store_true') parser.add_option("-m", "--main", help=_("name of the file to execute")) parser.add_option("", "--message", help=_("message to display when interacting with user")) parser.add_option("", "--not-before", help=_("minimum version to choose"), metavar='VERSION') parser.add_option("", "--os", help=_("target operation system type"), metavar='OS') parser.add_option("-o", "--offline", help=_("try to avoid using the network"), action='store_true') parser.add_option("-r", "--refresh", help=_("refresh all used interfaces"), action='store_true') parser.add_option("", "--select-only", help=_("only download the feeds"), action='store_true') parser.add_option("", "--set-selections", help=_("run versions specified in XML file"), metavar='FILE') parser.add_option("", "--show", help=_("show where components are installed"), action='store_true') parser.add_option("-s", "--source", help=_("select source code"), action='store_true') parser.add_option("-v", "--verbose", help=_("more verbose output"), action='count') parser.add_option("-V", "--version", help=_("display version information"), action='store_true') parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR') parser.add_option("-w", "--wrapper", help=_("execute program using a debugger, etc"), metavar='COMMAND') parser.disable_interspersed_args() (options, args) = parser.parse_args(command_args) if options.verbose: logger = logging.getLogger() if options.verbose == 1: logger.setLevel(logging.INFO) else: logger.setLevel(logging.DEBUG) import zeroinstall logging.info(_("Running 0launch %(version)s %(args)s; Python %(python_version)s"), {'version': zeroinstall.version, 'args': repr(args), 'python_version': sys.version}) if options.select_only or options.show: options.download_only = True if config is None: config = load_config() config.handler.dry_run = bool(options.dry_run) if options.with_store: from zeroinstall import zerostore for x in options.with_store: config.stores.stores.append(zerostore.Store(os.path.abspath(x))) logging.info(_("Stores search path is now %s"), config.stores.stores) if options.set_selections: args = [options.set_selections] + args try: if options.list: from zeroinstall.cmd import list list.handle(config, options, args) elif options.version: import zeroinstall print("0launch (zero-install) " + zeroinstall.version) print("Copyright (C) 2010 Thomas Leonard") print(_("This program comes with ABSOLUTELY NO WARRANTY," "\nto the extent permitted by law." "\nYou may redistribute copies of this program" "\nunder the terms of the GNU Lesser General Public License." "\nFor more information about these matters, see the file named COPYING.")) elif getattr(options, 'import'): # (import is a keyword) cmd = __import__('zeroinstall.cmd.import', globals(), locals(), ["import"], 0) cmd.handle(config, options, args) elif options.feed: from zeroinstall.cmd import add_feed add_feed.handle(config, options, args, add_ok = True, remove_ok = True) elif options.select_only: from zeroinstall.cmd import select if not options.show: options.quiet = True select.handle(config, options, args) elif options.download_only or options.xml or options.show: from zeroinstall.cmd import download download.handle(config, options, args) else: if len(args) < 1: if options.gui: from zeroinstall import helpers return helpers.get_selections_gui(None, []) else: raise UsageError() else: from zeroinstall.cmd import run run.handle(config, options, args) except NeedDownload as ex: # This only happens for dry runs print(ex) except KeyboardInterrupt: logging.info("KeyboardInterrupt") sys.exit(1) except UsageError: parser.print_help() sys.exit(1) except SafeException as ex: if options.verbose: raise try: print(unicode(ex), file=sys.stderr) except: print(repr(ex), file=sys.stderr) sys.exit(1)
def _check_for_updates(requirements, verbose, app): if app is not None: old_sels = app.get_selections() from zeroinstall.injector.driver import Driver from zeroinstall.injector.config import load_config background_handler = BackgroundHandler(requirements.interface_uri, requirements.interface_uri) background_config = load_config(background_handler) root_iface = background_config.iface_cache.get_interface(requirements.interface_uri).get_name() background_handler.title = root_iface driver = Driver(config = background_config, requirements = requirements) logger.info(_("Checking for updates to '%s' in a background process"), root_iface) if verbose: background_handler.notify("Zero Install", _("Checking for updates to '%s'...") % root_iface, timeout = 1) network_state = background_handler.get_network_state() if network_state not in (_NetworkState.NM_STATE_CONNECTED_SITE, _NetworkState.NM_STATE_CONNECTED_GLOBAL): logger.info(_("Not yet connected to network (status = %d). Sleeping for a bit..."), network_state) import time time.sleep(120) if network_state in (_NetworkState.NM_STATE_DISCONNECTED, _NetworkState.NM_STATE_ASLEEP): logger.info(_("Still not connected to network. Giving up.")) sys.exit(1) else: logger.info(_("NetworkManager says we're on-line. Good!")) background_config.freshness = 0 # Don't bother trying to refresh when getting the interface refresh = driver.solve_with_downloads(force = True) # (causes confusing log messages) tasks.wait_for_blocker(refresh) if background_handler.need_gui or driver.get_uncached_implementations(): if verbose: background_handler.notify("Zero Install", _("Updates ready to download for '%s'.") % root_iface, timeout = 1) # Run the GUI if possible... from zeroinstall import helpers gui_args = ['--refresh', '--systray', '--download'] + requirements.get_as_options() new_sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, use_gui = None) if new_sels is None: sys.exit(0) # Cancelled by user elif new_sels is helpers.DontUseGUI: tasks.wait_for_blocker(driver.download_uncached_implementations()) new_sels = driver.solver.selections if app is None: background_handler.notify("Zero Install", _("{name} updated.").format(name = root_iface), timeout = 1) else: if verbose: background_handler.notify("Zero Install", _("No updates to download."), timeout = 1) new_sels = driver.solver.selections if app is not None: assert driver.solver.ready from zeroinstall.support import xmltools if not xmltools.nodes_equal(new_sels.toDOM(), old_sels.toDOM()): app.set_selections(new_sels) background_handler.notify("Zero Install", _("{app} updated.").format(app = app.get_name()), timeout = 1) app.set_last_checked() sys.exit(0)