summaryrefslogtreecommitdiffstats
path: root/Lib/dircmp.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/dircmp.py')
-rw-r--r--Lib/dircmp.py368
1 files changed, 183 insertions, 185 deletions
diff --git a/Lib/dircmp.py b/Lib/dircmp.py
index 1227aa7..13a8a04 100644
--- a/Lib/dircmp.py
+++ b/Lib/dircmp.py
@@ -1,6 +1,4 @@
-# Module 'dirmp'
-#
-# Defines a class to build directory diff tools on.
+"""A class to build directory diff tools on."""
import os
@@ -9,195 +7,195 @@ 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.)
-#
+ """Directory comparison class."""
+
+ 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()
+
+
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
+ """Compare common files in two directories.
+ Return:
+ - files that compare equal
+ - files that compare different
+ - funny cases (can't stat etc.)"""
+ res = ([], [], [])
+ for x in common:
+ res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
+ return res
-# 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
+
+def cmp(a, b):
+ """Compare two files.
+ Return:
+ 0 for equal
+ 1 for different
+ 2 for funny cases (can't stat, etc.)"""
+
+ try:
+ if cmpcache.cmp(a, b): return 0
+ return 1
+ except os.error:
+ return 2
-# 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
+ """Return a copy with items that occur in skip removed."""
+
+ 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()
+ """Demonstration and testing."""
+
+ 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()
+
+if __name__ == "__main__":
+ demo()