@@ -121,7 +121,7 @@ function parsePackageJSON(packageJSONContent: CorepackPackageJSON) {
121121}
122122
123123export async function setLocalPackageManager ( cwd : string , info : PreparedPackageManagerInfo ) {
124- const lookup = await loadSpec ( cwd ) ;
124+ const lookup = await loadSpecAndEnv ( cwd ) ;
125125
126126 const range = `range` in lookup && lookup . range ;
127127 if ( range ) {
@@ -155,20 +155,42 @@ interface FoundSpecResult {
155155 envFilePath ?: string ;
156156}
157157export type LoadSpecResult =
158- | { type : `NoProject`, target : string }
159- | { type : `NoSpec`, target : string }
158+ | { type : `NoProject`, target : string , envFilePath ?: string }
159+ | { type : `NoSpec`, target : string , envFilePath ?: string }
160160 | FoundSpecResult ;
161161
162- export async function loadSpec ( initialCwd : string ) : Promise < LoadSpecResult > {
162+ async function loadEnvFileIfExists ( cwd : string ) : Promise < { env : LocalEnvFile , path : string } | void > {
163+ const envFilePath = path . resolve ( cwd , process . env . COREPACK_ENV_FILE ?? `.corepack.env` ) ;
164+ if ( process . env . COREPACK_ENV_FILE == `0` ) {
165+ debugUtils . log ( `Skipping env file as configured with COREPACK_ENV_FILE` ) ;
166+ return void 0 ;
167+ }
168+ debugUtils . log ( `Checking ${ envFilePath } ` ) ;
169+ try {
170+ const localEnv = {
171+ ...Object . fromEntries ( Object . entries ( parseEnv ( await fs . promises . readFile ( envFilePath , `utf8` ) ) ) . filter ( e => e [ 0 ] . startsWith ( `COREPACK_` ) ) ) ,
172+ ...process . env ,
173+ } ;
174+ debugUtils . log ( `Successfully loaded env file found at ${ envFilePath } ` ) ;
175+ return { env : localEnv , path : envFilePath } ;
176+ } catch ( err ) {
177+ if ( ( err as NodeError ) ?. code !== `ENOENT` )
178+ throw err ;
179+
180+ debugUtils . log ( `No env file found at ${ envFilePath } ` ) ;
181+ }
182+ return void 0 ;
183+ }
184+
185+ export async function loadSpecAndEnv ( initialCwd : string , { envOnly} = { envOnly : false } ) : Promise < LoadSpecResult > {
163186 let nextCwd = initialCwd ;
164187 let currCwd = `` ;
165188
166189 let selection : {
167190 data : any ;
168191 manifestPath : string ;
169- envFilePath ?: string ;
170- localEnv : LocalEnvFile ;
171192 } | null = null ;
193+ let localEnv : { env : LocalEnvFile , path : string } | void = void 0 ;
172194
173195 while ( nextCwd !== currCwd && ( ! selection || ! selection . data . packageManager ) ) {
174196 currCwd = nextCwd ;
@@ -177,6 +199,14 @@ export async function loadSpec(initialCwd: string): Promise<LoadSpecResult> {
177199 if ( nodeModulesRegExp . test ( currCwd ) )
178200 continue ;
179201
202+ if ( process . env . COREPACK_ENV_FILE !== `0` && ! localEnv )
203+ localEnv = await loadEnvFileIfExists ( currCwd ) ;
204+
205+ if ( envOnly ) {
206+ if ( localEnv ) break ;
207+ continue ;
208+ }
209+
180210 const manifestPath = path . join ( currCwd , `package.json` ) ;
181211 debugUtils . log ( `Checking ${ manifestPath } ` ) ;
182212 let content : string ;
@@ -193,56 +223,27 @@ export async function loadSpec(initialCwd: string): Promise<LoadSpecResult> {
193223 } catch { }
194224
195225 if ( typeof data !== `object` || data === null )
196- throw new UsageError ( `Invalid package.json in ${ path . relative ( initialCwd , manifestPath ) } ` ) ;
197-
198- let localEnv : LocalEnvFile ;
199- const envFilePath = path . resolve ( currCwd , process . env . COREPACK_ENV_FILE ?? `.corepack.env` ) ;
200- if ( process . env . COREPACK_ENV_FILE == `0` ) {
201- debugUtils . log ( `Skipping env file as configured with COREPACK_ENV_FILE` ) ;
202- localEnv = process . env ;
203- } else if ( typeof parseEnv !== `function` ) {
204- // TODO: remove this block when support for Node.js 18.x is dropped.
205- debugUtils . log ( `Skipping env file as it is not supported by the current version of Node.js` ) ;
206- localEnv = process . env ;
207- } else {
208- debugUtils . log ( `Checking ${ envFilePath } ` ) ;
209- try {
210- localEnv = {
211- ...Object . fromEntries ( Object . entries ( parseEnv ( await fs . promises . readFile ( envFilePath , `utf8` ) ) ) . filter ( e => e [ 0 ] . startsWith ( `COREPACK_` ) ) ) ,
212- ...process . env ,
213- } ;
214- debugUtils . log ( `Successfully loaded env file found at ${ envFilePath } ` ) ;
215- } catch ( err ) {
216- if ( ( err as NodeError ) ?. code !== `ENOENT` )
217- throw err ;
218-
219- debugUtils . log ( `No env file found at ${ envFilePath } ` ) ;
220- localEnv = process . env ;
221- }
222- }
226+ throw new UsageError ( `Invalid package.json in ${ path . relative ( currCwd , manifestPath ) } ` ) ;
223227
224- selection = { data, manifestPath, localEnv , envFilePath } ;
228+ selection = { data, manifestPath} ;
225229 }
226230
227- if ( selection === null )
228- return { type : `NoProject` , target : path . join ( initialCwd , `package.json` ) } ;
231+ if ( localEnv )
232+ process . env = localEnv . env ;
229233
230- let envFilePath : string | undefined ;
231- if ( selection . localEnv !== process . env ) {
232- envFilePath = selection . envFilePath ;
233- process . env = selection . localEnv ;
234- }
234+ if ( selection === null )
235+ return { type : `NoProject` , target : path . join ( initialCwd , `package.json` ) , envFilePath : localEnv ?. path } ;
235236
236237 const rawPmSpec = parsePackageJSON ( selection . data ) ;
237238 if ( typeof rawPmSpec === `undefined` )
238- return { type : `NoSpec` , target : selection . manifestPath } ;
239+ return { type : `NoSpec` , target : selection . manifestPath , envFilePath : localEnv ?. path } ;
239240
240241 debugUtils . log ( `${ selection . manifestPath } defines ${ rawPmSpec } as local package manager` ) ;
241242
242243 return {
243244 type : `Found` ,
244245 target : selection . manifestPath ,
245- envFilePath,
246+ envFilePath : localEnv ?. path ,
246247 range : selection . data . devEngines ?. packageManager ?. version && {
247248 name : selection . data . devEngines . packageManager . name ,
248249 range : selection . data . devEngines . packageManager . version ,
0 commit comments