@@ -28,35 +28,37 @@ const binPaths = []
2828const manifests = new Map ( )
2929
3030const getManifest = async ( spec , flatOptions ) => {
31- if ( ! manifests . get ( spec . raw ) ) {
31+ if ( ! manifests . has ( spec . raw ) ) {
3232 const manifest = await pacote . manifest ( spec , { ...flatOptions , preferOnline : true } )
3333 manifests . set ( spec . raw , manifest )
3434 }
3535 return manifests . get ( spec . raw )
3636}
3737
3838// Returns the required manifest if the spec is missing from the tree
39+ // Returns the found node if it is in the tree
3940const missingFromTree = async ( { spec, tree, flatOptions } ) => {
4041 if ( spec . registry && ( spec . rawSpec === '' || spec . type !== 'tag' ) ) {
4142 // registry spec that is not a specific tag.
4243 const nodesBySpec = tree . inventory . query ( 'packageName' , spec . name )
4344 for ( const node of nodesBySpec ) {
4445 if ( spec . type === 'tag' ) {
4546 // package requested by name only
46- return
47+ return { node }
4748 } else if ( spec . type === 'version' ) {
4849 // package requested by specific version
4950 if ( node . pkgid === spec . raw ) {
50- return
51+ return { node }
5152 }
5253 } else {
5354 // package requested by version range, only remaining registry type
5455 if ( semver . satisfies ( node . package . version , spec . rawSpec ) ) {
55- return
56+ return { node }
5657 }
5758 }
5859 }
59- return await getManifest ( spec , flatOptions )
60+ const manifest = await getManifest ( spec , flatOptions )
61+ return { manifest }
6062 } else {
6163 // non-registry spec, or a specific tag. Look up manifest and check
6264 // resolved to see if it's in the tree.
@@ -65,10 +67,10 @@ const missingFromTree = async ({ spec, tree, flatOptions }) => {
6567 for ( const node of nodesByManifest ) {
6668 if ( node . package . resolved === manifest . _resolved ) {
6769 // we have a package by the same name and the same resolved destination, nothing to add.
68- return
70+ return { node }
6971 }
7072 }
71- return manifest
73+ return { manifest }
7274 }
7375}
7476
@@ -132,35 +134,37 @@ const exec = async (opts) => {
132134
133135 // Find anything that isn't installed locally
134136 const needInstall = [ ]
135- await Promise . all ( packages . map ( async pkg => {
137+ let commandManifest
138+ await Promise . all ( packages . map ( async ( pkg , i ) => {
136139 const spec = npa ( pkg , path )
137- const manifest = await missingFromTree ( { spec, tree : localTree , flatOptions } )
140+ const { manifest, node } = await missingFromTree ( { spec, tree : localTree , flatOptions } )
138141 if ( manifest ) {
139142 // Package does not exist in the local tree
140143 needInstall . push ( { spec, manifest } )
144+ if ( i === 0 ) {
145+ commandManifest = manifest
146+ }
147+ } else if ( i === 0 ) {
148+ // The node.package has enough to look up the bin
149+ commandManifest = node . package
141150 }
142151 } ) )
143152
144153 if ( needPackageCommandSwap ) {
145- // Either we have a scoped package or the bin of our package we inferred
146- // from arg[0] might not be identical to the package name
147154 const spec = npa ( args [ 0 ] )
148- let commandManifest
149- if ( needInstall . length === 0 ) {
150- commandManifest = await getManifest ( spec , flatOptions )
151- } else {
152- commandManifest = needInstall [ 0 ] . manifest
153- }
154155
155156 args [ 0 ] = getBinFromManifest ( commandManifest )
156157
157- // See if the package is installed globally, and run the translated bin
158- const globalArb = new Arborist ( { ...flatOptions , path : globalPath , global : true } )
159- const globalTree = await globalArb . loadActual ( )
160- const globalManifest = await missingFromTree ( { spec, tree : globalTree , flatOptions } )
161- if ( ! globalManifest ) {
162- binPaths . push ( globalBin )
163- return await run ( )
158+ if ( needInstall . length > 0 ) {
159+ // See if the package is installed globally, and run the translated bin
160+ const globalArb = new Arborist ( { ...flatOptions , path : globalPath , global : true } )
161+ const globalTree = await globalArb . loadActual ( )
162+ const { manifest : globalManifest } =
163+ await missingFromTree ( { spec, tree : globalTree , flatOptions } )
164+ if ( ! globalManifest ) {
165+ binPaths . push ( globalBin )
166+ return await run ( )
167+ }
164168 }
165169 }
166170
@@ -183,7 +187,7 @@ const exec = async (opts) => {
183187 } )
184188 const npxTree = await npxArb . loadActual ( )
185189 await Promise . all ( needInstall . map ( async ( { spec } ) => {
186- const manifest = await missingFromTree ( { spec, tree : npxTree , flatOptions } )
190+ const { manifest } = await missingFromTree ( { spec, tree : npxTree , flatOptions } )
187191 if ( manifest ) {
188192 // Manifest is not in npxCache, we need to install it there
189193 if ( ! spec . registry ) {
0 commit comments