#!/usr/bin/python
import os.path
import shutil
import subprocess
import tempfile

# Compare a clone of the AWS git repository with the Debian source
# package, and check that only intended files are modified.
# See README.Debian for details.

# The implementation is quite inefficient, but this script should not
# be run often, and I do not want to reinvent diff -r

# Path to a GIT checkout of the gpl-2014 head.
upstream_git_repository = "/tmp/aws"
assert os.path.isdir (os.path.join (upstream_git_repository, ".git"))

# Path to the Debian source package.
debian_source_tree = "mtn"
assert os.path.isdir (os.path.join (debian_source_tree, "debian"))

expected_in_debian_but_not_git = (
    ".mtn-ignore",
    "_MTN",
    "debian",
    "CHANGES",
    "docs/source/confvars.py",
)
expected_in_git_but_not_debian = (
    ".git",
    ".gitattributes",
    ".gitignore",
    ".gitmodules",
    "COPYING.RUNTIME",
    "docs/rfc",
    "include/zlib",
    "templates_parser",
    "workspace",
)
extensions_expected_to_contain_substitutions = (
    ".adb",
    ".ads",
    ".c",
    ".gpr",
)
expected_substitutions = (
    ("""
package AWS with Pure is

   Version      : constant String := "3.2.0w";

""", """
package AWS with Pure is

   Version      : constant String := "3.2.0";

"""),
    ("""
--  As a special exception under Section 7 of GPL version 3, you are        --
--  granted additional permissions described in the GCC Runtime Library     --
--  Exception, version 3.1, as published by the Free Software Foundation.   --
""", "\n" + 3 * "--                                                                          --\n"),
    ("""
--  As a special exception, if other files instantiate generics from this   --
--  unit, or you link this unit with other files to produce an executable,  --
--  this  unit  does not  by itself cause  the resulting executable to be   --
--  covered by the GNU General Public License. This exception does not      --
--  however invalidate any other reasons why the executable file  might be  --
--  covered by the  GNU Public License.                                     --
""", "\n" + 6 * "--                                                                          --\n"),
    # Count the spaces before GNU in the last line.
    ("""
--  As a special exception, if other files instantiate generics from this   --
--  unit, or you link this unit with other files to produce an executable,  --
--  this  unit  does not  by itself cause  the resulting executable to be   --
--  covered by the GNU General Public License. This exception does not      --
--  however invalidate any other reasons why the executable file  might be  --
--  covered by the GNU Public License.                                      --
""", "\n" + 6 * "--                                                                          --\n"),
("""
 * As a special exception under Section 7 of GPL version 3, you are        *
 * granted additional permissions described in the GCC Runtime Library     *
 * Exception, version 3.1, as published by the Free Software Foundation.   *
""", "\n" + 3 * " *                                                                          * \n"),
)

def copy (source, destination, removals):
    shutil.copytree (source, destination)
    for f in removals:
        path = os.path.join (destination, f)
        if os.path.isdir (path):
            shutil.rmtree (path)
        else:
            os.remove (path)
            # Fails if path is missing (probably because you are
            # packaging a new revision).

def substitute_in_file (path, substitutions):
    modified = False
    with open (path, "r") as f:
        content = f.read ()
    for old, new in substitutions:
        index = str.find (content, old)
        if index != -1:
            modified = True
            content = content [:index] + new + content [index+len (old):]
    if modified:
        with open (path, "w") as f:
            f.write (content)

tmpdir = tempfile.mkdtemp ("aws-copy")
try:

    git = os.path.join (tmpdir, "git")
    copy (source = upstream_git_repository,
          destination = git,
          removals = expected_in_git_but_not_debian)

    deb = os.path.join (tmpdir, "deb")
    copy (source = debian_source_tree,
          destination = deb,
          removals = expected_in_debian_but_not_git)

    for d, _, filenames in os.walk (git):
        for n in filenames:
            for e in extensions_expected_to_contain_substitutions:
                if n.endswith (e):
                    substitute_in_file (os.path.join (d, n), expected_substitutions)
                    break

    process= subprocess.Popen (args = ("diff", "-urN", git, deb),
                               stdout = subprocess.PIPE)
    stdoutdata, stderrdata = process.communicate ()
    if stderrdata:
        print (stderrdata)
    diff_return_code = process.poll ()
    assert diff_return_code in (0, 1)

    print ("{} lines of unified diff.".format (str (stdoutdata.count ("\n"))))
    print (stdoutdata)

finally:
    shutil.rmtree (tmpdir)
