Exemple #1
0
	def __unicode__(self):
		if hasattr(SafeException, '__unicode__'):
			# Python >= 2.6
			if self.feed_url:
				return _('%s [%s]') % (SafeException.__unicode__(self), self.feed_url)
			return SafeException.__unicode__(self)
		else:
			return support.unicode(SafeException.__str__(self))
Exemple #2
0
	def __init__(self, message, ex = None):
		if ex:
			try:
				message += "\n\n(exact error: %s)" % ex
			except:
				# Some Python messages have type str but contain UTF-8 sequences.
				# (e.g. IOException). Adding these to a Unicode 'message' (e.g.
				# after gettext translation) will cause an error.
				import codecs
				decoder = codecs.lookup('utf-8')
				decex = decoder.decode(str(ex), errors = 'replace')[0]
				message += "\n\n(exact error: %s)" % decex

		SafeException.__init__(self, message)
Exemple #3
0
    def get_feed_targets(self, feed):
        """Return a list of Interfaces for which feed can be a feed.
		This is used by B{0install add-feed}.
		@param feed: the feed
		@type feed: L{model.ZeroInstallFeed} (or, deprecated, a URL)
		@rtype: [model.Interface]
		@raise SafeException: If there are no known feeds.
		@since: 0.53"""

        if not isinstance(feed, model.ZeroInstallFeed):
            # (deprecated)
            feed = self.get_feed(feed)
            if feed is None:
                raise SafeException(
                    "Feed is not cached and using deprecated API")

        if not feed.feed_for:
            raise SafeException(
                _("Missing <feed-for> element in '%s'; "
                  "it can't be used as a feed for any other interface.") %
                feed.url)
        feed_targets = feed.feed_for
        logger.debug(_("Feed targets: %s"), feed_targets)
        return [self.get_interface(uri) for uri in feed_targets]
Exemple #4
0
def sign_xml(config, source_xml):
	child = subprocess.Popen(['gpg', '--detach-sign', '--default-key', config.GPG_SIGNING_KEY, '--use-agent', '--output', '-', '-'],
			stdin = subprocess.PIPE,
			stdout = subprocess.PIPE,
			stderr = subprocess.PIPE)
	stdout, stderr = child.communicate(source_xml)
	exit_status = child.wait()
	if exit_status:
		raise SafeException("Error signing feed: %s" % stderr)
	if stderr:
		print(stderr, file=sys.stderr)

	encoded = base64.encodestring(stdout)
	sig = "<!-- Base64 Signature\n" + encoded + "\n-->\n"
	return source_xml + sig
Exemple #5
0
def get_size(url):
    print("Checking {url}... ".format(url=url), end='')
    try:
        scheme = urlparse.urlparse(url)[0].lower()
        if scheme.startswith('http') or scheme.startswith('https'):
            size = get_http_size(url)
        elif scheme.startswith('ftp'):
            size = get_ftp_size(url)
        else:
            raise SafeException("Unknown scheme '%s' in '%s'" % (scheme, url))
    except:
        print("ERROR")
        raise
    print(size, "bytes")
    return size
Exemple #6
0
 def run():
     keys_downloaded = tasks.Task(
         pending.download_keys(config.fetcher), "download keys")
     yield keys_downloaded.finished
     tasks.check(keys_downloaded.finished)
     if not config.iface_cache.update_feed_if_trusted(
             uri, pending.sigs, pending.new_xml):
         blocker = config.trust_mgr.confirm_keys(pending)
         if blocker:
             yield blocker
             tasks.check(blocker)
         if not config.iface_cache.update_feed_if_trusted(
                 uri, pending.sigs, pending.new_xml):
             raise SafeException(
                 _("No signing keys trusted; not importing"))
def extract_deb(stream, destdir, extract = None, start_offset = 0):
	if extract:
		raise SafeException(_('Sorry, but the "extract" attribute is not yet supported for Debs'))

	stream.seek(start_offset)
	# ar can't read from stdin, so make a copy...
	deb_copy_name = os.path.join(destdir, 'archive.deb')
	deb_copy = open(deb_copy_name, 'w')
	shutil.copyfileobj(stream, deb_copy)
	deb_copy.close()

	data_tar = None
	p = subprocess.Popen(('ar', 't', 'archive.deb'), stdout=subprocess.PIPE, cwd=destdir, universal_newlines=True)
	o = p.communicate()[0]
	for line in o.split('\n'):
		if line == 'data.tar':
			data_compression = None
		elif line == 'data.tar.gz':
			data_compression = 'gzip'
		elif line == 'data.tar.bz2':
			data_compression = 'bzip2'
		elif line == 'data.tar.lzma':
			data_compression = 'lzma'
		else:
			continue
		data_tar = line
		break
	else:
		raise SafeException(_("File is not a Debian package."))

	_extract(stream, destdir, ('ar', 'x', 'archive.deb', data_tar))
	os.unlink(deb_copy_name)
	data_name = os.path.join(destdir, data_tar)
	data_stream = open(data_name)
	os.unlink(data_name)
	extract_tar(data_stream, destdir, None, data_compression)
Exemple #8
0
def lookup(uri, missing_ok = False):
	"""Search repositories.json for the repository which hosts 'uri'."""
	path = basedir.load_first_config('0install.net', '0repo', 'repositories.json')
	if path:
		with open(path, 'rb') as stream:
			db = json.load(stream)
	else:
		db = {}
	
	from_registry = None
	for key, value in list(db.items()):
		if uri.startswith(key):
			if from_registry:
				raise SafeException("Multiple matching repositories! {a} and {b}".format(
					a = from_registry, b = value))
			from_registry = value

	if not from_registry:
		if missing_ok:
			return None
		else:
			raise SafeException("No registered repository for {uri} (hint: use '0repo register')".format(uri = uri))

	return from_registry
Exemple #9
0
	def parse(value):
		v = float(value[:-1])
		unit = value[-1]
		if unit == 's':
			return int(v)
		v *= 60
		if unit == 'm':
			return int(v)
		v *= 60
		if unit == 'h':
			return int(v)
		v *= 24
		if unit == 'd':
			return int(v)
		raise SafeException(_('Unknown unit "%s" - use e.g. 5d for 5 days') % unit)
def handle(config, options, args):
	if len(args) == 2:
		iface = config.iface_cache.get_interface(model.canonical_iface_uri(args[0]))
		feed_url = args[1]

		feed_import = add_feed.find_feed_import(iface, feed_url)
		if not feed_import:
			raise SafeException(_('Interface %(interface)s has no feed %(feed)s') %
						{'interface': iface.uri, 'feed': feed_url})
		iface.extra_feeds.remove(feed_import)
		writer.save_interface(iface)
	elif len(args) == 1:
		add_feed.handle(config, options, args, add_ok = False, remove_ok = True)
	else:
		raise UsageError()
	def get_implementation(self, interface):
		"""Get the chosen implementation.
		@type interface: Interface
		@rtype: L{model.Implementation}
		@raise SafeException: if interface has not been fetched or no implementation could be
		chosen."""
		assert isinstance(interface, Interface)

		if not interface.name and not interface.feeds:
			raise SafeException(_("We don't have enough information to "
					    "run this program yet. "
					    "Need to download:\n%s") % interface.uri)
		try:
			return self.implementation[interface]
		except KeyError, ex:
			if interface.implementations:
				offline = ""
				if self.network_use == network_offline:
					raise SafeException(_("No usable implementation found for '%s'.\n"
							"This may be because 'Network Use' is set to Off-line.") %
							interface.name)
				raise SafeException(_("No usable implementation found for '%s'.") %
						interface.name)
			raise ex
def handle(config, options, args):
    if len(args) == 1:
        extract = None
    elif len(args) == 2:
        extract = args[1]
    else:
        raise UsageError()

    source = args[0]
    alg = manifest.algorithms.get(options.algorithm or 'sha1new', None)
    if alg is None:
        raise SafeException(_('Unknown algorithm "%s"') % alg)

    def do_manifest(d):
        if extract is not None:
            d = os.path.join(d, extract)
        digest = alg.new_digest()
        for line in alg.generate_manifest(d):
            digest.update(line + '\n')
        print(alg.getID(digest))

    if os.path.isdir(source):
        if extract is not None:
            raise SafeException("Can't use extract with a directory")
        do_manifest(source)
    else:
        data = None
        tmpdir = tempfile.mkdtemp()
        try:
            data = open(args[0], 'rb')
            unpack.unpack_archive(source, data, tmpdir, extract)
            do_manifest(tmpdir)
        finally:
            support.ro_rmtree(tmpdir)
            if data:
                data.close()
Exemple #13
0
def extract_cab(stream, destdir, extract, start_offset=0):
    "@since: 0.24"
    if extract:
        raise SafeException(
            _('Sorry, but the "extract" attribute is not yet supported for Cabinet files'
              ))

    stream.seek(start_offset)
    # cabextract can't read from stdin, so make a copy...
    cab_copy_name = os.path.join(destdir, 'archive.cab')
    cab_copy = file(cab_copy_name, 'w')
    shutil.copyfileobj(stream, cab_copy)
    cab_copy.close()

    _extract(stream, destdir, ['cabextract', '-s', '-q', 'archive.cab'])
    os.unlink(cab_copy_name)
Exemple #14
0
    def create_app(self, name, requirements):
        validate_name(name)

        apps_dir = basedir.save_config_path(namespaces.config_site, "apps")
        app_dir = os.path.join(apps_dir, name)
        if os.path.isdir(app_dir):
            raise SafeException(
                _("Application '{name}' already exists: {path}").format(
                    name=name, path=app_dir))
        os.mkdir(app_dir)

        app = App(self.config, app_dir)
        app.set_requirements(requirements)
        app.set_last_checked()

        return app
Exemple #15
0
def handle_invoke(config, options, ticket, request):
    try:
        command = request[0]
        logger.debug("Got request '%s'", command)
        if command == 'get-selections-gui':
            response = do_get_selections_gui(config, request[1:])
        elif command == 'wait-for-network':
            response = do_wait_for_network(config)
        elif command == 'download-selections':
            l = stdin.readline().strip()
            xml = qdom.parse(BytesIO(stdin.read(int(l))))
            blocker = do_download_selections(config, options, request[1:], xml)
            reply_when_done(ticket, blocker)
            return  #async
        elif command == 'get-package-impls':
            l = stdin.readline().strip()
            xml = qdom.parse(BytesIO(stdin.read(int(l))))
            response = do_get_package_impls(config, options, request[1:], xml)
        elif command == 'is-distro-package-installed':
            l = stdin.readline().strip()
            xml = qdom.parse(BytesIO(stdin.read(int(l))))
            response = do_is_distro_package_installed(config, options, xml)
        elif command == 'get-distro-candidates':
            l = stdin.readline().strip()
            xml = qdom.parse(BytesIO(stdin.read(int(l))))
            blocker = do_get_distro_candidates(config, request[1:], xml)
            reply_when_done(ticket, blocker)
            return  # async
        elif command == 'download-and-import-feed':
            blocker = do_download_and_import_feed(config, request[1:])
            reply_when_done(ticket, blocker)
            return  # async
        elif command == 'notify-user':
            response = do_notify_user(config, request[1])
        else:
            raise SafeException("Internal error: unknown command '%s'" %
                                command)
        response = ['ok', response]
    except SafeException as ex:
        logger.info("Replying with error: %s", ex)
        response = ['error', str(ex)]
    except Exception as ex:
        import traceback
        logger.info("Replying with error: %s", ex)
        response = ['error', traceback.format_exc().strip()]

    send_json(["return", ticket, response])
Exemple #16
0
def do_gui(args):
    "gui [--no-prompt] [SOURCE-URI]"
    if args and args[0] == '--no-prompt':
        del args[0]
        # This option no longer has any effect, since it is the default.
        # However, old versions of 0launch's GUI pass it (< 0.52)

    from zeroinstall.gtkui import pygtkcompat
    pygtkcompat.enable()
    pygtkcompat.enable_gtk(version='3.0')

    import gui_support
    import gtk

    try:
        if len(args) == 0:
            pass
        elif len(args) == 1:
            import setup

            def get_dir_callback(default_dir):
                compile_dir = gui_support.choose_dir(
                    _('Create build directory'), default_dir)
                if compile_dir:
                    return compile_dir
                raise SafeException("Cancelled at user's request")

            setup.do_setup(args, get_dir_callback)
        else:
            raise SafeException("usage: 0compile gui URI")

        buildenv = BuildEnv()
        box = gui_support.CompileBox(buildenv.interface)
        box.connect('destroy', lambda b: gtk.main_quit())
        box.show()

        gtk.main()
    except KeyboardInterrupt:
        pass
    except SafeException as ex:
        gui_support.alert(None, '%s' % ex)
        sys.exit(1)
    except Exception as ex:
        import traceback
        traceback.print_exc()
        gui_support.alert(None, '%s: %s' % (ex.__class__, ex))
        sys.exit(1)
Exemple #17
0
        def recurse(sub):
            # To ensure that a line-by-line comparison of the manifests
            # is possible, we require that filenames don't contain newlines.
            # Otherwise, you can name a file so that the part after the \n
            # would be interpreted as another line in the manifest.
            if '\n' in sub: raise BadDigest("Newline in filename '%s'" % sub)
            assert sub.startswith('/')

            if sub == '/.manifest': return

            full = os.path.join(root, sub[1:].replace('/', os.sep))
            info = os.lstat(full)

            m = info.st_mode
            if stat.S_ISDIR(m):
                if sub != '/':
                    yield "D %s %s" % (int(info.st_mtime), sub)
                items = os.listdir(full)
                items.sort()
                subdir = sub
                if not subdir.endswith('/'):
                    subdir += '/'
                for x in items:
                    for y in recurse(subdir + x):
                        yield y
                return

            assert sub[1:]
            leaf = os.path.basename(sub[1:])
            if stat.S_ISREG(m):
                d = sha1_new(open(full).read()).hexdigest()
                if m & 0o111:
                    yield "X %s %s %s %s" % (d, int(
                        info.st_mtime), info.st_size, leaf)
                else:
                    yield "F %s %s %s %s" % (d, int(
                        info.st_mtime), info.st_size, leaf)
            elif stat.S_ISLNK(m):
                target = os.readlink(full)
                d = sha1_new(target).hexdigest()
                # Note: Can't use utime on symlinks, so skip mtime
                # Note: eCryptfs may report length as zero, so count ourselves instead
                yield "S %s %s %s" % (d, len(target), leaf)
            else:
                raise SafeException(
                    _("Unknown object '%s' (not a file, directory or symlink)")
                    % full)
Exemple #18
0
def do_audit(args):
    """audit [DIRECTORY]"""
    if len(args) == 0:
        audit_stores = stores.stores
    else:
        audit_stores = [zerostore.Store(x) for x in args]

    audit_ls = []
    total = 0
    for a in audit_stores:
        if os.path.isdir(a.dir):
            items = sorted(os.listdir(a.dir))
            audit_ls.append((a.dir, items))
            total += len(items)
        elif len(args):
            raise SafeException(_("No such directory '%s'") % a.dir)

    verified = 0
    failures = []
    i = 0
    for root, impls in audit_ls:
        print _("Scanning %s") % root
        for required_digest in impls:
            i += 1
            path = os.path.join(root, required_digest)
            if '=' not in required_digest:
                print _("Skipping non-implementation directory %s") % path
                continue
            try:
                msg = _("[%(done)d / %(total)d] Verifying %(digest)s") % {
                    'done': i,
                    'total': total,
                    'digest': required_digest
                }
                print msg,
                sys.stdout.flush()
                verify(path, required_digest)
                print "\r" + (" " * len(msg)) + "\r",
                verified += 1
            except zerostore.BadDigest, ex:
                print
                failures.append(path)
                print str(ex)
                if ex.detail:
                    print
                    print ex.detail
	def solve_and_download_impls(self, refresh = False):
		"""Run L{solve_with_downloads} and then get the selected implementations too.
		@raise SafeException: if we couldn't select a set of implementations
		@since: 0.40"""
		refreshed = self.solve_with_downloads(refresh)
		if refreshed:
			yield refreshed
			tasks.check(refreshed)

		if not self.solver.ready:
			raise SafeException(_("Can't find all required implementations:") + '\n' +
				'\n'.join(["- %s -> %s" % (iface, self.solver.selections[iface])
					   for iface  in self.solver.selections]))
		downloaded = self.download_uncached_implementations()
		if downloaded:
			yield downloaded
			tasks.check(downloaded)
Exemple #20
0
def ensure_no_uncommitted_changes(path):
    child = subprocess.Popen(
        ["git", "diff", "--exit-code", "HEAD", "--",
         abspath(path)],
        cwd=dirname(path),
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
    stdout, unused = child.communicate()
    if child.returncode == 0:
        return

    raise SafeException('Uncommitted changes in {feed}!\n'
                        'In the feeds directory, use:\n\n'
                        '"git commit -a" to commit them, or\n'
                        '"git stash" to discard.\n\n'
                        'Changes are:\n{changes}'.format(feed=path,
                                                         changes=stdout))
    def confirm_trust_keys(self, interface, sigs, iface_xml):
        """We don't trust any of the signatures yet. Ask the user.
		When done update the L{trust} database, and then call L{trust.TrustDB.notify}.
		@deprecated: see L{confirm_keys}
		@arg interface: the interface being updated
		@arg sigs: a list of signatures (from L{gpg.check_stream})
		@arg iface_xml: the downloaded data (not yet trusted)
		@return: a blocker, if confirmation will happen asynchronously, or None
		@rtype: L{tasks.Blocker}"""
        import warnings
        warnings.warn(_("Use confirm_keys, not confirm_trust_keys"),
                      DeprecationWarning,
                      stacklevel=2)
        from zeroinstall.injector import trust, gpg
        assert sigs
        valid_sigs = [s for s in sigs if isinstance(s, gpg.ValidSig)]
        if not valid_sigs:
            raise SafeException(
                'No valid signatures found on "%s". Signatures:%s' %
                (interface.uri, ''.join(['\n- ' + str(s) for s in sigs])))

        domain = trust.domain_from_url(interface.uri)

        # Ask on stderr, because we may be writing XML to stdout
        print >> sys.stderr, "\nInterface:", interface.uri
        print >> sys.stderr, "The interface is correctly signed with the following keys:"
        for x in valid_sigs:
            print >> sys.stderr, "-", x

        if len(valid_sigs) == 1:
            print >> sys.stderr, "Do you want to trust this key to sign feeds from '%s'?" % domain
        else:
            print >> sys.stderr, "Do you want to trust all of these keys to sign feeds from '%s'?" % domain
        while True:
            print >> sys.stderr, "Trust [Y/N] ",
            i = raw_input()
            if not i: continue
            if i in 'Nn':
                raise NoTrustedKeys(_('Not signed with a trusted key'))
            if i in 'Yy':
                break
        for key in valid_sigs:
            print >> sys.stderr, "Trusting", key.fingerprint, "for", domain
            trust.trust_db.trust_key(key.fingerprint, domain)

        trust.trust_db.notify()
Exemple #22
0
    def parse_update_options(self, options):
        """Update the settings based on the options (used for "0install update APP").
		@return: whether any settings were changed
		@rtype: bool
		@since: 1.9"""
        changed = False
        for key in ['not_before', 'before', 'message', 'cpu', 'os', 'command']:
            value = getattr(options, key)
            if value is not None:
                changed = changed or value != getattr(self, key)
                setattr(self, key, value)
        if options.source and not self.source:
            # (partly because it doesn't make much sense, and partly because you
            # can't undo it, as there's no --not-source option)
            from zeroinstall import SafeException
            raise SafeException("Can't update from binary to source type!")
        return changed
		def recurse(sub):
			# To ensure that a line-by-line comparison of the manifests
			# is possible, we require that filenames don't contain newlines.
			# Otherwise, you can name a file so that the part after the \n
			# would be interpreted as another line in the manifest.
			if '\n' in sub: raise BadDigest(_("Newline in filename '%s'") % sub)
			assert sub.startswith('/')

			full = os.path.join(root, sub[1:])
			info = os.lstat(full)
			new_digest = self.new_digest
			
			m = info.st_mode
			if not stat.S_ISDIR(m): raise Exception(_('Not a directory: "%s"') % full)
			if sub != '/':
				yield "D %s" % sub
			items = os.listdir(full)
			items.sort()
			dirs = []
			for leaf in items:
				path = os.path.join(root, sub[1:], leaf)
				info = os.lstat(path)
				m = info.st_mode

				if stat.S_ISREG(m):
					if leaf == '.manifest': continue

					d = new_digest(file(path).read()).hexdigest()
					if m & 0111:
						yield "X %s %s %s %s" % (d, int(info.st_mtime), info.st_size, leaf)
					else:
						yield "F %s %s %s %s" % (d, int(info.st_mtime), info.st_size, leaf)
				elif stat.S_ISLNK(m):
					target = os.readlink(path)
					d = new_digest(target).hexdigest()
					# Note: Can't use utime on symlinks, so skip mtime
					# Note: eCryptfs may report length as zero, so count ourselves instead
					yield "S %s %s %s" % (d, len(target), leaf)
				elif stat.S_ISDIR(m):
					dirs.append(leaf)
				else:
					raise SafeException(_("Unknown object '%s' (not a file, directory or symlink)") %
							path)
			for x in dirs:
				for y in recurse(os.path.join(sub, x)): yield y
			return
def extract_dmg(stream, destdir, extract, start_offset = 0):
	"@since: 0.46"
	if extract:
		raise SafeException(_('Sorry, but the "extract" attribute is not yet supported for DMGs'))

	stream.seek(start_offset)
	# hdiutil can't read from stdin, so make a copy...
	dmg_copy_name = os.path.join(destdir, 'archive.dmg')
	dmg_copy = open(dmg_copy_name, 'w')
	shutil.copyfileobj(stream, dmg_copy)
	dmg_copy.close()

	mountpoint = mkdtemp(prefix='archive')
	subprocess.check_call(["hdiutil", "attach", "-quiet", "-mountpoint", mountpoint, "-nobrowse", dmg_copy_name])
	subprocess.check_call(["cp", "-pR"] + glob.glob("%s/*" % mountpoint) + [destdir])
	subprocess.check_call(["hdiutil", "detach", "-quiet", mountpoint])
	os.rmdir(mountpoint)
	os.unlink(dmg_copy_name)
def _extract(stream, destdir, command, start_offset = 0):
	"""Run execvp('command') inside destdir in a child process, with
	stream seeked to 'start_offset' as stdin."""

	# Some zip archives are missing timezone information; force consistent results
	child_env = os.environ.copy()
	child_env['TZ'] = 'GMT'

	stream.seek(start_offset)

	# TODO: use pola-run if available, once it supports fchmod
	child = subprocess.Popen(command, cwd = destdir, stdin = stream, stderr = subprocess.PIPE, env = child_env)

	unused, cerr = child.communicate()

	status = child.wait()
	if status != 0:
		raise SafeException(_('Failed to extract archive (using %(command)s); exit code %(status)d:\n%(err)s') % {'command': command, 'status': status, 'err': cerr.strip()})
Exemple #26
0
	def __init__(self, need_config = True):
		if need_config and not os.path.isfile(ENV_FILE):
			raise SafeException("Run 0compile from a directory containing a '%s' file" % ENV_FILE)

		self.config = ConfigParser.RawConfigParser()
		self.config.add_section('compile')
		self.config.set('compile', 'download-base-url', '')
		self.config.set('compile', 'version-modifier', '')
		self.config.set('compile', 'interface', '')
		self.config.set('compile', 'selections', '')
		self.config.set('compile', 'metadir', '0install')
		self.config.set('compile', 'distdir', '')

		self.config.read(ENV_FILE)

		self._selections = None

		return
Exemple #27
0
def find_config(missing_ok=False):
    """Change to parent directory until we find one with 0repo-config.py."""
    def is_root_dir():
        if os.name == 'nt':
            # Top-level directories on Windows are always three characters long (e.g. 'C:\')
            return len(os.getcwd()) == 3
        else:
            return os.path.samefile('.', '..')

    # Walk up the directory tree to find the root of the repository
    while not os.path.isfile('0repo-config.py'):
        if is_root_dir():
            if missing_ok:
                return False
            raise SafeException(
                '0repo must be run from a repository directory (a directory that contains\n'
                'a "0repo-config.py" file). To create a new repository, use "0repo create"'
            )
        os.chdir('..')
    return True
Exemple #28
0
def extract_zip(stream, destdir, extract, start_offset=0):
    if extract:
        # Limit the characters we accept, to avoid sending dodgy
        # strings to zip
        if not re.match('^[a-zA-Z0-9][- _a-zA-Z0-9.]*$', extract):
            raise SafeException(_('Illegal character in extract attribute'))

    stream.seek(start_offset)
    # unzip can't read from stdin, so make a copy...
    zip_copy_name = os.path.join(destdir, 'archive.zip')
    with open(zip_copy_name, 'wb') as zip_copy:
        shutil.copyfileobj(stream, zip_copy)

    args = ['unzip', '-q', '-o', 'archive.zip']

    if extract:
        args.append(extract + '/*')

    _extract(stream, destdir, args)
    os.unlink(zip_copy_name)
Exemple #29
0
def expand_impl_relative_urls(config, parent, impl):
	for elem in parent.childNodes:
		if elem.nodeType != Node.ELEMENT_NODE: continue
		if elem.namespaceURI != XMLNS_IFACE: continue

		if elem.localName in ('archive', 'file'):
			archive = elem.getAttribute('href')
			assert archive
			if '/' not in archive:
				x = config.archive_db.lookup(archive)
				if not x and os.path.exists(os.path.join('incoming', archive)):
					x = import_missing_archive(config, impl, archive)
				if not x:
					raise SafeException("Missing entry for {basename} in {db}; can't build feeds."
							    "Place missing archives in 'incoming' and try again.".format(
						basename = archive,
						db = config.archive_db.path))
				elem.setAttribute('href', x.url)
		elif elem.localName == 'recipe':
			expand_impl_relative_urls(config, elem, impl = impl)
Exemple #30
0
    def spawn_build(self, iface_name):
        assert self.child is None

        self.details.insert_at_end_and_scroll('Building %s\n' % iface_name,
                                              'heading')

        # Group all the child processes so we can kill them easily
        def become_group_leader():
            os.setpgid(0, 0)

        devnull = os.open(os.devnull, os.O_RDONLY)
        try:
            self.child = subprocess.Popen(
                [sys.executable, '-u', sys.argv[0], 'build'],
                stdin=devnull,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                preexec_fn=become_group_leader)
        finally:
            os.close(devnull)

        import codecs
        decoder = codecs.getincrementaldecoder('utf-8')(errors='replace')

        while True:
            yield tasks.InputBlocker(self.child.stdout, 'output from child')
            got = os.read(self.child.stdout.fileno(), 100)
            chars = decoder.decode(got, final=not got)
            self.details.insert_at_end_and_scroll(chars)
            if not got: break

        self.child.wait()
        code = self.child.returncode
        self.child = None
        if code:
            self.details.insert_at_end_and_scroll(
                'Build process exited with error status %d\n' % code, 'error')
            raise SafeException('Build process exited with error status %d' %
                                code)
        self.details.insert_at_end_and_scroll('Build completed successfully\n',
                                              'heading')
Exemple #31
0
def add_to_menu(feed, icon_path, category, zlaunch=None):
    """Write a .desktop file for this application.
	@param feed: the master feed of the program being added
	@param icon_path: the path of the icon, or None
	@param category: the freedesktop.org menu category"""
    if isinstance(feed, model.Interface):
        import warnings
        warnings.warn("API change: pass a ZeroInstallFeed, not an Interface",
                      DeprecationWarning, 2)
        iface_uri = feed.uri
    else:
        iface_uri = feed.url

    tmpdir = tempfile.mkdtemp(prefix='zero2desktop-')
    try:
        desktop_name = os.path.join(
            tmpdir, 'zeroinstall-%s.desktop' %
            feed.get_name().lower().replace(os.sep, '-').replace(' ', ''))
        desktop = open(desktop_name, 'w')
        desktop.write(
            _template % {
                'name': feed.get_name(),
                'comment': feed.summary,
                '0launch': zlaunch or '0launch',
                'iface': iface_uri,
                'category': category
            })
        if icon_path:
            desktop.write(_icon_template % icon_path)
        if len(feed.get_metadata(namespaces.XMLNS_IFACE, 'needs-terminal')):
            desktop.write('Terminal=true\n')
        desktop.close()
        status = os.spawnlp(os.P_WAIT, 'xdg-desktop-menu', 'xdg-desktop-menu',
                            'install', desktop_name)
    finally:
        shutil.rmtree(tmpdir)

    if status:
        raise SafeException(
            _('Failed to run xdg-desktop-menu (error code %d)') % status)
Exemple #32
0
def suggest_release_version(snapshot_version):
    """Given a snapshot version, suggest a suitable release version.
	>>> suggest_release_version('1.0-pre')
	'1.0'
	>>> suggest_release_version('0.9-post')
	'0.10'
	>>> suggest_release_version('3')
	Traceback (most recent call last):
		...
	SafeException: Version '3' is not a snapshot version (should end in -pre or -post)
	"""
    version = model.parse_version(snapshot_version)
    mod = version[-1]
    if mod == 0:
        raise SafeException(
            "Version '%s' is not a snapshot version (should end in -pre or -post)"
            % snapshot_version)
    if mod > 0:
        # -post, so increment the number
        version[-2][-1] += 1
    version[-1] = 0  # Remove the modifier
    return model.format_version(version)
	def __init__(self, message = None):
		SafeException.__init__(self, message or _("Download aborted at user's request"))
Exemple #34
0
	def __str__(self):
		if self.feed_url:
			return SafeException.__str__(self) + ' in ' + self.feed_url
		return SafeException.__str__(self)