예제 #1
0
    def testDistro(self):
        with output_suppressed():
            native_url = 'http://example.com:8000/Native.xml'

            # Initially, we don't have the feed at all...
            master_feed = self.config.iface_cache.get_feed(native_url)
            assert master_feed is None, master_feed

            trust.trust_db.trust_key(
                'DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
            run_server(
                'Native.xml', '6FCF121BE2390E0B.gpg',
                '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B')
            driver = Driver(requirements=Requirements(native_url),
                            config=self.config)
            assert driver.need_download()

            solve = driver.solve_with_downloads()
            tasks.wait_for_blocker(solve)
            tasks.check(solve)

            master_feed = self.config.iface_cache.get_feed(native_url)
            assert master_feed is not None
            assert master_feed.implementations == {}

            distro_feed_url = master_feed.get_distro_feed()
            assert distro_feed_url is not None
            distro_feed = self.config.iface_cache.get_feed(distro_feed_url)
            assert distro_feed is not None
            assert len(
                distro_feed.implementations) == 2, distro_feed.implementations
예제 #2
0
    def testDLfeed(self):
        self.cache_iface(
            foo_iface_uri,
            """<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <feed src='http://example.com'/>
</interface>"""
            % foo_iface_uri,
        )
        driver = Driver(requirements=Requirements(foo_iface_uri), config=self.config)
        self.config.network_use = model.network_full

        assert driver.need_download()

        feed = self.config.iface_cache.get_feed(foo_iface_uri)
        feed.feeds = [model.Feed("/BadFeed", None, False)]

        logger.setLevel(logging.ERROR)
        assert driver.need_download()  # Triggers warning
        logger.setLevel(logging.WARN)
예제 #3
0
    def testImplMirror(self):
        with resourcewarnings_suppressed():
            # This is like testMirror, except we have a different archive (that generates the same content),
            # rather than an exact copy of the unavailable archive.
            trust.trust_db.trust_key(
                'DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
            run_server(
                '/Hello.xml', '/6FCF121BE2390E0B.gpg',
                server.Give404('/HelloWorld.tgz'),
                server.Give404(
                    '/0mirror/archive/http%3A%2F%2Flocalhost%3A8000%2FHelloWorld.tgz'
                ),
                '/0mirror/feeds/http/example.com:8000/Hello.xml/impl/sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
            )
            driver = Driver(
                requirements=Requirements('http://example.com:8000/Hello.xml'),
                config=self.config)
            self.config.mirror = 'http://example.com:8000/0mirror'

            refreshed = driver.solve_with_downloads()
            tasks.wait_for_blocker(refreshed)
            assert driver.solver.ready

            getLogger().setLevel(logging.ERROR)
            downloaded = driver.download_uncached_implementations()
            tasks.wait_for_blocker(downloaded)
            path = self.config.stores.lookup_any(
                driver.solver.selections.
                selections['http://example.com:8000/Hello.xml'].digests)
            assert os.path.exists(os.path.join(path, 'HelloWorld', 'main'))
예제 #4
0
    def testMirrors(self):
        with resourcewarnings_suppressed():
            getLogger().setLevel(logging.ERROR)
            trust.trust_db.trust_key(
                'DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
            run_server(
                server.Give404('/Hello.xml'),
                '/0mirror/feeds/http/example.com:8000/Hello.xml/latest.xml',
                '/0mirror/keys/6FCF121BE2390E0B.gpg',
                server.Give404('/HelloWorld.tgz'),
                '/0mirror/archive/http%3A%23%23example.com%3A8000%23HelloWorld.tgz'
            )
            driver = Driver(
                requirements=Requirements('http://example.com:8000/Hello.xml'),
                config=self.config)
            self.config.mirror = 'http://example.com:8000/0mirror'

            refreshed = driver.solve_with_downloads()
            tasks.wait_for_blocker(refreshed)
            assert driver.solver.ready

            #getLogger().setLevel(logging.WARN)
            downloaded = driver.download_uncached_implementations()
            tasks.wait_for_blocker(downloaded)
            path = self.config.stores.lookup_any(
                driver.solver.selections.
                selections['http://example.com:8000/Hello.xml'].digests)
            assert os.path.exists(os.path.join(path, 'HelloWorld', 'main'))
	def testLocalPath(self):
		# 0launch --get-selections Local.xml
		iface = os.path.join(mydir, "Local.xml")
		driver = Driver(requirements = Requirements(iface), config = self.config)
		driver.need_download()
		assert driver.solver.ready
		s1 = driver.solver.selections
		xml = s1.toDOM().toxml("utf-8")

		# Reload selections and check they're the same
		root = qdom.parse(BytesIO(xml))
		s2 = selections.Selections(root)
		local_path = s2.selections[iface].local_path
		assert os.path.isdir(local_path), local_path
		assert not s2.selections[iface].digests, s2.selections[iface].digests

		# Add a newer implementation and try again
		feed = self.config.iface_cache.get_feed(iface)
		impl = model.ZeroInstallImplementation(feed, "foo bar=123", local_path = None)
		impl.version = model.parse_version('1.0')
		impl.commands["run"] = model.Command(qdom.Element(namespaces.XMLNS_IFACE, 'command', {'path': 'dummy', 'name': 'run'}), None)
		impl.add_download_source('http://localhost/bar.tgz', 1000, None)
		feed.implementations = {impl.id: impl}
		assert driver.need_download()
		assert driver.solver.ready, driver.solver.get_failure_reason()
		s1 = driver.solver.selections
		xml = s1.toDOM().toxml("utf-8")
		root = qdom.parse(BytesIO(xml))
		s2 = selections.Selections(root)
		xml = s2.toDOM().toxml("utf-8")
		qdom.parse(BytesIO(xml))
		assert s2.selections[iface].local_path is None
		assert not s2.selections[iface].digests, s2.selections[iface].digests
		assert s2.selections[iface].id == 'foo bar=123'
예제 #6
0
    def testAbsMain(self):
        with tempfile.NamedTemporaryFile(prefix='test-', delete=False) as tmp:
            tmp.write(("""<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <group main='/bin/sh'>
   <implementation id='.' version='1'/>
  </group>
</interface>""" % foo_iface_uri).encode('utf-8'))

        driver = Driver(requirements=Requirements(tmp.name),
                        config=self.config)
        try:
            downloaded = driver.solve_and_download_impls()
            if downloaded:
                tasks.wait_for_blocker(downloaded)
            run.execute_selections(driver.solver.selections, [],
                                   stores=self.config.stores)
            assert False
        except SafeException as ex:
            assert 'Command path must be relative' in str(ex), ex
예제 #7
0
    def testAbsMain(self):
        p = Driver(requirements=Requirements(command_feed), config=self.config)
        self.config.handler.wait_for_blocker(p.solve_with_downloads())

        old_stdout = sys.stdout
        try:
            sys.stdout = StringIO()
            run.execute_selections(p.solver.selections, [],
                                   main='/runnable/runner',
                                   dry_run=True,
                                   stores=self.config.stores)
        finally:
            sys.stdout = old_stdout

        try:
            old_stdout = sys.stdout
            try:
                sys.stdout = StringIO()
                run.execute_selections(p.solver.selections, [],
                                       main='/runnable/not-there',
                                       dry_run=True,
                                       stores=self.config.stores)
            finally:
                sys.stdout = old_stdout
        except SafeException as ex:
            assert 'not-there' in unicode(ex)
예제 #8
0
def ensure_cached(uri, command = 'run', config = None):
	"""Ensure that an implementation of uri is cached.
	If not, it downloads one. It uses the GUI if a display is
	available, or the console otherwise.
	@param uri: the required interface
	@type uri: str
	@return: the selected implementations, or None if the user cancelled
	@rtype: L{zeroinstall.injector.selections.Selections}
	"""
	from zeroinstall.injector.driver import Driver

	if config is None:
		from zeroinstall.injector.config import load_config
		config = load_config()

	from zeroinstall.injector.requirements import Requirements
	requirements = Requirements(uri)
	requirements.command = command

	d = Driver(config, requirements)

	if d.need_download() or not d.solver.ready:
		sels = get_selections_gui(uri, ['--command', command], use_gui = None)
		if sels != DontUseGUI:
			return sels
		done = d.solve_and_download_impls()
		tasks.wait_for_blocker(done)

	return d.solver.selections
예제 #9
0
    def testSource(self):
        iface_cache = self.config.iface_cache

        foo = iface_cache.get_interface('http://foo/Binary.xml')
        self.import_feed(foo.uri, 'Binary.xml')
        foo_src = iface_cache.get_interface('http://foo/Source.xml')
        self.import_feed(foo_src.uri, 'Source.xml')
        compiler = iface_cache.get_interface('http://foo/Compiler.xml')
        self.import_feed(compiler.uri, 'Compiler.xml')

        self.config.freshness = 0
        self.config.network_use = model.network_full
        driver = Driver(requirements=Requirements('http://foo/Binary.xml'),
                        config=self.config)
        tasks.wait_for_blocker(driver.solve_with_downloads())
        assert driver.solver.selections.selections[foo.uri].id == 'sha1=123'

        # Now ask for source instead
        driver.requirements.source = True
        driver.requirements.command = 'compile'
        tasks.wait_for_blocker(driver.solve_with_downloads())
        assert driver.solver.ready, driver.solver.get_failure_reason()
        assert driver.solver.selections.selections[
            foo.uri].id == 'sha1=234'  # The source
        assert driver.solver.selections.selections[
            compiler.uri].id == 'sha1=345'  # A binary needed to compile it
예제 #10
0
	def testNoNeedDl(self):
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		assert driver.need_download()

		driver = Driver(requirements = Requirements(os.path.abspath('Foo.xml')), config = self.config)
		assert not driver.need_download()
		assert driver.solver.ready
예제 #11
0
	def testDistro(self):
		with output_suppressed():
			native_url = 'http://example.com:8000/Native.xml'

			# Initially, we don't have the feed at all...
			master_feed = self.config.iface_cache.get_feed(native_url)
			assert master_feed is None, master_feed

			trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
			run_server('Native.xml', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B')
			driver = Driver(requirements = Requirements(native_url), config = self.config)
			assert driver.need_download()

			solve = driver.solve_with_downloads()
			tasks.wait_for_blocker(solve)
			tasks.check(solve)

			master_feed = self.config.iface_cache.get_feed(native_url)
			assert master_feed is not None
			assert master_feed.implementations == {}

			distro_feed_url = master_feed.get_distro_feed()
			assert distro_feed_url is not None
			distro_feed = self.config.iface_cache.get_feed(distro_feed_url)
			assert distro_feed is not None
			assert len(distro_feed.implementations) == 2, distro_feed.implementations
예제 #12
0
	def testImplMirrorFails(self):
		with resourcewarnings_suppressed():
			trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
			run_server('/Hello.xml',
					'/6FCF121BE2390E0B.gpg',
					server.Give404('/HelloWorld.tgz'),
					server.Give404('/0mirror/archive/http%3A%23%23example.com%3A8000%23HelloWorld.tgz'),
					server.Give404('/0mirror/feeds/http/example.com:8000/Hello.xml/impl/sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'))
			driver = Driver(requirements = Requirements('http://example.com:8000/Hello.xml'), config = self.config)
			self.config.mirror = 'http://example.com:8000/0mirror'

			refreshed = driver.solve_with_downloads()
			tasks.wait_for_blocker(refreshed)
			assert driver.solver.ready

			getLogger().setLevel(logging.ERROR)
			try:
				downloaded = driver.download_uncached_implementations()
				tasks.wait_for_blocker(downloaded)
				assert 0
			except download.DownloadError as ex:
				assert 'Missing: HelloWorld.tgz' in str(ex), ex

			self.assertEqual([
				'http://example.com:8000/Hello.xml',
				'http://example.com:8000/6FCF121BE2390E0B.gpg',
				# The original archive:
				'http://example.com:8000/HelloWorld.tgz',
				# Mirror of original archive:
				'http://example.com:8000/0mirror/archive/http%3A%23%23example.com%3A8000%23HelloWorld.tgz',
				# Mirror of implementation:
				'http://example.com:8000/0mirror/feeds/http/example.com:8000/Hello.xml/impl/sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
				], traced_downloads)
예제 #13
0
def ensure_cached(uri, command = 'run', config = None):
	"""Ensure that an implementation of uri is cached.
	If not, it downloads one. It uses the GUI if a display is
	available, or the console otherwise.
	@param uri: the required interface
	@type uri: str
	@return: the selected implementations, or None if the user cancelled
	@rtype: L{zeroinstall.injector.selections.Selections}
	"""
	from zeroinstall.injector.driver import Driver

	if config is None:
		from zeroinstall.injector.config import load_config
		config = load_config()

	from zeroinstall.injector.requirements import Requirements
	requirements = Requirements(uri)
	requirements.command = command

	d = Driver(config, requirements)

	if d.need_download() or not d.solver.ready:
		sels = get_selections_gui(uri, ['--command', command], use_gui = None)
		if sels != DontUseGUI:
			return sels
		done = d.solve_and_download_impls()
		tasks.wait_for_blocker(done)

	return d.solver.selections
예제 #14
0
    def testLocalArchive(self):
        local_iface = os.path.join(mydir, 'LocalArchive.xml')
        with open(local_iface, 'rb') as stream:
            root = qdom.parse(stream)

        # Not local => error
        feed = model.ZeroInstallFeed(root)
        impl = feed.implementations['impl1']
        blocker = self.config.fetcher.download_impls([impl],
                                                     self.config.stores)
        try:
            tasks.wait_for_blocker(blocker)
            assert 0
        except model.SafeException as ex:
            assert "Relative URL 'HelloWorld.tgz' in non-local feed" in str(
                ex), ex

        feed = model.ZeroInstallFeed(root, local_path=local_iface)

        # Missing file
        impl2 = feed.implementations['impl2']
        blocker = self.config.fetcher.download_impls([impl2],
                                                     self.config.stores)
        try:
            tasks.wait_for_blocker(blocker)
            assert 0
        except model.SafeException as ex:
            assert 'tests/IDONTEXIST.tgz' in str(ex), ex

        # Wrong size
        impl3 = feed.implementations['impl3']
        blocker = self.config.fetcher.download_impls([impl3],
                                                     self.config.stores)
        try:
            tasks.wait_for_blocker(blocker)
            assert 0
        except model.SafeException as ex:
            assert 'feed says 177, but actually 176 bytes' in str(ex), ex

        self.config.network_use = model.network_offline
        r = Requirements(local_iface)
        r.command = None
        driver = Driver(requirements=r, config=self.config)
        driver.need_download()
        assert driver.solver.ready, driver.solver.get_failure_reason()

        # Local => OK
        impl = feed.implementations['impl1']

        path = self.config.stores.lookup_maybe(impl.digests)
        assert not path

        blocker = self.config.fetcher.download_impls([impl],
                                                     self.config.stores)
        tasks.wait_for_blocker(blocker)

        path = self.config.stores.lookup_any(impl.digests)
        assert os.path.exists(os.path.join(path, 'HelloWorld'))
예제 #15
0
	def testArgs(self):
		p = Driver(requirements = Requirements(runnable), config = self.config)
		self.config.handler.wait_for_blocker(p.solve_with_downloads())
		old_stdout = sys.stdout
		try:
			sys.stdout = StringIO()
			run.execute_selections(p.solver.selections, [], dry_run = True, stores = self.config.stores)
			out = sys.stdout.getvalue()
		finally:
			sys.stdout = old_stdout
		assert 'runner-arg' in out, out
예제 #16
0
	def testAcceptKey(self):
		with output_suppressed():
			run_server('Hello', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B', 'HelloWorld.tgz')
			driver = Driver(requirements = Requirements('http://localhost:8000/Hello'), config = self.config)
			assert driver.need_download()
			sys.stdin = Reply("Y\n")
			try:
				download_and_execute(driver, ['Hello'], main = 'Missing')
				assert 0
			except model.SafeException as ex:
				if "HelloWorld/Missing" not in str(ex):
					raise
예제 #17
0
	def testArgList(self):
		d = Driver(requirements = Requirements(arglist), config = self.config)
		self.config.handler.wait_for_blocker(d.solve_with_downloads())
		old_stdout = sys.stdout
		try:
			sys.stdout = StringIO()
			run.execute_selections(d.solver.selections, [], dry_run = True, stores = self.config.stores)
			out = sys.stdout.getvalue()
		finally:
			sys.stdout = old_stdout
		assert 'arg-for-runner -X ra1 -X ra2' in out, out
		assert 'command-arg ca1 ca2' in out, out
예제 #18
0
	def testAcceptKey(self):
		with output_suppressed():
			run_server('Hello', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B', 'HelloWorld.tgz')
			driver = Driver(requirements = Requirements('http://localhost:8000/Hello'), config = self.config)
			assert driver.need_download()
			sys.stdin = Reply("Y\n")
			try:
				download_and_execute(driver, ['Hello'], main = 'Missing')
				assert 0
			except model.SafeException as ex:
				if "HelloWorld/Missing" not in str(ex):
					raise
예제 #19
0
 def testArgs(self):
     p = Driver(requirements=Requirements(runnable), config=self.config)
     self.config.handler.wait_for_blocker(p.solve_with_downloads())
     old_stdout = sys.stdout
     try:
         sys.stdout = StringIO()
         run.execute_selections(p.solver.selections, [],
                                dry_run=True,
                                stores=self.config.stores)
         out = sys.stdout.getvalue()
     finally:
         sys.stdout = old_stdout
     assert 'runner-arg' in out, out
예제 #20
0
 def testArgList(self):
     d = Driver(requirements=Requirements(arglist), config=self.config)
     self.config.handler.wait_for_blocker(d.solve_with_downloads())
     old_stdout = sys.stdout
     try:
         sys.stdout = StringIO()
         run.execute_selections(d.solver.selections, [],
                                dry_run=True,
                                stores=self.config.stores)
         out = sys.stdout.getvalue()
     finally:
         sys.stdout = old_stdout
     assert 'arg-for-runner -X ra1 -X ra2' in out, out
     assert 'command-arg ca1 ca2' in out, out
예제 #21
0
	def testCommandBindings(self):
		if 'SELF_COMMAND' in os.environ:
			del os.environ['SELF_COMMAND']

		p = Driver(requirements = Requirements(command_feed), config = self.config)
		tasks.wait_for_blocker(p.solve_with_downloads())
		old_stdout = sys.stdout
		try:
			sys.stdout = StringIO()
			run.execute_selections(p.solver.selections, [], main = 'runnable/go.sh', dry_run = True, stores = self.config.stores)
		finally:
			sys.stdout = old_stdout
		assert 'local' in os.environ['LOCAL'], os.environ['LOCAL']
		assert 'SELF_COMMAND' in os.environ
예제 #22
0
	def testDryRun(self):
		with output_suppressed():
			run_server('Hello', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B', 'HelloWorld.tgz')
			self.config.handler.dry_run = True
			driver = Driver(requirements = Requirements('http://localhost:8000/Hello'), config = self.config)
			assert driver.need_download()
			sys.stdin = Reply("Y\n")
			sys.stdout = StringIO()
			download_and_execute(driver, ['Hello'], main = 'Missing', dry_run = True)

			out = sys.stdout.getvalue()
			assert '[dry-run] would trust key DE937DD411906ACF7C263B396FCF121BE2390E0B for localhost:8000' in out, out
			assert '[dry-run] would cache feed http://localhost:8000/Hello as ' in out, out
			assert '[dry-run] would store implementation as ' in out, out
			assert '[dry-run] would execute:' in out, out
예제 #23
0
	def testDryRun(self):
		with output_suppressed():
			run_server('Hello', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B', 'HelloWorld.tgz')
			self.config.handler.dry_run = True
			driver = Driver(requirements = Requirements('http://localhost:8000/Hello'), config = self.config)
			assert driver.need_download()
			sys.stdin = Reply("Y\n")
			sys.stdout = StringIO()
			download_and_execute(driver, ['Hello'], main = 'Missing', dry_run = True)

			out = sys.stdout.getvalue()
			assert '[dry-run] would trust key DE937DD411906ACF7C263B396FCF121BE2390E0B for localhost:8000' in out, out
			assert '[dry-run] would cache feed http://localhost:8000/Hello as ' in out, out
			assert '[dry-run] would store implementation as ' in out, out
			assert '[dry-run] would execute:' in out, out
예제 #24
0
	def testMirrors(self):
		old_out = sys.stdout
		try:
			sys.stdout = StringIO()
			getLogger().setLevel(ERROR)
			trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
			run_server(server.Give404('/Hello.xml'), 'latest.xml', '/0mirror/keys/6FCF121BE2390E0B.gpg')
			driver = Driver(requirements = Requirements('http://example.com:8000/Hello.xml'), config = self.config)
			self.config.feed_mirror = 'http://example.com:8000/0mirror'

			refreshed = driver.solve_with_downloads()
			tasks.wait_for_blocker(refreshed)
			assert driver.solver.ready
		finally:
			sys.stdout = old_out
예제 #25
0
	def testRejectKeyXML(self):
		with output_suppressed():
			run_server('Hello.xml', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B')
			driver = Driver(requirements = Requirements('http://example.com:8000/Hello.xml'), config = self.config)
			assert driver.need_download()
			sys.stdin = Reply("N\n")
			try:
				download_and_execute(driver, ['Hello'])
				assert 0
			except model.SafeException as ex:
				if "has no usable implementations" not in str(ex):
					raise ex
				if "Not signed with a trusted key" not in str(self.config.handler.ex):
					raise
				self.config.handler.ex = None
예제 #26
0
	def testRejectKeyXML(self):
		with output_suppressed():
			run_server('Hello.xml', '6FCF121BE2390E0B.gpg', '/key-info/key/DE937DD411906ACF7C263B396FCF121BE2390E0B')
			driver = Driver(requirements = Requirements('http://example.com:8000/Hello.xml'), config = self.config)
			assert driver.need_download()
			sys.stdin = Reply("N\n")
			try:
				download_and_execute(driver, ['Hello'])
				assert 0
			except model.SafeException as ex:
				if "No known implementations at all" not in str(ex):
					raise ex
				if "Not signed with a trusted key" not in str(self.config.handler.ex):
					raise
				self.config.handler.ex = None
예제 #27
0
	def testFeeds(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface last-modified="0"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <feed src='http://bar'/>
</interface>""" % foo_iface_uri)
		self.cache_iface('http://bar',
"""<?xml version="1.0" ?>
<interface last-modified="0"
 uri="http://bar"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <feed-for interface='%s'/>
  <name>Bar</name>
  <summary>Bar</summary>
  <description>Bar</description>
  <implementation version='1.0' id='sha1=123' main='dummy'>
    <archive href='foo' size='10'/>
  </implementation>
</interface>""" % foo_iface_uri)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		self.config.network_use = model.network_full
		recalculate(driver)
		assert driver.solver.ready
		foo_iface = self.config.iface_cache.get_interface(foo_iface_uri)
		self.assertEqual('sha1=123', driver.solver.selections[foo_iface].id)
예제 #28
0
    def testCommandBindings(self):
        if 'SELF_COMMAND' in os.environ:
            del os.environ['SELF_COMMAND']

        p = Driver(requirements=Requirements(command_feed), config=self.config)
        tasks.wait_for_blocker(p.solve_with_downloads())
        old_stdout = sys.stdout
        try:
            sys.stdout = StringIO()
            run.execute_selections(p.solver.selections, [],
                                   main='runnable/go.sh',
                                   dry_run=True,
                                   stores=self.config.stores)
        finally:
            sys.stdout = old_stdout
        assert 'local' in os.environ['LOCAL'], os.environ['LOCAL']
        assert 'SELF_COMMAND' in os.environ
예제 #29
0
	def testBadMain(self):
		r = Requirements(command_feed)
		r.command = None
		d = Driver(requirements = r, config = self.config)
		self.config.handler.wait_for_blocker(d.solve_with_downloads())

		try:
			run.execute_selections(d.solver.selections, [], dry_run = True, stores = self.config.stores)
			assert 0
		except SafeException as ex:
			self.assertEqual("Can't run: no command specified!", unicode(ex))

		try:
			run.execute_selections(d.solver.selections, [], main = 'relpath', dry_run = True, stores = self.config.stores)
			assert 0
		except SafeException as ex:
			self.assertEqual("Can't use a relative replacement main when there is no original one!", unicode(ex))
예제 #30
0
	def testLocalFeedMirror(self):
		with resourcewarnings_suppressed():
			# This is like testImplMirror, except we have a local feed.
			run_server(server.Give404('/HelloWorld.tgz'),
					'/0mirror/archive/http%3A%23%23example.com%3A8000%23HelloWorld.tgz')
			iface_uri = model.canonical_iface_uri('Hello.xml')
			driver = Driver(requirements = Requirements(iface_uri), config = self.config)
			self.config.mirror = 'http://example.com:8000/0mirror'

			refreshed = driver.solve_with_downloads()
			tasks.wait_for_blocker(refreshed)
			assert driver.solver.ready

			getLogger().setLevel(logging.ERROR)
			downloaded = driver.download_uncached_implementations()
			tasks.wait_for_blocker(downloaded)
			path = self.config.stores.lookup_any(driver.solver.selections.selections[iface_uri].digests)
			assert os.path.exists(os.path.join(path, 'HelloWorld', 'main'))
예제 #31
0
    def testConstraints(self):
        self.cache_iface(
            'http://bar', """<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="http://bar"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Bar</name>
  <summary>Bar</summary>
  <description>Bar</description>
  <implementation id='sha1=100' version='1.0'>
    <archive href='foo' size='10'/>
  </implementation>
  <implementation id='sha1=150' stability='developer' version='1.5'>
    <archive href='foo' size='10'/>
  </implementation>
  <implementation id='sha1=200' version='2.0'>
    <archive href='foo' size='10'/>
  </implementation>
</interface>""")
        self.cache_iface(
            foo_iface_uri, """<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <group main='dummy'>
   <requires interface='http://bar'>
    <version/>
   </requires>
   <implementation id='sha1=123' version='1.0'>
    <archive href='foo' size='10'/>
   </implementation>
  </group>
</interface>""" % foo_iface_uri)
        driver = Driver(requirements=Requirements(foo_iface_uri),
                        config=self.config)
        self.config.network_use = model.network_full
        #logger.setLevel(logging.DEBUG)
        recalculate(driver)
        #logger.setLevel(logging.WARN)
        foo_iface = self.config.iface_cache.get_interface(foo_iface_uri)
        bar_iface = self.config.iface_cache.get_interface('http://bar')
        assert driver.solver.selections[bar_iface].id == 'sha1=200'

        dep = driver.solver.selections[foo_iface].dependencies['http://bar']
        assert len(dep.restrictions) == 1
        restriction = dep.restrictions[0]

        restriction.before = model.parse_version('2.0')
        recalculate(driver)
        assert driver.solver.selections[bar_iface].id == 'sha1=100'

        restriction.not_before = model.parse_version('1.5')
        recalculate(driver)
        assert driver.solver.selections[bar_iface].id == 'sha1=150'
예제 #32
0
	def testLocalFeedMirror(self):
		with resourcewarnings_suppressed():
			# This is like testImplMirror, except we have a local feed.
			run_server(server.Give404('/HelloWorld.tgz'),
					'/0mirror/archive/http%3A%23%23example.com%3A8000%23HelloWorld.tgz')
			iface_uri = model.canonical_iface_uri('Hello.xml')
			driver = Driver(requirements = Requirements(iface_uri), config = self.config)
			self.config.mirror = 'http://example.com:8000/0mirror'

			refreshed = driver.solve_with_downloads()
			tasks.wait_for_blocker(refreshed)
			assert driver.solver.ready

			getLogger().setLevel(logging.ERROR)
			downloaded = driver.download_uncached_implementations()
			tasks.wait_for_blocker(downloaded)
			path = self.config.stores.lookup_any(driver.solver.selections.selections[iface_uri].digests)
			assert os.path.exists(os.path.join(path, 'HelloWorld', 'main'))
예제 #33
0
	def testNeedDL(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface last-modified="0"
 uri="%s"
 main='ThisBetterNotExist'
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <implementation version='1.0' id='sha1=123'>
    <archive href='http://foo/foo.tgz' size='100'/>
  </implementation>
</interface>""" % foo_iface_uri)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		self.config.network_use = model.network_full
		recalculate(driver)
		assert driver.need_download()
		assert driver.solver.ready
예제 #34
0
	def testExtractToNewSubdirectory(self):
		with output_suppressed():
			run_server(('HelloWorld.tar.bz2',))
			requirements = Requirements(os.path.abspath('HelloExtractToNewDest.xml'))
			requirements.command = None
			driver = Driver(requirements = requirements, config = self.config)
			driver_download(driver)
			digests = driver.solver.selections.selections[requirements.interface_uri].digests
			path = self.config.stores.lookup_any(digests)
			assert os.path.exists(os.path.join(path, 'src', 'HelloWorld', 'main'))
예제 #35
0
	def testRecipeRemoveDir(self):
		with output_suppressed():
			run_server(('HelloWorld.tar.bz2',))
			requirements = Requirements(os.path.abspath('RecipeRemoveDir.xml'))
			requirements.command = None
			driver = Driver(requirements = requirements, config = self.config)
			driver_download(driver)
			digests = driver.solver.selections.selections[requirements.interface_uri].digests
			path = self.config.stores.lookup_any(digests)
			assert not os.path.exists(os.path.join(path, 'HelloWorld'))
예제 #36
0
	def testNeedDL(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface last-modified="0"
 uri="%s"
 main='ThisBetterNotExist'
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <implementation version='1.0' id='sha1=123'>
    <archive href='http://foo/foo.tgz' size='100'/>
  </implementation>
</interface>""" % foo_iface_uri)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		self.config.network_use = model.network_full
		recalculate(driver)
		assert driver.need_download()
		assert driver.solver.ready
예제 #37
0
def _check_for_updates(requirements, verbose):
	from zeroinstall.injector.driver import Driver
	from zeroinstall.injector.config import load_config

	background_handler = BackgroundHandler(requirements.interface_uri, requirements.interface_uri)
	background_config = load_config(background_handler)
	root_iface = background_config.iface_cache.get_interface(requirements.interface_uri).get_name()
	background_handler.title = root_iface

	driver = Driver(config = background_config, requirements = requirements)

	info(_("Checking for updates to '%s' in a background process"), root_iface)
	if verbose:
		background_handler.notify("Zero Install", _("Checking for updates to '%s'...") % root_iface, timeout = 1)

	network_state = background_handler.get_network_state()
	if network_state not in (_NetworkState.NM_STATE_CONNECTED_SITE, _NetworkState.NM_STATE_CONNECTED_GLOBAL):
		info(_("Not yet connected to network (status = %d). Sleeping for a bit..."), network_state)
		import time
		time.sleep(120)
		if network_state in (_NetworkState.NM_STATE_DISCONNECTED, _NetworkState.NM_STATE_ASLEEP):
			info(_("Still not connected to network. Giving up."))
			sys.exit(1)
	else:
		info(_("NetworkManager says we're on-line. Good!"))

	background_config.freshness = 0			# Don't bother trying to refresh when getting the interface
	refresh = driver.solve_with_downloads(force = True)	# (causes confusing log messages)
	tasks.wait_for_blocker(refresh)

	# We could even download the archives here, but for now just
	# update the interfaces.

	if not driver.need_download():
		if verbose:
			background_handler.notify("Zero Install", _("No updates to download."), timeout = 1)
		sys.exit(0)

	background_handler.notify("Zero Install",
			      _("Updates ready to download for '%s'.") % root_iface,
			      timeout = 1)
	_exec_gui(requirements.interface_uri, '--refresh', '--systray')
	sys.exit(1)
예제 #38
0
	def testAbsMain(self):
		p = Driver(requirements = Requirements(command_feed), config = self.config)
		self.config.handler.wait_for_blocker(p.solve_with_downloads())

		old_stdout = sys.stdout
		try:
			sys.stdout = StringIO()
			run.execute_selections(p.solver.selections, [], main = '/runnable/runner', dry_run = True, stores = self.config.stores)
		finally:
			sys.stdout = old_stdout

		try:
			old_stdout = sys.stdout
			try:
				sys.stdout = StringIO()
				run.execute_selections(p.solver.selections, [], main = '/runnable/not-there', dry_run = True, stores = self.config.stores)
			finally:
				sys.stdout = old_stdout
		except SafeException as ex:
			assert 'not-there' in unicode(ex)
예제 #39
0
	def testUnknownAlg(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <implementation main='.' id='unknown=123' version='1.0'>
    <archive href='http://foo/foo.tgz' size='100'/>
  </implementation>
</interface>""" % foo_iface_uri)
		self.config.fetcher = fetch.Fetcher(self.config)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		try:
			assert driver.need_download()
			download_and_execute(driver, [])
		except model.SafeException as ex:
			assert "Use '_' not '=' for new algorithms, in unknown=123" in str(ex), ex
예제 #40
0
	def testRecipeExtractToExistingSubdirectory(self):
		with output_suppressed():
			run_server(('HelloWorld.tar.bz2','HelloWorld.tar.bz2'))
			requirements = Requirements(os.path.abspath('RecipeExtractToExistingDest.xml'))
			requirements.command = None
			driver = Driver(requirements = requirements, config = self.config)
			driver_download(driver)
			digests = driver.solver.selections.selections[requirements.interface_uri].digests
			path = self.config.stores.lookup_any(digests)
			assert os.path.exists(os.path.join(path, 'HelloWorld', 'main')) # first archive's main
			assert os.path.exists(os.path.join(path, 'HelloWorld', 'HelloWorld', 'main')) # second archive, extracted to HelloWorld/
예제 #41
0
	def testDownloadFile(self):
		with output_suppressed():
			run_server(('HelloWorldMain',))
			requirements = Requirements(os.path.abspath('HelloSingleFile.xml'))
			requirements.command = None
			driver = Driver(requirements = requirements, config = self.config)
			driver_download(driver)
			digests = driver.solver.selections.selections[requirements.interface_uri].digests
			path = self.config.stores.lookup_any(digests)
			with open(os.path.join(path, 'main'), 'rt') as stream:
				assert 'Hello World' in stream.read()
예제 #42
0
	def testUnknownAlg(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <implementation main='.' id='unknown=123' version='1.0'>
    <archive href='http://foo/foo.tgz' size='100'/>
  </implementation>
</interface>""" % foo_iface_uri)
		self.config.fetcher = fetch.Fetcher(self.config)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		try:
			assert driver.need_download()
			download_and_execute(driver, [])
		except model.SafeException as ex:
			assert "Use '_' not '=' for new algorithms, in unknown=123" in str(ex), ex
예제 #43
0
	def testCommands(self):
		iface = os.path.join(mydir, "Command.xml")
		driver = Driver(requirements = Requirements(iface), config = self.config)
		driver.need_download()
		assert driver.solver.ready

		impl = driver.solver.selections[self.config.iface_cache.get_interface(iface)]
		assert impl.id == 'c'
		assert impl.main == 'test-gui'

		dep_impl_uri = impl.commands['run'].requires[0].interface
		dep_impl = driver.solver.selections[self.config.iface_cache.get_interface(dep_impl_uri)]
		assert dep_impl.id == 'sha1=256'

		s1 = driver.solver.selections
		assert s1.commands[0].path == 'test-gui'
		xml = s1.toDOM().toxml("utf-8")
		root = qdom.parse(BytesIO(xml))
		s2 = selections.Selections(root)

		assert s2.commands[0].path == 'test-gui'
		impl = s2.selections[iface]
		assert impl.id == 'c'

		assert s2.commands[0].qdom.attrs['http://custom attr'] == 'namespaced'
		custom_element = s2.commands[0].qdom.childNodes[0]
		assert custom_element.name == 'child'

		dep_impl = s2.selections[dep_impl_uri]
		assert dep_impl.id == 'sha1=256'

		d = Driver(self.config, requirements.Requirements(runexec))
		need_download = d.need_download()
		assert need_download == False

		xml = d.solver.selections.toDOM().toxml("utf-8")
		root = qdom.parse(BytesIO(xml))
		s3 = selections.Selections(root)
		runnable_impl = s3.selections[runnable]
		assert 'foo' in runnable_impl.commands
		assert 'run' in runnable_impl.commands
예제 #44
0
	def testBadConfig(self):
		path = basedir.save_config_path(namespaces.config_site,
						namespaces.config_prog)
		glob = os.path.join(path, 'global')
		assert not os.path.exists(glob)
		stream = open(glob, 'w')
		stream.write('hello!')
		stream.close()

		logger.setLevel(logging.ERROR)
		Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		logger.setLevel(logging.WARN)
예제 #45
0
	def testMirrors(self):
		with resourcewarnings_suppressed():
			getLogger().setLevel(logging.ERROR)
			trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
			run_server(server.Give404('/Hello.xml'),
					'/0mirror/feeds/http/example.com:8000/Hello.xml/latest.xml',
					'/0mirror/keys/6FCF121BE2390E0B.gpg',
					server.Give404('/HelloWorld.tgz'),
					'/0mirror/archive/http%3A%23%23example.com%3A8000%23HelloWorld.tgz')
			driver = Driver(requirements = Requirements('http://example.com:8000/Hello.xml'), config = self.config)
			self.config.mirror = 'http://example.com:8000/0mirror'

			refreshed = driver.solve_with_downloads()
			tasks.wait_for_blocker(refreshed)
			assert driver.solver.ready

			#getLogger().setLevel(logging.WARN)
			downloaded = driver.download_uncached_implementations()
			tasks.wait_for_blocker(downloaded)
			path = self.config.stores.lookup_any(driver.solver.selections.selections['http://example.com:8000/Hello.xml'].digests)
			assert os.path.exists(os.path.join(path, 'HelloWorld', 'main'))
예제 #46
0
    def testLocalPath(self):
        # 0launch --get-selections Local.xml
        iface = os.path.join(mydir, "Local.xml")
        driver = Driver(requirements=Requirements(iface), config=self.config)
        driver.need_download()
        assert driver.solver.ready
        s1 = driver.solver.selections
        xml = s1.toDOM().toxml("utf-8")

        # Reload selections and check they're the same
        root = qdom.parse(BytesIO(xml))
        s2 = selections.Selections(root)
        local_path = s2.selections[iface].local_path
        assert os.path.isdir(local_path), local_path
        assert not s2.selections[iface].digests, s2.selections[iface].digests

        # Add a newer implementation and try again
        feed = self.config.iface_cache.get_feed(iface)
        impl = model.ZeroInstallImplementation(feed,
                                               "foo bar=123",
                                               local_path=None)
        impl.version = model.parse_version('1.0')
        impl.commands["run"] = model.Command(
            qdom.Element(namespaces.XMLNS_IFACE, 'command', {
                'path': 'dummy',
                'name': 'run'
            }), None)
        impl.add_download_source('http://localhost/bar.tgz', 1000, None)
        feed.implementations = {impl.id: impl}
        assert driver.need_download()
        assert driver.solver.ready, driver.solver.get_failure_reason()
        s1 = driver.solver.selections
        xml = s1.toDOM().toxml("utf-8")
        root = qdom.parse(BytesIO(xml))
        s2 = selections.Selections(root)
        xml = s2.toDOM().toxml("utf-8")
        qdom.parse(BytesIO(xml))
        assert s2.selections[iface].local_path is None
        assert not s2.selections[iface].digests, s2.selections[iface].digests
        assert s2.selections[iface].id == 'foo bar=123'
예제 #47
0
	def testNoNeedDl(self):
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		assert driver.need_download()

		driver = Driver(requirements = Requirements(os.path.abspath('Foo.xml')), config = self.config)
		assert not driver.need_download()
		assert driver.solver.ready
예제 #48
0
	def testImplMirror(self):
		with resourcewarnings_suppressed():
			# This is like testMirror, except we have a different archive (that generates the same content),
			# rather than an exact copy of the unavailable archive.
			trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')
			run_server('/Hello.xml',
					'/6FCF121BE2390E0B.gpg',
					server.Give404('/HelloWorld.tgz'),
					server.Give404('/0mirror/archive/http%3A%2F%2Flocalhost%3A8000%2FHelloWorld.tgz'),
					'/0mirror/feeds/http/example.com:8000/Hello.xml/impl/sha1=3ce644dc725f1d21cfcf02562c76f375944b266a')
			driver = Driver(requirements = Requirements('http://example.com:8000/Hello.xml'), config = self.config)
			self.config.mirror = 'http://example.com:8000/0mirror'

			refreshed = driver.solve_with_downloads()
			tasks.wait_for_blocker(refreshed)
			assert driver.solver.ready

			getLogger().setLevel(logging.ERROR)
			downloaded = driver.download_uncached_implementations()
			tasks.wait_for_blocker(downloaded)
			path = self.config.stores.lookup_any(driver.solver.selections.selections['http://example.com:8000/Hello.xml'].digests)
			assert os.path.exists(os.path.join(path, 'HelloWorld', 'main'))
예제 #49
0
	def testDLfeed(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <feed src='http://example.com'/>
</interface>""" % foo_iface_uri)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		self.config.network_use = model.network_full

		assert driver.need_download()

		feed = self.config.iface_cache.get_feed(foo_iface_uri)
		feed.feeds = [model.Feed('/BadFeed', None, False)]

		logger.setLevel(logging.ERROR)
		assert driver.need_download()	# Triggers warning
		logger.setLevel(logging.WARN)
예제 #50
0
	def testSource(self):
		iface_cache = self.config.iface_cache

		foo = iface_cache.get_interface('http://foo/Binary.xml')
		self.import_feed(foo.uri, 'Binary.xml')
		foo_src = iface_cache.get_interface('http://foo/Source.xml')
		self.import_feed(foo_src.uri, 'Source.xml')
		compiler = iface_cache.get_interface('http://foo/Compiler.xml')
		self.import_feed(compiler.uri, 'Compiler.xml')

		self.config.freshness = 0
		self.config.network_use = model.network_full
		driver = Driver(requirements = Requirements('http://foo/Binary.xml'), config = self.config)
		tasks.wait_for_blocker(driver.solve_with_downloads())
		assert driver.solver.selections[foo].id == 'sha1=123'

		# Now ask for source instead
		driver.requirements.source = True
		driver.requirements.command = 'compile'
		tasks.wait_for_blocker(driver.solve_with_downloads())
		assert driver.solver.ready, driver.solver.get_failure_reason()
		assert driver.solver.selections[foo].id == 'sha1=234'		# The source
		assert driver.solver.selections[compiler].id == 'sha1=345'	# A binary needed to compile it
예제 #51
0
	def testNoArchives(self):
		self.cache_iface(foo_iface_uri,
"""<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <implementation id='sha1=123' version='1.0' main='dummy'/>
</interface>""" % foo_iface_uri)
		driver = Driver(requirements = Requirements(foo_iface_uri), config = self.config)
		recalculate(driver)
		assert not driver.solver.ready
예제 #52
0
	def testRecipeFailure(self):
		with resourcewarnings_suppressed():
			old_out = sys.stdout
			try:
				run_server('*')
				driver = Driver(requirements = Requirements(os.path.abspath('Recipe.xml')), config = self.config)
				try:
					download_and_execute(driver, [])
					assert False
				except download.DownloadError as ex:
					if "Connection" not in str(ex):
						raise
			finally:
				sys.stdout = old_out
예제 #53
0
	def testAbsMain(self):
		with tempfile.NamedTemporaryFile(prefix = 'test-', delete = False) as tmp:
			tmp.write((
"""<?xml version="1.0" ?>
<interface last-modified="1110752708"
 uri="%s"
 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
  <name>Foo</name>
  <summary>Foo</summary>
  <description>Foo</description>
  <group main='/bin/sh'>
   <implementation id='.' version='1'/>
  </group>
</interface>""" % foo_iface_uri).encode('utf-8'))

		driver = Driver(requirements = Requirements(tmp.name), config = self.config)
		try:
			downloaded = driver.solve_and_download_impls()
			if downloaded:
				tasks.wait_for_blocker(downloaded)
			run.execute_selections(driver.solver.selections, [], stores = self.config.stores)
			assert False
		except SafeException as ex:
			assert 'Command path must be relative' in str(ex), ex
예제 #54
0
	def testBackgroundUnsolvable(self):
		my_dbus.system_services = {"org.freedesktop.NetworkManager": {"/org/freedesktop/NetworkManager": NetworkManager()}}

		trust.trust_db.trust_key('DE937DD411906ACF7C263B396FCF121BE2390E0B', 'example.com:8000')

		global ran_gui

		# Select a version of Hello
		run_server('Hello.xml', '6FCF121BE2390E0B.gpg', 'HelloWorld.tgz')
		r = Requirements('http://example.com:8000/Hello.xml')
		driver = Driver(requirements = r, config = self.config)
		tasks.wait_for_blocker(driver.solve_with_downloads())
		assert driver.solver.ready
		kill_server_process()

		# Save it as an app
		app = self.config.app_mgr.create_app('test-app', r)

		# Replace the selection with a bogus and unusable <package-implementation>
		sels = driver.solver.selections
		sel, = sels.selections.values()
		sel.attrs['id'] = "package:dummy:badpackage"
		sel.attrs['package'] = "badpackage"
		sel.get_command('run').qdom.attrs['path'] = '/i/dont/exist'

		app.set_selections(driver.solver.selections)

		# 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'
		try:
			app.get_selections(may_update = True)
			assert 0
		except model.SafeException as ex:
			assert 'Aborted by user' in str(ex)
		assert ran_gui
		ran_gui = False

		# Check we can also work without the GUI...
		del os.environ['DISPLAY']

		run_server('Hello.xml', 'HelloWorld.tgz')
		sels = app.get_selections(may_update = True)
		kill_server_process()

		dl = app.download_selections(sels)
		assert dl == None

		assert not ran_gui

		# Now trigger a background update which discovers that no solution is possible
		timestamp = os.path.join(app.path, 'last-checked')
		last_check_attempt = os.path.join(app.path, 'last-check-attempt')
		selections_path = os.path.join(app.path, '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()

		r.source = True
		app.set_requirements(r)
		run_server('Hello.xml')
		with trapped_exit(1):
			sels = app.get_selections(may_update = True)
		kill_server_process()
예제 #55
0
	def testSelections(self):
		requirements = Requirements('http://foo/Source.xml')
		requirements.source = True
		requirements.command = 'compile'
		driver = Driver(requirements = requirements, config = self.config)
		source = self.config.iface_cache.get_interface('http://foo/Source.xml')
		compiler = self.config.iface_cache.get_interface('http://foo/Compiler.xml')
		self.import_feed(source.uri, 'Source.xml')
		self.import_feed(compiler.uri, 'Compiler.xml')

		self.config.network_use = model.network_full
		#import logging
		#logging.getLogger().setLevel(logging.DEBUG)
		assert driver.need_download()

		def assertSel(s):
			self.assertEqual('http://foo/Source.xml', s.interface)
			self.assertEqual(2, len(s.selections))

			sels = [(sel.interface, sel) for sel in s.selections.values()]
			sels.sort()
			sels = [sel for uri,sel in sels]
			
			self.assertEqual('http://foo/Compiler.xml', sels[0].interface)
			self.assertEqual('http://foo/Source.xml', sels[1].interface)

			self.assertEqual("sha1=345", sels[0].id)
			self.assertEqual("1.0", sels[0].version)

			self.assertEqual('sha1=234', sels[1].id)
			self.assertEqual("1.0", sels[1].version)
			self.assertEqual("bar", sels[1].attrs['http://namespace foo'])
			self.assertEqual("1.0", sels[1].attrs['version'])
			assert 'version-modifier' not in sels[1].attrs

			self.assertEqual(0, len(sels[0].bindings))
			self.assertEqual(0, len(sels[0].dependencies))

			self.assertEqual(3, len(sels[1].bindings))
			self.assertEqual('.', sels[1].bindings[0].insert)
			self.assertEqual('/', sels[1].bindings[1].mount_point)
			self.assertEqual('source', sels[1].bindings[2].qdom.attrs['foo'])

			self.assertEqual(1, len(sels[1].dependencies))
			dep = sels[1].dependencies[0]
			self.assertEqual('http://foo/Compiler.xml', dep.interface)
			self.assertEqual(4, len(dep.bindings))
			self.assertEqual('bin', dep.bindings[0].insert)
			self.assertEqual('PATH', dep.bindings[0].name)
			self.assertEqual('prepend', dep.bindings[0].mode)
			assert dep.bindings[0].separator in ';:'

			self.assertEqual('bin', dep.bindings[1].value)
			self.assertEqual('NO_PATH', dep.bindings[1].name)
			self.assertEqual(',', dep.bindings[1].separator)

			self.assertEqual('bin', dep.bindings[2].insert)
			self.assertEqual('BINDIR', dep.bindings[2].name)
			self.assertEqual('replace', dep.bindings[2].mode)

			foo_binding = dep.bindings[3]
			self.assertEqual('compiler', foo_binding.qdom.attrs['foo'])
			self.assertEqual('child', foo_binding.qdom.childNodes[0].name)
			self.assertEqual('run', foo_binding.command)

			self.assertEqual(["sha1=345", 'sha256new_345'], sorted(sels[0].digests))

		assert driver.solver.ready, driver.solver.get_failure_reason()
		s1 = driver.solver.selections
		s1.selections['http://foo/Source.xml'].attrs['http://namespace foo'] = 'bar'
		assertSel(s1)

		xml = s1.toDOM().toxml("utf-8")
		root = qdom.parse(BytesIO(xml))
		self.assertEqual(namespaces.XMLNS_IFACE, root.uri)

		s2 = selections.Selections(root)
		assertSel(s2)
예제 #56
0
	def _check_for_updates(self, sels, use_gui):
		"""Check whether the selections need to be updated.
		If any input feeds have changed, we re-run the solver. If the
		new selections require a download, we schedule one in the
		background and return the old selections. Otherwise, we return the
		new selections. If we can select better versions without downloading,
		we update the app's selections and return the new selections.
		If we can't use the current selections, we update in the foreground.
		We also schedule a background update from time-to-time anyway.
		@type sels: L{zeroinstall.injector.selections.Selections}
		@type use_gui: bool
		@return: the selections to use
		@rtype: L{selections.Selections}"""
		need_solve = False		# Rerun solver (cached feeds have changed)
		need_update = False		# Update over the network

		if sels:
			utime = self._get_mtime('last-checked', warn_if_missing = True)
			last_solve = max(self._get_mtime('last-solve', warn_if_missing = False), utime)

			# Ideally, this would return all the files which were inputs into the solver's
			# decision. Currently, we approximate with:
			# - the previously selected feed files (local or cached)
			# - configuration files for the selected interfaces
			# - the global configuration
			# We currently ignore feeds and interfaces which were
			# considered but not selected.
			# Can yield None (ignored), paths or (path, mtime) tuples.
			# If this throws an exception, we will log it and resolve anyway.
			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')

			# If any of the feeds we used have been updated since the last check, do a quick re-solve
			try:
				for item in get_inputs():
					if not item: continue
					if isinstance(item, tuple):
						path, mtime = item
					else:
						path = item
						try:
							mtime = os.stat(path).st_mtime
						except OSError as ex:
							logger.info("Triggering update to {app} due to error: {ex}".format(
								app = self, path = path, ex = ex))
							need_solve = True
							break

					if mtime and mtime > last_solve:
						logger.info("Triggering update to %s because %s has changed", self, path)
						need_solve = True
						break
			except Exception as ex:
				logger.info("Error checking modification times: %s", ex)
				need_solve = True
				need_update = True

			# Is it time for a background update anyway?
			if not need_update:
				staleness = time.time() - utime
				logger.info("Staleness of app %s is %d hours", self, staleness / (60 * 60))
				freshness_threshold = self.config.freshness
				if freshness_threshold > 0 and staleness >= freshness_threshold:
					need_update = True

			# If any of the saved selections aren't available then we need
			# to download right now, not later in the background.
			unavailable_selections = sels.get_unavailable_selections(config = self.config, include_packages = True)
			if unavailable_selections:
				logger.info("Saved selections are unusable (missing %s)",
					    ', '.join(str(s) for s in unavailable_selections))
				need_solve = True
		else:
			# No current selections
			need_solve = True
			unavailable_selections = True

		if need_solve:
			from zeroinstall.injector.driver import Driver
			driver = Driver(config = self.config, requirements = self.get_requirements())
			if driver.need_download():
				if unavailable_selections:
					return self._foreground_update(driver, use_gui)
				else:
					# Continue with the current (cached) selections while we download
					need_update = True
			else:
				old_sels = sels
				sels = driver.solver.selections
				from zeroinstall.support import xmltools
				if old_sels is None or not xmltools.nodes_equal(sels.toDOM(), old_sels.toDOM()):
					self.set_selections(sels, set_last_checked = False)
			try:
				self._touch('last-solve')
			except OSError as ex:
				logger.warning("Error checking for updates: %s", ex)

		# If we tried to check within the last hour, don't try again.
		if need_update:
			last_check_attempt = self._get_mtime('last-check-attempt', warn_if_missing = False)
			if last_check_attempt and last_check_attempt + 60 * 60 > time.time():
				logger.info("Tried to check within last hour; not trying again now")
				need_update = False

		if need_update:
			try:
				self.set_last_check_attempt()
			except OSError as ex:
				logger.warning("Error checking for updates: %s", ex)
			else:
				from zeroinstall.injector import background
				r = self.get_requirements()
				background.spawn_background_update2(r, False, self)

		return sels
예제 #57
0
def get_selections_for(requirements, config, options, select_only, download_only, test_callback):
	"""Get selections for given requirements.
	@since: 1.9"""
	if options.offline:
		config.network_use = model.network_offline

	iface_cache = config.iface_cache

	driver = Driver(config = config, requirements = requirements)

	# Note that need_download() triggers a solve
	if options.refresh or options.gui:
		# We could run immediately, but the user asked us not to
		can_run_immediately = False
	else:
		if select_only:
			# --select-only: we only care that we've made a selection, not that we've cached the implementations
			driver.need_download()
			can_run_immediately = driver.solver.ready
		else:
			can_run_immediately = not driver.need_download()

		stale_feeds = [feed for feed in driver.solver.feeds_used if
				not feed.startswith('distribution:') and	# Ignore (memory-only) PackageKit feeds
				iface_cache.is_stale(feed, config.freshness)]

		if download_only and stale_feeds:
			can_run_immediately = False

	if can_run_immediately:
		if stale_feeds:
			if config.network_use == model.network_offline:
				logger.debug(_("No doing background update because we are in off-line mode."))
			else:
				# There are feeds we should update, but we can run without them.
				# Do the update in the background while the program is running.
				from zeroinstall.injector import background
				background.spawn_background_update(driver, options.verbose)
		return driver.solver.selections

	# If we need to download anything, we might as well
	# refresh all the feeds first.
	options.refresh = True

	if options.gui != False:
		# If the user didn't say whether to use the GUI, choose for them.
		gui_args = driver.requirements.get_as_options()
		if download_only:
			# Just changes the button's label
			gui_args.append('--download-only')
		if options.refresh:
			gui_args.append('--refresh')
		if options.verbose:
			gui_args.insert(0, '--verbose')
			if options.verbose > 1:
				gui_args.insert(0, '--verbose')
		if options.with_store:
			for x in options.with_store:
				gui_args += ['--with-store', x]
		if select_only:
			gui_args.append('--select-only')

		from zeroinstall import helpers
		sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, test_callback, use_gui = options.gui)

		if not sels:
			return None		# Aborted
		elif sels is helpers.DontUseGUI:
			sels = None
	else:
		sels = None

	if sels is None:
		# Note: --download-only also makes us stop and download stale feeds first.
		downloaded = driver.solve_and_download_impls(refresh = options.refresh or download_only or False,
							     select_only = select_only)
		if downloaded:
			tasks.wait_for_blocker(downloaded)
		sels = driver.solver.selections

	return sels
mydir = os.path.dirname(os.path.abspath(__file__))
site_config = os.path.join(mydir, 'site-config.xml')
if not os.path.exists(site_config):
	print "Copy site-config.xml.template as site-config.xml and edit..."
	sys.exit(1)

drupal = "http://repo.roscidus.com/drupal/core"

config = load_config()

import local_config
local_config.apply_local_config(config)

requirements = Requirements(site_config)
requirements.command = None
driver = Driver(config, requirements)
tasks.wait_for_blocker(driver.solve_and_download_impls(refresh = refresh))
selections = driver.solver.selections.selections

drupal_impl = selections[drupal]
drupal_root = drupal_impl.local_path or config.stores.lookup_any(drupal_impl.digests)

config_impl = selections[site_config]

site_config_settings = {}
for binding in config_impl.bindings:
	site_config_settings[binding.name] = binding.value

doc_root = site_config_settings["doc_root"]
apache_user = pwd.getpwnam(site_config_settings["apache_user"])
예제 #59
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():
			# Select a version of Hello
			run_server('Hello.xml', '6FCF121BE2390E0B.gpg', 'HelloWorld.tgz')
			r = Requirements('http://example.com:8000/Hello.xml')
			driver = Driver(requirements = r, config = self.config)
			tasks.wait_for_blocker(driver.solve_with_downloads())
			assert driver.solver.ready
			kill_server_process()

			# Save it as an app
			app = self.config.app_mgr.create_app('test-app', r)
			app.set_selections(driver.solver.selections)
			timestamp = os.path.join(app.path, 'last-checked')
			last_check_attempt = os.path.join(app.path, 'last-check-attempt')
			selections_path = os.path.join(app.path, '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)

			# Download the implementation
			sels = app.get_selections(may_update = True)
			run_server('HelloWorld.tgz')
			tasks.wait_for_blocker(app.download_selections(sels))
			kill_server_process()

			# Not time for a background update yet
			self.config.freshness = 100
			dl = app.download_selections(app.get_selections(may_update = True))
			assert dl == None
			assert not ran_gui

			# Trigger a background update - no updates found
			reset_timestamps()
			run_server('Hello.xml')
			with trapped_exit(1):
				dl = app.download_selections(app.get_selections(may_update = True))
				assert dl == None
			assert not ran_gui
			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.path, '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')
			with trapped_exit(1):
				dl = app.download_selections(app.get_selections(may_update = True))
				assert dl == None
			assert not ran_gui
			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
			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')
			with trapped_exit(1):
				dl = app.download_selections(app.get_selections(may_update = True))
				assert dl == None
			assert ran_gui	# (so doesn't actually update)
			kill_server_process()

			# Now again with no DISPLAY
			reset_timestamps()
			del os.environ['DISPLAY']
			run_server('Hello.xml', 'HelloWorld.tgz')
			with trapped_exit(1):
				dl = app.download_selections(app.get_selections(may_update = True))
				assert dl == None
			assert not ran_gui	# (so doesn't actually update)

			self.assertNotEqual(1, os.stat(timestamp).st_mtime)
			self.assertNotEqual(1, os.stat(selections_path).st_mtime)
			kill_server_process()

			sels = app.get_selections()
			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')
			with trapped_exit(1):
				#import logging; logging.getLogger().setLevel(logging.INFO)
				dl = app.download_selections(app.get_selections(may_update = True))
				assert dl == None
			assert ran_gui
			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))
			dl = app.download_selections(app.get_selections(may_update = True))
			assert dl == None
			assert not ran_gui