<commit_before># Copyright (C) 2006, <NAME>
# See http://0install.net/0compile.html

import os, sys, shutil
import subprocess
from os.path import join
from logging import info
import ConfigParser

from zeroinstall.injector import model, selections, qdom, arch
from zeroinstall.injector.arch import canonicalize_os, canonicalize_machine

from zeroinstall.injector.iface_cache import iface_cache
from zeroinstall import SafeException
from zeroinstall.zerostore import Store, NotStored

def _(x): return x


# This is An os.uname() substitute that uses as much of ZI's
# arch._uname as is available and yet has all four elements one
# normally expects from os.uname() on Posix (on Windows, arch._uname
# has only two elements).
import platform
uname = arch._uname + platform.uname()[len(arch._uname):]

ENV_FILE = '0compile.properties'
XMLNS_0COMPILE = 'http://zero-install.sourceforge.net/2006/namespaces/0compile'

zeroinstall_dir = os.environ.get('0COMPILE_ZEROINSTALL', None)
if zeroinstall_dir:
	# XXX: we're assuming that, if installed through 0install, 0launch requires
	# the same version of Python as 0compile. This is currently needed for Arch
	# Linux, but long-term we need to use the <runner>.
	install_prog = [sys.executable, os.path.join(zeroinstall_dir, '0install')]
	if not os.path.exists(install_prog[1]):
		# For the Windows version...
		install_prog[1] = os.path.join(zeroinstall_dir, 'zeroinstall', 'scripts', 'install.py')
else:
	install_prog = ['0install']

if os.path.isdir('dependencies'):
	dep_dir = os.path.realpath('dependencies')
	iface_cache.stores.stores.append(Store(dep_dir))
	install_prog.append('--with-store='+ dep_dir)

class NoImpl:
	id = "none"
	version = "none"
no_impl = NoImpl()

def is_package_impl(impl):
	return impl.id.startswith("package:")

def lookup(impl_or_sel):
	id = impl_or_sel.id
	if id.startswith('package:'):
		return None
	local_path = impl_or_sel.local_path
	if local_path is not None:
		if os.path.isdir(local_path):
			return local_path
		raise SafeException("Directory '%s' no longer exists. Try '0compile setup'" % local_path)
	try:
		return iface_cache.stores.lookup_any(impl_or_sel.digests)
	except NotStored, ex:
		raise NotStored(str(ex) + "\nHint: try '0compile setup'")

def ensure_dir(d, clean = False):
	if os.path.isdir(d):
		if clean:
			print "Removing", d
			shutil.rmtree(d)
		else:
			return
	if os.path.exists(d):
		raise SafeException("'%s' exists, but is not a directory!" % d)
	os.mkdir(d)

def find_in_path(prog):
	for d in os.environ['PATH'].split(':'):
		path = os.path.join(d, prog)
		if os.path.isfile(path):
			return path
	return None

def spawn_and_check(prog, args):
	status = os.spawnv(os.P_WAIT, prog, [prog] + args)
	if status > 0:
		raise SafeException("Program '%s' failed with exit code %d" % (prog, status))
	elif status < 0:
		raise SafeException("Program '%s' failed with signal %d" % (prog, -status))

def spawn_and_check_maybe_sandboxed(readable, writable, tmpdir, prog, args):
	child = spawn_maybe_sandboxed(readable, writable, tmpdir, prog, args)
	status = child.wait()
	if status > 0:
		raise SafeException('Command failed with exit status %d' %  status)
	elif status < 0:
		raise SafeException('Command failed with signal %d' % -status)

def spawn_maybe_sandboxed(readable, writable, tmpdir, prog, args):
	"""spawn prog, with (only) the 'writable' directories writable if sandboxing is available.
	The readable directories will be readable, as well as various standard locations.
	If no sandbox is available, run without a sandbox."""

	USE_PLASH = 'USE_PLASH_0COMPILE'

	assert os.path.isabs(prog)
	_pola_run = find_in_path('pola-run')

	if _pola_run is None:
		print "Not using sandbox (plash not installed)"
		use_plash = False
	else:
		use_plash = os.environ.get(USE_PLASH, '').lower() or 'not set'
		if use_plash in ('not set', 'false'):
			print "Not using plash: $%s is %s" % (USE_PLASH, use_plash)
			use_plash = False
		elif use_plash == 'true':
			use_plash = True
		else:
			raise Exception('$%s must be "true" or "false", not "%s"' % (USE_PLASH, use_plash))

	if not use_plash:
		return subprocess.Popen([prog] + args)
	
	print "Using plash to sandbox the build..."
	
	# We have pola-shell :-)
	pola_args = ['--prog', prog, '-B']
	for a in args:
		pola_args += ['-a', a]
	for r in readable:
		pola_args += ['-f', r]
	for w in writable:
		pola_args += ['-fw', w]
	pola_args += ['-tw', '/tmp', tmpdir]
	os.environ['TMPDIR'] = '/tmp'
	return subprocess.Popen([_pola_run] + pola_args)

def get_arch_name():
	target_os = canonicalize_os(uname[0])
	target_machine = canonicalize_machine(uname[4])
	if target_os == 'Darwin' and target_machine == 'i386':
		# this system detection shell script comes from config.guess (20090918):
		CC = os.getenv("CC_FOR_BUILD") or os.getenv("CC") or os.getenv("HOST_CC") or "cc"
		process = subprocess.Popen("(echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | " +
		                           "(CCOPTS= %s -E - 2>/dev/null) | " % CC +
		                           "grep IS_64BIT_ARCH >/dev/null", stdout=subprocess.PIPE, shell=True)
		output, error = process.communicate()
		retcode = process.poll()
		if retcode == 0:
			target_machine='x86_64'
	if target_machine in ('i585', 'i686'):
		target_machine = 'i486'	# (sensible default)
	return target_os + '-' + target_machine

class BuildEnv:
	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

	@property
	def iface_name(self):
		iface_name = os.path.basename(self.interface)
		if iface_name.endswith('.xml'):
			iface_name = iface_name[:-4]
		iface_name = iface_name.replace(' ', '-')
		if iface_name.endswith('-src'):
			iface_name = iface_name[:-4]
		return iface_name

	interface = property(lambda self: model.canonical_iface_uri(self.config.get('compile', 'interface')))

	@property
	def distdir(self):
		distdir_name = self.config.get('compile', 'distdir')
		if not distdir_name:
			arch = self.target_arch.replace('*', 'any')
			distdir_name = self.iface_name.lower()
			distdir_name += '-' + arch.lower()
		assert os.path.dirname(distdir_name) == ''
		return os.path.realpath(distdir_name)

	def get_binary_template(self):
		"""Find the <compile:implementation> element for the selected compile command, if any"""
		sels = self.get_selections()
		if sels.commands:
			for elem in sels.commands[0].qdom.childNodes:
				if elem.uri == XMLNS_0COMPILE and elem.name == 'implementation':
					return elem

				# XXX: hack for 0launch < 0.54 which messes up the namespace
				if elem.name == 'implementation':
					return elem
		return None

	@property
	def metadir(self):
		metadir = self.config.get('compile', 'metadir')
		assert not os.path.isabs(metadir)
		return join(self.distdir, metadir)

	@property
	def local_iface_file(self):<commit_msg>Removed no-longer-needed hack for old versions of 0install<commit_after># Copyright (C) 2006, <NAME>
# See http://0install.net/0compile.html

import os, sys, shutil
import subprocess
from os.path import join
from logging import info
import ConfigParser

from zeroinstall.injector import model, selections, qdom, arch
from zeroinstall.injector.arch import canonicalize_os, canonicalize_machine

from zeroinstall.injector.iface_cache import iface_cache
from zeroinstall import SafeException
from zeroinstall.zerostore import Store, NotStored

def _(x): return x


# This is An os.uname() substitute that uses as much of ZI's
# arch._uname as is available and yet has all four elements one
# normally expects from os.uname() on Posix (on Windows, arch._uname
# has only two elements).
import platform
uname = arch._uname + platform.uname()[len(arch._uname):]

ENV_FILE = '0compile.properties'
XMLNS_0COMPILE = 'http://zero-install.sourceforge.net/2006/namespaces/0compile'

zeroinstall_dir = os.environ.get('0COMPILE_ZEROINSTALL', None)
if zeroinstall_dir:
	# XXX: we're assuming that, if installed through 0install, 0launch requires
	# the same version of Python as 0compile. This is currently needed for Arch
	# Linux, but long-term we need to use the <runner>.
	install_prog = [sys.executable, os.path.join(zeroinstall_dir, '0install')]
	if not os.path.exists(install_prog[1]):
		# For the Windows version...
		install_prog[1] = os.path.join(zeroinstall_dir, 'zeroinstall', 'scripts', 'install.py')
else:
	install_prog = ['0install']

if os.path.isdir('dependencies'):
	dep_dir = os.path.realpath('dependencies')
	iface_cache.stores.stores.append(Store(dep_dir))
	install_prog.append('--with-store='+ dep_dir)

class NoImpl:
	id = "none"
	version = "none"
no_impl = NoImpl()

def is_package_impl(impl):
	return impl.id.startswith("package:")

def lookup(impl_or_sel):
	id = impl_or_sel.id
	if id.startswith('package:'):
		return None
	local_path = impl_or_sel.local_path
	if local_path is not None:
		if os.path.isdir(local_path):
			return local_path
		raise SafeException("Directory '%s' no longer exists. Try '0compile setup'" % local_path)
	try:
		return iface_cache.stores.lookup_any(impl_or_sel.digests)
	except NotStored, ex:
		raise NotStored(str(ex) + "\nHint: try '0compile setup'")

def ensure_dir(d, clean = False):
	if os.path.isdir(d):
		if clean:
			print "Removing", d
			shutil.rmtree(d)
		else:
			return
	if os.path.exists(d):
		raise SafeException("'%s' exists, but is not a directory!" % d)
	os.mkdir(d)

def find_in_path(prog):
	for d in os.environ['PATH'].split(':'):
		path = os.path.join(d, prog)
		if os.path.isfile(path):
			return path
	return None

def spawn_and_check(prog, args):
	status = os.spawnv(os.P_WAIT, prog, [prog] + args)
	if status > 0:
		raise SafeException("Program '%s' failed with exit code %d" % (prog, status))
	elif status < 0:
		raise SafeException("Program '%s' failed with signal %d" % (prog, -status))

def spawn_and_check_maybe_sandboxed(readable, writable, tmpdir, prog, args):
	child = spawn_maybe_sandboxed(readable, writable, tmpdir, prog, args)
	status = child.wait()
	if status > 0:
		raise SafeException('Command failed with exit status %d' %  status)
	elif status < 0:
		raise SafeException('Command failed with signal %d' % -status)

def spawn_maybe_sandboxed(readable, writable, tmpdir, prog, args):
	"""spawn prog, with (only) the 'writable' directories writable if sandboxing is available.
	The readable directories will be readable, as well as various standard locations.
	If no sandbox is available, run without a sandbox."""

	USE_PLASH = 'USE_PLASH_0COMPILE'

	assert os.path.isabs(prog)
	_pola_run = find_in_path('pola-run')

	if _pola_run is None:
		print "Not using sandbox (plash not installed)"
		use_plash = False
	else:
		use_plash = os.environ.get(USE_PLASH, '').lower() or 'not set'
		if use_plash in ('not set', 'false'):
			print "Not using plash: $%s is %s" % (USE_PLASH, use_plash)
			use_plash = False
		elif use_plash == 'true':
			use_plash = True
		else:
			raise Exception('$%s must be "true" or "false", not "%s"' % (USE_PLASH, use_plash))

	if not use_plash:
		return subprocess.Popen([prog] + args)
	
	print "Using plash to sandbox the build..."
	
	# We have pola-shell :-)
	pola_args = ['--prog', prog, '-B']
	for a in args:
		pola_args += ['-a', a]
	for r in readable:
		pola_args += ['-f', r]
	for w in writable:
		pola_args += ['-fw', w]
	pola_args += ['-tw', '/tmp', tmpdir]
	os.environ['TMPDIR'] = '/tmp'
	return subprocess.Popen([_pola_run] + pola_args)

def get_arch_name():
	target_os = canonicalize_os(uname[0])
	target_machine = canonicalize_machine(uname[4])
	if target_os == 'Darwin' and target_machine == 'i386':
		# this system detection shell script comes from config.guess (20090918):
		CC = os.getenv("CC_FOR_BUILD") or os.getenv("CC") or os.getenv("HOST_CC") or "cc"
		process = subprocess.Popen("(echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | " +
		                           "(CCOPTS= %s -E - 2>/dev/null) | " % CC +
		                           "grep IS_64BIT_ARCH >/dev/null", stdout=subprocess.PIPE, shell=True)
		output, error = process.communicate()
		retcode = process.poll()
		if retcode == 0:
			target_machine='x86_64'
	if target_machine in ('i585', 'i686'):
		target_machine = 'i486'	# (sensible default)
	return target_os + '-' + target_machine

class BuildEnv:
	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

	@property
	def iface_name(self):
		iface_name = os.path.basename(self.interface)
		if iface_name.endswith('.xml'):
			iface_name = iface_name[:-4]
		iface_name = iface_name.replace(' ', '-')
		if iface_name.endswith('-src'):
			iface_name = iface_name[:-4]
		return iface_name

	interface = property(lambda self: model.canonical_iface_uri(self.config.get('compile', 'interface')))

	@property
	def distdir(self):
		distdir_name = self.config.get('compile', 'distdir')
		if not distdir_name:
			arch = self.target_arch.replace('*', 'any')
			distdir_name = self.iface_name.lower()
			distdir_name += '-' + arch.lower()
		assert os.path.dirname(distdir_name) == ''
		return os.path.realpath(distdir_name)

	def get_binary_template(self):
		"""Find the <compile:implementation> element for the selected compile command, if any"""
		sels = self.get_selections()
		if sels.commands:
			for elem in sels.commands[0].qdom.childNodes:
				if elem.uri == XMLNS_0COMPILE and elem.name == 'implementation':
					return elem
		return None

	@property
	def metadir(self):
		metadir = self.config.get('compile', 'metadir')
		assert not os.path.isabs(metadir)
		return join(self.distdir, metadir)

	@property
	def local_iface_file(self):
{'fraction_non_alphanumeric': 0.13439385628085573, 'fraction_numerical': 0.00966812945693911, 'mean_word_length': 4.487208427389015, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7673963', 'n_tokens_mistral': 5488, 'n_tokens_neox': 5081, 'n_words': 1357}