@@ -14,8 +14,11 @@ import {run as runRemove} from './remove.js';
14
14
import { run as runUpgrade } from './upgrade.js' ;
15
15
import { run as runUpgradeInteractive } from './upgrade-interactive.js' ;
16
16
import { linkBin } from '../../package-linker.js' ;
17
+ import { POSIX_GLOBAL_PREFIX , FALLBACK_GLOBAL_PREFIX } from '../../constants.js' ;
17
18
import * as fs from '../../util/fs.js' ;
18
19
20
+ const nativeFs = require ( 'fs' ) ;
21
+
19
22
class GlobalAdd extends Add {
20
23
maybeOutputSaveTree ( ) : Promise < void > {
21
24
for ( const pattern of this . addedPatterns ) {
@@ -69,44 +72,44 @@ async function getBins(config: Config): Promise<Set<string>> {
69
72
return paths ;
70
73
}
71
74
72
- function getGlobalPrefix ( config : Config , flags : Object ) : string {
75
+ async function getGlobalPrefix ( config : Config , flags : Object ) : Promise < string > {
73
76
if ( flags . prefix ) {
74
77
return flags . prefix ;
75
78
} else if ( config . getOption ( 'prefix' ) ) {
76
79
return String ( config . getOption ( 'prefix' ) ) ;
77
80
} else if ( process . env . PREFIX ) {
78
81
return process . env . PREFIX ;
79
- } else if ( process . platform === 'win32' ) {
82
+ }
83
+
84
+ let prefix = FALLBACK_GLOBAL_PREFIX ;
85
+ if ( process . platform === 'win32' ) {
86
+ // %LOCALAPPDATA%\Yarn --> C:\Users\Alice\AppData\Local\Yarn
80
87
if ( process . env . LOCALAPPDATA ) {
81
- return path . join ( process . env . LOCALAPPDATA , 'Yarn' , 'bin ') ;
88
+ prefix = path . join ( process . env . LOCALAPPDATA , 'Yarn' ) ;
82
89
}
83
- // c:\node\node.exe --> prefix=c:\node\
84
- return path . dirname ( process . execPath ) ;
85
90
} else {
86
- // /usr/local/bin/node --> prefix=/usr/local
87
- let prefix = path . dirname ( path . dirname ( process . execPath ) ) ;
88
-
89
- // destdir only is respected on Unix
90
- if ( process . env . DESTDIR ) {
91
- prefix = path . join ( process . env . DESTDIR , prefix ) ;
91
+ prefix = POSIX_GLOBAL_PREFIX ;
92
+ }
93
+ try {
94
+ await fs . access ( path . join ( prefix , 'bin' ) , ( nativeFs . constants || nativeFs ) . W_OK ) ;
95
+ } catch ( err ) {
96
+ if ( err . code === 'EACCES' ) {
97
+ prefix = FALLBACK_GLOBAL_PREFIX ;
98
+ } else {
99
+ throw err ;
92
100
}
93
-
94
- return prefix ;
95
101
}
102
+ return prefix ;
96
103
}
97
104
98
- export function getBinFolder ( config : Config , flags : Object ) : string {
99
- const prefix = getGlobalPrefix ( config , flags ) ;
100
- if ( process . platform === 'win32' ) {
101
- return prefix ;
102
- } else {
103
- return path . resolve ( prefix , 'bin' ) ;
104
- }
105
+ export async function getBinFolder ( config : Config , flags : Object ) : Promise < string > {
106
+ const prefix = await getGlobalPrefix ( config , flags ) ;
107
+ return path . resolve ( prefix , 'bin' ) ;
105
108
}
106
109
107
110
async function initUpdateBins ( config : Config , reporter : Reporter , flags : Object ) : Promise < ( ) => Promise < void >> {
108
111
const beforeBins = await getBins ( config ) ;
109
- const binFolder = getBinFolder ( config , flags ) ;
112
+ const binFolder = await getBinFolder ( config , flags ) ;
110
113
111
114
function throwPermError ( err : Error & { [ code : string ] : string } , dest : string ) {
112
115
if ( err . code === 'EACCES' ) {
@@ -205,8 +208,8 @@ const {run, setFlags: _setFlags} = buildSubCommands('global', {
205
208
await updateBins ( ) ;
206
209
} ,
207
210
208
- bin ( config : Config , reporter : Reporter , flags : Object , args : Array < string > ) {
209
- reporter. log ( getBinFolder ( config , flags ) ) ;
211
+ async bin ( config : Config , reporter : Reporter , flags : Object , args : Array < string > ) : Promise < void > {
212
+ reporter. log ( await getBinFolder ( config , flags ) ) ;
210
213
} ,
211
214
212
215
async ls ( config : Config , reporter : Reporter , flags : Object , args : Array < string > ) : Promise < void > {
0 commit comments