def execute(policy, prog_args, dry_run = False, main = None, wrapper = None): """Execute program. On success, doesn't return. On failure, raises an Exception. Returns normally only for a successful dry run. @param policy: a policy with the selected versions @type policy: L{policy.Policy} @param prog_args: arguments to pass to the program @type prog_args: [str] @param dry_run: if True, just print a message about what would have happened @type dry_run: bool @param main: the name of the binary to run, or None to use the default @type main: str @param wrapper: a command to use to actually run the binary, or None to run the binary directly @type wrapper: str @precondition: C{policy.ready and policy.get_uncached_implementations() == []} """ for iface, impl in policy.implementation.iteritems(): assert impl _do_bindings(impl, impl.bindings) for dep in policy.solver.requires[iface]: dep_iface = iface_cache.get_interface(dep.interface) dep_impl = policy.get_implementation(dep_iface) if isinstance(dep_impl, ZeroInstallImplementation): _do_bindings(dep_impl, dep.bindings) else: debug(_("Implementation %s is native; no bindings needed"), dep_impl) root_iface = iface_cache.get_interface(policy.root) root_impl = policy.get_implementation(root_iface) _execute(root_impl, prog_args, dry_run, main, wrapper)
def process(impl): for dep in impl.requires: dep_iface = iface_cache.get_interface(dep.interface) dep_impl = policy.implementation.get(dep_iface) if dep_impl is not None: putenv(dep, dep_impl) process(dep_impl)
def update_uri(self, combo): env_insert = self.widgets.get_widget('env_insert') env_insert.get_model().clear() uri = combo.get_active_text() if uri not in self.known_ifaces: return impls = iface_cache.get_interface(uri).implementations.values() impls.sort() for impl in impls: if impl.id.startswith('/'): cached_impl = impl.id elif impl.id.startswith('package:'): cached_impl = None else: try: cached_impl = main.stores.lookup(impl.id) except NotStored, ex: cached_impl = None if cached_impl: for (dirpath, dirnames, filenames) in os.walk(cached_impl): for d in dirnames[:]: if d in ('.svn', 'CVS'): dirnames.remove(d) new = dirpath[len(cached_impl) + 1:] env_insert.append_text(new) break
def recalculate(self, fetch_stale_interfaces = True): """@deprecated: see L{solve_with_downloads} """ self.stale_feeds = set() host_arch = self.target_arch if self.src: host_arch = arch.SourceArchitecture(host_arch) self.solver.solve(self.root, host_arch) if self.network_use == network_offline: fetch_stale_interfaces = False blockers = [] for f in self.solver.feeds_used: if f.startswith('/'): continue feed = iface_cache.get_feed(f) if feed is None or feed.last_modified is None: self.download_and_import_feed_if_online(f) # Will start a download elif self.is_stale(feed): debug(_("Adding %s to stale set"), f) self.stale_feeds.add(iface_cache.get_interface(f)) # Legacy API if fetch_stale_interfaces: self.download_and_import_feed_if_online(f) # Will start a download for w in self.watchers: w() return blockers
def get_feed_targets(self, feed_iface_uri): """Return a list of Interfaces for which feed_iface can be a feed. This is used by B{0launch --feed}. @rtype: [model.Interface] @raise SafeException: If there are no known feeds.""" # TODO: what if it isn't cached yet? feed_iface = iface_cache.get_interface(feed_iface_uri) if not feed_iface.feed_for: if not feed_iface.name: raise SafeException(_("Can't get feed targets for '%s'; failed to load interface.") % feed_iface_uri) raise SafeException(_("Missing <feed-for> element in '%s'; " "this interface can't be used as a feed.") % feed_iface_uri) feed_targets = feed_iface.feed_for debug(_("Feed targets: %s"), feed_targets) if not feed_iface.name: warn(_("Warning: unknown interface '%s'") % feed_iface_uri) return [iface_cache.get_interface(uri) for uri in feed_targets]
def finish(): import xdgutils iface = iface_cache.get_interface(model.canonical_iface_uri(uri.get_text())) try: icon_path = iface_cache.get_icon_path(iface) xdgutils.add_to_menu(iface, icon_path, categories[category.get_active()]) except SafeException, ex: box = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, str(ex)) box.run() box.destroy()
def finish(): import xdgutils iface = iface_cache.get_interface(model.canonical_iface_uri(uri.get_text())) try: icon_path = iface_cache.get_icon_path(iface) xdgutils.add_to_menu(iface, icon_path, category.get_active_text()) except SafeException, ex: box = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, str(ex)) box.run() box.destroy()
def solve_with_downloads(self, force = False): """Run the solver, then download any feeds that are missing or that need to be updated. Each time a new feed is imported into the cache, the solver is run again, possibly adding new downloads. @param force: whether to download even if we're already ready to run.""" downloads_finished = set() # Successful or otherwise downloads_in_progress = {} # URL -> Download host_arch = self.target_arch if self.src: host_arch = arch.SourceArchitecture(host_arch) while True: postponed = self.solver.solve(self.root, host_arch, return_postponed=True) if postponed: while postponed: yield postponed postponed = [i for i in postponed if not i.happened] continue for w in self.watchers: w() if self.solver.ready and not force: break else: if self.network_use == network_offline and not force: info(_("Can't choose versions and in off-line mode, so aborting")) break # Once we've starting downloading some things, # we might as well get them all. force = True for f in self.solver.feeds_used: if f in downloads_finished or f in downloads_in_progress: continue if f.startswith('/'): continue feed = iface_cache.get_interface(f) downloads_in_progress[f] = self.fetcher.download_and_import_feed(f, iface_cache) if not downloads_in_progress: break blockers = downloads_in_progress.values() yield blockers tasks.check(blockers, self.handler.report_error) for f in downloads_in_progress.keys(): if downloads_in_progress[f].happened: del downloads_in_progress[f] downloads_finished.add(f)
def sel_changed(self, sel): model, miter = sel.get_selected() if not miter: return # build in progress iface = model[miter][Feeds.URI] # Only enable removing user_override feeds enable_remove = False for x in self.interface.feeds: if x.uri == iface: if x.user_override: enable_remove = True self.remove_feed_button.set_sensitive(enable_remove) self.description.set_details(iface_cache.get_interface(iface))
def finish(): from . import xdgutils iface_uri = model.canonical_iface_uri(uri.get_text()) iface = iface_cache.get_interface(iface_uri) feed = iface_cache.get_feed(iface_uri) try: icon_path = iface_cache.get_icon_path(iface) xdgutils.add_to_menu(feed, icon_path, categories[category.get_active()]) except SafeException as ex: box = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, str(ex)) box.run() box.destroy() else: self.window.destroy()
def detach(self, blocker): status = self._child.wait() if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0: msg = _('* failed to build;') self.emit('verbose', msg) return None else: msg = _('* done;') self.emit('verbose', msg) # XXX remove outdated cache values # pylint: disable-msg=W0212 root_iface = iface_cache.get_interface(self._src_uri) for feed in root_iface.feeds: del iface_cache._interfaces[feed.uri] del iface_cache._interfaces[root_iface.uri] return []
def update_details_page(): iface = iface_cache.get_interface(model.canonical_iface_uri(uri.get_text())) about.set_text('%s - %s' % (iface.get_name(), iface.summary)) icon_path = iface_cache.get_icon_path(iface) from zeroinstall.gtkui import icon icon_pixbuf = icon.load_icon(icon_path) if icon_pixbuf: icon_widget.set_from_pixbuf(icon_pixbuf) feed_category = None for meta in iface.get_metadata(XMLNS_IFACE, 'category'): feed_category = meta.content break if feed_category: i = 0 for row in categories: if row.lower() == feed_category.lower(): category.set_active(i) break i += 1 self.window.set_response_sensitive(_RESPONSE_PREV, True)
def update_details_page(): iface = iface_cache.get_interface(model.canonical_iface_uri(uri.get_text())) about.set_text('%s - %s' % (iface.get_name(), iface.summary)) icon_path = iface_cache.get_icon_path(iface) from zeroinstall.gtkui import icon icon_pixbuf = icon.load_icon(icon_path) if icon_pixbuf: icon_widget.set_from_pixbuf(icon_pixbuf) feed_category = None for meta in iface.get_metadata(XMLNS_IFACE, 'category'): feed_category = meta.content break if feed_category: i = 0 for row in category.get_model(): if row[0].lower() == feed_category.lower(): category.set_active(i) break i += 1 self.window.set_response_sensitive(_RESPONSE_PREV, True)
def _import_feed(args): from zeroinstall.support import tasks from zeroinstall.injector import gpg, handler from zeroinstall.injector.iface_cache import PendingFeed from xml.dom import minidom handler = handler.Handler() for x in args: if not os.path.isfile(x): raise SafeException(_("File '%s' does not exist") % x) logging.info(_("Importing from file '%s'"), x) signed_data = file(x) data, sigs = gpg.check_stream(signed_data) doc = minidom.parseString(data.read()) uri = doc.documentElement.getAttribute('uri') if not uri: raise SafeException(_("Missing 'uri' attribute on root element in '%s'") % x) iface = iface_cache.get_interface(uri) logging.info(_("Importing information about interface %s"), iface) signed_data.seek(0) pending = PendingFeed(uri, signed_data) def run(): keys_downloaded = tasks.Task(pending.download_keys(handler), "download keys") yield keys_downloaded.finished tasks.check(keys_downloaded.finished) if not iface_cache.update_interface_if_trusted(iface, pending.sigs, pending.new_xml): blocker = handler.confirm_trust_keys(iface, pending.sigs, pending.new_xml) if blocker: yield blocker tasks.check(blocker) if not iface_cache.update_interface_if_trusted(iface, pending.sigs, pending.new_xml): raise SafeException(_("No signing keys trusted; not importing")) task = tasks.Task(run(), "import feed") errors = handler.wait_for_blocker(task.finished) if errors: raise SafeException(_("Errors during download: ") + '\n'.join(errors))
def add_node(parent, iface): if iface in done: return done[iface] = True iter = self.model.append(parent) self.model[iter][InterfaceBrowser.INTERFACE] = iface self.model[iter][ InterfaceBrowser.INTERFACE_NAME] = iface.get_name() self.model[iter][InterfaceBrowser.SUMMARY] = iface.summary self.model[iter][InterfaceBrowser. ICON] = self.get_icon(iface) or self.default_icon impl = self.policy.implementation.get(iface, None) if impl: old_impl = self.original_implementation.get(iface, None) version_str = impl.get_version() if old_impl is not None and old_impl is not impl: version_str += _(' (was %s)') % old_impl.get_version() self.model[iter][InterfaceBrowser.VERSION] = version_str self.model[iter][ InterfaceBrowser.DOWNLOAD_SIZE] = utils.get_fetch_info( self.policy, impl) children = self.policy.solver.requires[iface] for child in children: if isinstance(child, model.InterfaceDependency): add_node(iter, iface_cache.get_interface(child.interface)) else: child_iter = self.model.append(parent) self.model[child_iter][ InterfaceBrowser.INTERFACE_NAME] = '?' self.model[child_iter][InterfaceBrowser.SUMMARY] = \ _('Unknown dependency type : %s') % child self.model[child_iter][ InterfaceBrowser.ICON] = self.default_icon else: self.model[iter][InterfaceBrowser.VERSION] = _('(choose)')
def have_source_for(policy, interface): # Note: we don't want to actually fetch the source interfaces at # this point, so we check whether: # - We have a feed of type 'src' (not fetched), or # - We have a source implementation in a regular feed have_src = False for f in interface.feeds: if f.machine == 'src': return True # Don't have any src feeds. Do we have a source implementation # as part of a regular feed? impls = interface.implementations.values() for f in policy.usable_feeds(interface): try: feed_iface = iface_cache.get_interface(f.uri) if feed_iface.implementations: impls.extend(feed_iface.implementations.values()) except zeroinstall.NeedDownload: pass # OK, will get called again later except Exception, ex: warn(_("Failed to load feed '%(feed)s': %(exception)s"), { 'feed': f.uri, 'exception': str(ex) })
def _check_for_updates(policy, verbose): root_iface = iface_cache.get_interface(policy.root).get_name() policy.handler = BackgroundHandler(root_iface, policy.root) info(_("Checking for updates to '%s' in a background process"), root_iface) if verbose: policy.handler.notify("Zero Install", _("Checking for updates to '%s'...") % root_iface, timeout=1) network_state = policy.handler.get_network_state() if network_state != _NetworkState.NM_STATE_CONNECTED: 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): info(_("Still not connected to network. Giving up.")) sys.exit(1) else: info(_("NetworkManager says we're on-line. Good!")) policy.freshness = 0 # Don't bother trying to refresh when getting the interface refresh = policy.refresh_all() # (causes confusing log messages) policy.handler.wait_for_blocker(refresh) # We could even download the archives here, but for now just # update the interfaces. if not policy.need_download(): if verbose: policy.handler.notify("Zero Install", _("No updates to download."), timeout=1) sys.exit(0) if not policy.handler.have_actions_support(): # Can't ask the user to choose, so just notify them # In particular, Ubuntu/Jaunty doesn't support actions policy.handler.notify("Zero Install", _("Updates ready to download for '%s'.") % root_iface, timeout=1) _exec_gui(policy.root, '--refresh', '--download-only', '--systray') sys.exit(1) notification_closed = tasks.Blocker("wait for notification response") def _NotificationClosed(nid, *unused): if nid != our_question: return notification_closed.trigger() def _ActionInvoked(nid, action): if nid != our_question: return if action == 'download': _exec_gui(policy.root) notification_closed.trigger() policy.handler.notification_service.connect_to_signal( 'NotificationClosed', _NotificationClosed) policy.handler.notification_service.connect_to_signal( 'ActionInvoked', _ActionInvoked) our_question = policy.handler.notify( "Zero Install", _("Updates ready to download for '%s'.") % root_iface, actions=['download', 'Download']) policy.handler.wait_for_blocker(notification_closed)
def run_gui(args): parser = OptionParser(usage=_("usage: %prog [options] interface")) parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION') parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU') parser.add_option("-c", "--cache", help=_("show the cache"), action='store_true') parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true') 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("-r", "--refresh", help=_("check for updates of all interfaces"), action='store_true') parser.add_option("-s", "--source", help=_("select source code"), action='store_true') parser.add_option("", "--systray", help=_("download in the background"), 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.disable_interspersed_args() (options, args) = parser.parse_args(args) if options.verbose: import logging logger = logging.getLogger() if options.verbose == 1: logger.setLevel(logging.INFO) else: logger.setLevel(logging.DEBUG) if options.cache: # Must fork before importing gtk, or ATK dies if os.fork(): # We exit, so our parent can call waitpid and unblock. sys.exit(0) # The grandchild continues... if options.with_store: from zeroinstall import zerostore for x in options.with_store: iface_cache.stores.stores.append(zerostore.Store(os.path.abspath(x))) import gui if options.version: print "0launch-gui (zero-install) " + gui.version print "Copyright (C) 2009 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.") sys.exit(0) import gtk if gtk.gdk.get_display() is None: print >>sys.stderr, "Failed to connect to display. Aborting." sys.exit(1) if not hasattr(gtk, 'combo_box_new_text'): import combo_compat if options.cache: import cache cache_explorer = cache.CacheExplorer() cache_explorer.show() cache_explorer.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) gtk.gdk.flush() cache_explorer.populate_model() cache_explorer.window.set_cursor(None) gtk.main() sys.exit(0) handler = gui.GUIHandler() if len(args) < 1: import preferences # Once we separate configuration from Policy, this hack can go away class DummyPolicy(Policy): def recalculate(fetch_stale_interfaces = True): pass def solve_with_downloads(force = False): pass box = preferences.show_preferences(DummyPolicy('http://localhost/dummy', handler)) box.connect('destroy', gtk.main_quit) gtk.main() sys.exit(0) interface_uri = args[0] if len(args) > 1: parser.print_help() sys.exit(1) import mainwindow, dialog restrictions = [] if options.before or options.not_before: restrictions.append(model.VersionRangeRestriction(model.parse_version(options.before), model.parse_version(options.not_before))) widgets = dialog.Template('main') policy = Policy(interface_uri, handler, src = bool(options.source)) policy.target_arch = arch.get_architecture(options.os, options.cpu) root_iface = iface_cache.get_interface(interface_uri) policy.solver.extra_restrictions[root_iface] = restrictions policy.solver.record_details = True window = mainwindow.MainWindow(policy, widgets, download_only = bool(options.download_only)) handler.mainwindow = window if options.message: window.set_message(options.message) root = iface_cache.get_interface(policy.root) window.browser.set_root(root) window.window.connect('destroy', lambda w: handler.abort_all_downloads()) if options.systray: window.use_systray_icon() @tasks.async def main(): force_refresh = bool(options.refresh) while True: window.refresh_button.set_sensitive(False) window.browser.set_update_icons(force_refresh) solved = policy.solve_with_downloads(force = force_refresh) if not window.systray_icon: window.show() yield solved try: window.refresh_button.set_sensitive(True) tasks.check(solved) except Exception, ex: window.report_exception(ex) if window.systray_icon and window.systray_icon.get_visible() and \ window.systray_icon.is_embedded(): if policy.ready: window.systray_icon.set_tooltip(_('Downloading updates for %s') % root_iface.get_name()) window.run_button.set_active(True) else: # Should already be reporting an error, but # blink it again just in case window.systray_icon.set_blinking(True) yield dialog.ButtonClickedBlocker(window.refresh_button) force_refresh = True
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 add_remote_feed(policy, parent, interface): try: d = gtk.MessageDialog( parent, 0, gtk.MESSAGE_QUESTION, gtk.BUTTONS_CANCEL, _('Enter the URL of the new source of implementations of this interface:' )) d.add_button(gtk.STOCK_ADD, gtk.RESPONSE_OK) d.set_default_response(gtk.RESPONSE_OK) entry = gtk.Entry() align = gtk.VBox(False, 0) align.set_border_width(4) align.add(entry) d.vbox.pack_start(align) entry.set_activates_default(True) entry.set_text('') d.vbox.show_all() error_label = gtk.Label('') error_label.set_padding(4, 4) align.pack_start(error_label) d.show() def error(message): if message: error_label.set_text(message) error_label.show() else: error_label.hide() while True: got_response = DialogResponse(d) yield got_response tasks.check(got_response) resp = got_response.response error(None) if resp == gtk.RESPONSE_OK: try: url = entry.get_text() if not url: raise zeroinstall.SafeException(_('Enter a URL')) fetch = policy.fetcher.download_and_import_feed( url, iface_cache) if fetch: d.set_sensitive(False) yield fetch d.set_sensitive(True) tasks.check(fetch) iface = iface_cache.get_interface(url) d.set_sensitive(True) if not iface.name: error(_('Failed to read interface')) return if not iface.feed_for: error( _("Feed '%(feed)s' is not a feed for '%(feed_for)s'." ) % { 'feed': iface.get_name(), 'feed_for': interface.get_name() }) elif interface.uri not in iface.feed_for: error( _("This is not a feed for '%(uri)s'.\nOnly for:\n%(feed_for)s" ) % { 'uri': interface.uri, 'feed_for': '\n'.join(iface.feed_for) }) elif iface.uri in [f.uri for f in interface.feeds]: error( _("Feed from '%s' has already been added!") % iface.uri) else: interface.extra_feeds.append( Feed(iface.uri, arch=None, user_override=True)) writer.save_interface(interface) d.destroy() policy.recalculate() except zeroinstall.SafeException, ex: error(str(ex)) else: d.destroy() return except Exception, ex: import traceback traceback.print_exc() policy.handler.report_error(ex)
def translate(s): if not s: return if s in done: return done.add(s) lines = escaped(s).split('\n') s = '\\n\\\n'.join(lines) result.write('_("%s")\n' % s) for uri in known: print uri assert uri.startswith('http://') assert not uri.startswith('http://0install.net/tests/') assert not uri.startswith('http://localhost') iface = iface_cache.get_interface(uri) if not iface.summary: print >>sys.stderr, "Unreadable:", iface.uri os.system("0launch -g -- '%s'" % uri) continue result.write('\n// Translations for %s (%s)\n' % (iface.get_name(), iface.uri)) translate(iface.summary) paragraphs = [format_para(p) for p in iface.description.split('\n\n')] translate('\n'.join(paragraphs)) result.close() if os.system('xgettext --keyword=_ --from-code=utf-8 feed-translations.c -o feed-translations.pot'):
def get_interface(self, uri): """@deprecated: use L{iface_cache.IfaceCache.get_interface} instead""" import warnings warnings.warn(_("Policy.get_interface is deprecated!"), DeprecationWarning, stacklevel = 2) return iface_cache.get_interface(uri)
def response(box, resp): if resp == RESPONSE_SETUP: def done_setup(): self.add_msg('Now use Build to compile the chosen source code.') self.run_command((sys.executable, main_path, 'setup'), done_setup) elif resp == RESPONSE_BUILD: def done_build(): self.add_msg('\nBuild successful. Now register or publish the build.') def build_failed(): self.add_msg('\nIf the messages displayed above indicate a missing dependency (e.g. no C compiler ' "or a library that isn't available through Zero Install) then install it using your " 'normal package manager and click on Build again. Note that for libraries you often ' 'need the -dev version of the package. ' '\nOtherwise, please notify the developers of this problem (this will transmit ' 'the contents of the build/build-failure.log file):') end = self.buffer.get_end_iter() anchor = self.buffer.create_child_anchor(end) align = gtk.Alignment(0.0, 0.0, 1.0, 1.0) button = ButtonMixed(gtk.STOCK_YES, 'Notify developers') align.add(button) align.set_padding(8, 8, 8, 8) align.show_all() self.tv.add_child_at_anchor(align, anchor) self.add_msg('\n') def report_bug(button): def done_notify(): self.add_msg("\nReport sent. Thank you! (note: you won't get a reply, as " "no contact details were sent; write to the project's mailing " "list if you want to discuss the problem)") self.run_command((sys.executable, main_path, 'report-bug'), done_notify) button.connect('clicked', report_bug) buildenv = BuildEnv() changes = buildenv.get_build_changes() if changes: options = get_build_options(box, '\n'.join(changes) + '\n\nIt would be best to do a clean (full) build.') else: options = [] if options is not None: box.run_command([sys.executable, main_path, 'build'] + options, done_build, build_failed) elif resp == RESPONSE_REGISTER: buildenv = BuildEnv() iface = iface_cache.get_interface(interface) reader.update_from_cache(iface) # Register using the feed-for, if available real_iface = iface for uri in iface.feed_for or []: real_iface = iface_cache.get_interface(uri) self.add_msg("Registering as a feed for %s" % real_iface.uri) break else: if os.path.isabs(iface.uri): self.add_msg("Warning: no <feed-for> in local feed %s!" % iface.uri) feed = buildenv.local_iface_file for f in real_iface.feeds or []: if f.uri == feed: self.add_msg("Feed '%s' is already registered for interface '%s'!\n" % (feed, real_iface.uri)) return box.buffer.insert_at_cursor("Registering feed '%s'\n" % feed) real_iface.extra_feeds.append(model.Feed(feed, arch = None, user_override = True)) writer.save_interface(real_iface) box.buffer.insert_at_cursor("Done. You can now close this window.\n") elif resp == RESPONSE_PUBLISH: buildenv = BuildEnv() box = PublishBox(self, buildenv) resp = box.run() box.destroy() if resp == gtk.RESPONSE_OK: def done_publish(): self.add_msg("\nYou can use '0publish --local' to add this " "into the main feed. If you don't have a main feed then this " "will create one. See " "http://0install.net/injector-packagers.html for more information.") self.run_command((sys.executable, main_path, 'publish', box.archive_dir.get_text()), done_publish) elif resp == gtk.RESPONSE_CANCEL or resp == gtk.RESPONSE_DELETE_EVENT: if self.kill_child(): return self.destroy() else: self.add_msg('Unknown response: %s' % resp)
def save_feed(feed): # This is wrong. Feed and interface settings should be saved in separate files. save_interface(iface_cache.get_interface(feed.url))