aboutsummaryrefslogtreecommitdiffstats
path: root/build/scripts/filter_zip.py
blob: b2121b9c9ed191f84a347be91222eba7963be872 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import argparse
import os
import re
import uuid
import zipfile


def pattern_to_regexp(p):
    return re.compile(
        '^'
        + re.escape(p)
        .replace(r'\*\*\/', '[_DIR_]')
        .replace(r'\*', '[_FILE_]')
        .replace('[_DIR_]', '(.*/)?')
        .replace('[_FILE_]', '([^/]*)')
        + '$'
    )


def is_deathman(positive_filter, negative_filter, candidate):
    remove = positive_filter
    for pf in positive_filter:
        if pf.match(candidate):
            remove = False
            break
    if not negative_filter or remove:
        return remove
    for nf in negative_filter:
        if nf.match(candidate):
            remove = True
            break
    return remove


def just_do_it():
    parser = argparse.ArgumentParser()
    parser.add_argument('--positive', action='append', default=[])
    parser.add_argument('--negative', action='append', default=[])
    parser.add_argument('--file', action='store', required=True)
    args = parser.parse_args()
    if not args.positive and not args.negative:
        return
    pos = [pattern_to_regexp(i) for i in args.positive]
    neg = [pattern_to_regexp(i) for i in args.negative]
    temp_dirname = None
    for _ in range(10):
        candidate = '__unpacked_{}__'.format(uuid.uuid4())
        if not os.path.exists(candidate):
            temp_dirname = candidate
            os.makedirs(temp_dirname)
    if not temp_dirname:
        raise Exception("Can't generate name for temp dir")

    with zipfile.ZipFile(args.file, 'r') as zip_ref:
        zip_ref.extractall(temp_dirname)

    for root, _, files in os.walk(temp_dirname):
        for f in files:
            candidate = os.path.join(root, f).replace('\\', '/')
            if is_deathman(pos, neg, os.path.relpath(candidate, temp_dirname)):
                os.remove(candidate)

    with zipfile.ZipFile(args.file, 'w') as zip_ref:
        for root, _, files in os.walk(temp_dirname):
            for f in files:
                realname = os.path.join(root, f)
                zip_ref.write(realname, os.path.sep.join(os.path.normpath(realname).split(os.path.sep, 2)[1:]))


if __name__ == '__main__':
    just_do_it()