|
2 | 2 |
|
3 | 3 | 'use strict' |
4 | 4 |
|
5 | | -const fs = require('fs') |
| 5 | +const fs = require('fs/promises') |
6 | 6 | const path = require('path') |
7 | | -const semver = require('semver') |
8 | | -const map = require('map-async') |
9 | | - |
10 | | -const ltsNames = { |
11 | | - 4: 'argon', |
12 | | - 6: 'boron', |
13 | | - 8: 'carbon', |
14 | | - 10: 'dubnium', |
15 | | - 12: 'erbium', |
16 | | - 14: 'fermium', |
17 | | - 16: 'gallium', |
18 | | - 18: 'hydrogen' |
19 | | -} |
| 7 | +const { Linker } = require('./common.js') |
20 | 8 |
|
| 9 | +/* c8 ignore next 3 */ |
21 | 10 | if (process.argv.length < 3) { |
22 | 11 | throw new Error('Usage: latest-linker.js <downloads directory> [docs directory]') |
23 | 12 | } |
24 | 13 |
|
25 | 14 | const dir = path.resolve(process.argv[2]) |
26 | | -const docsDir = process.argv[3] && path.resolve(process.argv[3]) |
27 | | - |
28 | | -if (!fs.statSync(dir).isDirectory()) { |
29 | | - throw new Error('Usage: latest-linker.js <downloads directory> [docs directory]') |
30 | | -} |
| 15 | +const docsDir = process.argv[3] && path.resolve(process.argv[3]); |
31 | 16 |
|
32 | | -if (docsDir && !fs.statSync(docsDir).isDirectory()) { |
33 | | - throw new Error('Usage: latest-linker.js <downloads directory> [docs directory]') |
34 | | -} |
35 | | - |
36 | | -map( |
37 | | - fs.readdirSync(dir).map((d) => path.join(dir, d)), |
38 | | - (d, callback) => fs.stat(d, (_, stat) => callback(null, { d, stat })), |
39 | | - afterMap |
40 | | -) |
41 | | - |
42 | | -function afterMap (err, allDirs) { |
43 | | - if (err) { |
44 | | - throw err |
| 17 | +(async function main () { |
| 18 | + /* c8 ignore next 3 */ |
| 19 | + if (!(await fs.stat(dir)).isDirectory()) { |
| 20 | + throw new Error('Usage: latest-linker.js <downloads directory> [docs directory]') |
45 | 21 | } |
46 | 22 |
|
47 | | - allDirs = allDirs.filter((d) => d.stat && d.stat.isDirectory()) |
48 | | - .map((d) => path.basename(d.d)) |
49 | | - .map((d) => { |
50 | | - try { |
51 | | - return semver.parse(d) |
52 | | - } catch (e) {} |
53 | | - }) |
54 | | - .filter(Boolean) |
55 | | - |
56 | | - makeDocsLinks(allDirs.map((v) => v.raw)) |
57 | | - |
58 | | - const dirs = allDirs.filter((d) => semver.satisfies(d, '~0.10 || ~0.12 || >= 1.0')) |
59 | | - .map((d) => d.raw) |
60 | | - |
61 | | - dirs.sort((d1, d2) => semver.compare(d1, d2)) |
62 | | - |
63 | | - link('0.10', dirs) |
64 | | - link(0.12, dirs) |
65 | | - |
66 | | - for (let i = 1; ; i++) { |
67 | | - if (!link(i, dirs) && i >= 4) { |
68 | | - break |
69 | | - } |
| 23 | + /* c8 ignore next 3 */ |
| 24 | + if (docsDir && !(await fs.stat(docsDir)).isDirectory()) { |
| 25 | + throw new Error('Usage: latest-linker.js <downloads directory> [docs directory]') |
70 | 26 | } |
71 | 27 |
|
72 | | - const max = link(null, dirs) |
73 | | - const tbreg = new RegExp(`(\\w+)-${max}.tar.gz`) |
74 | | - |
75 | | - let tarball = fs.readdirSync(path.join(dir, 'latest')) |
76 | | - .filter((f) => tbreg.test(f)) |
77 | | - |
78 | | - if (tarball.length !== 1) { |
79 | | - throw new Error('Could not find latest.tar.gz') |
| 28 | + const allDirs = (await fs.readdir(dir, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name) |
| 29 | + const linker = new Linker({ baseDir: dir, docsDir }) |
| 30 | + const links = await linker.getLinks(allDirs, fs.readdir) |
| 31 | + for (const [dest, src] of links) { |
| 32 | + await fs.unlink(dest).catch(() => {}) |
| 33 | + await fs.symlink(src, dest) |
80 | 34 | } |
81 | | - |
82 | | - tarball = tarball[0] |
83 | | - const name = tarball.match(tbreg)[1] |
84 | | - const dst = path.join(dir, `${name}-latest.tar.gz`) |
85 | | - try { |
86 | | - fs.unlinkSync(dst) |
87 | | - } catch (e) {} |
88 | | - fs.symlinkSync(path.join(dir, 'latest', tarball), dst) |
89 | | -} |
90 | | - |
91 | | -function makeDocsLinks (versions) { |
92 | | - if (!docsDir) { |
93 | | - return |
94 | | - } |
95 | | - |
96 | | - versions.forEach((version) => { |
97 | | - const src = path.join(dir, version, 'docs') |
98 | | - const dst = path.join(docsDir, version) |
99 | | - |
100 | | - fs.stat(src, (err, stat) => { |
101 | | - if (err || !stat.isDirectory()) { |
102 | | - return |
103 | | - } |
104 | | - |
105 | | - fs.unlink(dst, () => { |
106 | | - fs.symlink(src, dst, (err) => { |
107 | | - if (err) { |
108 | | - throw err |
109 | | - } |
110 | | - }) |
111 | | - }) |
112 | | - }) |
113 | | - }) |
114 | | -} |
115 | | - |
116 | | -function link (version, dirs) { |
117 | | - const line = version && `${version}.x` |
118 | | - const range = version ? `${Number(version) < 1 ? '~' : '^'}${line}` : '*' |
119 | | - const max = semver.maxSatisfying(dirs, range) |
120 | | - |
121 | | - if (!max) { |
122 | | - return false |
123 | | - } |
124 | | - |
125 | | - function symlink (name) { |
126 | | - const dst = path.join(dir, name) |
127 | | - const src = path.join(dir, max) |
128 | | - |
129 | | - try { |
130 | | - fs.unlinkSync(dst) |
131 | | - } catch (e) {} |
132 | | - fs.symlinkSync(src, dst) |
133 | | - |
134 | | - if (!docsDir) { |
135 | | - return |
136 | | - } |
137 | | - |
138 | | - const dsrc = path.join(dir, max, 'docs') |
139 | | - const ddst = path.join(docsDir, name) |
140 | | - |
141 | | - try { |
142 | | - fs.unlinkSync(ddst) |
143 | | - } catch (e) {} |
144 | | - fs.symlinkSync(dsrc, ddst) |
145 | | - } |
146 | | - |
147 | | - if (line) { |
148 | | - symlink(`latest-v${line}`) |
149 | | - if (ltsNames[version]) { |
150 | | - symlink(`latest-${ltsNames[version]}`) |
151 | | - } |
152 | | - } else { |
153 | | - symlink('latest') |
154 | | - } |
155 | | - |
156 | | - return max |
157 | | -} |
| 35 | +})() |
0 commit comments