def ensure_uptodate(self): if self._dry_run: if self.keys is None: self.keys = {} return from xml.dom import minidom # This is a bit inefficient... (could cache things) self.keys = {} trust = basedir.load_first_config(config_site, config_prog, 'trustdb.xml') if trust: keys = minidom.parse(trust).documentElement for key in keys.getElementsByTagNameNS(XMLNS_TRUST, 'key'): domains = set() self.keys[key.getAttribute('fingerprint')] = domains for domain in key.getElementsByTagNameNS(XMLNS_TRUST, 'domain'): domains.add(domain.getAttribute('value')) else: # Convert old database to XML format trust = basedir.load_first_config(config_site, config_prog, 'trust') if trust: #print "Loading trust from", trust_db with open(trust, 'rt') as stream: for key in stream: if key: self.keys[key] = set(['*'])
def get_inputs(): for sel in sels.selections.values(): logger.info("Checking %s", sel.feed) if sel.feed.startswith('distribution:'): # If the package has changed version, we'll detect that below # with get_unavailable_selections. pass elif os.path.isabs(sel.feed): # Local feed yield sel.feed else: # Cached feed cached = basedir.load_first_cache( namespaces.config_site, 'interfaces', model.escape(sel.feed)) if cached: yield cached else: raise IOError("Input %s missing; update" % sel.feed) # Per-feed configuration yield basedir.load_first_config( namespaces.config_site, namespaces.config_prog, 'interfaces', model._pretty_escape(sel.interface)) # Global configuration yield basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'global')
def ensure_uptodate(self): from xml.dom import minidom # This is a bit inefficient... (could cache things) self.keys = {} trust = basedir.load_first_config(config_site, config_prog, 'trustdb.xml') if trust: keys = minidom.parse(trust).documentElement for key in keys.getElementsByTagNameNS(XMLNS_TRUST, 'key'): domains = set() self.keys[key.getAttribute('fingerprint')] = domains for domain in key.getElementsByTagNameNS( XMLNS_TRUST, 'domain'): domains.add(domain.getAttribute('value')) else: # Convert old database to XML format trust = basedir.load_first_config(config_site, config_prog, 'trust') if trust: #print "Loading trust from", trust_db for key in file(trust).read().split('\n'): if key: self.keys[key] = set(['*']) else: # No trust database found. # Trust Thomas Leonard's key for 0install.net by default. # Avoids distracting confirmation box on first run when we check # for updates to the GUI. self.keys['92429807C9853C0744A68B9AAE07828059A53CC1'] = set( ['0install.net'])
def get_inputs(): for sel in sels.selections.values(): logger.info("Checking %s", sel.feed) if sel.feed.startswith('distribution:'): # If the package has changed version, we'll detect that below # with get_unavailable_selections. pass elif os.path.isabs(sel.feed): # Local feed yield sel.feed else: # Cached feed cached = basedir.load_first_cache(namespaces.config_site, 'interfaces', model.escape(sel.feed)) if cached: yield cached else: raise IOError("Input %s missing; update" % sel.feed) # Per-feed configuration yield basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'interfaces', model._pretty_escape(sel.interface)) # Global configuration yield basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'global')
def ensure_uptodate(self): if self._dry_run: if self.keys is None: self.keys = {} return from xml.dom import minidom # This is a bit inefficient... (could cache things) self.keys = {} trust = basedir.load_first_config(config_site, config_prog, 'trustdb.xml') if trust: keys = minidom.parse(trust).documentElement for key in keys.getElementsByTagNameNS(XMLNS_TRUST, 'key'): domains = set() self.keys[key.getAttribute('fingerprint')] = domains for domain in key.getElementsByTagNameNS( XMLNS_TRUST, 'domain'): domains.add(domain.getAttribute('value')) else: # Convert old database to XML format trust = basedir.load_first_config(config_site, config_prog, 'trust') if trust: #print "Loading trust from", trust_db with open(trust, 'rt') as stream: for key in stream: if key: self.keys[key] = set(['*'])
def ensure_uptodate(self): from xml.dom import minidom # This is a bit inefficient... (could cache things) self.keys = {} trust = basedir.load_first_config(config_site, config_prog, "trustdb.xml") if trust: keys = minidom.parse(trust).documentElement for key in keys.getElementsByTagNameNS(XMLNS_TRUST, "key"): domains = set() self.keys[key.getAttribute("fingerprint")] = domains for domain in key.getElementsByTagNameNS(XMLNS_TRUST, "domain"): domains.add(domain.getAttribute("value")) else: # Convert old database to XML format trust = basedir.load_first_config(config_site, config_prog, "trust") if trust: # print "Loading trust from", trust_db for key in file(trust).read().split("\n"): if key: self.keys[key] = set(["*"]) else: # No trust database found. # Trust Thomas Leonard's key for 0install.net by default. # Avoids distracting confirmation box on first run when we check # for updates to the GUI. self.keys["92429807C9853C0744A68B9AAE07828059A53CC1"] = set(["0install.net"])
def update_user_overrides(interface): """Update an interface with user-supplied information. Sets preferred stability and updates extra_feeds. @param interface: the interface object to update @type interface: L{model.Interface} """ user = basedir.load_first_config(config_site, config_prog, 'interfaces', model._pretty_escape(interface.uri)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(interface.uri)) if not user: return try: root = qdom.parse(file(user)) except Exception as ex: warn(_("Error reading '%(user)s': %(exception)s"), {'user': user, 'exception': ex}) raise stability_policy = root.getAttribute('stability-policy') if stability_policy: interface.set_stability_policy(stability_levels[str(stability_policy)]) for item in root.childNodes: if item.uri != XMLNS_IFACE: continue if item.name == 'feed': feed_src = item.getAttribute('src') if not feed_src: raise InvalidInterface(_('Missing "src" attribute in <feed>')) interface.extra_feeds.append(Feed(feed_src, item.getAttribute('arch'), True, langs = item.getAttribute('langs')))
def update_user_overrides(interface, known_site_feeds=frozenset()): """Update an interface with user-supplied information. Sets preferred stability and updates extra_feeds. @param interface: the interface object to update @type interface: L{model.Interface} @param known_site_feeds: feeds to ignore (for backwards compatibility) """ user = basedir.load_first_config(config_site, config_prog, 'interfaces', model._pretty_escape(interface.uri)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(interface.uri)) if not user: return try: with open(user, 'rb') as stream: root = qdom.parse(stream) except Exception as ex: logger.warn(_("Error reading '%(user)s': %(exception)s"), { 'user': user, 'exception': ex }) raise stability_policy = root.getAttribute('stability-policy') if stability_policy: interface.set_stability_policy(stability_levels[str(stability_policy)]) for item in root.childNodes: if item.uri != XMLNS_IFACE: continue if item.name == 'feed': feed_src = item.getAttribute('src') if not feed_src: raise InvalidInterface(_('Missing "src" attribute in <feed>')) # (note: 0install 1.9..1.12 used a different scheme and the "site-package" attribute; # we deliberately use a different attribute name to avoid confusion) if item.getAttribute('is-site-package'): # Site packages are detected earlier. This test isn't completely reliable, # since older versions will remove the attribute when saving the config # (hence the next test). continue if feed_src in known_site_feeds: continue interface.extra_feeds.append( Feed(feed_src, item.getAttribute('arch'), True, langs=item.getAttribute('langs')))
def lookup(uri, missing_ok=False): """Search repositories.json for the repository which hosts 'uri'.""" path = basedir.load_first_config('0install.net', '0repo', 'repositories.json') if path: with open(path, 'rb') as stream: db = json.load(stream) else: db = {} from_registry = None for key, value in db.items(): if uri.startswith(key): if from_registry: raise SafeException( "Multiple matching repositories! {a} and {b}".format( a=from_registry, b=value)) from_registry = value if not from_registry: if missing_ok: return None else: raise SafeException( "No registered repository for {uri} (hint: use '0repo register')" .format(uri=uri)) return from_registry
def load_config(handler = None): """@type handler: L{zeroinstall.injector.handler.Handler} | None @rtype: L{Config}""" config = Config(handler) parser = ConfigParser.RawConfigParser() parser.add_section('global') parser.set('global', 'help_with_testing', 'False') parser.set('global', 'freshness', str(60 * 60 * 24 * 30)) # One month parser.set('global', 'network_use', 'full') parser.set('global', 'auto_approve_keys', 'True') path = basedir.load_first_config(config_site, config_prog, 'global') if path: logger.info("Loading configuration from %s", path) try: parser.read(path) except Exception as ex: logger.warning(_("Error loading config: %s"), str(ex) or repr(ex)) config.help_with_testing = parser.getboolean('global', 'help_with_testing') config.network_use = parser.get('global', 'network_use') config.freshness = int(parser.get('global', 'freshness')) config.auto_approve_keys = parser.getboolean('global', 'auto_approve_keys') assert config.network_use in network_levels, config.network_use return config
def __init__(self): user_store = os.path.join(basedir.xdg_cache_home, '0install.net', 'implementations') self.stores = [Store(user_store)] impl_dirs = basedir.load_first_config('0install.net', 'injector', 'implementation-dirs') debug(_("Location of 'implementation-dirs' config file being used: '%s'"), impl_dirs) if impl_dirs: dirs = open(impl_dirs) else: if os.name == "nt": from win32com.shell import shell, shellcon localAppData = shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, 0, 0) commonAppData = shell.SHGetFolderPath(0, shellcon.CSIDL_COMMON_APPDATA, 0, 0) userCache = os.path.join(localAppData, "0install.net", "implementations") sharedCache = os.path.join(commonAppData, "0install.net", "implementations") dirs = [userCache, sharedCache] else: dirs = ['/var/cache/0install.net/implementations'] for directory in dirs: directory = directory.strip() if directory and not directory.startswith('#'): debug(_("Added system store '%s'"), directory) self.stores.append(Store(directory))
def __init__(self): user_store = os.path.join(basedir.xdg_cache_home, '0install.net', 'implementations') self.stores = [Store(user_store)] impl_dirs = basedir.load_first_config('0install.net', 'injector', 'implementation-dirs') logger.debug(_("Location of 'implementation-dirs' config file being used: '%s'"), impl_dirs) if impl_dirs: with open(impl_dirs, 'rt') as stream: dirs = stream.readlines() else: if os.name == "nt": from win32com.shell import shell, shellcon localAppData = shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, 0, 0) commonAppData = shell.SHGetFolderPath(0, shellcon.CSIDL_COMMON_APPDATA, 0, 0) userCache = os.path.join(localAppData, "0install.net", "implementations") sharedCache = os.path.join(commonAppData, "0install.net", "implementations") dirs = [userCache, sharedCache] else: dirs = ['/var/cache/0install.net/implementations'] for directory in dirs: directory = directory.strip() if directory and not directory.startswith('#'): logger.debug(_("Added system store '%s'"), directory) self.stores.append(Store(directory))
def load_config(handler=None): """@type handler: L{zeroinstall.injector.handler.Handler} | None @rtype: L{Config}""" config = Config(handler) parser = ConfigParser.RawConfigParser() parser.add_section('global') parser.set('global', 'help_with_testing', 'False') parser.set('global', 'freshness', str(60 * 60 * 24 * 30)) # One month parser.set('global', 'network_use', 'full') parser.set('global', 'auto_approve_keys', 'True') path = basedir.load_first_config(config_site, config_prog, 'global') if path: logger.info("Loading configuration from %s", path) try: parser.read(path) except Exception as ex: logger.warning(_("Error loading config: %s"), str(ex) or repr(ex)) config.help_with_testing = parser.getboolean('global', 'help_with_testing') config.network_use = parser.get('global', 'network_use') config.freshness = int(parser.get('global', 'freshness')) config.auto_approve_keys = parser.getboolean('global', 'auto_approve_keys') assert config.network_use in network_levels, config.network_use return config
def update_user_feed_overrides(feed): """Update a feed with user-supplied information. Sets last_checked and user_stability ratings. @param feed: feed to update @since 0.49 """ user = basedir.load_first_config(config_site, config_prog, 'feeds', model._pretty_escape(feed.url)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(feed.url)) if not user: return try: with open(user, 'rb') as stream: root = qdom.parse(stream) except Exception as ex: logger.warn(_("Error reading '%(user)s': %(exception)s"), { 'user': user, 'exception': ex }) raise last_checked = root.getAttribute('last-checked') if last_checked: feed.last_checked = int(last_checked) for item in root.childNodes: if item.uri != XMLNS_IFACE: continue if item.name == 'implementation': id = item.getAttribute('id') assert id is not None impl = feed.implementations.get(id, None) if not impl: logger.debug( _("Ignoring user-override for unknown implementation %(id)s in %(interface)s" ), { 'id': id, 'interface': feed }) continue user_stability = item.getAttribute('user-stability') if user_stability: impl.user_stability = stability_levels[str(user_stability)]
def testSitePackages(self): # The old system (0install < 1.9): # - 0compile stores implementations to ~/.cache, and # - adds to extra_feeds # # The middle system (0install 1.9..1.12) # - 0compile stores implementations to ~/.local/0install.net/site-packages # but using an obsolete escaping scheme, and # - modern 0install finds them via extra_feeds # # The new system (0install >= 1.13): # - 0compile stores implementations to ~/.local/0install.net/site-packages, and # - 0install finds them automatically # For backwards compatibility, 0install >= 1.9: # - writes discovered feeds to extra_feeds # - skips such entries in extra_feeds when loading expected_escape = 'section__prog_5f_1.xml' meta_dir = basedir.save_data_path('0install.net', 'site-packages', 'http', 'example.com', expected_escape, '1.0', '0install') feed = os.path.join(meta_dir, 'feed.xml') shutil.copyfile(os.path.join(mydir, 'Local.xml'), feed) # Check that we find the feed without us having to register it iface = self.config.iface_cache.get_interface('http://example.com/section/prog_1.xml') self.assertEqual(1, len(iface.extra_feeds)) site_feed, = iface.extra_feeds self.assertEqual(True, site_feed.site_package) # Check that we write it out, so that older 0installs can find it writer.save_interface(iface) config_file = basedir.load_first_config('0install.net', 'injector', 'interfaces', 'http:##example.com#section#prog_1.xml') with open(config_file, 'rb') as s: doc = qdom.parse(s) feed_node = None for item in doc.childNodes: if item.name == 'feed': feed_node = item self.assertEqual('True', feed_node.getAttribute('is-site-package')) # Check we ignore this element iface.reset() self.assertEqual([], iface.extra_feeds) reader.update_user_overrides(iface) self.assertEqual([], iface.extra_feeds) # Check feeds are automatically removed again reader.update_from_cache(iface, iface_cache = self.config.iface_cache) self.assertEqual(1, len(iface.extra_feeds)) shutil.rmtree(basedir.load_first_data('0install.net', 'site-packages', 'http', 'example.com', expected_escape)) reader.update_from_cache(iface, iface_cache = self.config.iface_cache) self.assertEqual(0, len(iface.extra_feeds))
def get_inputs(): for sel in sels.selections.values(): logger.info("Checking %s", sel.feed) feed = iface_cache.get_feed(sel.feed) if not feed: raise IOError("Input %s missing; update" % sel.feed) else: if feed.local_path: yield feed.local_path else: yield (feed.url, feed.last_modified) # Per-feed configuration yield basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'interfaces', model._pretty_escape(sel.interface)) # Global configuration yield basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'global')
def update_user_overrides(interface, known_site_feeds=frozenset()): """Update an interface with user-supplied information. Sets preferred stability and updates extra_feeds. @param interface: the interface object to update @type interface: L{model.Interface} @param known_site_feeds: feeds to ignore (for backwards compatibility) """ user = basedir.load_first_config(config_site, config_prog, "interfaces", model._pretty_escape(interface.uri)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, "user_overrides", escape(interface.uri)) if not user: return try: with open(user, "rb") as stream: root = qdom.parse(stream) except Exception as ex: logger.warn(_("Error reading '%(user)s': %(exception)s"), {"user": user, "exception": ex}) raise stability_policy = root.getAttribute("stability-policy") if stability_policy: interface.set_stability_policy(stability_levels[str(stability_policy)]) for item in root.childNodes: if item.uri != XMLNS_IFACE: continue if item.name == "feed": feed_src = item.getAttribute("src") if not feed_src: raise InvalidInterface(_('Missing "src" attribute in <feed>')) # (note: 0install 1.9..1.12 used a different scheme and the "site-package" attribute; # we deliberately use a different attribute name to avoid confusion) if item.getAttribute("is-site-package"): # Site packages are detected earlier. This test isn't completely reliable, # since older versions will remove the attribute when saving the config # (hence the next test). continue if feed_src in known_site_feeds: continue interface.extra_feeds.append( Feed(feed_src, item.getAttribute("arch"), True, langs=item.getAttribute("langs")) )
def update_user_feed_overrides(feed): """Update a feed with user-supplied information. Sets last_checked and user_stability ratings. @param feed: feed to update @since 0.49 """ user = basedir.load_first_config(config_site, config_prog, 'feeds', model._pretty_escape(feed.url)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(feed.url)) if not user: return try: root = qdom.parse(file(user)) except Exception, ex: warn(_("Error reading '%(user)s': %(exception)s"), {'user': user, 'exception': ex}) raise
def update_user_overrides(interface): """Update an interface with user-supplied information. Sets preferred stability and updates extra_feeds. @param interface: the interface object to update @type interface: L{model.Interface} """ user = basedir.load_first_config(config_site, config_prog, 'interfaces', model._pretty_escape(interface.uri)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(interface.uri)) if not user: return try: root = qdom.parse(file(user)) except Exception, ex: warn(_("Error reading '%(user)s': %(exception)s"), {'user': user, 'exception': ex}) raise
def get_inputs(): for sel in sels.selections.values(): logger.info("Checking %s", sel.feed) feed = iface_cache.get_feed(sel.feed) if not feed: raise IOError("Input %s missing; update" % sel.feed) else: if feed.local_path: yield feed.local_path else: yield (feed.url, feed.last_modified) # Per-feed configuration yield basedir.load_first_config( namespaces.config_site, namespaces.config_prog, 'interfaces', model._pretty_escape(sel.interface)) # Global configuration yield basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'global')
def update_user_feed_overrides(feed): """Update a feed with user-supplied information. Sets last_checked and user_stability ratings. @param feed: feed to update @since 0.49 """ user = basedir.load_first_config(config_site, config_prog, "feeds", model._pretty_escape(feed.url)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, "user_overrides", escape(feed.url)) if not user: return try: with open(user, "rb") as stream: root = qdom.parse(stream) except Exception as ex: logger.warn(_("Error reading '%(user)s': %(exception)s"), {"user": user, "exception": ex}) raise last_checked = root.getAttribute("last-checked") if last_checked: feed.last_checked = int(last_checked) for item in root.childNodes: if item.uri != XMLNS_IFACE: continue if item.name == "implementation": id = item.getAttribute("id") assert id is not None impl = feed.implementations.get(id, None) if not impl: logger.debug( _("Ignoring user-override for unknown implementation %(id)s in %(interface)s"), {"id": id, "interface": feed}, ) continue user_stability = item.getAttribute("user-stability") if user_stability: impl.user_stability = stability_levels[str(user_stability)]
def delete(self): if not os.path.isabs(self.uri): cached_iface = basedir.load_first_cache(namespaces.config_site, "interfaces", model.escape(self.uri)) if cached_iface: # print "Delete", cached_iface os.unlink(cached_iface) user_overrides = basedir.load_first_config( namespaces.config_site, namespaces.config_prog, "user_overrides", model.escape(self.uri) ) if user_overrides: # print "Delete", user_overrides os.unlink(user_overrides)
def _populate_model(self): # Find cached implementations unowned = {} # Impl ID -> Store duplicates = [] # TODO for s in self.iface_cache.stores.stores: if os.path.isdir(s.dir): for id in os.listdir(s.dir): if id in unowned: duplicates.append(id) unowned[id] = s ok_interfaces = [] error_interfaces = [] # Look through cached interfaces for implementation owners all = self.iface_cache.list_all_interfaces() all.sort() for uri in all: iface_size = 0 try: if uri.startswith('/'): cached_iface = uri else: cached_iface = basedir.load_first_cache( namespaces.config_site, 'interfaces', model.escape(uri)) user_overrides = basedir.load_first_config( namespaces.config_site, namespaces.config_prog, 'user_overrides', model.escape(uri)) iface_size = size_if_exists(cached_iface) + size_if_exists( user_overrides) iface = self.iface_cache.get_interface(uri) except Exception, ex: error_interfaces.append((uri, str(ex), iface_size)) else: cached_iface = ValidInterface(iface, iface_size) for impl in iface.implementations.values(): if impl.id.startswith('/') or impl.id.startswith('.'): cached_iface.in_cache.append(LocalImplementation(impl)) if impl.id in unowned: cached_dir = unowned[impl.id].dir impl_path = os.path.join(cached_dir, impl.id) impl_size = get_size(impl_path) cached_iface.in_cache.append( KnownImplementation(cached_iface, cached_dir, impl, impl_size)) del unowned[impl.id] cached_iface.in_cache.sort() ok_interfaces.append(cached_iface)
def testSitePackages(self): # The old system (0install < 1.9): # - 0compile stores implementations to ~/.cache, and # - adds to extra_feeds # The new system (0install >= 1.9): # - 0compile stores implementations to ~/.local/0install.net/site-packages, and # - 0install finds them automatically # For backwards compatibility, 0install >= 1.9: # - writes discovered feeds to extra_feeds # - skips such entries in extra_feeds when loading meta_dir = basedir.save_data_path('0install.net', 'site-packages', 'http:##example.com#prog.xml', '1.0', '0install') feed = os.path.join(meta_dir, 'feed.xml') shutil.copyfile(os.path.join(mydir, 'Local.xml'), feed) # Check that we find the feed without us having to register it iface = self.config.iface_cache.get_interface('http://example.com/prog.xml') self.assertEqual(1, len(iface.extra_feeds)) site_feed, = iface.extra_feeds self.assertEqual(True, site_feed.site_package) # Check that we write it out, so that older 0installs can find it writer.save_interface(iface) config_file = basedir.load_first_config('0install.net', 'injector', 'interfaces', 'http:##example.com#prog.xml') with open(config_file, 'rb') as s: doc = qdom.parse(s) feed_node = None for item in doc.childNodes: if item.name == 'feed': feed_node = item self.assertEqual('True', feed_node.getAttribute('site-package')) # Check we ignore this element iface.reset() self.assertEqual([], iface.extra_feeds) reader.update_user_overrides(iface) self.assertEqual([], iface.extra_feeds) # Check feeds are automatically removed again reader.update_from_cache(iface, iface_cache = self.config.iface_cache) self.assertEqual(1, len(iface.extra_feeds)) shutil.rmtree(basedir.load_first_data('0install.net', 'site-packages', 'http:##example.com#prog.xml')) reader.update_from_cache(iface, iface_cache = self.config.iface_cache) self.assertEqual(0, len(iface.extra_feeds))
def update_user_feed_overrides(feed): """Update a feed with user-supplied information. Sets last_checked and user_stability ratings. @param feed: feed to update @since 0.49 """ user = basedir.load_first_config(config_site, config_prog, 'feeds', model._pretty_escape(feed.url)) if user is None: # For files saved by 0launch < 0.49 user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(feed.url)) if not user: return try: root = qdom.parse(file(user)) except Exception as ex: warn(_("Error reading '%(user)s': %(exception)s"), {'user': user, 'exception': ex}) raise last_checked = root.getAttribute('last-checked') if last_checked: feed.last_checked = int(last_checked) for item in root.childNodes: if item.uri != XMLNS_IFACE: continue if item.name == 'implementation': id = item.getAttribute('id') assert id is not None impl = feed.implementations.get(id, None) if not impl: debug(_("Ignoring user-override for unknown implementation %(id)s in %(interface)s"), {'id': id, 'interface': feed}) continue user_stability = item.getAttribute('user-stability') if user_stability: impl.user_stability = stability_levels[str(user_stability)]
def load_config(handler): config = Config(handler) parser = ConfigParser.RawConfigParser() parser.add_section('global') parser.set('global', 'help_with_testing', 'False') parser.set('global', 'freshness', str(60 * 60 * 24 * 30)) # One month parser.set('global', 'network_use', 'full') path = basedir.load_first_config(config_site, config_prog, 'global') if path: info("Loading configuration from %s", path) try: parser.read(path) except Exception, ex: warn(_("Error loading config: %s"), str(ex) or repr(ex))
def delete(self): if not self.uri.startswith('/'): cached_iface = basedir.load_first_cache(namespaces.config_site, 'interfaces', model.escape(self.uri)) if cached_iface: #print "Delete", cached_iface os.unlink(cached_iface) user_overrides = basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'user_overrides', model.escape(self.uri)) if user_overrides: #print "Delete", user_overrides os.unlink(user_overrides)
def delete(self): if not os.path.isabs(self.uri): cached_iface = basedir.load_first_cache(namespaces.config_site, "interfaces", model.escape(self.uri)) if cached_iface: if SAFE_MODE: print("Delete", cached_iface) else: os.unlink(cached_iface) user_overrides = basedir.load_first_config( namespaces.config_site, namespaces.config_prog, "interfaces", model._pretty_escape(self.uri) ) if user_overrides: if SAFE_MODE: print("Delete", user_overrides) else: os.unlink(user_overrides)
def _populate_model(self): # Find cached implementations unowned = {} # Impl ID -> Store duplicates = [] # TODO for s in self.iface_cache.stores.stores: if os.path.isdir(s.dir): for id in os.listdir(s.dir): if id in unowned: duplicates.append(id) unowned[id] = s ok_interfaces = [] error_interfaces = [] # Look through cached interfaces for implementation owners all = self.iface_cache.list_all_interfaces() all.sort() for uri in all: iface_size = 0 try: if os.path.isabs(uri): cached_iface = uri else: cached_iface = basedir.load_first_cache(namespaces.config_site, "interfaces", model.escape(uri)) user_overrides = basedir.load_first_config( namespaces.config_site, namespaces.config_prog, "user_overrides", model.escape(uri) ) iface_size = size_if_exists(cached_iface) + size_if_exists(user_overrides) iface = self.iface_cache.get_interface(uri) except Exception, ex: error_interfaces.append((uri, str(ex), iface_size)) else: cached_iface = ValidInterface(iface, iface_size) for impl in iface.implementations.values(): if impl.local_path: cached_iface.in_cache.append(LocalImplementation(impl)) if impl.id in unowned: cached_dir = unowned[impl.id].dir impl_path = os.path.join(cached_dir, impl.id) impl_size = get_size(impl_path) cached_iface.in_cache.append(KnownImplementation(cached_iface, cached_dir, impl, impl_size)) del unowned[impl.id] cached_iface.in_cache.sort() ok_interfaces.append(cached_iface)
def lookup_app(self, name, missing_ok = False): """Get the App for name. Returns None if name is not an application (doesn't exist or is not a valid name). Since / and : are not valid name characters, it is generally safe to try this before calling L{injector.model.canonical_iface_uri}.""" if not valid_name.match(name): if missing_ok: return None else: raise SafeException("Invalid application name '{name}'".format(name = name)) app_dir = basedir.load_first_config(namespaces.config_site, "apps", name) if app_dir: return App(self.config, app_dir) if missing_ok: return None else: raise SafeException("No such application '{name}'".format(name = name))
def delete(self): if not os.path.isabs(self.uri): cached_iface = basedir.load_first_cache(namespaces.config_site, 'interfaces', model.escape(self.uri)) if cached_iface: if SAFE_MODE: print("Delete", cached_iface) else: os.unlink(cached_iface) user_overrides = basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'interfaces', model._pretty_escape(self.uri)) if user_overrides: if SAFE_MODE: print("Delete", user_overrides) else: os.unlink(user_overrides)
def __init__(self): user_store = os.path.join(basedir.xdg_cache_home, '0install.net', 'implementations') self.stores = [Store(user_store)] impl_dirs = basedir.load_first_config('0install.net', 'injector', 'implementation-dirs') debug( _("Location of 'implementation-dirs' config file being used: '%s'" ), impl_dirs) if impl_dirs: dirs = file(impl_dirs) else: dirs = ['/var/cache/0install.net/implementations'] for directory in dirs: directory = directory.strip() if directory and not directory.startswith('#'): debug(_("Added system store '%s'"), directory) self.stores.append(Store(directory))
def lookup_app(self, name, missing_ok=False): """Get the App for name. Returns None if name is not an application (doesn't exist or is not a valid name). Since / and : are not valid name characters, it is generally safe to try this before calling L{injector.model.canonical_iface_uri}.""" if not valid_name.match(name): if missing_ok: return None else: raise SafeException( "Invalid application name '{name}'".format(name=name)) app_dir = basedir.load_first_config(namespaces.config_site, "apps", name) if app_dir: return App(self.config, app_dir) if missing_ok: return None else: raise SafeException( "No such application '{name}'".format(name=name))
def update_user_overrides(interface, main_feed=None): """Update an interface with user-supplied information. @param interface: the interface object to update @type interface: L{model.Interface} @param main_feed: feed to update with last_checked information @note: feed updates shouldn't really be here. main_feed may go away in future. """ user = basedir.load_first_config(config_site, config_prog, 'user_overrides', escape(interface.uri)) if not user: return try: root = qdom.parse(file(user)) except Exception, ex: warn(_("Error reading '%(user)s': %(exception)s"), { 'user': user, 'exception': ex }) raise
def __init__(self, options, src_feed_name, release_version): self.src_feed_name = src_feed_name self.src_feed = support.load_feed(src_feed_name) self.archive_dir_public_url = support.get_archive_url( options, release_version, '') self.config = ConfigParser.RawConfigParser() # Start with a default configuration self.config.add_section('global') self.config.set('global', 'builders', 'host') self.config.add_section('builder-host') #self.config.set('builder-host', 'build', '0launch --not-before 0.10 http://0install.net/2007/interfaces/0release.xml --build-slave "$@"') self.config.set('builder-host', 'build', '') self.src_impl = support.get_singleton_impl(self.src_feed) if self.src_impl.arch and self.src_impl.arch.endswith('-src'): path = basedir.load_first_config('0install.net', '0release', 'builders.conf') if path: info("Loading configuration file '%s'", path) self.config.read(path) else: info( "No builders.conf configuration; will build a binary for this host only" ) if options.builders is not None: builders = options.builders else: builders = self.config.get('global', 'builders').strip() if builders: self.targets = [x.strip() for x in builders.split(',')] info("%d build targets configured: %s", len(self.targets), self.targets) else: self.targets = [] info("No builders set; no binaries will be built") else: self.targets = []
def __init__(self, root, handler = None, src = False): """ @param root: The URI of the root interface (the program we want to run). @param handler: A handler for main-loop integration. @type handler: L{zeroinstall.injector.handler.Handler} @param src: Whether we are looking for source code. @type src: bool """ self.watchers = [] self.freshness = 60 * 60 * 24 * 30 self.src = src # Root impl must be a "src" machine type self.stale_feeds = set() from zeroinstall.injector.solver import DefaultSolver self.solver = DefaultSolver(network_full, iface_cache, iface_cache.stores) # If we need to download something but can't because we are offline, # warn the user. But only the first time. self._warned_offline = False self._fetcher = None # (allow self for backwards compat) self.handler = handler or self debug(_("Supported systems: '%s'"), arch.os_ranks) debug(_("Supported processors: '%s'"), arch.machine_ranks) path = basedir.load_first_config(config_site, config_prog, 'global') if path: try: config = ConfigParser.ConfigParser() config.read(path) self.solver.help_with_testing = config.getboolean('global', 'help_with_testing') self.solver.network_use = config.get('global', 'network_use') self.freshness = int(config.get('global', 'freshness')) assert self.solver.network_use in network_levels, self.solver.network_use except Exception, ex: warn(_("Error loading config: %s"), str(ex) or repr(ex))
def __init__(self, options, src_feed_name, release_version): self.src_feed_name = src_feed_name self.src_feed = support.load_feed(src_feed_name) self.archive_dir_public_url = support.get_archive_url(options, release_version, '') self.config = ConfigParser.RawConfigParser() # Start with a default configuration self.config.add_section('global') self.config.set('global', 'builders', 'host') self.config.add_section('builder-host') #self.config.set('builder-host', 'build', '0launch --not-before 0.10 http://0install.net/2007/interfaces/0release.xml --build-slave "$@"') self.config.set('builder-host', 'build', '') self.src_impl = support.get_singleton_impl(self.src_feed) if self.src_impl.arch and self.src_impl.arch.endswith('-src'): path = basedir.load_first_config('0install.net', '0release', 'builders.conf') if path: info("Loading configuration file '%s'", path) self.config.read(path) else: info("No builders.conf configuration; will build a binary for this host only") if options.builders is not None: builders = options.builders else: builders = self.config.get('global', 'builders').strip() if builders: self.targets = [x.strip() for x in builders.split(',')] info("%d build targets configured: %s", len(self.targets), self.targets) else: self.targets = [] info("No builders set; no binaries will be built") else: self.targets = []
def lookup(uri, missing_ok = False): """Search repositories.json for the repository which hosts 'uri'.""" path = basedir.load_first_config('0install.net', '0repo', 'repositories.json') if path: with open(path, 'rb') as stream: db = json.load(stream) else: db = {} from_registry = None for key, value in db.items(): if uri.startswith(key): if from_registry: raise SafeException("Multiple matching repositories! {a} and {b}".format( a = from_registry, b = value)) from_registry = value if not from_registry: if missing_ok: return None else: raise SafeException("No registered repository for {uri} (hint: use '0repo register')".format(uri = uri)) return from_registry
def testBackgroundApp(self): my_dbus.system_services = {"org.freedesktop.NetworkManager": {"/org/freedesktop/NetworkManager": NetworkManager()}} trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000') global ran_gui with output_suppressed(): # Create an app, downloading a version of Hello run_server('Hello.xml', '6FCF121BE2390E0B.gpg', 'HelloWorld.tgz') out, err = self.run_ocaml(['add', 'test-app', 'http://example.com:8000/Hello.xml']) assert not out, out assert not err, err kill_server_process() app = basedir.load_first_config(namespaces.config_site, "apps", 'test-app') timestamp = os.path.join(app, 'last-checked') last_check_attempt = os.path.join(app, 'last-check-attempt') selections_path = os.path.join(app, 'selections.xml') def reset_timestamps(): global ran_gui ran_gui = False os.utime(timestamp, (1, 1)) # 1970 os.utime(selections_path, (1, 1)) if os.path.exists(last_check_attempt): os.unlink(last_check_attempt) # Not time for a background update yet self.config.freshness = 100 self.run_ocaml(['download', 'test-app']) assert not ran_gui # Trigger a background update - no updates found os.environ['ZEROINSTALL_TEST_BACKGROUND'] = 'true' reset_timestamps() run_server('Hello.xml') # (-vv mode makes us wait for the background process to finish) out, err = self.run_ocaml(['download', '-vv', 'test-app']) assert not out, out assert 'Background update: no updates found for test-app' in err, err self.assertNotEqual(1, os.stat(timestamp).st_mtime) self.assertEqual(1, os.stat(selections_path).st_mtime) kill_server_process() # Change the selections sels_path = os.path.join(app, 'selections.xml') with open(sels_path) as stream: old = stream.read() with open(sels_path, 'w') as stream: stream.write(old.replace('Hello', 'Goodbye')) # Trigger another background update - metadata changes found reset_timestamps() run_server('Hello.xml') out, err = self.run_ocaml(['download', '-vv', 'test-app']) assert not out, out assert 'Quick solve succeeded; saving new selections' in err, err self.assertNotEqual(1, os.stat(timestamp).st_mtime) self.assertNotEqual(1, os.stat(selections_path).st_mtime) kill_server_process() # Trigger another background update - GUI needed now # Delete cached implementation so we need to download it again out, err = self.run_ocaml(['select', '--xml', 'test-app'], binary = True) sels = selections.Selections(qdom.parse(BytesIO(out))) stored = sels.selections['http://example.com:8000/Hello.xml'].get_path(self.config.stores) assert os.path.basename(stored).startswith('sha1') ro_rmtree(stored) # Replace with a valid local feed so we don't have to download immediately with open(sels_path, 'w') as stream: stream.write(local_hello) os.environ['DISPLAY'] = 'dummy' reset_timestamps() run_server('Hello.xml') out, err = self.run_ocaml(['download', '-vv', 'test-app']) assert not out, out assert 'get-selections-gui' in err, err kill_server_process() # Now again with no DISPLAY reset_timestamps() del os.environ['DISPLAY'] run_server('Hello.xml', 'HelloWorld.tgz') out, err = self.run_ocaml(['download', '-vv', 'test-app']) assert not out, out assert 'GUI unavailable; downloading with no UI' in err, err self.assertNotEqual(1, os.stat(timestamp).st_mtime) self.assertNotEqual(1, os.stat(selections_path).st_mtime) kill_server_process() out, err = self.run_ocaml(['select', '--xml', 'test-app'], binary = True) sels = selections.Selections(qdom.parse(BytesIO(out))) sel, = sels.selections.values() self.assertEqual("sha1=3ce644dc725f1d21cfcf02562c76f375944b266a", sel.id) # Untrust the key trust.trust_db.untrust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000') os.environ['DISPLAY'] = 'dummy' reset_timestamps() run_server('Hello.xml') out, err = self.run_ocaml(['download', '-vv', 'test-app']) assert not out, out assert 'need to switch to GUI to confirm keys' in err, err assert 'get-selections-gui' in err, err kill_server_process() # Update not triggered because of last-check-attempt ran_gui = False os.utime(timestamp, (1, 1)) # 1970 os.utime(selections_path, (1, 1)) out, err = self.run_ocaml(['download', '-vv', 'test-app']) assert not out, out assert 'Tried to check within last hour; not trying again now' in err, err
def testBackgroundUnsolvable(self): my_dbus.system_services = {"org.freedesktop.NetworkManager": {"/org/freedesktop/NetworkManager": NetworkManager()}} trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000') # Create new app run_server('Hello.xml', '6FCF121BE2390E0B.gpg', 'HelloWorld.tgz') out, err = self.run_ocaml(['add', 'test-app', 'http://example.com:8000/Hello.xml']) kill_server_process() assert not out, out assert not err, err # Delete cached implementation so we need to download it again out, err = self.run_ocaml(['select', '--xml', 'test-app'], binary = True) sels = selections.Selections(qdom.parse(BytesIO(out))) stored = sels.selections['http://example.com:8000/Hello.xml'].get_path(self.config.stores) assert os.path.basename(stored).startswith('sha1') ro_rmtree(stored) out, err = self.run_ocaml(['select', '--xml', 'test-app'], binary = True) assert not err, err sels = selections.Selections(qdom.parse(BytesIO(out))) # Replace the selection with a bogus and unusable <package-implementation> sel, = sels.selections.values() sel.attrs['id'] = "package:dummy:badpackage" sel.attrs['from-feed'] = "distribution:http://example.com:8000/Hello.xml" sel.attrs['package'] = "badpackage" sel.get_command('run').qdom.attrs['path'] = '/i/dont/exist' app = basedir.load_first_config(namespaces.config_site, "apps", 'test-app') with open(os.path.join(app, 'selections.xml'), 'wt') as stream: doc = sels.toDOM() doc.writexml(stream, addindent=" ", newl="\n", encoding = 'utf-8') # Not time for a background update yet, but the missing binary should trigger # an update anyway. self.config.freshness = 0 # Check we try to launch the GUI... os.environ['DISPLAY'] = 'dummy' run_server('Hello.xml', 'HelloWorld.tgz') out, err = self.run_ocaml(['download', '--xml', '-v', 'test-app'], binary = True) kill_server_process() err = err.decode('utf-8') assert 'get new selections; current ones are not usable' in err, err assert 'get-selections-gui' in err, err sels = selections.Selections(qdom.parse(BytesIO(out))) # Check we can also work without the GUI... del os.environ['DISPLAY'] # Delete cached implementation so we need to download it again out, err = self.run_ocaml(['select', '--xml', 'test-app'], binary = True) sels = selections.Selections(qdom.parse(BytesIO(out))) stored = sels.selections['http://example.com:8000/Hello.xml'].get_path(self.config.stores) assert os.path.basename(stored).startswith('sha1') ro_rmtree(stored) run_server('Hello.xml', 'HelloWorld.tgz') out, err = self.run_ocaml(['download', '--xml', '-v', 'test-app'], binary = True) kill_server_process() err = err.decode('utf-8') assert 'get new selections; current ones are not usable' in err, err assert 'get-selections-gui' not in err, err sels = selections.Selections(qdom.parse(BytesIO(out))) # Now trigger a background update which discovers that no solution is possible timestamp = os.path.join(app, 'last-checked') last_check_attempt = os.path.join(app, 'last-check-attempt') selections_path = os.path.join(app, 'selections.xml') def reset_timestamps(): global ran_gui ran_gui = False os.utime(timestamp, (1, 1)) # 1970 os.utime(selections_path, (1, 1)) if os.path.exists(last_check_attempt): os.unlink(last_check_attempt) reset_timestamps() out, err = self.run_ocaml(['destroy', 'test-app']) assert not out, out assert not err, err run_server('Hello.xml') out, err = self.run_ocaml(['add', '--source', 'test-app', 'http://example.com:8000/Hello.xml']) assert not out, out assert 'We want source and this is a binary' in err, err
def _populate_model(self): # Find cached implementations unowned = {} # Impl ID -> Store duplicates = [] # TODO for s in self.iface_cache.stores.stores: if os.path.isdir(s.dir): for id in os.listdir(s.dir): if id in unowned: duplicates.append(id) unowned[id] = s ok_feeds = [] error_feeds = [] # Look through cached feeds for implementation owners all_interfaces = self.iface_cache.list_all_interfaces() all_feeds = {} for uri in all_interfaces: try: iface = self.iface_cache.get_interface(uri) except Exception as ex: error_feeds.append((uri, str(ex), 0)) else: all_feeds.update(self.iface_cache.get_feeds(iface)) for url, feed in all_feeds.items(): if not feed: continue yield feed_size = 0 try: if url != feed.url: # (e.g. for .new feeds) raise Exception('Incorrect URL for feed (%s vs %s)' % (url, feed.url)) if os.path.isabs(url): cached_feed = url feed_type = LocalFeed else: feed_type = RemoteFeed cached_feed = basedir.load_first_cache(namespaces.config_site, 'interfaces', model.escape(url)) user_overrides = basedir.load_first_config(namespaces.config_site, namespaces.config_prog, 'interfaces', model._pretty_escape(url)) feed_size = size_if_exists(cached_feed) + size_if_exists(user_overrides) except Exception as ex: error_feeds.append((url, str(ex), feed_size)) else: cached_feed = feed_type(feed, feed_size) for impl in feed.implementations.values(): if impl.local_path: cached_feed.in_cache.append(LocalImplementation(impl)) for digest in impl.digests: if digest in unowned: cached_dir = unowned[digest].dir impl_path = os.path.join(cached_dir, digest) impl_size = get_size(impl_path) cached_feed.in_cache.append(KnownImplementation(cached_feed, cached_dir, impl, impl_size, digest)) del unowned[digest] cached_feed.in_cache.sort() ok_feeds.append(cached_feed) if error_feeds: iter = SECTION_INVALID_INTERFACES.append_to(self.raw_model) for uri, ex, size in error_feeds: item = InvalidFeed(uri, ex, size) item.append_to(self.raw_model, iter) unowned_sizes = [] local_dir = os.path.join(basedir.xdg_cache_home, '0install.net', 'implementations') for id in unowned: if unowned[id].dir == local_dir: impl = UnusedImplementation(local_dir, id) unowned_sizes.append((impl.size, impl)) if unowned_sizes: iter = SECTION_UNOWNED_IMPLEMENTATIONS.append_to(self.raw_model) for size, item in unowned_sizes: item.append_to(self.raw_model, iter) if ok_feeds: iter = SECTION_INTERFACES.append_to(self.raw_model) for item in ok_feeds: yield item.append_to(self.raw_model, iter) self._update_sizes()