Exemple #1
0
	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(['*'])
Exemple #2
0
            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')
Exemple #3
0
    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'])
Exemple #4
0
			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')
Exemple #5
0
    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(['*'])
Exemple #6
0
    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')))
Exemple #8
0
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')))
Exemple #9
0
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
Exemple #11
0
	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))
Exemple #12
0
	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))
Exemple #13
0
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
Exemple #14
0
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))
Exemple #16
0
		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')
Exemple #17
0
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"))
            )
Exemple #18
0
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
Exemple #19
0
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
Exemple #20
0
        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')
Exemple #21
0
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)]
Exemple #22
0
 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)
Exemple #23
0
    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)
Exemple #24
0
	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))
Exemple #25
0
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)]
Exemple #26
0
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))
Exemple #27
0
 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)
Exemple #28
0
 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)
Exemple #29
0
    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)
Exemple #30
0
	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))
Exemple #31
0
	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)
Exemple #32
0
    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))
Exemple #33
0
    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
Exemple #35
0
    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))
Exemple #37
0
	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 = []
Exemple #38
0
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
Exemple #39
0
	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
Exemple #40
0
	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
Exemple #41
0
	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()