@@ -104,36 +104,63 @@ export async function findInstalledVersion(installTarget: string, descriptor: De
104104 return bestMatch ;
105105}
106106
107+ export function isSupportedPackageManagerDescriptor ( descriptor : Descriptor ) {
108+ return ! URL . canParse ( descriptor . range ) ;
109+ }
110+
111+ export function isSupportedPackageManagerLocator ( locator : Locator ) {
112+ return ! URL . canParse ( locator . reference ) ;
113+ }
114+
115+ function parseURLReference ( locator : Locator ) {
116+ const { hash, href} = new URL ( locator . reference ) ;
117+ if ( hash ) {
118+ return {
119+ version : encodeURIComponent ( href . slice ( 0 , - hash . length ) ) ,
120+ build : hash . slice ( 1 ) . split ( `.` ) ,
121+ } ;
122+ }
123+ return { version : encodeURIComponent ( href ) , build : [ ] } ;
124+ }
125+
107126export async function installVersion ( installTarget : string , locator : Locator , { spec} : { spec : PackageManagerSpec } ) {
108- const locatorReference = semver . parse ( locator . reference ) ! ;
127+ const locatorIsASupportedPackageManager = isSupportedPackageManagerLocator ( locator ) ;
128+ const locatorReference = locatorIsASupportedPackageManager ? semver . parse ( locator . reference ) ! : parseURLReference ( locator ) ;
109129 const { version, build} = locatorReference ;
110130
111131 const installFolder = path . join ( installTarget , locator . name , version ) ;
112132
113133 try {
114134 const corepackFile = path . join ( installFolder , `.corepack` ) ;
115135 const corepackContent = await fs . promises . readFile ( corepackFile , `utf8` ) ;
136+
116137 const corepackData = JSON . parse ( corepackContent ) ;
117138
118139 debugUtils . log ( `Reusing ${ locator . name } @${ locator . reference } ` ) ;
119140
120141 return {
121142 hash : corepackData . hash as string ,
122143 location : installFolder ,
144+ bin : corepackData . bin ,
123145 } ;
124146 } catch ( err ) {
125- if ( ( err as nodeUtils . NodeError ) . code !== `ENOENT` ) {
147+ if ( ( err as nodeUtils . NodeError ) ? .code !== `ENOENT` ) {
126148 throw err ;
127149 }
128150 }
129151
130- const defaultNpmRegistryURL = spec . url . replace ( `{}` , version ) ;
131- const url = process . env . COREPACK_NPM_REGISTRY ?
132- defaultNpmRegistryURL . replace (
133- npmRegistryUtils . DEFAULT_NPM_REGISTRY_URL ,
134- ( ) => process . env . COREPACK_NPM_REGISTRY ! ,
135- ) :
136- defaultNpmRegistryURL ;
152+ let url : string ;
153+ if ( locatorIsASupportedPackageManager ) {
154+ const defaultNpmRegistryURL = spec . url . replace ( `{}` , version ) ;
155+ url = process . env . COREPACK_NPM_REGISTRY ?
156+ defaultNpmRegistryURL . replace (
157+ npmRegistryUtils . DEFAULT_NPM_REGISTRY_URL ,
158+ ( ) => process . env . COREPACK_NPM_REGISTRY ! ,
159+ ) :
160+ defaultNpmRegistryURL ;
161+ } else {
162+ url = decodeURIComponent ( version ) ;
163+ }
137164
138165 // Creating a temporary folder inside the install folder means that we
139166 // are sure it'll be in the same drive as the destination, so we can
@@ -163,6 +190,15 @@ export async function installVersion(installTarget: string, locator: Locator, {s
163190 const hash = stream . pipe ( createHash ( algo ) ) ;
164191 await once ( sendTo , `finish` ) ;
165192
193+ let bin ;
194+ if ( ! locatorIsASupportedPackageManager ) {
195+ if ( ext === `.tgz` ) {
196+ bin = require ( path . join ( tmpFolder , `package.json` ) ) . bin ;
197+ } else if ( ext === `.js` ) {
198+ bin = [ locator . name ] ;
199+ }
200+ }
201+
166202 const actualHash = hash . digest ( `hex` ) ;
167203 if ( build [ 1 ] && actualHash !== build [ 1 ] )
168204 throw new Error ( `Mismatch hashes. Expected ${ build [ 1 ] } , got ${ actualHash } ` ) ;
@@ -171,6 +207,7 @@ export async function installVersion(installTarget: string, locator: Locator, {s
171207
172208 await fs . promises . writeFile ( path . join ( tmpFolder , `.corepack` ) , JSON . stringify ( {
173209 locator,
210+ bin,
174211 hash : serializedHash ,
175212 } ) ) ;
176213
@@ -190,15 +227,16 @@ export async function installVersion(installTarget: string, locator: Locator, {s
190227 }
191228 }
192229
193- if ( process . env . COREPACK_DEFAULT_TO_LATEST !== `0` ) {
230+ if ( locatorIsASupportedPackageManager && process . env . COREPACK_DEFAULT_TO_LATEST !== `0` ) {
194231 let lastKnownGoodFile : FileHandle ;
195232 try {
196233 lastKnownGoodFile = await engine . getLastKnownGoodFile ( `r+` ) ;
197234 const lastKnownGood = await engine . getJSONFileContent ( lastKnownGoodFile ) ;
198235 const defaultVersion = engine . getLastKnownGoodFromFileContent ( lastKnownGood , locator . name ) ;
199236 if ( defaultVersion ) {
200237 const currentDefault = semver . parse ( defaultVersion ) ! ;
201- if ( currentDefault . major === locatorReference . major && semver . lt ( currentDefault , locatorReference ) ) {
238+ const downloadedVersion = locatorReference as semver . SemVer ;
239+ if ( currentDefault . major === downloadedVersion . major && semver . lt ( currentDefault , downloadedVersion ) ) {
202240 await engine . activatePackageManagerFromFileHandle ( lastKnownGoodFile , lastKnownGood , locator ) ;
203241 }
204242 }
@@ -217,6 +255,7 @@ export async function installVersion(installTarget: string, locator: Locator, {s
217255
218256 return {
219257 location : installFolder ,
258+ bin,
220259 hash : serializedHash ,
221260 } ;
222261}
0 commit comments