#
# Interactively decide what to distribute
#
#
# The exclude file signals files to always exclude,
# The pattern file lines are of the form
# *.c
# This excludes all files ending in .c.
#
# The include file signals files and directories to include.
# Records are of the form
# ('Tools:bgen:AE:AppleEvents.py', 'Lib:MacToolbox:AppleEvents.py')
# This includes the specified file, putting it in the given place, or
# ('Tools:bgen:AE:AppleEvents.py', None)
# This excludes the specified file.
#
from MkDistr_ui import *
import fnmatch
import regex
import os
import sys
import macfs
import macostools

SyntaxError='Include/exclude file syntax error'

class Matcher:
	"""Include/exclude database, common code"""
	
	def __init__(self, filename):
		self.filename = filename
		self.rawdata = []
		self.parse(filename)
		self.rawdata.sort()
		self.rebuild()
		self.modified = 0

	def parse(self, dbfile):
		try:
			fp = open(dbfile)
		except IOError:
			return
		data = fp.readlines()
		fp.close()
		for d in data:
			d = d[:-1]
			if not d or d[0] == '#': continue
			pat = self.parseline(d)
			self.rawdata.append(pat)
				
	def save(self):
		fp = open(self.filename, 'w')
		self.savedata(fp, self.rawdata)
		self.modified = 0
			
	def add(self, value):
		if len(value) == 1:
			value = value + ('',)
		self.rawdata.append(value)
		self.rebuild1(value)
		self.modified = 1
		
	def delete(self, value):
		key = value
		for i in range(len(self.rawdata)):
			if self.rawdata[i][0] == key:
				del self.rawdata[i]
				self.unrebuild1(i, key)
				self.modified = 1
				return
		print 'Not found!', key
				
	def getall(self):
		return map(lambda x: x[0], self.rawdata)
	
	def get(self, value):
		for src, dst in self.rawdata:
			if src == value:
				return src, dst
		print 'Not found!', value
				
	def is_modified(self):
		return self.modified
							
class IncMatcher(Matcher):
	"""Include filename database and matching engine"""

	def rebuild(self):
		self.idict = {}
		self.edict = {}
		for v in self.rawdata:
			self.rebuild1(v)
			
	def parseline(self, line):
		try:
			data = eval(line)
		except:
			raise SyntaxError, line
		if type(data) <> type(()) or len(data) not in (1,2):
			raise SyntaxError, line
		if len(data) == 1:
			data = data + ('',)
		return data
		
	def savedata(self, fp, data):
		for d in self.rawdata:
			fp.write(`d`+'\n')
		
	def rebuild1(self, (src, dst)):
		if dst == '':
			dst = src
		if dst == None:
			self.edict[src] = None
		else:
			self.idict[src] = dst
			
	def unrebuild1(self, num, src):
		if self.idict.has_key(src):
			del self.idict[src]
		else:
			del self.edict[src]
	
	def match(self, patharg):
		removed = []
		# First check the include directory
		path = patharg
		while 1:
			if self.idict.has_key(path):
				# We know of this path (or initial piece of path)
				dstpath = self.idict[path]
				# We do want it distributed. Tack on the tail.
				while removed:
					dstpath = os.path.join(dstpath, removed[0])
					removed = removed[1:]
				# Finally, if the resultant string ends in a separator
				# tack on our input filename
				if dstpath[-1] == os.sep:
					dir, file = os.path.split(path)
					dstpath = os.path.join(dstpath, file)
				return dstpath
			path, lastcomp = os.path.split(path)
			if not path:
				break
			removed[0:0] = [lastcomp]
		# Next check the exclude directory
		path = patharg
		while 1:
			if self.edict.has_key(path):
				return ''
			path, lastcomp = os.path.split(path)
			if not path:
				break
			removed[0:0] = [lastcomp]
		return None
			
	def checksourcetree(self):
		rv = []
		for name in self.idict.keys():
			if not os.path.exists(name):
				rv.append(name)
		return rv
				
class ExcMatcher(Matcher):
	"""Exclude pattern database and matching engine"""

	def rebuild(self):
		self.relist = []
		for v in self.rawdata:
			self.rebuild1(v)
		
	def parseline(self, data):
		return (data, None)

	def savedata(self, fp, data):
		for d in self.rawdata:
			fp.write(d[0]+'\n')		
		
	def rebuild1(self, (src, dst)):
		pat = fnmatch.translate(src)
		self.relist.append(regex.compile(pat))
		
	def unrebuild1(self, num, src):
		del self.relist[num]
	
	def match(self, path):
		comps = os.path.split(path)
		file = comps[-1]
		for pat in self.relist:
			if pat and pat.match(file) == len(file):
				return 1
		return 0		
		 
		
class Main:
	"""The main program glueing it all together"""
	
	def __init__(self):
		InitUI()
		fss, ok = macfs.GetDirectory('Source directory:')
		if not ok:
			sys.exit(0)
		os.chdir(fss.as_pathname())
		if not os.path.isdir(':Mac:Distributions'):
			os.mkdir(':Mac:Distributions')
		typedist = GetType()
		self.inc = IncMatcher(':Mac:Distributions:%s.include'%typedist)
		self.exc = ExcMatcher(':Mac:Distributions:%s.exclude'%typedist)
		self.ui = MkDistrUI(self)
		self.ui.mainloop()
		
	def check(self):
		return self.checkdir(':', 1)
		
	def checkdir(self, path, istop):
		files = os.listdir(path)
		rv = []
		todo = []
		for f in files:
			if self.exc.match(f):
				continue
			fullname = os.path.join(path, f)
			if self.inc.match(fullname) == None:
				if os.path.isdir(fullname):
					todo.append(fullname)
				else:
					rv.append(fullname)
		for d in todo:
			if len(rv) > 500:
				if istop:
					rv.append('... and more ...')
				return rv
			rv = rv + self.checkdir(d, 0)
		return rv
		
	def run(self, destprefix):
		missing = self.inc.checksourcetree()
		if missing:
			print '==== Missing source files ===='
			for i in missing:
				print i
			print '==== Fix and retry ===='
			return
		if not self.rundir(':', destprefix, 0):
			return
		self.rundir(':', destprefix, 1)

	def rundir(self, path, destprefix, doit):
		files = os.listdir(path)
		todo = []
		rv = 1
		for f in files:
			if self.exc.match(f):
				continue
			fullname = os.path.join(path, f)
			if os.path.isdir(fullname):
				todo.append(fullname)
			else:
				dest = self.inc.match(fullname)
				if dest == None:
					print 'Not yet resolved:', fullname
					rv = 0
				if dest:
					if doit:
						print 'COPY ', fullname
						print '  -> ', os.path.join(destprefix, dest)
						macostools.copy(fullname, os.path.join(destprefix, dest), 1)
		for d in todo:
			if not self.rundir(d, destprefix, doit):
				rv = 0
		return rv
		
	def save(self):
		self.inc.save()
		self.exc.save()
		
	def is_modified(self):
		return self.inc.is_modified() or self.exc.is_modified()

if __name__ == '__main__':
	Main()
	
