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
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 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
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)
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)
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
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'))
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
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
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
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
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
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
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
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))
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
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'))
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)
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)
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 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'))
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))
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
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()
def _check_for_updates(requirements, verbose, app): """@type requirements: L{zeroinstall.injector.requirements.Requirements} @type verbose: bool @type app: L{zeroinstall.apps.App}""" if app is not None: old_sels = app.get_selections() from zeroinstall.injector.driver import Driver from zeroinstall.injector.config import load_config background_handler = BackgroundHandler(requirements.interface_uri, requirements.interface_uri) background_config = load_config(background_handler) root_iface = background_config.iface_cache.get_interface( requirements.interface_uri).get_name() background_handler.title = root_iface driver = Driver(config=background_config, requirements=requirements) logger.info(_("Checking for updates to '%s' in a background process"), root_iface) if verbose: background_handler.notify("Zero Install", _("Checking for updates to '%s'...") % root_iface, timeout=1) network_state = background_handler.get_network_state() if network_state not in (_NetworkState.NM_STATE_CONNECTED_SITE, _NetworkState.NM_STATE_CONNECTED_GLOBAL): logger.info( _("Not yet connected to network (status = %d). Sleeping for a bit..." ), network_state) import time time.sleep(120) if network_state in (_NetworkState.NM_STATE_DISCONNECTED, _NetworkState.NM_STATE_ASLEEP): logger.info(_("Still not connected to network. Giving up.")) sys.exit(1) else: logger.info(_("NetworkManager says we're on-line. Good!")) background_config.freshness = 0 # Don't bother trying to refresh when getting the interface refresh = driver.solve_with_downloads( force=True) # (causes confusing log messages) tasks.wait_for_blocker(refresh) if background_handler.need_gui or not driver.solver.ready or driver.get_uncached_implementations( ): if verbose: background_handler.notify( "Zero Install", _("Updates ready to download for '%s'.") % root_iface, timeout=1) # Run the GUI if possible... from zeroinstall import helpers gui_args = ['--refresh', '--systray', '--download' ] + requirements.get_as_options() new_sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, use_gui=None) if new_sels is None: sys.exit(0) # Cancelled by user elif new_sels is helpers.DontUseGUI: if not driver.solver.ready: background_handler.notify("Zero Install", _("Can't update '%s'") % root_iface) sys.exit(1) tasks.wait_for_blocker(driver.download_uncached_implementations()) new_sels = driver.solver.selections if app is None: background_handler.notify( "Zero Install", _("{name} updated.").format(name=root_iface), timeout=1) else: if verbose: background_handler.notify("Zero Install", _("No updates to download."), timeout=1) new_sels = driver.solver.selections if app is not None: assert driver.solver.ready from zeroinstall.support import xmltools if not xmltools.nodes_equal(new_sels.toDOM(), old_sels.toDOM()): app.set_selections(new_sels) background_handler.notify( "Zero Install", _("{app} updated.").format(app=app.get_name()), timeout=1) app.set_last_checked() sys.exit(0)
def _check_for_updates(requirements, verbose, app): if app is not None: old_sels = app.get_selections() from zeroinstall.injector.driver import Driver from zeroinstall.injector.config import load_config background_handler = BackgroundHandler(requirements.interface_uri, requirements.interface_uri) background_config = load_config(background_handler) root_iface = background_config.iface_cache.get_interface(requirements.interface_uri).get_name() background_handler.title = root_iface driver = Driver(config = background_config, requirements = requirements) logger.info(_("Checking for updates to '%s' in a background process"), root_iface) if verbose: background_handler.notify("Zero Install", _("Checking for updates to '%s'...") % root_iface, timeout = 1) network_state = background_handler.get_network_state() if network_state not in (_NetworkState.NM_STATE_CONNECTED_SITE, _NetworkState.NM_STATE_CONNECTED_GLOBAL): logger.info(_("Not yet connected to network (status = %d). Sleeping for a bit..."), network_state) import time time.sleep(120) if network_state in (_NetworkState.NM_STATE_DISCONNECTED, _NetworkState.NM_STATE_ASLEEP): logger.info(_("Still not connected to network. Giving up.")) sys.exit(1) else: logger.info(_("NetworkManager says we're on-line. Good!")) background_config.freshness = 0 # Don't bother trying to refresh when getting the interface refresh = driver.solve_with_downloads(force = True) # (causes confusing log messages) tasks.wait_for_blocker(refresh) if background_handler.need_gui or driver.get_uncached_implementations(): if verbose: background_handler.notify("Zero Install", _("Updates ready to download for '%s'.") % root_iface, timeout = 1) # Run the GUI if possible... from zeroinstall import helpers gui_args = ['--refresh', '--systray', '--download'] + requirements.get_as_options() new_sels = helpers.get_selections_gui(requirements.interface_uri, gui_args, use_gui = None) if new_sels is None: sys.exit(0) # Cancelled by user elif new_sels is helpers.DontUseGUI: tasks.wait_for_blocker(driver.download_uncached_implementations()) new_sels = driver.solver.selections if app is None: background_handler.notify("Zero Install", _("{name} updated.").format(name = root_iface), timeout = 1) else: if verbose: background_handler.notify("Zero Install", _("No updates to download."), timeout = 1) new_sels = driver.solver.selections if app is not None: assert driver.solver.ready from zeroinstall.support import xmltools if not xmltools.nodes_equal(new_sels.toDOM(), old_sels.toDOM()): app.set_selections(new_sels) background_handler.notify("Zero Install", _("{app} updated.").format(app = app.get_name()), timeout = 1) app.set_last_checked() sys.exit(0)
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()
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