#!@PYTHON@

name = 'package-diff'
version = '0.62'

import sys
import os
from string import *
import getopt
import pipes

def program_id ():
	return name + ' ' + version;


def mailaddress():
	try:
		return os.environ['MAILADDRESS']
	except KeyError:
		return '(address unknown)'


def identify ():
	sys.stdout.write (program_id () + '\n')

class Flags:
	def __init__ (self):
		self.to_version = 0
		self.from_version = 0
		self.package = 0

flags = Flags ()

def help ():
	sys.stdout.write (
		'Generate a patch to go to current version\n'
		'  -f, --from=FROM      old is FROM\n'
		'  -h, --help	        print this help\n'
		'  -p, --package=DIR    specify package\n'
		'  -r, --release        diff against latest release\n'  
		'  -t, --to=TO          to version TO\n'  
		'  -F, --dir-from=FROM  diff from directory FROM\n'  
		'  -T, --dir-to=TO      diff to directory TO\n'  
		)

def untar (fn):
	# os.system ('pwd');
	sys.stderr.write ('untarring ' + fn + '\n')
	os.system ('gzip --quiet -dc ' + fn + '| tar xf - ')
	sys.stderr.flush ()

def remove_automatic (dirnames):
	files = []
	# urg, again?
	from flower import *
	files = files + multiple_find (pats, dirnames)
	dirs = multiple_find (['out'], dirnames)
	for d in dirs:
		files = files + multiple_find (['*'], [d])
	for f in files:
		os.remove (f)

def dirname (v):
	# urg, again?
	from packagepython import *
	return flags.package.name + '-' + version_tuple_to_str (v)

def tarball(v):
	return dirname (v)  + '.tar.gz'

def released_tarball(v):
	return flags.package.release_dir + tarball (v)


def remove_configure (dir):
	os.chdir (dir)
	# ugh
	os.system ('rm -f *.ly')

	# should do 'make distclean ?'
	os.system ('rm -rf debian/out')
	os.system ('rm -f GNUmakefile config.cache config.h config.hh config.log config.make config.status configure')
	os.system ('rm -f stepmake/GNUmakefile stepmake/config.hh stepmake/config.log stepmake/config.status stepmake/config.make')

	# ugh: symlinks
	os.system ('rm -f stepmake/stepmake/stepmake')
	os.system ('rm -f stepmake/stepmake/bin')


# ugh, how to get rid of .tex files generated by lily?
pats = ['configure', '*.diff', '*.diff.gz', '*.pyc',  '*.txt']

header = 'Generated by %s using %s,\
\nFrom = %s, To = %s\n\
\n\
usage \n\
\n\
    cd %s-source-dir; patch -E -p1 < %s\n\
\n\
Patches do not contain automatically generated files \n\
or (urg) empty directories, \n\
i.e., you should rerun autoconf, configure \n\
and possibly make outdirs.\n\n'

def makediff (fromdir, todir, patch_name):

	# urg, again?
	from packagepython import *

	remove_automatic ([fromdir, todir])
	
	# ugh
	remove_configure (fromdir)
	remove_configure (todir)
	os.chdir (todir)
	
	fromname = fromdir
	toname = todir
	if os.path.dirname (fromname) == os.path.dirname (toname):
		fromname = os.path.basename (fromname)
		toname = os.path.basename (toname)
		fromdir = '../' + fromname

	f = open (patch_name, 'w')
	f.write (header %
		(mailaddress (), program_id (),  fromname, toname, 
		 flags.package.name, os.path.basename (patch_name)))

	# write state vector
	f.write ('--state\n')
	state_vec = gulp_file ('make/STATE-VECTOR')
	from_str = version_tuple_to_str (flags.from_version)
	to_str = version_tuple_to_str (flags.to_version)
	i = regex.search (from_str, state_vec)
	if i == -1:
		f.write (from_str + '\n')
	else:
		state_vec = state_vec[i:]
	i = regex.search (to_str, state_vec)
	if i == -1:
		f.write (to_str + '\n')
	else:
		i = i + len (version_tuple_to_str (flags.to_version))
		state_vec = state_vec[:i]
		f.write (state_vec)
		f.write ('\n')
	f.write ('++state\n')
	f.close ()
			
	sys.stderr.write ('diffing to %s... ' % patch_name)
	os.system ('pwd')
	print ('diff -urN %s . >> %s' % (fromdir, patch_name))
	os.system ('diff -urN %s . >> %s' % (fromdir, patch_name))
	os.system ('gzip --quiet -9f %s' % patch_name)
   
def main ():
	os.environ['GZIP'] = '-q'
	identify ()
	print 'argv: ' + join (sys.argv[2:])
	(options, files) = getopt.getopt (sys.argv[1:], 
		'hF:f:o:p:rT:t:', ['from=', 'dir-from=', 'dir-to=', 'help', 'output=', 'package=', 'release', 'to='])

	patch_name = ''
	from_src = ''
	to_src = ''
	release=0
	from_version=0
	to_version=0
	for opt in options:
		o = opt[0]
		a = opt[1]
		if o == '--from' or o == '-f':
			 from_version = a
		elif o == '--to' or o == '-t':
			 to_version = a
		elif o == '--dir-from' or o == '-F':
			 from_src = a;
		elif o == '--dir-to' or o == '-T':
			 to_src = a;
		elif o == '--help' or o == '-h':
			help ()
			return 0;
		elif o == '--output' or o == '-o':
			patch_name = os.path.join (os.getcwd (), a)
		elif o == '-p' or o == '--package':
			topdir = a
		elif o == '--release' or o == '-r':
			release=1
		else:
			raise getopt.error

	sys.path.append (topdir + '/stepmake/bin')
	from packagepython import *
	package = Package (topdir)
	flags.package = package
	packager = Packager ()
	from flower import *

	if from_src:
		from_package = Package (from_src)
		flags.from_version = from_package.version
	if from_version:
		flags.from_version = version_str_to_tuple (from_version)
		from_src = ''
			
	if to_src:
		to_package = Package (to_src)
		flags.to_version = to_package.version
	if to_version:
		flags.to_version = version_str_to_tuple (to_version)
		to_src = ''
			
	if not flags.to_version:
		flags.to_version = package.version

	if not flags.from_version:
		flags.from_version = prev_version (flags.to_version)

	# urg
	if release:
		flags.from_version = (flags.from_version[0], 
			flags.from_version[1], flags.from_version[2], '');

	import tempfile
	prev_cwd = os.getcwd ();

	os.system ('rm -rf /tmp/package-diff') 
	try:
		os.mkdir ('/tmp/package-diff')
	except:
		pass
		
	from_diff = dirname (flags.from_version)
	to_diff =  dirname (flags.to_version)
	if to_diff == from_diff:
		if from_src:
		      from_diff = from_diff + '.src'
		elif to_src:
		      to_diff = to_diff + '.src'
		else:
		      sys.stderr.write (name + ': nothing to do: to == from == ' + from_diff + '\n')
		      sys.exit (1)

	if not patch_name:
		pn = to_diff + '.diff'
		patch_name =  os.path.join (os.getcwd (), pn)

	from_diff = '/tmp/package-diff/' + from_diff
	to_diff =  '/tmp/package-diff/' + to_diff

	if not from_src:
		os.chdir ('/tmp/package-diff')
		untar (released_tarball (flags.from_version))
		os.chdir (prev_cwd)
	else:
		sys.stderr.write ('copying ' + from_src + ' to ' + from_diff + '\n')
		# os.system ('cp -pr %s %s' % (srcdir, from_diff))
		os.system ('mkdir -p %s '% (from_diff))
		os.chdir (from_src)
		os.system ('tar cf - --exclude out --exclude out-www . \
			| tar -xf - -C %s' % from_diff)


	if not to_src:
		os.chdir ('/tmp/package-diff')
		untar (released_tarball (flags.to_version))
		os.chdir (prev_cwd)
	else:
		sys.stderr.write ('copying ' + to_src + ' to ' + to_diff + '\n')
		os.system ('mkdir -p %s '% (to_diff))
		# os.system ('cp -pr %s %s'  (to_src, to_diff))%
		os.chdir (to_src)
		os.system ('tar -cf - --exclude out --exclude out-www . \
			. | tar -xf - -C %s ' % to_diff)

	os.chdir (to_diff)
	makediff (from_diff, to_diff, patch_name) 

	os.chdir ('/tmp/package-diff')
	sys.stderr.write ('cleaning ... ')
	os.system ('rm -fr %s %s' % (from_diff, to_diff))
	sys.stderr.write ('\n')
	os.chdir (prev_cwd)

main ()
