#! /usr/bin/env python
# encoding: utf-8
# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file

import os,shutil,traceback,errno,sys,stat
from waflib import Utils,Configure,Logs,Options,ConfigSet,Context,Errors,Build,Node
build_dir_override=None
no_climb_commands=['configure']
default_cmd="build"
def waf_entry_point(current_directory,version,wafdir):
	Logs.init_log()
	if Context.WAFVERSION!=version:
		Logs.error('Waf script %r and library %r do not match (directory %r)'%(version,Context.WAFVERSION,wafdir))
		sys.exit(1)
	if'--version'in sys.argv:
		Context.run_dir=current_directory
		ctx=Context.create_context('options')
		ctx.curdir=current_directory
		ctx.parse_args()
		sys.exit(0)
	Context.waf_dir=wafdir
	Context.launch_dir=current_directory
	no_climb=os.environ.get('NOCLIMB',None)
	if not no_climb:
		for k in no_climb_commands:
			if k in sys.argv:
				no_climb=True
				break
	cur=current_directory
	while cur:
		lst=os.listdir(cur)
		if Options.lockfile in lst:
			env=ConfigSet.ConfigSet()
			try:
				env.load(os.path.join(cur,Options.lockfile))
				ino=os.stat(cur)[stat.ST_INO]
			except Exception:
				pass
			else:
				for x in[env.run_dir,env.top_dir,env.out_dir]:
					if Utils.is_win32:
						if cur==x:
							load=True
							break
					else:
						try:
							ino2=os.stat(x)[stat.ST_INO]
						except:
							pass
						else:
							if ino==ino2:
								load=True
								break
				else:
					Logs.warn('invalid lock file in %s'%cur)
					load=False
				if load:
					Context.run_dir=env.run_dir
					Context.top_dir=env.top_dir
					Context.out_dir=env.out_dir
					break
		if not Context.run_dir:
			if Context.WSCRIPT_FILE in lst:
				Context.run_dir=cur
		next=os.path.dirname(cur)
		if next==cur:
			break
		cur=next
		if no_climb:
			break
	if not Context.run_dir:
		if'-h'in sys.argv or'--help'in sys.argv:
			Logs.warn('No wscript file found: the help message may be incomplete')
			Context.run_dir=current_directory
			ctx=Context.create_context('options')
			ctx.curdir=current_directory
			ctx.parse_args()
			sys.exit(0)
		Logs.error('Waf: Run from a directory containing a file named %r'%Context.WSCRIPT_FILE)
		sys.exit(1)
	try:
		os.chdir(Context.run_dir)
	except OSError:
		Logs.error('Waf: The folder %r is unreadable'%Context.run_dir)
		sys.exit(1)
	try:
		set_main_module(Context.run_dir+os.sep+Context.WSCRIPT_FILE)
	except Errors.WafError ,e:
		Logs.pprint('RED',e.verbose_msg)
		Logs.error(str(e))
		sys.exit(1)
	except Exception ,e:
		Logs.error('Waf: The wscript in %r is unreadable'%Context.run_dir,e)
		traceback.print_exc(file=sys.stdout)
		sys.exit(2)
	try:
		run_commands()
	except Errors.WafError ,e:
		if Logs.verbose>1:
			Logs.pprint('RED',e.verbose_msg)
		Logs.error(e.msg)
		sys.exit(1)
	except Exception ,e:
		traceback.print_exc(file=sys.stdout)
		sys.exit(2)
	except KeyboardInterrupt:
		Logs.pprint('RED','Interrupted')
		sys.exit(68)
def set_main_module(file_path):
	Context.g_module=Context.load_module(file_path)
	Context.g_module.root_path=file_path
	def set_def(obj):
		name=obj.__name__
		if not name in Context.g_module.__dict__:
			setattr(Context.g_module,name,obj)
	for k in[update,dist,distclean,distcheck,update]:
		set_def(k)
	if not'init'in Context.g_module.__dict__:
		Context.g_module.init=Utils.nada
	if not'shutdown'in Context.g_module.__dict__:
		Context.g_module.shutdown=Utils.nada
	if not'options'in Context.g_module.__dict__:
		Context.g_module.options=Utils.nada
def parse_options():
	Context.create_context('options').execute()
	if not Options.commands:
		Options.commands=[default_cmd]
	Options.commands=[x for x in Options.commands if x!='options']
	Logs.verbose=Options.options.verbose
	Logs.init_log()
	if Options.options.zones:
		Logs.zones=Options.options.zones.split(',')
		if not Logs.verbose:
			Logs.verbose=1
	elif Logs.verbose>0:
		Logs.zones=['runner']
	if Logs.verbose>2:
		Logs.zones=['*']
def run_command(cmd_name):
	ctx=Context.create_context(cmd_name)
	ctx.options=Options.options
	ctx.cmd=cmd_name
	ctx.execute()
	return ctx
def run_commands():
	parse_options()
	run_command('init')
	while Options.commands:
		cmd_name=Options.commands.pop(0)
		timer=Utils.Timer()
		run_command(cmd_name)
		if not Options.options.progress_bar:
			elapsed=' (%s)'%str(timer)
			Logs.info('%r finished successfully%s'%(cmd_name,elapsed))
	run_command('shutdown')
def _can_distclean(name):
	for k in'.o .moc .exe'.split():
		if name.endswith(k):
			return True
	return False
def distclean_dir(dirname):
	for(root,dirs,files)in os.walk(dirname):
		for f in files:
			if _can_distclean(f):
				fname=root+os.sep+f
				try:
					os.unlink(fname)
				except:
					Logs.warn('could not remove %r'%fname)
	for x in[Context.DBFILE,'config.log']:
		try:
			os.unlink(x)
		except:
			pass
	try:
		shutil.rmtree('c4che')
	except:
		pass
def distclean(ctx):
	'''removes the build directory'''
	lst=os.listdir('.')
	for f in lst:
		if f==Options.lockfile:
			try:
				proj=ConfigSet.ConfigSet(f)
			except:
				Logs.warn('could not read %r'%f)
				continue
			if proj['out_dir']!=proj['top_dir']:
				try:
					shutil.rmtree(proj['out_dir'])
				except IOError:
					pass
				except OSError ,e:
					if e.errno!=errno.ENOENT:
						Logs.warn('project %r cannot be removed'%proj[Context.OUT])
			else:
				distclean_dir(proj['out_dir'])
			for k in(proj['out_dir'],proj['top_dir'],proj['run_dir']):
				try:
					os.remove(os.path.join(k,Options.lockfile))
				except OSError ,e:
					if e.errno!=errno.ENOENT:
						Logs.warn('file %r cannot be removed'%f)
		if f.startswith('.waf')and not Options.commands:
			shutil.rmtree(f,ignore_errors=True)
class Dist(Context.Context):
	cmd='dist'
	fun='dist'
	algo='tar.bz2'
	ext_algo={}
	def execute(self):
		self.recurse([os.path.dirname(Context.g_module.root_path)])
		self.archive()
	def archive(self):
		import tarfile
		arch_name=self.get_arch_name()
		try:
			self.base_path
		except:
			self.base_path=self.path
		node=self.base_path.make_node(arch_name)
		try:
			node.delete()
		except:
			pass
		files=self.get_files()
		if self.algo.startswith('tar.'):
			tar=tarfile.open(arch_name,'w:'+self.algo.replace('tar.',''))
			for x in files:
				self.add_tar_file(x,tar)
			tar.close()
		elif self.algo=='zip':
			import zipfile
			zip=zipfile.ZipFile(arch_name,'w',compression=zipfile.ZIP_DEFLATED)
			for x in files:
				archive_name=self.get_base_name()+'/'+x.path_from(self.base_path)
				zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED)
			zip.close()
		else:
			self.fatal('Valid algo types are tar.bz2, tar.gz or zip')
		try:
			from hashlib import sha1 as sha
		except ImportError:
			from sha import sha
		try:
			digest=" (sha=%r)"%sha(node.read()).hexdigest()
		except:
			digest=''
		Logs.info('New archive created: %s%s'%(self.arch_name,digest))
	def get_tar_path(self,node):
		return node.abspath()
	def add_tar_file(self,x,tar):
		p=self.get_tar_path(x)
		tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path))
		tinfo.uid=0
		tinfo.gid=0
		tinfo.uname='root'
		tinfo.gname='root'
		fu=None
		try:
			fu=open(p,'rb')
			tar.addfile(tinfo,fileobj=fu)
		finally:
			if fu:
				fu.close()
	def get_tar_prefix(self):
		try:
			return self.tar_prefix
		except:
			return self.get_base_name()
	def get_arch_name(self):
		try:
			self.arch_name
		except:
			self.arch_name=self.get_base_name()+'.'+self.ext_algo.get(self.algo,self.algo)
		return self.arch_name
	def get_base_name(self):
		try:
			self.base_name
		except:
			appname=getattr(Context.g_module,Context.APPNAME,'noname')
			version=getattr(Context.g_module,Context.VERSION,'1.0')
			self.base_name=appname+'-'+version
		return self.base_name
	def get_excl(self):
		try:
			return self.excl
		except:
			self.excl=Node.exclude_regs+' **/waf-1.6.* **/.waf-1.6* **/waf3-1.6.* **/.waf3-1.6* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*'
			nd=self.root.find_node(Context.out_dir)
			if nd:
				self.excl+=' '+nd.path_from(self.base_path)
			return self.excl
	def get_files(self):
		try:
			files=self.files
		except:
			files=self.base_path.ant_glob('**/*',excl=self.get_excl())
		return files
def dist(ctx):
	'''makes a tarball for redistributing the sources'''
	pass
class DistCheck(Dist):
	fun='distcheck'
	cmd='distcheck'
	def execute(self):
		self.recurse([os.path.dirname(Context.g_module.root_path)])
		self.archive()
		self.check()
	def check(self):
		import tempfile,tarfile
		t=None
		try:
			t=tarfile.open(self.get_arch_name())
			for x in t:
				t.extract(x)
		finally:
			if t:
				t.close()
		instdir=tempfile.mkdtemp('.inst',self.get_base_name())
		ret=Utils.subprocess.Popen([sys.argv[0],'configure','install','uninstall','--destdir='+instdir],cwd=self.get_base_name()).wait()
		if ret:
			raise Errors.WafError('distcheck failed with code %i'%ret)
		if os.path.exists(instdir):
			raise Errors.WafError('distcheck succeeded, but files were left in %s'%instdir)
		shutil.rmtree(self.get_base_name())
def distcheck(ctx):
	'''checks if the project compiles (tarball from 'dist')'''
	pass
def update(ctx):
	'''updates the plugins from the *waflib/extras* directory'''
	lst=Options.options.files.split(',')
	if not lst:
		lst=[x for x in Utils.listdir(Context.waf_dir+'/waflib/extras')if x.endswith('.py')]
	for x in lst:
		tool=x.replace('.py','')
		try:
			Configure.download_tool(tool,force=True,ctx=ctx)
		except Errors.WafError:
			Logs.error('Could not find the tool %s in the remote repository'%x)
def autoconfigure(execute_method):
	def execute(self):
		if not Configure.autoconfig:
			return execute_method(self)
		env=ConfigSet.ConfigSet()
		do_config=False
		try:
			env.load(os.path.join(Context.top_dir,Options.lockfile))
		except Exception:
			Logs.warn('Configuring the project')
			do_config=True
		else:
			if env.run_dir!=Context.run_dir:
				do_config=True
			else:
				h=0
				for f in env['files']:
					h=hash((h,Utils.readf(f,'rb')))
				do_config=h!=env.hash
		if do_config:
			Options.commands.insert(0,self.cmd)
			Options.commands.insert(0,'configure')
			return
		return execute_method(self)
	return execute
Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute)
