# Module 'dirmp'
#
# Defines a class to build directory diff tools on.

import os

import dircache
import cmpcache
import statcache
from stat import *

# Directory comparison class.
#
class dircmp:
	#
	def new(dd, (a, b)): # Initialize
		dd.a = a
		dd.b = b
		# Properties that caller may change before calling dd.run():
		dd.hide = [os.curdir, os.pardir] # Names never to be shown
		dd.ignore = ['RCS', 'tags'] # Names ignored in comparison
		#
		return dd
	#
	def run(dd): # Compare everything except common subdirectories
		dd.a_list = filter(dircache.listdir(dd.a), dd.hide)
		dd.b_list = filter(dircache.listdir(dd.b), dd.hide)
		dd.a_list.sort()
		dd.b_list.sort()
		dd.phase1()
		dd.phase2()
		dd.phase3()
	#
	def phase1(dd): # Compute common names
		dd.a_only = []
		dd.common = []
		for x in dd.a_list:
			if x in dd.b_list:
				dd.common.append(x)
			else:
				dd.a_only.append(x)
		#
		dd.b_only = []
		for x in dd.b_list:
			if x not in dd.common:
				dd.b_only.append(x)
	#
	def phase2(dd): # Distinguish files, directories, funnies
		dd.common_dirs = []
		dd.common_files = []
		dd.common_funny = []
		#
		for x in dd.common:
			a_path = os.path.join(dd.a, x)
			b_path = os.path.join(dd.b, x)
			#
			ok = 1
			try:
				a_stat = statcache.stat(a_path)
			except os.error, why:
				# print 'Can\'t stat', a_path, ':', why[1]
				ok = 0
			try:
				b_stat = statcache.stat(b_path)
			except os.error, why:
				# print 'Can\'t stat', b_path, ':', why[1]
				ok = 0
			#
			if ok:
				a_type = S_IFMT(a_stat[ST_MODE])
				b_type = S_IFMT(b_stat[ST_MODE])
				if a_type <> b_type:
					dd.common_funny.append(x)
				elif S_ISDIR(a_type):
					dd.common_dirs.append(x)
				elif S_ISREG(a_type):
					dd.common_files.append(x)
				else:
					dd.common_funny.append(x)
			else:
				dd.common_funny.append(x)
	#
	def phase3(dd): # Find out differences between common files
		xx = cmpfiles(dd.a, dd.b, dd.common_files)
		dd.same_files, dd.diff_files, dd.funny_files = xx
	#
	def phase4(dd): # Find out differences between common subdirectories
		# A new dircmp object is created for each common subdirectory,
		# these are stored in a dictionary indexed by filename.
		# The hide and ignore properties are inherited from the parent
		dd.subdirs = {}
		for x in dd.common_dirs:
			a_x = os.path.join(dd.a, x)
			b_x = os.path.join(dd.b, x)
			dd.subdirs[x] = newdd = dircmp().new(a_x, b_x)
			newdd.hide = dd.hide
			newdd.ignore = dd.ignore
			newdd.run()
	#
	def phase4_closure(dd): # Recursively call phase4() on subdirectories
		dd.phase4()
		for x in dd.subdirs.keys():
			dd.subdirs[x].phase4_closure()
	#
	def report(dd): # Print a report on the differences between a and b
		# Assume that phases 1 to 3 have been executed
		# Output format is purposely lousy
		print 'diff', dd.a, dd.b
		if dd.a_only:
			print 'Only in', dd.a, ':', dd.a_only
		if dd.b_only:
			print 'Only in', dd.b, ':', dd.b_only
		if dd.same_files:
			print 'Identical files :', dd.same_files
		if dd.diff_files:
			print 'Differing files :', dd.diff_files
		if dd.funny_files:
			print 'Trouble with common files :', dd.funny_files
		if dd.common_dirs:
			print 'Common subdirectories :', dd.common_dirs
		if dd.common_funny:
			print 'Common funny cases :', dd.common_funny
	#
	def report_closure(dd): # Print reports on dd and on subdirs
		# If phase 4 hasn't been done, no subdir reports are printed
		dd.report()
		try:
			x = dd.subdirs
		except AttributeError:
			return # No subdirectories computed
		for x in dd.subdirs.keys():
			print
			dd.subdirs[x].report_closure()
	#
	def report_phase4_closure(dd): # Report and do phase 4 recursively
		dd.report()
		dd.phase4()
		for x in dd.subdirs.keys():
			print
			dd.subdirs[x].report_phase4_closure()


# Compare common files in two directories.
# Return:
#	- files that compare equal
#	- files that compare different
#	- funny cases (can't stat etc.)
#
def cmpfiles(a, b, common):
	res = ([], [], [])
	for x in common:
		res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
	return res


# Compare two files.
# Return:
#	0 for equal
#	1 for different
#	2 for funny cases (can't stat, etc.)
#
def cmp(a, b):
	try:
		if cmpcache.cmp(a, b): return 0
		return 1
	except os.error:
		return 2


# Remove a list item.
# NB: This modifies the list argument.
#
def remove(list, item):
	for i in range(len(list)):
		if list[i] == item:
			del list[i]
			break


# Return a copy with items that occur in skip removed.
#
def filter(list, skip):
	result = []
	for item in list:
		if item not in skip: result.append(item)
	return result


# Demonstration and testing.
#
def demo():
	import sys
	import getopt
	options, args = getopt.getopt(sys.argv[1:], 'r')
	if len(args) <> 2: raise getopt.error, 'need exactly two args'
	dd = dircmp().new(args[0], args[1])
	dd.run()
	if ('-r', '') in options:
		dd.report_phase4_closure()
	else:
		dd.report()

# demo()
