/
index.ts
87 lines (83 loc) · 2.66 KB
/
index.ts
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
import path from 'path'
import { promises as fs } from 'fs'
import { globalWarn } from '@pnpm/logger'
export async function hardLinkDir (src: string, destDirs: string[]) {
if (destDirs.length === 0) return
// Don't try to hard link the source directory to itself
destDirs = destDirs.filter((destDir) => path.relative(destDir, src) !== '')
await _hardLinkDir(src, destDirs, true)
}
async function _hardLinkDir (src: string, destDirs: string[], isRoot?: boolean) {
let files: string[] = []
try {
files = await fs.readdir(src)
} catch (err: any) { // eslint-disable-line
if (!isRoot || err.code !== 'ENOENT') throw err
globalWarn(`Source directory not found when creating hardLinks for: ${src}. Creating destinations as empty: ${destDirs.join(', ')}`)
await Promise.all(
destDirs.map((dir) => fs.mkdir(dir, { recursive: true }))
)
return
}
await Promise.all(
files.map(async (file) => {
if (file === 'node_modules') return
const srcFile = path.join(src, file)
if ((await fs.lstat(srcFile)).isDirectory()) {
const destSubdirs = await Promise.all(
destDirs.map(async (destDir) => {
const destSubdir = path.join(destDir, file)
try {
await fs.mkdir(destSubdir, { recursive: true })
} catch (err: any) { // eslint-disable-line
if (err.code !== 'EEXIST') throw err
}
return destSubdir
})
)
await _hardLinkDir(srcFile, destSubdirs)
return
}
await Promise.all(
destDirs.map(async (destDir) => {
const destFile = path.join(destDir, file)
try {
await linkOrCopyFile(srcFile, destFile)
} catch (err: any) { // eslint-disable-line
if (err.code === 'ENOENT') {
// Ignore broken symlinks
return
}
throw err
}
})
)
})
)
}
async function linkOrCopyFile (srcFile: string, destFile: string) {
try {
await linkOrCopy(srcFile, destFile)
} catch (err: any) { // eslint-disable-line
if (err.code === 'ENOENT') {
await fs.mkdir(path.dirname(destFile), { recursive: true })
await linkOrCopy(srcFile, destFile)
return
}
if (err.code !== 'EEXIST') {
throw err
}
}
}
/*
* This function could be optimized because we don't really need to try linking again
* if linking failed once.
*/
async function linkOrCopy (srcFile: string, destFile: string) {
try {
await fs.link(srcFile, destFile)
} catch (err: any) { // eslint-disable-line
if (err.code !== 'EXDEV') throw err
await fs.copyFile(srcFile, destFile)
}
}