# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# check-sync-dirs.py --- check that one directory is an exact subset of another
#
# Usage: python check-sync-dirs.py COPY ORIGINAL
#
# Check that the files present in the directory tree COPY are exact
# copies of their counterparts in the directory tree ORIGINAL.  COPY
# need not have all the files in ORIGINAL, but COPY may not have files
# absent from ORIGINAL.
# 
# Each directory in COPY may have a file named
# 'check-sync-exceptions', which lists files in COPY that need not be
# the same as the corresponding file in ORIGINAL, or exist at all in
# ORIGINAL.  (The 'check-sync-exceptions' file itself is always
# treated as exceptional.)  Blank lines and '#' comments in the file
# are ignored.

import sys
import os
from os.path import join
import filecmp
import textwrap
import fnmatch

if len(sys.argv) != 3:
    print >> sys.stderr, 'TEST-UNEXPECTED-FAIL | check-sync-dirs.py | Usage: %s COPY ORIGINAL' % sys.argv[0]
    sys.exit(1)

copy = os.path.abspath(sys.argv[1])
original = os.path.abspath(sys.argv[2])

# Return the contents of FILENAME, a 'check-sync-exceptions' file, as
# a dictionary whose keys are exactly the list of filenames, along
# with the basename of FILENAME itself.  If FILENAME does not exist,
# return the empty dictionary.
def read_exceptions(filename):
    if (os.path.exists(filename)):
        f = file(filename)
        exceptions = {}
        for line in f:
            line = line.strip()
            if line != '' and line[0] != '#':
                exceptions[line] = None
        exceptions[os.path.basename (filename)] = None
        f.close()
        return exceptions
    else:
        return {}

# Return true if FILENAME matches any pattern in the list of filename
# patterns PATTERNS.
def fnmatch_any(filename, patterns):
    for pattern in patterns:
        if fnmatch.fnmatch(filename, pattern):
            return True
    return False

# Check the contents of the directory tree COPY against ORIGINAL.  For each
# file that differs, apply REPORT to COPY, ORIGINAL, and the file's
# relative path.  COPY and ORIGINAL should be absolute.  Ignore files 
# that match patterns given in the list IGNORE.
def check(copy, original):
    os.chdir(copy)
    for (dirpath, dirnames, filenames) in os.walk('.'):
        exceptions = read_exceptions(join(dirpath, 'check-sync-exceptions'))
        for dirname in dirnames:
            if fnmatch_any(dirname, exceptions):
                dirnames.remove(dirname)
                break
        for filename in filenames:
            if fnmatch_any(filename, exceptions):
                continue
            relative_name = join(dirpath, filename)
            original_name = join(original, relative_name)
            if (os.path.exists(original_name)
                and filecmp.cmp(relative_name, original_name, False)):
                continue
            report(copy, original, relative_name)

differences_found = False

# Print an error message for DIFFERING, which was found to differ
# between COPY and ORIGINAL.  Set the global variable differences_found.
def report(copy, original, differing):
    global differences_found
    if not differences_found:
        print >> sys.stderr, 'TEST-UNEXPECTED-FAIL | check-sync-dirs.py | build file copies are not in sync\n' \
                             'TEST-INFO | check-sync-dirs.py | file(s) found in:               %s\n' \
                             'TEST-INFO | check-sync-dirs.py | differ from their originals in: %s' \
                             % (copy, original)
    print >> sys.stderr, 'TEST-INFO | check-sync-dirs.py | differing file:                 %s' % differing
    differences_found = True

check(copy, original)

if differences_found:
    msg = '''In general, the files in '%s' should always be exact copies of
originals in '%s'.  A change made to one should also be made to the
other.  See 'check-sync-dirs.py' for more details.''' \
         % (copy, original)
    print >> sys.stderr, textwrap.fill(msg, 75)
    sys.exit(1)

print >> sys.stderr, 'TEST-PASS | check-sync-dirs.py | %s <= %s' % (copy, original)
sys.exit(0)
