Exemplo n.º 1
0
def do_publish(args):
	"""publish [ DOWNLOAD-BASE-URL ]"""

	parser = OptionParser(usage="usage: %prog publish [options] [ DOWNLOAD-BASE-URL ]")

	parser.add_option('', "--target-feed", help="name of output feed file to create", metavar='FILE')
	(options, args2) = parser.parse_args(args)

	buildenv = BuildEnv()
	if len(args2) == 0:
		if not buildenv.download_base_url:
			raise SafeException("No download base set. Give the URL for a remote directory.")
	elif len(args2) == 1:
		buildenv.config.set('compile', 'download-base-url', args2[0])
		buildenv.save()

	info("Using download base URL: %s", buildenv.download_base_url)

	if not os.path.isdir(buildenv.distdir):
		raise SafeException("Directory '%s' does not exist. Try 'compile build'." % buildenv.distdir)

	distdir = os.path.basename(buildenv.distdir)
	archive_name = buildenv.archive_stem + '.tar.bz2'

	# Make all directories in the archive user writable
	for main, dirs, files in os.walk(distdir):
		os.chmod(main, os.stat(main).st_mode | 0200)

	import tarfile
	archive = tarfile.open(archive_name, mode = 'w:bz2')
	archive.add(distdir, buildenv.archive_stem)
	archive.close()

	target_feed = options.target_feed or buildenv.local_download_iface

	download_url = os.path.join(buildenv.download_base_url, archive_name)
	shutil.copyfile(buildenv.local_iface_file, target_feed)
	
	# XXX: we're assuming that 0publish requires the same version of Python as
	# 0compile. This is currently needed for Arch Linux, but long-term we need to
	# use the <runner>.
	spawn_and_check(sys.executable, [
		pubish_command,
		target_feed,
		'--archive-url', download_url,
		'--archive-extract', buildenv.archive_stem])

	if options.target_feed is None:
		# If --target-feed is used this is probably a script, so don't print
		# out hints.
		print "Now upload '%s' as:\n%s\n" % (archive_name, download_url)

		print "Once uploaded, you can download and run with:"
		print "$ 0launch %s" % target_feed
Exemplo n.º 2
0
def do_publish(args):
    """publish [ DOWNLOAD-BASE-URL ]"""

    parser = OptionParser(
        usage="usage: %prog publish [options] [ DOWNLOAD-BASE-URL ]")

    parser.add_option('',
                      "--target-feed",
                      help="name of output feed file to create",
                      metavar='FILE')
    (options, args2) = parser.parse_args(args)

    buildenv = BuildEnv()
    if len(args2) == 1:
        buildenv.config.set('compile', 'download-base-url', args2[0])
        buildenv.save()
    elif len(args2) > 1:
        parser.print_help()
        sys.exit(1)

    download_base_url = buildenv.download_base_url or None

    if download_base_url:
        info("Using download base URL: %s", download_base_url)

    if not os.path.isdir(buildenv.distdir):
        raise SafeException(
            "Directory '%s' does not exist. Try 'compile build'." %
            buildenv.distdir)

    distdir = os.path.basename(buildenv.distdir)
    archive_name = buildenv.archive_stem + '.tar.bz2'

    # Make all directories in the archive user writable
    for main, dirs, files in os.walk(distdir):
        os.chmod(main, os.stat(main).st_mode | 0o200)

    import tarfile
    archive = tarfile.open(archive_name, mode='w:bz2')
    archive.add(distdir, buildenv.archive_stem)
    archive.close()

    target_feed = options.target_feed or buildenv.local_download_iface

    if download_base_url:
        download_url = os.path.join(download_base_url, archive_name)
    else:
        download_url = archive_name
    shutil.copyfile(buildenv.local_iface_file, target_feed)

    # XXX: we're assuming that 0publish requires the same version of Python as
    # 0compile. This is currently needed for Arch Linux, but long-term we need to
    # use the <runner>.
    spawn_and_check(sys.executable, [
        pubish_command, target_feed, '--archive-url', download_url,
        '--archive-extract', buildenv.archive_stem
    ])

    if options.target_feed is None:
        # If --target-feed is used this is probably a script, so don't print
        # out hints.
        if download_base_url:
            print("Now upload '%s' as:\n%s\n" % (archive_name, download_url))
            print("Once uploaded, you can download and run with:")
            print("0launch %s" % target_feed)
        else:
            print("Generated archive '%s' and feed '%s'." %
                  (archive_name, target_feed))
            print("Upload it to a repository with:")
            print("0repo add %s" % target_feed)
Exemplo n.º 3
0
def do_build_internal(options, args):
    """build-internal"""
    # If a sandbox is being used, we're in it now.
    import getpass, socket

    buildenv = BuildEnv()
    sels = buildenv.get_selections()

    builddir = os.path.realpath('build')
    ensure_dir(buildenv.metadir)

    build_env_xml = join(buildenv.metadir, 'build-environment.xml')

    buildenv_doc = sels.toDOM()

    # Create build-environment.xml file
    root = buildenv_doc.documentElement
    info = buildenv_doc.createElementNS(XMLNS_0COMPILE, 'build-info')
    root.appendChild(info)
    info.setAttributeNS(None, 'time', time.strftime('%Y-%m-%d %H:%M').strip())
    info.setAttributeNS(None, 'host', socket.getfqdn())
    info.setAttributeNS(None, 'user', getpass.getuser())
    info.setAttributeNS(None, 'arch', '%s-%s' % (uname[0], uname[4]))
    stream = file(build_env_xml, 'w')
    buildenv_doc.writexml(stream, addindent="  ", newl="\n")
    stream.close()

    # Create local binary interface file.
    # We use the main feed for the interface as the template for the name,
    # summary, etc (note: this is not necessarily the feed that contained
    # the source code).
    master_feed = iface_cache.get_feed(buildenv.interface)
    src_impl = buildenv.chosen_impl(buildenv.interface)
    write_sample_feed(buildenv, master_feed, src_impl)

    # Check 0compile is new enough
    min_version = model.parse_version(
        src_impl.attrs.get(XMLNS_0COMPILE + ' min-version', None))
    if min_version and min_version > model.parse_version(__main__.version):
        raise SafeException(
            "%s-%s requires 0compile >= %s, but we are only version %s" %
            (master_feed.get_name(), src_impl.version,
             model.format_version(min_version), __main__.version))

    # Create the patch
    patch_file = join(buildenv.metadir, 'from-%s.patch' % src_impl.version)
    if buildenv.user_srcdir:
        with open(patch_file, 'w') as stream:
            # (ignore errors; will already be shown on stderr)
            try:
                subprocess.call(["diff", "-urN", buildenv.orig_srcdir, 'src'],
                                stdout=stream)
            except OSError as ex:
                print >> sys.stderr, "WARNING: Failed to run 'diff': ", ex
        if os.path.getsize(patch_file) == 0:
            os.unlink(patch_file)
    elif os.path.exists(patch_file):
        os.unlink(patch_file)

    env('BUILDDIR', builddir)
    env('DISTDIR', buildenv.distdir)
    env('SRCDIR', buildenv.user_srcdir or buildenv.orig_srcdir)
    env('BINARYFEED', buildenv.local_iface_file)
    os.chdir(builddir)
    print "cd", builddir

    setup = CompileSetup(iface_cache.stores, sels)
    setup.prepare_env()

    # These mappings are needed when mixing Zero Install -dev packages with
    # native package binaries.
    mappings = {}
    for impl in sels.selections.values():
        # Add mappings that have been set explicitly...
        new_mappings = impl.attrs.get(XMLNS_0COMPILE + ' lib-mappings', '')
        if new_mappings:
            new_mappings = new_mappings.split(' ')
            for mapping in new_mappings:
                assert ':' in mapping, "lib-mappings missing ':' in '%s' from '%s'" % (
                    mapping, impl.feed)
                name, major_version = mapping.split(':', 1)
                assert '/' not in mapping, "lib-mappings '%s' contains a / in the version number (from '%s')!" % (
                    mapping, impl.feed)
                if sys.platform == 'darwin':
                    mappings[name] = 'lib%s.%s.dylib' % (name, major_version)
                else:
                    mappings[name] = 'lib%s.so.%s' % (name, major_version)
        # Auto-detect required mappings where possible...
        # (if the -dev package is native, the symlinks will be OK)
        if not is_package_impl(impl):
            impl_path = lookup(impl)
            for libdirname in ['lib', 'usr/lib', 'lib64', 'usr/lib64']:
                libdir = os.path.join(impl_path, libdirname)
                if os.path.isdir(libdir):
                    find_broken_version_symlinks(libdir, mappings)

    if mappings:
        set_up_mappings(mappings)

    overrides_dir = os.path.join(os.environ['TMPDIR'], PKG_CONFIG_OVERRIDES)
    if os.path.isdir(overrides_dir):
        add_overrides = model.EnvironmentBinding('PKG_CONFIG_PATH',
                                                 PKG_CONFIG_OVERRIDES)
        do_env_binding(add_overrides, os.environ['TMPDIR'])

    # Some programs want to put temporary build files in the source directory.
    # Make a copy of the source if needed.
    dup_src_type = src_impl.attrs.get(XMLNS_0COMPILE + ' dup-src', None)
    if dup_src_type == 'true':
        dup_src(copy_file)
        env('SRCDIR', builddir)
    elif dup_src_type:
        raise Exception("Unknown dup-src value '%s'" % dup_src_type)

    if options.shell:
        spawn_and_check(find_in_path('cmd' if os.name == 'nt' else 'sh'), [])
    else:
        command = sels.commands[0].qdom.attrs.get('shell-command', None)
        if command is None:
            # New style <command>
            prog_args = setup.build_command(sels.interface,
                                            sels.command) + args
        else:
            # Old style shell-command='...'
            if os.name == 'nt':
                prog_args = [
                    os.environ['0COMPILE_BASH'], '-eux', '-c', command
                ] + args
            else:
                prog_args = ['/bin/sh', '-c', command + ' "$@"', '-'] + args
            assert len(sels.commands) == 1

        # Remove any existing log files
        for log in ['build.log', 'build-success.log', 'build-failure.log']:
            if os.path.exists(log):
                os.unlink(log)

        # Run the command, copying output to a new log
        with open('build.log', 'w') as log:
            print >> log, "Build log for %s-%s" % (master_feed.get_name(),
                                                   src_impl.version)
            print >> log, "\nBuilt using 0compile-%s" % __main__.version
            print >> log, "\nBuild system: " + ', '.join(uname)
            print >> log, "\n%s:\n" % ENV_FILE
            with open(os.path.join(os.pardir, ENV_FILE)) as properties_file:
                shutil.copyfileobj(properties_file, log)

            log.write('\n')

            if os.path.exists(patch_file):
                print >> log, "\nPatched with:\n"
                shutil.copyfileobj(file(patch_file), log)
                log.write('\n')

            if command:
                print "Executing: " + command, args
                print >> log, "Executing: " + command, args
            else:
                print "Executing: " + str(prog_args)
                print >> log, "Executing: " + str(prog_args)

            # Tee the output to the console and to the log
            child = subprocess.Popen(prog_args,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT)
            while True:
                data = os.read(child.stdout.fileno(), 100)
                if not data: break
                sys.stdout.write(data)
                log.write(data)
            status = child.wait()
            failure = None
            if status == 0:
                print >> log, "Build successful"
                shorten_dynamic_library_install_names()
                fixup_generated_pkgconfig_files()
                remove_la_files()
            elif status > 0:
                failure = "Build failed with exit code %d" % status
            else:
                failure = "Build failure: exited due to signal %d" % (-status)
            if failure:
                print >> log, failure

        if failure:
            os.rename('build.log', 'build-failure.log')
            raise SafeException("Command '%s': %s" % (prog_args, failure))
        else:
            os.rename('build.log', 'build-success.log')
Exemplo n.º 4
0
def do_build_internal(options, args):
	"""build-internal"""
	# If a sandbox is being used, we're in it now.
	import getpass, socket

	buildenv = BuildEnv()
	sels = buildenv.get_selections()

	builddir = os.path.realpath('build')
	ensure_dir(buildenv.metadir)

	build_env_xml = join(buildenv.metadir, 'build-environment.xml')

	buildenv_doc = sels.toDOM()

	# Create build-environment.xml file
	root = buildenv_doc.documentElement
	info = buildenv_doc.createElementNS(XMLNS_0COMPILE, 'build-info')
	root.appendChild(info)
	info.setAttributeNS(None, 'time', time.strftime('%Y-%m-%d %H:%M').strip())
	info.setAttributeNS(None, 'host', socket.getfqdn())
	info.setAttributeNS(None, 'user', getpass.getuser())
	info.setAttributeNS(None, 'arch', '%s-%s' % (uname[0], uname[4]))
	stream = file(build_env_xml, 'w')
	buildenv_doc.writexml(stream, addindent="  ", newl="\n")
	stream.close()

	# Create local binary interface file.
	# We use the main feed for the interface as the template for the name,
	# summary, etc (note: this is not necessarily the feed that contained
	# the source code).
	master_feed = iface_cache.get_feed(buildenv.interface)
	src_impl = buildenv.chosen_impl(buildenv.interface)
	write_sample_feed(buildenv, master_feed, src_impl)

	# Check 0compile is new enough
	min_version = model.parse_version(src_impl.attrs.get(XMLNS_0COMPILE + ' min-version', None))
	if min_version and min_version > model.parse_version(__main__.version):
		raise SafeException("%s-%s requires 0compile >= %s, but we are only version %s" %
				(master_feed.get_name(), src_impl.version, model.format_version(min_version), __main__.version))

	# Create the patch
	patch_file = join(buildenv.metadir, 'from-%s.patch' % src_impl.version)
	if buildenv.user_srcdir:
		with open(patch_file, 'w') as stream:
			# (ignore errors; will already be shown on stderr)
			try:
				subprocess.call(["diff", "-urN", buildenv.orig_srcdir, 'src'], stdout = stream)
			except OSError as ex:
				print >>sys.stderr, "WARNING: Failed to run 'diff': ", ex
		if os.path.getsize(patch_file) == 0:
			os.unlink(patch_file)
	elif os.path.exists(patch_file):
		os.unlink(patch_file)

	env('BUILDDIR', builddir)
	env('DISTDIR', buildenv.distdir)
	env('SRCDIR', buildenv.user_srcdir or buildenv.orig_srcdir)
	env('BINARYFEED', buildenv.local_iface_file)
	os.chdir(builddir)
	print "cd", builddir

	setup = CompileSetup(iface_cache.stores, sels)
	setup.prepare_env()

	# These mappings are needed when mixing Zero Install -dev packages with
	# native package binaries.
	mappings = {}
	for impl in sels.selections.values():
		# Add mappings that have been set explicitly...
		new_mappings = impl.attrs.get(XMLNS_0COMPILE + ' lib-mappings', '')
		if new_mappings:
			new_mappings = new_mappings.split(' ')
			for mapping in new_mappings:
				assert ':' in mapping, "lib-mappings missing ':' in '%s' from '%s'" % (mapping, impl.feed)
				name, major_version = mapping.split(':', 1)
				assert '/' not in mapping, "lib-mappings '%s' contains a / in the version number (from '%s')!" % (mapping, impl.feed)
				if sys.platform == 'darwin':
					mappings[name] = 'lib%s.%s.dylib' % (name, major_version)
				else:
					mappings[name] = 'lib%s.so.%s' % (name, major_version)
		# Auto-detect required mappings where possible...
		# (if the -dev package is native, the symlinks will be OK)
		if not is_package_impl(impl):
			impl_path = lookup(impl)
			for libdirname in ['lib', 'usr/lib', 'lib64', 'usr/lib64']:
				libdir = os.path.join(impl_path, libdirname)
				if os.path.isdir(libdir):
					find_broken_version_symlinks(libdir, mappings)

	if mappings:
		set_up_mappings(mappings)

	overrides_dir = os.path.join(os.environ['TMPDIR'], PKG_CONFIG_OVERRIDES)
	if os.path.isdir(overrides_dir):
		add_overrides = model.EnvironmentBinding('PKG_CONFIG_PATH', PKG_CONFIG_OVERRIDES)
		do_env_binding(add_overrides, os.environ['TMPDIR'])

	# Some programs want to put temporary build files in the source directory.
	# Make a copy of the source if needed.
	dup_src_type = src_impl.attrs.get(XMLNS_0COMPILE + ' dup-src', None)
	if dup_src_type == 'true':
		dup_src(shutil.copy2)
		env('SRCDIR', builddir)
	elif dup_src_type:
		raise Exception("Unknown dup-src value '%s'" % dup_src_type)

	if options.shell:
		spawn_and_check(find_in_path('cmd' if os.name == 'nt' else 'sh'), [])
	else:
		command = sels.commands[0].qdom.attrs.get('shell-command', None)
		if command is None:
			# New style <command>
			prog_args = setup.build_command(sels.interface, sels.command) + args
		else:
			# Old style shell-command='...'
			if os.name == 'nt':
				prog_args = ['cmd', '/c', command] + args
			else:
				prog_args = ['/bin/sh', '-c', command + ' "$@"', '-'] + args
			assert len(sels.commands) == 1

		# Remove any existing log files
		for log in ['build.log', 'build-success.log', 'build-failure.log']:
			if os.path.exists(log):
				os.unlink(log)

		# Run the command, copying output to a new log
		with open('build.log', 'w') as log:
			print >>log, "Build log for %s-%s" % (master_feed.get_name(),
							      src_impl.version)
			print >>log, "\nBuilt using 0compile-%s" % __main__.version
			print >>log, "\nBuild system: " + ', '.join(uname)
			print >>log, "\n%s:\n" % ENV_FILE
			with open(os.path.join(os.pardir, ENV_FILE)) as properties_file:
				shutil.copyfileobj(properties_file, log)

			log.write('\n')

			if os.path.exists(patch_file):
				print >>log, "\nPatched with:\n"
				shutil.copyfileobj(file(patch_file), log)
				log.write('\n')

			if command:
				print "Executing: " + command, args
				print >>log, "Executing: " + command, args
			else:
				print "Executing: " + str(prog_args)
				print >>log, "Executing: " + str(prog_args)

			# Tee the output to the console and to the log
			child = subprocess.Popen(prog_args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
			while True:
				data = os.read(child.stdout.fileno(), 100)
				if not data: break
				sys.stdout.write(data)
				log.write(data)
			status = child.wait()
			failure = None
			if status == 0:
				print >>log, "Build successful"
				shorten_dynamic_library_install_names()
				fixup_generated_pkgconfig_files()
				remove_la_files()
			elif status > 0:
				failure = "Build failed with exit code %d" % status
			else:
				failure = "Build failure: exited due to signal %d" % (-status)
			if failure:
				print >>log, failure

		if failure:
			os.rename('build.log', 'build-failure.log')
			raise SafeException("Command '%s': %s" % (prog_args, failure))
		else:
			os.rename('build.log', 'build-success.log')