Skip to content

Commit db9be90

Browse files
committed
fix executable linking on windows for real
1 parent 957e08d commit db9be90

File tree

9 files changed

+138
-110
lines changed

9 files changed

+138
-110
lines changed

packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
jest.setTimeout(30000)
22

3-
const fs = require('fs')
43
const path = require('path')
4+
const { linkBin } = require('@vue/cli-shared-utils')
55
const create = require('@vue/cli-test-utils/createTestProject')
66

77
const runSilently = fn => {
@@ -37,10 +37,9 @@ test('should work', async () => {
3737
require('yorkie/src/install')(path.join(project.dir, 'node_modules'))
3838
// since yorkie isn't actually installed in the test project, we need to
3939
// symlink it
40-
fs.symlinkSync(
40+
linkBin(
4141
path.resolve(require.resolve('yorkie/src/install'), '../../'),
42-
path.join(project.dir, 'node_modules', 'yorkie'),
43-
'junction' // needed for windows
42+
path.join(project.dir, 'node_modules', 'yorkie')
4443
)
4544
})
4645
const hook = await read('.git/hooks/pre-commit')

packages/@vue/cli-shared-utils/env.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const { execSync } = require('child_process')
2+
3+
// env detection
4+
exports.hasYarn = (() => {
5+
if (process.env.VUE_CLI_TEST) {
6+
return true
7+
}
8+
try {
9+
execSync('yarnpkg --version', { stdio: 'ignore' })
10+
return true
11+
} catch (e) {
12+
return false
13+
}
14+
})()
15+
16+
exports.hasGit = () => {
17+
if (process.env.VUE_CLI_TEST) {
18+
return true
19+
}
20+
try {
21+
execSync('git --version', { stdio: 'ignore' })
22+
return true
23+
} catch (e) {
24+
return false
25+
}
26+
}
+4-99
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,4 @@
1-
const joi = require('joi')
2-
const chalk = require('chalk')
3-
const spinner = require('./spinner')
4-
const readline = require('readline')
5-
const { execSync } = require('child_process')
6-
const padStart = require('string.prototype.padstart')
7-
8-
const format = (label, msg) => {
9-
return msg.split('\n').map((line, i) => {
10-
return i === 0
11-
? `${label} ${line}`
12-
: padStart(line, chalk.reset(label).length)
13-
}).join('\n')
14-
}
15-
16-
Object.assign(exports, spinner)
17-
18-
exports.log = msg => console.log(msg || '')
19-
20-
exports.info = msg => {
21-
console.log(format(chalk.bgBlue.black(' INFO '), msg))
22-
}
23-
24-
exports.done = msg => {
25-
console.log(format(chalk.bgGreen.black(' DONE '), msg))
26-
}
27-
28-
exports.warn = msg => {
29-
console.warn(format(chalk.bgYellow.black(' WARN '), chalk.yellow(msg)))
30-
}
31-
32-
exports.error = msg => {
33-
console.error(format(chalk.bgRed(' ERROR '), chalk.red(msg)))
34-
if (msg instanceof Error) {
35-
console.error(msg.stack)
36-
}
37-
}
38-
39-
exports.clearConsole = title => {
40-
if (process.stdout.isTTY) {
41-
const blank = '\n'.repeat(process.stdout.rows)
42-
console.log(blank)
43-
readline.cursorTo(process.stdout, 0, 0)
44-
readline.clearScreenDown(process.stdout)
45-
if (title) {
46-
console.log(title)
47-
}
48-
}
49-
}
50-
51-
// silent all logs except errors during tests and keep record
52-
if (process.env.VUE_CLI_TEST) {
53-
const logs = {}
54-
Object.keys(exports).forEach(key => {
55-
if (key !== 'error') {
56-
exports[key] = (...args) => {
57-
if (!logs[key]) logs[key] = []
58-
logs[key].push(args)
59-
}
60-
}
61-
})
62-
exports.logs = logs
63-
}
64-
65-
// proxy to joi for option validation
66-
exports.createSchema = fn => fn(joi)
67-
68-
exports.validate = (obj, schema, options = {}) => {
69-
joi.validate(obj, schema, options, err => {
70-
if (err) {
71-
throw err
72-
}
73-
})
74-
}
75-
76-
// env detection
77-
exports.hasYarn = (() => {
78-
if (process.env.VUE_CLI_TEST) {
79-
return true
80-
}
81-
try {
82-
execSync('yarnpkg --version', { stdio: 'ignore' })
83-
return true
84-
} catch (e) {
85-
return false
86-
}
87-
})()
88-
89-
exports.hasGit = () => {
90-
if (process.env.VUE_CLI_TEST) {
91-
return true
92-
}
93-
try {
94-
execSync('git --version', { stdio: 'ignore' })
95-
return true
96-
} catch (e) {
97-
return false
98-
}
99-
}
1+
Object.assign(exports, require('./env'))
2+
Object.assign(exports, require('./logger'))
3+
Object.assign(exports, require('./validate'))
4+
Object.assign(exports, require('./linkBin'))
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* eslint-disable vue-libs/no-async-functions */
2+
3+
// cross-platform executable link, mostly for Windows
4+
5+
const fs = require('fs')
6+
const path = require('path')
7+
const { promisify } = require('util')
8+
9+
const chmod = promisify(fs.chmod)
10+
const symlink = promisify(fs.symlink)
11+
const mkdirp = promisify(require('mkdirp'))
12+
const cmdShim = promisify(require('cmd-shim'))
13+
14+
exports.linkBin = async (src, dest) => {
15+
if (!process.env.VUE_CLI_TEST && !process.env.VUE_CLI_DEBUG) {
16+
throw new Error(`linkBin should only be used during tests or debugging.`)
17+
}
18+
if (process.platform === 'win32') {
19+
// not doing mutex lock because this is only used in dev and the
20+
// src will not be modified
21+
await cmdShim(src, dest)
22+
} else {
23+
await mkdirp(path.dirname(dest))
24+
await symlink(src, dest)
25+
await chmod(dest, '755')
26+
}
27+
}
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const chalk = require('chalk')
2+
const spinner = require('./spinner')
3+
const readline = require('readline')
4+
const padStart = require('string.prototype.padstart')
5+
6+
Object.assign(exports, spinner)
7+
8+
const format = (label, msg) => {
9+
return msg.split('\n').map((line, i) => {
10+
return i === 0
11+
? `${label} ${line}`
12+
: padStart(line, chalk.reset(label).length)
13+
}).join('\n')
14+
}
15+
16+
exports.log = msg => console.log(msg || '')
17+
18+
exports.info = msg => {
19+
console.log(format(chalk.bgBlue.black(' INFO '), msg))
20+
}
21+
22+
exports.done = msg => {
23+
console.log(format(chalk.bgGreen.black(' DONE '), msg))
24+
}
25+
26+
exports.warn = msg => {
27+
console.warn(format(chalk.bgYellow.black(' WARN '), chalk.yellow(msg)))
28+
}
29+
30+
exports.error = msg => {
31+
console.error(format(chalk.bgRed(' ERROR '), chalk.red(msg)))
32+
if (msg instanceof Error) {
33+
console.error(msg.stack)
34+
}
35+
}
36+
37+
exports.clearConsole = title => {
38+
if (process.stdout.isTTY) {
39+
const blank = '\n'.repeat(process.stdout.rows)
40+
console.log(blank)
41+
readline.cursorTo(process.stdout, 0, 0)
42+
readline.clearScreenDown(process.stdout)
43+
if (title) {
44+
console.log(title)
45+
}
46+
}
47+
}
48+
49+
// silent all logs except errors during tests and keep record
50+
if (process.env.VUE_CLI_TEST) {
51+
const logs = {}
52+
Object.keys(exports).forEach(key => {
53+
if (key !== 'error') {
54+
exports[key] = (...args) => {
55+
if (!logs[key]) logs[key] = []
56+
logs[key].push(args)
57+
}
58+
}
59+
})
60+
exports.logs = logs
61+
}

packages/@vue/cli-shared-utils/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"homepage": "https://github.com/vuejs/vue-cli/packages/@vue/cli-shared-utils#readme",
2121
"dependencies": {
2222
"chalk": "^2.3.0",
23+
"cmd-shim": "^2.0.2",
2324
"joi": "^13.1.0",
2425
"ora": "^1.3.0",
2526
"readline": "^1.3.0",
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const joi = require('joi')
2+
3+
// proxy to joi for option validation
4+
exports.createSchema = fn => fn(joi)
5+
6+
exports.validate = (obj, schema, options = {}) => {
7+
joi.validate(obj, schema, options, err => {
8+
if (err) {
9+
throw err
10+
}
11+
})
12+
}

packages/@vue/cli/lib/Creator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ module.exports = class Creator {
104104
const deps = Object.keys(options.plugins)
105105
if (isTestOrDebug) {
106106
// in development, avoid installation process
107-
setupDevProject(context, deps)
107+
await setupDevProject(context, deps)
108108
} else {
109109
await installDeps(context, packageManager, deps, cliOptions.registry)
110110
}

packages/@vue/cli/lib/util/setupDevProject.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const fs = require('fs')
44
const path = require('path')
5-
const mkdirp = require('mkdirp')
5+
const { linkBin } = require('@vue/cli-shared-utils')
66

77
module.exports = function setupDevProject (targetDir, deps) {
88
const pkg = require(path.resolve(targetDir, 'package.json'))
@@ -19,11 +19,8 @@ module.exports = function setupDevProject (targetDir, deps) {
1919
path.resolve(targetDir, 'package.json'),
2020
JSON.stringify(pkg, null, 2)
2121
)
22-
const binPath = path.join(targetDir, 'node_modules', '.bin')
23-
mkdirp.sync(binPath)
24-
fs.symlinkSync(
22+
return linkBin(
2523
require.resolve('@vue/cli-service/bin/vue-cli-service'),
26-
path.join(binPath, 'vue-cli-service'),
27-
'junction' // needed for windows
24+
path.join(targetDir, 'node_modules', '.bin', 'vue-cli-service')
2825
)
2926
}

0 commit comments

Comments
 (0)