#! /usr/bin/env python
# encoding: utf-8
# Thomas Nagy, 2009 (ita)

VERSION='0.0.1'
APPNAME='cc_test'

top = '.'
out = 'build'

def set_options(opt):
	pass

def configure(conf):
	conf.check_tool('gcc')

def build(bld):

	bld(rule='cp ${SRC} ${TGT}', source='atest', target='main.c', before='cc')

	bld(
		features = 'cc cprogram',
		source = 'main.c',
		target = 'test_c_app')

# =========== code below to enable the behaviour listed in #473 ==============

import os
import Build, Task, Node, Utils, Options, Logs
from Constants import *

def patch():
	def post_run(self):
		"called after a successful task run"
		bld = self.generator.bld
		env = self.env
		sig = self.signature()

		cnt = 0
		variant = env.variant()
		for node in self.outputs:
			# check if the node exists ..
			try:
				os.stat(node.abspath(env))
			except OSError:
				self.has_run = MISSING
				self.err_msg = '-> missing file: %r' % node.abspath(env)
				raise Utils.WafError

			# important, store the signature for the next run
			#bld.node_sigs[variant][node.id] = sig

			# TODO do this too when files are retrieved from the cache
			bld.node_sigs[variant][node.id] = Utils.h_file(node.abspath(self.env))

			if Options.cache_global:
				ssig = sig.encode('hex')
				dest = os.path.join(Options.cache_global, '%s_%d_%s' % (ssig, cnt, node.name))
				try: shutil.copy2(node.abspath(env), dest)
				except IOError: warn('Could not write the file to the cache')
				cnt += 1

		bld.task_sigs[self.unique_id()] = self.cache_sig
	Task.Task.post_run = post_run

	def runnable_status(self):
		"SKIP_ME RUN_ME or ASK_LATER"
		#return 0 # benchmarking

		if self.inputs and (not self.outputs):
			if not getattr(self.__class__, 'quiet', None):
				warn("invalid task (no inputs OR outputs): override in a Task subclass or set the attribute 'quiet' %r" % self)

		for t in self.run_after:
			if not t.hasrun:
				return ASK_LATER

		env = self.env
		bld = self.generator.bld

		# first compute the signature
		try:
			new_sig = self.signature()
		except KeyError:
			debug("task: something is wrong, computing the task %r signature failed" % self)
			return RUN_ME

		# compare the signature to a signature computed previously
		key = self.unique_id()
		try:
			prev_sig = bld.task_sigs[key][0]
		except KeyError:
			debug("task: task %r must run as it was never run before or the task code changed" % self)
			return RUN_ME

		# just check the signature of the output
		try:
			for node in self.outputs:
				variant = node.variant(env)
				bld.node_sigs[variant][node.id]
		except KeyError:
			debug("task: task %r must run as the output nodes do not exist" % self)
			return RUN_ME

		# debug if asked to
		if Logs.verbose: self.debug_why(bld.task_sigs[key])

		if new_sig != prev_sig:
			return RUN_ME
		return SKIP_ME
	Task.Task.runnable_status = runnable_status


	def listdir_bld(self, parent_node, path, variant):
		"""in this function we do not add timestamps but we remove them
		when the files no longer exist (file removed in the build dir)"""

		i_existing_nodes = [x for x in parent_node.childs.values() if x.id & 3 == Node.BUILD]

		lst = set(Utils.listdir(path))
		node_names = set([x.name for x in i_existing_nodes])
		remove_names = node_names - lst

		# remove the stamps of the build nodes that no longer exist on the filesystem
		ids_to_remove = [x.id for x in i_existing_nodes if x.name in remove_names]
		cache = self.node_sigs[variant]
		for nid in ids_to_remove:
			if nid in cache:
				cache.__delitem__(nid)

		for x in i_existing_nodes:
			if x.name in lst:
				self.node_sigs[variant][x.id] = Utils.h_file(os.sep.join((path, x.name)))
	Build.BuildContext.listdir_bld = listdir_bld

patch()
