tachograph 0.2.5 → 0.2.7
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/install.js +61 -20
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -16,24 +16,56 @@ const { assetFor, downloadURL, checksumsURL, checksumFor } = require("./asset");
|
|
|
16
16
|
const { version } = require("./package.json");
|
|
17
17
|
const binDir = path.join(__dirname, "bin");
|
|
18
18
|
|
|
19
|
+
// Abort hung downloads instead of letting `npm install` block forever; the
|
|
20
|
+
// timeout covers headers and body, and the catch at the bottom points users
|
|
21
|
+
// at the go-install fallback.
|
|
22
|
+
const FETCH_TIMEOUT_MS = 120_000;
|
|
23
|
+
|
|
24
|
+
// fetchBuffer downloads url fully and maps failures (HTTP errors, timeouts)
|
|
25
|
+
// to messages that name what was being fetched.
|
|
26
|
+
async function fetchBuffer(url, what) {
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(url, {
|
|
29
|
+
redirect: "follow",
|
|
30
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
throw new Error(`${what} failed: ${res.status} ${res.statusText} for ${url}`);
|
|
34
|
+
}
|
|
35
|
+
return Buffer.from(await res.arrayBuffer());
|
|
36
|
+
} catch (err) {
|
|
37
|
+
if (err.name === "TimeoutError") {
|
|
38
|
+
throw new Error(`${what} timed out after ${FETCH_TIMEOUT_MS / 1000}s for ${url}`);
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// tarBin picks the extractor. On Windows the zip asset needs bsdtar, but PATH
|
|
45
|
+
// can resolve Git for Windows' GNU tar, which cannot read zip archives
|
|
46
|
+
// ("This does not look like a tar archive"). System32's tar.exe is bsdtar on
|
|
47
|
+
// Windows 10 1803+, so prefer it explicitly; elsewhere the system tar handles
|
|
48
|
+
// our tar.gz (bsdtar on macOS, GNU tar on Linux).
|
|
49
|
+
function tarBin() {
|
|
50
|
+
if (process.platform !== "win32") return "tar";
|
|
51
|
+
const sys = path.join(
|
|
52
|
+
process.env.SystemRoot || "C:\\Windows",
|
|
53
|
+
"System32",
|
|
54
|
+
"tar.exe",
|
|
55
|
+
);
|
|
56
|
+
return fs.existsSync(sys) ? sys : "tar";
|
|
57
|
+
}
|
|
58
|
+
|
|
19
59
|
async function main() {
|
|
20
60
|
const { asset, binary } = assetFor(process.platform, process.arch);
|
|
21
|
-
const url = downloadURL(version, asset);
|
|
22
61
|
|
|
23
|
-
const
|
|
24
|
-
if (!res.ok) {
|
|
25
|
-
throw new Error(`download failed: ${res.status} ${res.statusText} for ${url}`);
|
|
26
|
-
}
|
|
27
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
62
|
+
const buf = await fetchBuffer(downloadURL(version, asset), "download");
|
|
28
63
|
|
|
29
64
|
// Verify the archive against GoReleaser's published checksums.txt before
|
|
30
65
|
// extracting and running it, so a corrupted/tampered/partial download is
|
|
31
66
|
// caught rather than executed.
|
|
32
|
-
const sums = await
|
|
33
|
-
|
|
34
|
-
throw new Error(`checksums download failed: ${sums.status} ${sums.statusText}`);
|
|
35
|
-
}
|
|
36
|
-
const want = checksumFor(await sums.text(), asset);
|
|
67
|
+
const sums = await fetchBuffer(checksumsURL(version), "checksums download");
|
|
68
|
+
const want = checksumFor(sums.toString("utf8"), asset);
|
|
37
69
|
if (!want) {
|
|
38
70
|
throw new Error(`no checksum listed for ${asset}`);
|
|
39
71
|
}
|
|
@@ -43,17 +75,26 @@ async function main() {
|
|
|
43
75
|
}
|
|
44
76
|
|
|
45
77
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "tacho-"));
|
|
46
|
-
const
|
|
47
|
-
|
|
78
|
+
const binPath = path.join(binDir, binary);
|
|
79
|
+
try {
|
|
80
|
+
fs.writeFileSync(path.join(tmp, asset), buf);
|
|
48
81
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
82
|
+
// Run inside tmp with relative names only: GNU tar (which can shadow
|
|
83
|
+
// bsdtar in PATH, e.g. Git for Windows' usr/bin) parses the colon in
|
|
84
|
+
// absolute Windows paths ("C:\...") as a remote host:path spec and fails
|
|
85
|
+
// with "Cannot connect to C:".
|
|
86
|
+
execFileSync(tarBin(), ["-xf", asset], { cwd: tmp, stdio: "inherit" });
|
|
53
87
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
88
|
+
const extracted = path.join(tmp, binary);
|
|
89
|
+
if (!fs.existsSync(extracted)) {
|
|
90
|
+
throw new Error(`extracted archive but ${binary} not found in it`);
|
|
91
|
+
}
|
|
92
|
+
// Copy just the binary; the archive also carries LICENSE/README, which
|
|
93
|
+
// don't belong in bin/.
|
|
94
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
95
|
+
fs.copyFileSync(extracted, binPath);
|
|
96
|
+
} finally {
|
|
97
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
57
98
|
}
|
|
58
99
|
if (process.platform !== "win32") {
|
|
59
100
|
fs.chmodSync(binPath, 0o755);
|
package/package.json
CHANGED