#! /usr/bin/python3

"""
This utility opens an archive and erases paths defined in
debian/copyright; then it ouputs the modified archive in stdout
or in another file when it is specified with the --output switch.
"""
import re
import argparse
from subprocess import call
import sys, os, tarfile, tempfile

packagedir = os.path.dirname(os.path.dirname(__file__))

def exclude_iter():
    """
    @return an iterator for paths to exclude from the input archive
    """
    lines = open(f"{packagedir}/debian/copyright").readlines()
    excluding = False
    result =[]
    for l in lines:
        m = re.match(r"^Files-Excluded:(.*)",l)
        if m:
            excluding = True
            result.append(m.group(1))
            continue
        if excluding:
            m = re.match(r"^\s(.*)",l)
            if m:
                result.append(m.group(1))
            else:
                excluding = False
                break
    return (r.strip() for r in result if r.strip())

def make_exclude(archive, output):
    """
    Copy the contents of archive to output, excluding some paths
    @param archive the input file path
    @param output the output file path; if None, it will be stdout
    """
    with tempfile.TemporaryDirectory(prefix="exclude-") as tmpdir:
        pName = os.path.join(
            tmpdir, re.sub(r"\.tar.*","", os.path.basename(args.archive)))
        os.mkdir(pName)
        with tarfile.open(name=args.archive, mode='r:*') as archive:
            sys.stderr.write(f"Extracting {args.archive} ...")
            sys.stderr.flush()
            archive.extractall(path=pName)
            sys.stderr.write(" [Done]\nRemoving excluded paths ...")
            sys.stderr.flush()
            cmd = "cd " + pName + ";"
            for path in exclude_iter():
                cmd += " rm -rf " + path +";"
            call(cmd, shell=True)
            sys.stderr.write(" [Done]\nCompressing into a new archive ...")
            sys.stderr.flush()
            repackedName = pName + "+repack"
            os.rename(pName, repackedName)
            resultName = repackedName + ".tar.xz"
            with tarfile.open(name=resultName, mode='w:xz') as result:
                result.add(
                    repackedName, arcname = os.path.basename(repackedName))
            # the output archive file is now closed
            if args.output:
                os.chdir(pwd)
                cmd = "cp " + os.path.join(tmpdir, resultName) + " " + \
                    args.output
            else:
                cmd = "cat " + os.path.join(tmpdir, resultName)
            call(cmd, shell = True)
        sys.stderr.write(" [Done]\n")
    return

if __name__ == "__main__":
    pwd = os.getcwd()
    parser = argparse.ArgumentParser(description='Exclude some paths from a given archive.')
    parser.add_argument(
        '-o', '--output', dest='output',
        help='The output file for the modified archive (format tar.xz); when this file is not given, the standard output is used.')
    parser.add_argument('archive', help='The archive file from which some paths will be excluded')
    args = parser.parse_args()
    if not args.archive:
        parser.print_help()
    else:
         make_exclude(args.archive, args.output)
            
