-
Notifications
You must be signed in to change notification settings - Fork 18
/
mk_distinfo.py
124 lines (94 loc) · 3.45 KB
/
mk_distinfo.py
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# This script handles the creation of the PEP 376 .dist-info directory for a
# package.
#
# Copyright (c) 2018 Riverbank Computing Limited <[email protected]>
#
# This script is distributed under the terms of the GNU General Public License
# v3 as published by the Free Software Foundation.
#
# This script is supplied WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
import base64
import hashlib
import os
import shutil
import sys
def error(message):
""" Display an error message and terminate. """
sys.stderr.write(message + '\n')
sys.exit(1)
# Parse the command line.
if len(sys.argv) != 4:
error("usage: {0} prefix dist-info installed".format(sys.argv[0]))
prefix_dir = sys.argv[1]
distinfo_dir = sys.argv[2]
installed_fn = sys.argv[3]
# Read the list of installed files.
installed_f = open(installed_fn)
installed = installed_f.read().strip().split('\n')
installed_f.close()
# The prefix directory corresponds to DESTDIR or INSTALL_ROOT.
real_distinfo_dir = prefix_dir + distinfo_dir
# Remove any existing dist-info directory and create an empty one.
if os.path.exists(real_distinfo_dir):
try:
shutil.rmtree(real_distinfo_dir)
except:
error("unable to delete existing {0}".format(real_distinfo_dir))
try:
os.mkdir(real_distinfo_dir)
except:
error("unable to create {0}".format(real_distinfo_dir))
# Create the INSTALLER file. We pretend that pip was the installer.
installer_fn = os.path.join(distinfo_dir, 'INSTALLER')
installer_f = open(prefix_dir + installer_fn, 'w')
installer_f.write('pip\n')
installer_f.close()
installed.append(installer_fn)
# Create the METADATA file.
METADATA = '''Metadata-Version: 1.1
Name: {0}
Version: {1}
'''
distinfo_path, distinfo_base = os.path.split(distinfo_dir)
pkg_name, version = os.path.splitext(distinfo_base)[0].split('-')
metadata_fn = os.path.join(distinfo_dir, 'METADATA')
metadata_f = open(prefix_dir + metadata_fn, 'w')
metadata_f.write(METADATA.format(pkg_name, version))
metadata_f.close()
installed.append(metadata_fn)
# Create the RECORD file.
record_fn = os.path.join(distinfo_dir, 'RECORD')
record_f = open(prefix_dir + record_fn, 'w')
for name in installed:
native_name = prefix_dir + name.replace('/', os.sep)
if os.path.isdir(native_name):
all_fns = []
for root, dirs, files in os.walk(native_name):
# Reproducable builds.
dirs.sort()
files.sort()
for f in files:
all_fns.append(os.path.join(root, f).replace(os.sep, '/'))
if '__pycache__' in dirs:
dirs.remove('__pycache__')
else:
all_fns = [prefix_dir + name]
for fn in all_fns:
real_distinfo_path = prefix_dir + distinfo_path
if fn.startswith(real_distinfo_path):
fn_name = fn[len(real_distinfo_path) + 1:].replace('\\', '/')
elif fn.startswith(prefix_dir + sys.prefix):
fn_name = os.path.relpath(
fn, real_distinfo_path).replace('\\', '/')
else:
fn_name = fn[len(prefix_dir):]
fn_f = open(fn, 'rb')
data = fn_f.read()
fn_f.close()
digest = base64.urlsafe_b64encode(
hashlib.sha256(data).digest()).rstrip(b'=').decode('ascii')
record_f.write(
'{0},sha256={1},{2}\n'.format(fn_name, digest, len(data)))
record_f.write('{0}/RECORD,,\n'.format(distinfo_base))
record_f.close()