build/buildutils/comparedirs.py
branchRCL_3
changeset 19 04becd199f91
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 #
       
     2 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description:
       
    15 #
       
    16 # Script for comparing contents of two directories.
       
    17 #
       
    18 # Usage:
       
    19 # python -u comparedirs.py <source_path> <target_path>
       
    20 #
       
    21 
       
    22 import datetime, filecmp, os, sys, traceback, zlib
       
    23 from optparse import OptionParser
       
    24 
       
    25 class ResultCounter:
       
    26     def __init__(self):
       
    27         self.source_only_dirs = 0
       
    28         self.source_only_files = 0
       
    29         self.target_only_dirs = 0
       
    30         self.target_only_files = 0
       
    31         self.diff_case_dirs = 0
       
    32         self.diff_case_files = 0
       
    33         self.diff_files = 0
       
    34         self.identical_files = 0
       
    35         self.start_time = datetime.datetime.now()
       
    36         self.stop_time = None
       
    37     def __str__(self):
       
    38         if self.stop_time is None:
       
    39             self.stop_time = datetime.datetime.now()
       
    40         msg = "Execution time " + str(self.stop_time - self.start_time) + "\n"
       
    41         msg += "Summary of differences:\n"
       
    42         if self.source_only_dirs > 0:
       
    43             msg += "Source only dirs: " + str(self.source_only_dirs) + "\n"
       
    44         if self.source_only_files > 0:
       
    45             msg += "Source only files: " + str(self.source_only_files) + "\n"
       
    46         if self.target_only_dirs > 0:
       
    47             msg += "Target only dirs: " + str(self.target_only_dirs) + "\n"
       
    48         if self.target_only_files > 0:
       
    49             msg += "Target only files: " + str(self.target_only_files) + "\n"
       
    50         if self.diff_case_dirs > 0:
       
    51             msg += "Different case dirs: " + str(self.diff_case_dirs) + "\n"
       
    52         if self.diff_case_files > 0:
       
    53             msg += "Different case files: " + str(self.diff_case_files) + "\n"
       
    54         if self.diff_files > 0:
       
    55             msg += "Different files: " + str(self.diff_files) + "\n"
       
    56         msg += "Identical files: " + str(self.identical_files)
       
    57         return msg
       
    58     def differences_found(self):
       
    59         if self.source_only_dirs > 0 or \
       
    60                 self.source_only_files > 0 or \
       
    61                 self.target_only_dirs > 0 or \
       
    62                 self.target_only_files > 0 or \
       
    63                 self.diff_case_dirs > 0 or \
       
    64                 self.diff_case_files > 0 or \
       
    65                 self.diff_files > 0:
       
    66             return True
       
    67         else:
       
    68             return False
       
    69 
       
    70 # Counter for differences.
       
    71 result_counter = ResultCounter()
       
    72 
       
    73 # Command line options.
       
    74 opts = None
       
    75 
       
    76 def main():
       
    77     global opts, result_counter
       
    78     # Parse command line options and arguments.
       
    79     parser = OptionParser(
       
    80         usage = "python -u %prog [options] <source_path> <target_path>")
       
    81     parser.add_option("-i", "--ignore", dest="ignore", action="append",
       
    82                       help="dir or file name to be ignored in the root directory")
       
    83     parser.add_option("--ignore_all", dest="ignore_all", action="append",
       
    84                       help="dir or file name to be ignored in all directories")
       
    85     parser.add_option("-v", "--verbose", dest="verbose",
       
    86                       action="store_true", default=False,
       
    87                       help="verbose output, lists also identical files")
       
    88     (opts, args) = parser.parse_args()
       
    89     if opts.ignore is None:
       
    90         opts.ignore = []
       
    91     if opts.ignore_all is None:
       
    92         opts.ignore_all = []
       
    93     source_path = args[0]
       
    94     target_path = args[1]
       
    95     if len(args) > 2:
       
    96         print "ERROR: Too many arguments"
       
    97         sys.exit(1)
       
    98 
       
    99     try:
       
   100         # Compare the source and target directories.
       
   101         print "%s: Comparing source %s and target %s" % \
       
   102             (str(datetime.datetime.now()), source_path, target_path)
       
   103         if len(opts.ignore) > 0:
       
   104             print "Ignoring from root directory: " + ", ".join(opts.ignore)
       
   105         if len(opts.ignore_all) > 0:
       
   106             print "Ignoring from all directories: " + ", ".join(opts.ignore_all)
       
   107         compare_dirs(source_path, target_path, opts.ignore, opts.ignore_all + [".svn", "_ccmwaid.inf"])
       
   108 
       
   109         # Comparison finished, display results.
       
   110         result_counter.stop_time = datetime.datetime.now()
       
   111         print "%s: Finished" % str(result_counter.stop_time)
       
   112         print str(result_counter)
       
   113     except:
       
   114         print "ERROR: Unexpected exception", datetime.datetime.now()
       
   115         traceback.print_exc()
       
   116         print str(result_counter)
       
   117         sys.exit(1)
       
   118 
       
   119     # if differences were found, exit with error status.
       
   120     if result_counter.differences_found():
       
   121         print "Directories differ."
       
   122         sys.exit(1)
       
   123     else:
       
   124         print "Directories are identical."
       
   125 
       
   126 def compare_dirs(source, target, ignore, ignore_all):
       
   127     global opts, result_counter
       
   128     dircmp = filecmp.dircmp(source, target, ignore + ignore_all)
       
   129     #dircmp.report()
       
   130     filelist = get_filelist(target)
       
   131     # Loop the common files.
       
   132     for p in dircmp.common:
       
   133         sp = os.path.join(source, p)
       
   134         tp = os.path.join(target, p)
       
   135         tp_old = os.path.join(target, get_filename_case(p, filelist))
       
   136         # Check if source has a file and target has a dir or vice versa,
       
   137         # or if the dir/file name case is different.
       
   138         if os.path.isdir(sp) and os.path.isfile(tp_old):
       
   139             print "Source dir, target file: %s, %s" % (sp, tp_old)
       
   140             result_counter.source_only_dirs += 1
       
   141             result_counter.target_only_files += 1
       
   142         elif os.path.isfile(sp) and os.path.isdir(tp_old):
       
   143             print "Source file, target dir: %s, %s" % (sp, tp_old)
       
   144             result_counter.source_only_files += 1
       
   145             result_counter.target_only_dirs += 1
       
   146         elif not tp == tp_old:
       
   147             if os.path.isdir(tp_old):
       
   148                 print "Dir cases differ: %s, %s" %  (sp, tp_old)
       
   149                 result_counter.diff_case_dirs += 1
       
   150             else:
       
   151                 print "File cases differ: %s, %s" %  (sp, tp_old)
       
   152                 result_counter.diff_case_files += 1
       
   153         # Compare existing dir or count existing file.
       
   154         elif os.path.isdir(sp) and os.path.isdir(tp):
       
   155             compare_dirs(sp, tp, [], ignore_all)
       
   156         else:
       
   157             if not files_equal(sp, tp):
       
   158                 # Files are different.
       
   159                 print "Files differ: %s, %s" % (sp, tp_old)
       
   160                 result_counter.diff_files += 1
       
   161             else:
       
   162                 # Files are identical.
       
   163                 if opts.verbose:
       
   164                     print "Identical files: %s, %s" % (sp, tp_old)
       
   165                 result_counter.identical_files += 1
       
   166     # Loop the files which only exist in source.
       
   167     for p in dircmp.left_only:
       
   168         sp = os.path.join(source, p)
       
   169         if os.path.isdir(sp):
       
   170             print "Source only dir: %s" % sp
       
   171             result_counter.source_only_dirs += 1
       
   172         else:
       
   173             print "Source only file: %s" % sp
       
   174             result_counter.source_only_files += 1
       
   175     # Loop the files which only exist in target.
       
   176     for p in dircmp.right_only:
       
   177         tp = os.path.join(target, p)
       
   178         if os.path.isdir(tp):
       
   179             print "Target only dir: %s" % tp
       
   180             result_counter.target_only_dirs += 1
       
   181         else:
       
   182             print "Target only file: %s" % tp
       
   183             result_counter.target_only_files += 1
       
   184 
       
   185 def get_filelist(path):
       
   186     if os.path.isdir(path):
       
   187         return os.listdir(path)
       
   188     else:
       
   189         return None
       
   190 
       
   191 def get_filename_case(filename, filelist):
       
   192     filename = os.path.basename(filename)
       
   193     if filelist is None:
       
   194         result = [filename]
       
   195     else:
       
   196         result = [f for f in filelist if f.lower() == filename.lower()]
       
   197     return result[0]
       
   198 
       
   199 def files_equal(source, target):
       
   200     if digest(source) == digest(target):
       
   201         return True
       
   202     else:
       
   203         return False
       
   204 
       
   205 def digest(file):
       
   206     f = open(file, "rb")
       
   207     try:
       
   208         h = zlib.crc32(f.read())
       
   209     finally:
       
   210         f.close()
       
   211     return h
       
   212 
       
   213 if __name__ == "__main__":
       
   214     main()