home *** CD-ROM | disk | FTP | other *** search
/ PC Extra 07 & 08 / pca1507.iso / Software / psp8 / Data1.cab / filecmp.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2003-04-22  |  13.0 KB  |  362 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.2)
  3.  
  4. '''Utilities for comparing files and directories.
  5.  
  6. Classes:
  7.     dircmp
  8.  
  9. Functions:
  10.     cmp(f1, f2, shallow=1, use_statcache=0) -> int
  11.     cmpfiles(a, b, common) -> ([], [], [])
  12.  
  13. '''
  14. import os
  15. import stat
  16. import statcache
  17. __all__ = [
  18.     'cmp',
  19.     'dircmp',
  20.     'cmpfiles']
  21. _cache = { }
  22. BUFSIZE = 8 * 1024
  23.  
  24. def cmp(f1, f2, shallow = 1, use_statcache = 0):
  25.     """Compare two files.
  26.  
  27.     Arguments:
  28.  
  29.     f1 -- First file name
  30.  
  31.     f2 -- Second file name
  32.  
  33.     shallow -- Just check stat signature (do not read the files).
  34.                defaults to 1.
  35.  
  36.     use_statcache -- Do not stat() each file directly: go through
  37.                      the statcache module for more efficiency.
  38.  
  39.     Return value:
  40.  
  41.     integer -- 1 if the files are the same, 0 otherwise.
  42.  
  43.     This function uses a cache for past comparisons and the results,
  44.     with a cache invalidation mechanism relying on stale signatures.
  45.     Of course, if 'use_statcache' is true, this mechanism is defeated,
  46.     and the cache will never grow stale.
  47.  
  48.     """
  49.     if use_statcache:
  50.         stat_function = statcache.stat
  51.     else:
  52.         stat_function = os.stat
  53.     s1 = _sig(stat_function(f1))
  54.     s2 = _sig(stat_function(f2))
  55.     if s1[0] != stat.S_IFREG or s2[0] != stat.S_IFREG:
  56.         return 0
  57.     
  58.     if shallow and s1 == s2:
  59.         return 1
  60.     
  61.     if s1[1] != s2[1]:
  62.         return 0
  63.     
  64.     result = _cache.get((f1, f2))
  65.     if result and (s1, s2) == result[:2]:
  66.         return result[2]
  67.     
  68.     outcome = _do_cmp(f1, f2)
  69.     _cache[(f1, f2)] = (s1, s2, outcome)
  70.     return outcome
  71.  
  72.  
  73. def _sig(st):
  74.     return (stat.S_IFMT(st[stat.ST_MODE]), st[stat.ST_SIZE], st[stat.ST_MTIME])
  75.  
  76.  
  77. def _do_cmp(f1, f2):
  78.     bufsize = BUFSIZE
  79.     fp1 = open(f1, 'rb')
  80.     fp2 = open(f2, 'rb')
  81.     while 1:
  82.         b1 = fp1.read(bufsize)
  83.         b2 = fp2.read(bufsize)
  84.         if b1 != b2:
  85.             return 0
  86.         
  87.         if not b1:
  88.             return 1
  89.         
  90.  
  91.  
  92. class dircmp:
  93.     """A class that manages the comparison of 2 directories.
  94.  
  95.     dircmp(a,b,ignore=None,hide=None)
  96.       A and B are directories.
  97.       IGNORE is a list of names to ignore,
  98.         defaults to ['RCS', 'CVS', 'tags'].
  99.       HIDE is a list of names to hide,
  100.         defaults to [os.curdir, os.pardir].
  101.  
  102.     High level usage:
  103.       x = dircmp(dir1, dir2)
  104.       x.report() -> prints a report on the differences between dir1 and dir2
  105.        or
  106.       x.report_partial_closure() -> prints report on differences between dir1
  107.             and dir2, and reports on common immediate subdirectories.
  108.       x.report_full_closure() -> like report_partial_closure,
  109.             but fully recursive.
  110.  
  111.     Attributes:
  112.      left_list, right_list: The files in dir1 and dir2,
  113.         filtered by hide and ignore.
  114.      common: a list of names in both dir1 and dir2.
  115.      left_only, right_only: names only in dir1, dir2.
  116.      common_dirs: subdirectories in both dir1 and dir2.
  117.      common_files: files in both dir1 and dir2.
  118.      common_funny: names in both dir1 and dir2 where the type differs between
  119.         dir1 and dir2, or the name is not stat-able.
  120.      same_files: list of identical files.
  121.      diff_files: list of filenames which differ.
  122.      funny_files: list of files which could not be compared.
  123.      subdirs: a dictionary of dircmp objects, keyed by names in common_dirs.
  124.      """
  125.     
  126.     def __init__(self, a, b, ignore = None, hide = None):
  127.         self.left = a
  128.         self.right = b
  129.         if hide is None:
  130.             self.hide = [
  131.                 os.curdir,
  132.                 os.pardir]
  133.         else:
  134.             self.hide = hide
  135.         if ignore is None:
  136.             self.ignore = [
  137.                 'RCS',
  138.                 'CVS',
  139.                 'tags']
  140.         else:
  141.             self.ignore = ignore
  142.  
  143.     
  144.     def phase0(self):
  145.         self.left_list = _filter(os.listdir(self.left), self.hide + self.ignore)
  146.         self.right_list = _filter(os.listdir(self.right), self.hide + self.ignore)
  147.         self.left_list.sort()
  148.         self.right_list.sort()
  149.  
  150.     __p4_attrs = ('subdirs',)
  151.     __p3_attrs = ('same_files', 'diff_files', 'funny_files')
  152.     __p2_attrs = ('common_dirs', 'common_files', 'common_funny')
  153.     __p1_attrs = ('common', 'left_only', 'right_only')
  154.     __p0_attrs = ('left_list', 'right_list')
  155.     
  156.     def __getattr__(self, attr):
  157.         if attr in self._dircmp__p4_attrs:
  158.             self.phase4()
  159.         elif attr in self._dircmp__p3_attrs:
  160.             self.phase3()
  161.         elif attr in self._dircmp__p2_attrs:
  162.             self.phase2()
  163.         elif attr in self._dircmp__p1_attrs:
  164.             self.phase1()
  165.         elif attr in self._dircmp__p0_attrs:
  166.             self.phase0()
  167.         else:
  168.             raise AttributeError, attr
  169.         return getattr(self, attr)
  170.  
  171.     
  172.     def phase1(self):
  173.         (a_only, b_only) = ([], [])
  174.         common = { }
  175.         b = { }
  176.         for fnm in self.right_list:
  177.             b[fnm] = 1
  178.         
  179.         for x in self.left_list:
  180.             if b.get(x, 0):
  181.                 common[x] = 1
  182.             else:
  183.                 a_only.append(x)
  184.         
  185.         for x in self.right_list:
  186.             if common.get(x, 0):
  187.                 pass
  188.             else:
  189.                 b_only.append(x)
  190.         
  191.         self.common = common.keys()
  192.         self.left_only = a_only
  193.         self.right_only = b_only
  194.  
  195.     
  196.     def phase2(self):
  197.         self.common_dirs = []
  198.         self.common_files = []
  199.         self.common_funny = []
  200.         for x in self.common:
  201.             a_path = os.path.join(self.left, x)
  202.             b_path = os.path.join(self.right, x)
  203.             ok = 1
  204.             
  205.             try:
  206.                 a_stat = statcache.stat(a_path)
  207.             except os.error:
  208.                 why = None
  209.                 ok = 0
  210.  
  211.             
  212.             try:
  213.                 b_stat = statcache.stat(b_path)
  214.             except os.error:
  215.                 why = None
  216.                 ok = 0
  217.  
  218.             if ok:
  219.                 a_type = stat.S_IFMT(a_stat[stat.ST_MODE])
  220.                 b_type = stat.S_IFMT(b_stat[stat.ST_MODE])
  221.                 if a_type != b_type:
  222.                     self.common_funny.append(x)
  223.                 elif stat.S_ISDIR(a_type):
  224.                     self.common_dirs.append(x)
  225.                 elif stat.S_ISREG(a_type):
  226.                     self.common_files.append(x)
  227.                 else:
  228.                     self.common_funny.append(x)
  229.             else:
  230.                 self.common_funny.append(x)
  231.         
  232.  
  233.     
  234.     def phase3(self):
  235.         xx = cmpfiles(self.left, self.right, self.common_files)
  236.         (self.same_files, self.diff_files, self.funny_files) = xx
  237.  
  238.     
  239.     def phase4(self):
  240.         self.subdirs = { }
  241.         for x in self.common_dirs:
  242.             a_x = os.path.join(self.left, x)
  243.             b_x = os.path.join(self.right, x)
  244.             self.subdirs[x] = dircmp(a_x, b_x, self.ignore, self.hide)
  245.         
  246.  
  247.     
  248.     def phase4_closure(self):
  249.         self.phase4()
  250.         for x in self.subdirs.keys():
  251.             self.subdirs[x].phase4_closure()
  252.         
  253.  
  254.     
  255.     def report(self):
  256.         print 'diff', self.left, self.right
  257.         if self.left_only:
  258.             self.left_only.sort()
  259.             print 'Only in', self.left, ':', self.left_only
  260.         
  261.         if self.right_only:
  262.             self.right_only.sort()
  263.             print 'Only in', self.right, ':', self.right_only
  264.         
  265.         if self.same_files:
  266.             self.same_files.sort()
  267.             print 'Identical files :', self.same_files
  268.         
  269.         if self.diff_files:
  270.             self.diff_files.sort()
  271.             print 'Differing files :', self.diff_files
  272.         
  273.         if self.funny_files:
  274.             self.funny_files.sort()
  275.             print 'Trouble with common files :', self.funny_files
  276.         
  277.         if self.common_dirs:
  278.             self.common_dirs.sort()
  279.             print 'Common subdirectories :', self.common_dirs
  280.         
  281.         if self.common_funny:
  282.             self.common_funny.sort()
  283.             print 'Common funny cases :', self.common_funny
  284.         
  285.  
  286.     
  287.     def report_partial_closure(self):
  288.         self.report()
  289.         for x in self.subdirs.keys():
  290.             print 
  291.             self.subdirs[x].report()
  292.         
  293.  
  294.     
  295.     def report_full_closure(self):
  296.         self.report()
  297.         for x in self.subdirs.keys():
  298.             print 
  299.             self.subdirs[x].report_full_closure()
  300.         
  301.  
  302.  
  303.  
  304. def cmpfiles(a, b, common, shallow = 1, use_statcache = 0):
  305.     """Compare common files in two directories.
  306.  
  307.     a, b -- directory names
  308.     common -- list of file names found in both directories
  309.     shallow -- if true, do comparison based solely on stat() information
  310.     use_statcache -- if true, use statcache.stat() instead of os.stat()
  311.  
  312.     Returns a tuple of three lists:
  313.       files that compare equal
  314.       files that are different
  315.       filenames that aren't regular files.
  316.  
  317.     """
  318.     res = ([], [], [])
  319.     for x in common:
  320.         ax = os.path.join(a, x)
  321.         bx = os.path.join(b, x)
  322.         res[_cmp(ax, bx, shallow, use_statcache)].append(x)
  323.     
  324.     return res
  325.  
  326.  
  327. def _cmp(a, b, sh, st):
  328.     
  329.     try:
  330.         return not abs(cmp(a, b, sh, st))
  331.     except os.error:
  332.         return 2
  333.  
  334.  
  335.  
  336. def _filter(list, skip):
  337.     result = []
  338.     for item in list:
  339.         if item not in skip:
  340.             result.append(item)
  341.         
  342.     
  343.     return result
  344.  
  345.  
  346. def demo():
  347.     import sys
  348.     import getopt
  349.     (options, args) = getopt.getopt(sys.argv[1:], 'r')
  350.     if len(args) != 2:
  351.         raise getopt.error, 'need exactly two args'
  352.     
  353.     dd = dircmp(args[0], args[1])
  354.     if ('-r', '') in options:
  355.         dd.report_full_closure()
  356.     else:
  357.         dd.report()
  358.  
  359. if __name__ == '__main__':
  360.     demo()
  361.  
  362.