mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	 89a78697b8
			
		
	
	
		89a78697b8
		
	
	
	
	
		
			
			* Many modules: fixes for new, stricter, argument passing rules (most changes were automatic ones -- not all of this is tested!). * gwin.py: now uses mainloop.py for its main loop and window admin. * mainloop.py: always call dispatch() with event as a tuple! * Fix bug in pdb's 'clear' command -- don't set the bpt but clear it!
		
			
				
	
	
		
			203 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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()
 |