/
create-symlink.js
66 lines (50 loc) · 1.73 KB
/
create-symlink.js
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
"use strict";
const cmdShim = require("@zkochan/cmd-shim");
const fs = require("fs-extra");
const log = require("npmlog");
const path = require("path");
module.exports = createSymlink;
function createSymlink(src, dest, type) {
log.silly("createSymlink", [src, dest, type]);
if (process.platform === "win32") {
return createWindowsSymlink(src, dest, type);
}
return createPosixSymlink(src, dest, type);
}
function createSymbolicLink(src, dest, type) {
log.silly("createSymbolicLink", [src, dest, type]);
return fs
.lstat(dest)
.then(() => fs.unlink(dest))
.catch(() => {
/* nothing exists at destination */
})
.then(() => fs.symlink(src, dest, type));
}
function createPosixSymlink(src, dest, _type) {
const type = _type === "exec" ? "file" : _type;
const relativeSymlink = path.relative(path.dirname(dest), src);
if (_type === "exec") {
// If the src exists, create a real symlink.
// If the src doesn't exist yet, create a shim shell script.
return fs.pathExists(src).then(exists => {
if (exists) {
return createSymbolicLink(relativeSymlink, dest, type).then(() => fs.chmod(src, 0o755));
}
return shShim(src, dest, type).then(() => fs.chmod(dest, 0o755));
});
}
return createSymbolicLink(relativeSymlink, dest, type);
}
function createWindowsSymlink(src, dest, type) {
if (type === "exec") {
return cmdShim(src, dest);
}
return createSymbolicLink(src, dest, type);
}
function shShim(src, dest, type) {
log.silly("shShim", [src, dest, type]);
const absTarget = path.resolve(path.dirname(dest), src);
const scriptLines = ["#!/bin/sh", `chmod +x ${absTarget} && exec ${absTarget} "$@"`];
return fs.writeFile(dest, scriptLines.join("\n"));
}