# 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(self, a, b): # Initialize
		self.a = a
		self.b = b
		# Properties that caller may change before calling self.run():
		self.hide = [os.curdir, os.pardir] # Names never to be shown
		self.ignore = ['RCS', 'tags'] # Names ignored in comparison
		#
		return self
	#
	def run(self): # Compare everything except common subdirectories
		self.a_list = filter(dircache.listdir(self.a), self.hide)
		self.b_list = filter(dircache.listdir(self.b), self.hide)
		self.a_list.sort()
		self.b_list.sort()
		self.phase1()
		self.phase2()
		self.phase3()
	#
	def phase1(self): # Compute common names
		self.a_only = []
		self.common = []
		for x in self.a_list:
			if x in self.b_list:
				self.common.append(x)
			else:
				self.a_only.append(x)
		#
		self.b_only = []
		for x in self.b_list:
			if x not in self.common:
				self.b_only.append(x)
	#
	def phase2(self): # Distinguish files, directories, funnies
		self.common_dirs = []
		self.common_files = []
		self.common_funny = []
		#
		for x in self.common:
			a_path = os.path.join(self.a, x)
			b_path = os.path.join(self.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:
					self.common_funny.append(x)
				elif S_ISDIR(a_type):
					self.common_dirs.append(x)
				elif S_ISREG(a_type):
					self.common_files.append(x)
				else:
					self.common_funny.append(x)
			else:
				self.common_funny.append(x)
	#
	def phase3(self): # Find out differences between common files
		xx = cmpfiles(self.a, self.b, self.common_files)
		self.same_files, self.diff_files, self.funny_files = xx
	#
	def phase4(self): # 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
		self.subdirs = {}
		for x in self.common_dirs:
			a_x = os.path.join(self.a, x)
			b_x = os.path.join(self.b, x)
			self.subdirs[x] = newdd = dircmp().new(a_x, b_x)
			newdd.hide = self.hide
			newdd.ignore = self.ignore
			newdd.run()
	#
	def phase4_closure(self): # Recursively call phase4() on subdirectories
		self.phase4()
		for x in self.subdirs.keys():
			self.subdirs[x].phase4_closure()
	#
	def report(self): # 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', self.a, self.b
		if self.a_only:
			print 'Only in', self.a, ':', self.a_only
		if self.b_only:
			print 'Only in', self.b, ':', self.b_only
		if self.same_files:
			print 'Identical files :', self.same_files
		if self.diff_files:
			print 'Differing files :', self.diff_files
		if self.funny_files:
			print 'Trouble with common files :', self.funny_files
		if self.common_dirs:
			print 'Common subdirectories :', self.common_dirs
		if self.common_funny:
			print 'Common funny cases :', self.common_funny
	#
	def report_closure(self): # Print reports on self and on subdirs
		# If phase 4 hasn't been done, no subdir reports are printed
		self.report()
		try:
			x = self.subdirs
		except AttributeError:
			return # No subdirectories computed
		for x in self.subdirs.keys():
			print
			self.subdirs[x].report_closure()
	#
	def report_phase4_closure(self): # Report and do phase 4 recursively
		self.report()
		self.phase4()
		for x in self.subdirs.keys():
			print
			self.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()
