1#!/usr/bin/env python
2"""
3Helper script to rebuild virtualenv.py from virtualenv_support
4"""
5from __future__ import print_function
6
7import os
8import re
9import codecs
10from zlib import crc32
11
12here = os.path.dirname(__file__)
13script = os.path.join(here, '..', 'virtualenv.py')
14
15gzip = codecs.lookup('zlib')
16b64 = codecs.lookup('base64')
17
18file_regex = re.compile(
19    br'##file (.*?)\n([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*convert\("""\n(.*?)"""\)',
20    re.S)
21file_template = b'##file %(filename)s\n%(varname)s = convert("""\n%(data)s""")'
22
23def rebuild(script_path):
24    with open(script_path, 'rb') as f:
25        script_content = f.read()
26    parts = []
27    last_pos = 0
28    match = None
29    for match in file_regex.finditer(script_content):
30        parts += [script_content[last_pos:match.start()]]
31        last_pos = match.end()
32        filename, fn_decoded = match.group(1), match.group(1).decode()
33        varname = match.group(2)
34        data = match.group(3)
35
36        print('Found file %s' % fn_decoded)
37        pathname = os.path.join(here, '..', 'virtualenv_embedded', fn_decoded)
38
39        with open(pathname, 'rb') as f:
40            embedded = f.read()
41        new_crc = crc32(embedded)
42        new_data = b64.encode(gzip.encode(embedded)[0])[0]
43
44        if new_data == data:
45            print('  File up to date (crc: %s)' % new_crc)
46            parts += [match.group(0)]
47            continue
48        # Else: content has changed
49        crc = crc32(gzip.decode(b64.decode(data)[0])[0])
50        print('  Content changed (crc: %s -> %s)' %
51              (crc, new_crc))
52        new_match = file_template % {
53            b'filename': filename,
54            b'varname': varname,
55            b'data': new_data
56        }
57        parts += [new_match]
58
59    parts += [script_content[last_pos:]]
60    new_content = b''.join(parts)
61
62    if new_content != script_content:
63        print('Content updated; overwriting... ', end='')
64        with open(script_path, 'wb') as f:
65            f.write(new_content)
66        print('done.')
67    else:
68        print('No changes in content')
69    if match is None:
70        print('No variables were matched/found')
71
72if __name__ == '__main__':
73    rebuild(script)
74