@sentry/cli 1.75.2 → 1.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -9
- package/bin/sentry-cli +4 -4
- package/checksums.txt +9 -9
- package/js/helper.js +12 -2
- package/js/index.d.ts +37 -29
- package/js/releases/index.js +15 -18
- package/js/releases/options/uploadSourcemaps.js +12 -0
- package/package.json +21 -33
- package/scripts/build-in-docker.sh +1 -2
- package/scripts/install.js +117 -108
- package/scripts/test-vercel-nft.js +1 -12
- package/scripts/wheels +174 -0
- package/CHANGELOG.md +0 -1138
package/scripts/install.js
CHANGED
|
@@ -11,18 +11,24 @@ const zlib = require('zlib');
|
|
|
11
11
|
const stream = require('stream');
|
|
12
12
|
const process = require('process');
|
|
13
13
|
|
|
14
|
-
const HttpsProxyAgent = require('https-proxy-agent');
|
|
15
14
|
const fetch = require('node-fetch');
|
|
15
|
+
const HttpsProxyAgent = require('https-proxy-agent');
|
|
16
16
|
const ProgressBar = require('progress');
|
|
17
17
|
const Proxy = require('proxy-from-env');
|
|
18
|
-
// NOTE: Can be dropped in favor of `fs.mkdirSync(path, { recursive: true })` once we stop supporting Node 8.x
|
|
19
|
-
const mkdirp = require('mkdirp');
|
|
20
18
|
const which = require('which');
|
|
21
19
|
|
|
22
20
|
const helper = require('../js/helper');
|
|
23
21
|
const pkgInfo = require('../package.json');
|
|
24
22
|
const Logger = require('../js/logger');
|
|
25
23
|
|
|
24
|
+
const logger = new Logger(getLogStream('stderr'));
|
|
25
|
+
|
|
26
|
+
const CDN_URL =
|
|
27
|
+
process.env.SENTRYCLI_LOCAL_CDNURL ||
|
|
28
|
+
process.env.npm_config_sentrycli_cdnurl ||
|
|
29
|
+
process.env.SENTRYCLI_CDNURL ||
|
|
30
|
+
'https://downloads.sentry-cdn.com/sentry-cli';
|
|
31
|
+
|
|
26
32
|
function getLogStream(defaultStream) {
|
|
27
33
|
const logStream = process.env.SENTRYCLI_LOG_STREAM || defaultStream;
|
|
28
34
|
|
|
@@ -39,22 +45,14 @@ function getLogStream(defaultStream) {
|
|
|
39
45
|
);
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
const logger = new Logger(getLogStream('stderr'));
|
|
43
|
-
|
|
44
|
-
const CDN_URL =
|
|
45
|
-
process.env.SENTRYCLI_LOCAL_CDNURL ||
|
|
46
|
-
process.env.npm_config_sentrycli_cdnurl ||
|
|
47
|
-
process.env.SENTRYCLI_CDNURL ||
|
|
48
|
-
'https://downloads.sentry-cdn.com/sentry-cli';
|
|
49
|
-
|
|
50
48
|
function shouldRenderProgressBar() {
|
|
51
|
-
const silentFlag = process.argv.some(v => v === '--silent');
|
|
49
|
+
const silentFlag = process.argv.some((v) => v === '--silent');
|
|
52
50
|
const silentConfig = process.env.npm_config_loglevel === 'silent';
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
51
|
+
const silentEnv = process.env.SENTRYCLI_NO_PROGRESS_BAR;
|
|
52
|
+
const ciEnv = process.env.CI === 'true' || process.env.CI === '1';
|
|
53
|
+
const notTTY = !process.stdout.isTTY;
|
|
56
54
|
// If any of possible options is set, skip rendering of progress bar
|
|
57
|
-
return !(silentFlag || silentConfig || silentEnv || ciEnv);
|
|
55
|
+
return !(silentFlag || silentConfig || silentEnv || ciEnv || notTTY);
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
function getDownloadUrl(platform, arch) {
|
|
@@ -113,7 +111,7 @@ function createProgressBar(name, total) {
|
|
|
113
111
|
let pct = null;
|
|
114
112
|
let current = 0;
|
|
115
113
|
return {
|
|
116
|
-
tick: length => {
|
|
114
|
+
tick: (length) => {
|
|
117
115
|
current += length;
|
|
118
116
|
const next = Math.round((current / total) * 100);
|
|
119
117
|
if (next > pct) {
|
|
@@ -125,21 +123,21 @@ function createProgressBar(name, total) {
|
|
|
125
123
|
}
|
|
126
124
|
|
|
127
125
|
function npmCache() {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
env.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
)
|
|
126
|
+
const keys = ['npm_config_cache', 'npm_config_cache_folder', 'npm_config_yarn_offline_mirror'];
|
|
127
|
+
|
|
128
|
+
for (let key of [...keys, ...keys.map((k) => k.toUpperCase())]) {
|
|
129
|
+
if (process.env[key]) return process.env[key];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (process.env.APPDATA) {
|
|
133
|
+
return path.join(process.env.APPDATA, 'npm-cache');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return path.join(os.homedir(), '.npm');
|
|
135
137
|
}
|
|
136
138
|
|
|
137
139
|
function getCachedPath(url) {
|
|
138
|
-
const digest = crypto
|
|
139
|
-
.createHash('md5')
|
|
140
|
-
.update(url)
|
|
141
|
-
.digest('hex')
|
|
142
|
-
.slice(0, 6);
|
|
140
|
+
const digest = crypto.createHash('md5').update(url).digest('hex').slice(0, 6);
|
|
143
141
|
|
|
144
142
|
return path.join(
|
|
145
143
|
npmCache(),
|
|
@@ -149,9 +147,7 @@ function getCachedPath(url) {
|
|
|
149
147
|
}
|
|
150
148
|
|
|
151
149
|
function getTempFile(cached) {
|
|
152
|
-
return `${cached}.${process.pid}-${Math.random()
|
|
153
|
-
.toString(16)
|
|
154
|
-
.slice(2)}.tmp`;
|
|
150
|
+
return `${cached}.${process.pid}-${Math.random().toString(16).slice(2)}.tmp`;
|
|
155
151
|
}
|
|
156
152
|
|
|
157
153
|
function validateChecksum(tempPath, name) {
|
|
@@ -178,10 +174,7 @@ function validateChecksum(tempPath, name) {
|
|
|
178
174
|
return;
|
|
179
175
|
}
|
|
180
176
|
|
|
181
|
-
const currentHash = crypto
|
|
182
|
-
.createHash('sha256')
|
|
183
|
-
.update(fs.readFileSync(tempPath))
|
|
184
|
-
.digest('hex');
|
|
177
|
+
const currentHash = crypto.createHash('sha256').update(fs.readFileSync(tempPath)).digest('hex');
|
|
185
178
|
|
|
186
179
|
if (storedHash !== currentHash) {
|
|
187
180
|
fs.unlinkSync(tempPath);
|
|
@@ -193,14 +186,16 @@ function validateChecksum(tempPath, name) {
|
|
|
193
186
|
}
|
|
194
187
|
}
|
|
195
188
|
|
|
196
|
-
function downloadBinary() {
|
|
189
|
+
async function downloadBinary() {
|
|
197
190
|
const arch = os.arch();
|
|
198
191
|
const platform = os.platform();
|
|
199
192
|
const outputPath = helper.getPath();
|
|
200
193
|
|
|
201
194
|
if (process.env.SENTRYCLI_USE_LOCAL === '1') {
|
|
202
195
|
try {
|
|
203
|
-
const
|
|
196
|
+
const binPaths = which.sync('sentry-cli', { all: true });
|
|
197
|
+
if (!binPaths.length) throw new Error('Binary not found');
|
|
198
|
+
const binPath = binPaths[binPaths.length - 1];
|
|
204
199
|
logger.log(`Using local binary: ${binPath}`);
|
|
205
200
|
fs.copyFileSync(binPath, outputPath);
|
|
206
201
|
return Promise.resolve();
|
|
@@ -214,14 +209,14 @@ function downloadBinary() {
|
|
|
214
209
|
|
|
215
210
|
const downloadUrl = getDownloadUrl(platform, arch);
|
|
216
211
|
if (!downloadUrl) {
|
|
217
|
-
|
|
212
|
+
throw new Error(`Unsupported target ${platform}-${arch}`);
|
|
218
213
|
}
|
|
219
214
|
|
|
220
215
|
const cachedPath = getCachedPath(downloadUrl);
|
|
221
216
|
if (fs.existsSync(cachedPath)) {
|
|
222
217
|
logger.log(`Using cached binary: ${cachedPath}`);
|
|
223
218
|
fs.copyFileSync(cachedPath, outputPath);
|
|
224
|
-
return
|
|
219
|
+
return;
|
|
225
220
|
}
|
|
226
221
|
|
|
227
222
|
const proxyUrl = Proxy.getProxyForUrl(downloadUrl);
|
|
@@ -233,74 +228,85 @@ function downloadBinary() {
|
|
|
233
228
|
logger.log(`Using proxy URL: ${proxyUrl}`);
|
|
234
229
|
}
|
|
235
230
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
231
|
+
let response;
|
|
232
|
+
try {
|
|
233
|
+
response = await fetch(downloadUrl, {
|
|
234
|
+
agent,
|
|
235
|
+
compress: false,
|
|
236
|
+
headers: {
|
|
237
|
+
'accept-encoding': 'gzip, deflate, br',
|
|
238
|
+
},
|
|
239
|
+
redirect: 'follow',
|
|
240
|
+
});
|
|
241
|
+
} catch (error) {
|
|
242
|
+
let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nError message: ${error.message}`;
|
|
243
|
+
if (error.code) {
|
|
244
|
+
errorMsg += `\nError code: ${error.code}`;
|
|
245
|
+
}
|
|
246
|
+
throw new Error(errorMsg);
|
|
247
|
+
}
|
|
250
248
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
249
|
+
if (!response.ok) {
|
|
250
|
+
let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nServer returned: ${response.status}`;
|
|
251
|
+
if (response.statusText) {
|
|
252
|
+
errorMsg += ` - ${response.statusText}`;
|
|
253
|
+
}
|
|
254
|
+
throw new Error(errorMsg);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const contentEncoding = response.headers.get('content-encoding');
|
|
258
|
+
let decompressor;
|
|
259
|
+
if (/\bgzip\b/.test(contentEncoding)) {
|
|
260
|
+
decompressor = zlib.createGunzip();
|
|
261
|
+
} else if (/\bdeflate\b/.test(contentEncoding)) {
|
|
262
|
+
decompressor = zlib.createInflate();
|
|
263
|
+
} else if (/\bbr\b/.test(contentEncoding)) {
|
|
264
|
+
decompressor = zlib.createBrotliDecompress();
|
|
265
|
+
} else {
|
|
266
|
+
decompressor = new stream.PassThrough();
|
|
267
|
+
}
|
|
268
|
+
const name = downloadUrl.match(/.*\/(.*?)$/)[1];
|
|
269
|
+
let downloadedBytes = 0;
|
|
270
|
+
const totalBytes = parseInt(response.headers.get('content-length'), 10);
|
|
271
|
+
const progressBar = createProgressBar(name, totalBytes);
|
|
272
|
+
const tempPath = getTempFile(cachedPath);
|
|
273
|
+
fs.mkdirSync(path.dirname(tempPath), { recursive: true });
|
|
274
|
+
|
|
275
|
+
await new Promise((resolve, reject) => {
|
|
276
|
+
response.body
|
|
277
|
+
.on('error', (e) => reject(e))
|
|
278
|
+
.on('data', (chunk) => {
|
|
279
|
+
downloadedBytes += chunk.length;
|
|
280
|
+
progressBar.tick(chunk.length);
|
|
281
|
+
})
|
|
282
|
+
.pipe(decompressor)
|
|
283
|
+
.pipe(fs.createWriteStream(tempPath, { mode: '0755' }))
|
|
284
|
+
.on('error', (e) => reject(e))
|
|
285
|
+
.on('close', () => {
|
|
286
|
+
if (downloadedBytes >= totalBytes) {
|
|
287
|
+
resolve();
|
|
288
|
+
} else {
|
|
289
|
+
reject(new Error('connection interrupted'));
|
|
279
290
|
}
|
|
280
|
-
fs.copyFileSync(tempPath, cachedPath);
|
|
281
|
-
fs.copyFileSync(tempPath, outputPath);
|
|
282
|
-
fs.unlinkSync(tempPath);
|
|
283
291
|
});
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
if (process.env.SENTRYCLI_SKIP_CHECKSUM_VALIDATION !== '1') {
|
|
295
|
+
validateChecksum(tempPath, name);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
fs.copyFileSync(tempPath, cachedPath);
|
|
299
|
+
fs.copyFileSync(tempPath, outputPath);
|
|
300
|
+
fs.unlinkSync(tempPath);
|
|
294
301
|
}
|
|
295
302
|
|
|
296
|
-
function checkVersion() {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
});
|
|
303
|
+
async function checkVersion() {
|
|
304
|
+
const output = await helper.execute(['--version']);
|
|
305
|
+
const version = output.replace('sentry-cli ', '').trim();
|
|
306
|
+
const expected = process.env.SENTRYCLI_LOCAL_CDNURL ? 'DEV' : pkgInfo.version;
|
|
307
|
+
if (version !== expected) {
|
|
308
|
+
throw new Error(`Unexpected sentry-cli version "${version}", expected "${expected}"`);
|
|
309
|
+
}
|
|
304
310
|
}
|
|
305
311
|
|
|
306
312
|
if (process.env.SENTRYCLI_LOCAL_CDNURL) {
|
|
@@ -323,11 +329,14 @@ if (process.env.SENTRYCLI_SKIP_DOWNLOAD === '1') {
|
|
|
323
329
|
process.exit(0);
|
|
324
330
|
}
|
|
325
331
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
332
|
+
(async () => {
|
|
333
|
+
try {
|
|
334
|
+
await downloadBinary();
|
|
335
|
+
await checkVersion();
|
|
336
|
+
process.exit(0);
|
|
337
|
+
} catch (e) {
|
|
330
338
|
// eslint-disable-next-line no-console
|
|
331
339
|
console.error(e.toString());
|
|
332
340
|
process.exit(1);
|
|
333
|
-
}
|
|
341
|
+
}
|
|
342
|
+
})();
|
|
@@ -1,27 +1,16 @@
|
|
|
1
|
-
const major = process.versions.node.split('.')[0];
|
|
2
|
-
|
|
3
|
-
// @vercel/nft doe not support Node.js v8
|
|
4
|
-
if (major < 10) {
|
|
5
|
-
process.exit(0);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
9
1
|
const { nodeFileTrace } = require('@vercel/nft');
|
|
10
2
|
|
|
11
3
|
const entryPoint = require.resolve('..');
|
|
12
4
|
|
|
13
5
|
// Trace the module entrypoint
|
|
14
|
-
nodeFileTrace([entryPoint]).then(result => {
|
|
15
|
-
// eslint-disable-next-line no-console
|
|
6
|
+
nodeFileTrace([entryPoint]).then((result) => {
|
|
16
7
|
console.log('@vercel/nft traced dependencies:', Array.from(result.fileList));
|
|
17
8
|
|
|
18
9
|
// If either binary is picked up, fail the test
|
|
19
10
|
if (result.fileList.has('sentry-cli') || result.fileList.has('sentry-cli.exe')) {
|
|
20
|
-
// eslint-disable-next-line no-console
|
|
21
11
|
console.error('ERROR: The sentry-cli binary should not be found by @vercel/nft');
|
|
22
12
|
process.exit(-1);
|
|
23
13
|
} else {
|
|
24
|
-
// eslint-disable-next-line no-console
|
|
25
14
|
console.log('The sentry-cli binary was not traced by @vercel/nft');
|
|
26
15
|
}
|
|
27
16
|
});
|
package/scripts/wheels
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
import base64
|
|
4
|
+
import hashlib
|
|
5
|
+
import os.path
|
|
6
|
+
import shutil
|
|
7
|
+
import tempfile
|
|
8
|
+
import zipfile
|
|
9
|
+
from typing import NamedTuple
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Wheel(NamedTuple):
|
|
13
|
+
src: str
|
|
14
|
+
plat: str
|
|
15
|
+
exe: str = 'sentry-cli'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
WHEELS = (
|
|
19
|
+
Wheel(
|
|
20
|
+
src='sentry-cli-Darwin-arm64',
|
|
21
|
+
plat='macosx_11_0_arm64',
|
|
22
|
+
),
|
|
23
|
+
Wheel(
|
|
24
|
+
src='sentry-cli-Darwin-universal',
|
|
25
|
+
plat='macosx_11_0_universal2',
|
|
26
|
+
),
|
|
27
|
+
Wheel(
|
|
28
|
+
src='sentry-cli-Darwin-x86_64',
|
|
29
|
+
plat='macosx_10_15_x86_64',
|
|
30
|
+
),
|
|
31
|
+
Wheel(
|
|
32
|
+
src='sentry-cli-Linux-aarch64',
|
|
33
|
+
plat='manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_2_aarch64',
|
|
34
|
+
),
|
|
35
|
+
Wheel(
|
|
36
|
+
src='sentry-cli-Linux-armv7',
|
|
37
|
+
plat='manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_2_armv7l',
|
|
38
|
+
),
|
|
39
|
+
Wheel(
|
|
40
|
+
src='sentry-cli-Linux-i686',
|
|
41
|
+
plat='manylinux_2_17_i686.manylinux2014_i686.musllinux_1_2_i686',
|
|
42
|
+
),
|
|
43
|
+
Wheel(
|
|
44
|
+
src='sentry-cli-Linux-x86_64',
|
|
45
|
+
plat='manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_2_x86_64',
|
|
46
|
+
),
|
|
47
|
+
Wheel(
|
|
48
|
+
src='sentry-cli-Windows-i686.exe',
|
|
49
|
+
plat='win32',
|
|
50
|
+
exe='sentry-cli.exe',
|
|
51
|
+
),
|
|
52
|
+
Wheel(
|
|
53
|
+
src='sentry-cli-Windows-x86_64.exe',
|
|
54
|
+
plat='win_amd64',
|
|
55
|
+
exe='sentry-cli.exe',
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main() -> int:
|
|
61
|
+
parser = argparse.ArgumentParser()
|
|
62
|
+
parser.add_argument('--binaries', required=True)
|
|
63
|
+
parser.add_argument('--base', required=True)
|
|
64
|
+
parser.add_argument('--dest', required=True)
|
|
65
|
+
args = parser.parse_args()
|
|
66
|
+
|
|
67
|
+
expected = {wheel.src for wheel in WHEELS}
|
|
68
|
+
received = set(os.listdir(args.binaries))
|
|
69
|
+
if expected < received:
|
|
70
|
+
raise SystemExit(
|
|
71
|
+
f'Unexpected binaries:\n\n'
|
|
72
|
+
f'- extra: {", ".join(sorted(received - expected))}\n'
|
|
73
|
+
f'- missing: {", ".join(sorted(expected - received))}'
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
sdist_path = wheel_path = None
|
|
77
|
+
for fname in os.listdir(args.base):
|
|
78
|
+
if fname.endswith('.tar.gz'):
|
|
79
|
+
sdist_path = os.path.join(args.base, fname)
|
|
80
|
+
elif fname.endswith('.whl'):
|
|
81
|
+
wheel_path = os.path.join(args.base, fname)
|
|
82
|
+
else:
|
|
83
|
+
raise SystemExit(f'unexpected file in `--base`: {fname}')
|
|
84
|
+
|
|
85
|
+
if sdist_path is None or wheel_path is None:
|
|
86
|
+
raise SystemExit('expected wheel and sdist in `--base`')
|
|
87
|
+
|
|
88
|
+
os.makedirs(args.dest, exist_ok=True)
|
|
89
|
+
shutil.copy(sdist_path, args.dest)
|
|
90
|
+
|
|
91
|
+
for wheel in WHEELS:
|
|
92
|
+
binary_src = os.path.join(args.binaries, wheel.src)
|
|
93
|
+
binary_size = os.stat(binary_src).st_size
|
|
94
|
+
with open(binary_src, 'rb') as bf:
|
|
95
|
+
digest = hashlib.sha256(bf.read()).digest()
|
|
96
|
+
digest_b64 = base64.urlsafe_b64encode(digest).rstrip(b'=').decode()
|
|
97
|
+
|
|
98
|
+
basename = os.path.basename(wheel_path)
|
|
99
|
+
wheelname, _ = os.path.splitext(basename)
|
|
100
|
+
name, version, py, abi, plat = wheelname.split('-')
|
|
101
|
+
|
|
102
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
103
|
+
with zipfile.ZipFile(wheel_path) as zipf:
|
|
104
|
+
zipf.extractall(tmp)
|
|
105
|
+
|
|
106
|
+
distinfo = os.path.join(tmp, f'{name}-{version}.dist-info')
|
|
107
|
+
scripts = os.path.join(tmp, f'{name}-{version}.data', 'scripts')
|
|
108
|
+
|
|
109
|
+
# replace the script binary with our copy
|
|
110
|
+
os.remove(os.path.join(scripts, 'sentry-cli'))
|
|
111
|
+
shutil.copy(binary_src, os.path.join(scripts, wheel.exe))
|
|
112
|
+
|
|
113
|
+
# rewrite RECORD to include the new file
|
|
114
|
+
record_fname = os.path.join(distinfo, 'RECORD')
|
|
115
|
+
with open(record_fname) as f:
|
|
116
|
+
record_lines = list(f)
|
|
117
|
+
|
|
118
|
+
record = f'{name}-{version}.data/scripts/sentry-cli,'
|
|
119
|
+
for i, line in enumerate(record_lines):
|
|
120
|
+
if line.startswith(record):
|
|
121
|
+
record_lines[i] = (
|
|
122
|
+
f'{name}-{version}.data/scripts/{wheel.exe},'
|
|
123
|
+
f'sha256={digest_b64},'
|
|
124
|
+
f'{binary_size}\n'
|
|
125
|
+
)
|
|
126
|
+
break
|
|
127
|
+
else:
|
|
128
|
+
raise SystemExit(f'could not find {record!r} in RECORD')
|
|
129
|
+
|
|
130
|
+
with open(record_fname, 'w') as f:
|
|
131
|
+
f.writelines(record_lines)
|
|
132
|
+
|
|
133
|
+
# rewrite WHEEL to have the new tags
|
|
134
|
+
wheel_fname = os.path.join(distinfo, 'WHEEL')
|
|
135
|
+
with open(wheel_fname) as f:
|
|
136
|
+
wheel_lines = list(f)
|
|
137
|
+
|
|
138
|
+
for i, line in enumerate(wheel_lines):
|
|
139
|
+
if line.startswith('Tag: '):
|
|
140
|
+
wheel_lines[i:i + 1] = [
|
|
141
|
+
f'Tag: {py}-{abi}-{plat}\n'
|
|
142
|
+
for plat in wheel.plat.split('.')
|
|
143
|
+
]
|
|
144
|
+
break
|
|
145
|
+
else:
|
|
146
|
+
raise SystemExit("could not find 'Tag: ' in WHEEL")
|
|
147
|
+
|
|
148
|
+
with open(wheel_fname, 'w') as f:
|
|
149
|
+
f.writelines(wheel_lines)
|
|
150
|
+
|
|
151
|
+
# write out the final zip
|
|
152
|
+
new_basename = f'{name}-{version}-{py}-{abi}-{wheel.plat}.whl'
|
|
153
|
+
tmp_new_wheel = os.path.join(tmp, new_basename)
|
|
154
|
+
fnames = sorted(
|
|
155
|
+
os.path.join(root, fname)
|
|
156
|
+
for root, _, fnames in os.walk(tmp)
|
|
157
|
+
for fname in fnames
|
|
158
|
+
)
|
|
159
|
+
with zipfile.ZipFile(tmp_new_wheel, 'w') as zipf:
|
|
160
|
+
for fname in fnames:
|
|
161
|
+
zinfo = zipfile.ZipInfo(os.path.relpath(fname, tmp))
|
|
162
|
+
if '/scripts/' in zinfo.filename:
|
|
163
|
+
zinfo.external_attr = 0o100755 << 16
|
|
164
|
+
with open(fname, 'rb') as fb:
|
|
165
|
+
zipf.writestr(zinfo, fb.read())
|
|
166
|
+
|
|
167
|
+
# move into dest
|
|
168
|
+
shutil.move(tmp_new_wheel, args.dest)
|
|
169
|
+
|
|
170
|
+
return 0
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
if __name__ == '__main__':
|
|
174
|
+
raise SystemExit(main())
|