@@ -35,7 +35,7 @@ pub struct Package {
3535
3636impl Package {
3737 pub fn new ( name : String , version : VersionSpec ) -> Fallible < Self > {
38- let staging = setup_staging_directory ( PackageManager :: Npm ) ?;
38+ let staging = setup_staging_directory ( PackageManager :: Npm , NeedsScope :: No ) ?;
3939
4040 Ok ( Package {
4141 name,
@@ -123,16 +123,34 @@ impl Display for Package {
123123///
124124/// Provides methods to simplify installing into a staging directory and then moving that install
125125/// into the proper location after it is complete.
126+ ///
127+ /// Note: We don't always know the name of the package up-front, as the install could be from a
128+ /// tarball or a git coordinate. If we do know ahead of time, then we can skip looking it up
126129pub struct DirectInstall {
127130 staging : TempDir ,
128131 manager : PackageManager ,
132+ name : Option < String > ,
129133}
130134
131135impl DirectInstall {
132136 pub fn new ( manager : PackageManager ) -> Fallible < Self > {
133- let staging = setup_staging_directory ( manager) ?;
137+ let staging = setup_staging_directory ( manager, NeedsScope :: No ) ?;
138+
139+ Ok ( DirectInstall {
140+ staging,
141+ manager,
142+ name : None ,
143+ } )
144+ }
134145
135- Ok ( DirectInstall { staging, manager } )
146+ pub fn with_name ( manager : PackageManager , name : String ) -> Fallible < Self > {
147+ let staging = setup_staging_directory ( manager, name. contains ( '/' ) . into ( ) ) ?;
148+
149+ Ok ( DirectInstall {
150+ staging,
151+ manager,
152+ name : Some ( name) ,
153+ } )
136154 }
137155
138156 pub fn setup_command ( & self , command : & mut Command ) {
@@ -141,16 +159,20 @@ impl DirectInstall {
141159 }
142160
143161 pub fn complete_install ( self , image : & Image ) -> Fallible < ( ) > {
144- let name = self
145- . manager
146- . get_installed_package ( self . staging . path ( ) . to_owned ( ) )
162+ let DirectInstall {
163+ staging,
164+ name,
165+ manager,
166+ } = self ;
167+
168+ let name = name
169+ . or_else ( || manager. get_installed_package ( staging. path ( ) . to_owned ( ) ) )
147170 . ok_or ( ErrorKind :: InstalledPackageNameError ) ?;
148- let manifest =
149- configure:: parse_manifest ( & name, self . staging . path ( ) . to_owned ( ) , self . manager ) ?;
171+ let manifest = configure:: parse_manifest ( & name, staging. path ( ) . to_owned ( ) , manager) ?;
150172
151- persist_install ( & name, & manifest. version , self . staging . path ( ) ) ?;
152- link_package_to_shared_dir ( & name, self . manager ) ?;
153- configure:: write_config_and_shims ( & name, & manifest, image, self . manager )
173+ persist_install ( & name, & manifest. version , staging. path ( ) ) ?;
174+ link_package_to_shared_dir ( & name, manager) ?;
175+ configure:: write_config_and_shims ( & name, & manifest, image, manager)
154176 }
155177}
156178
@@ -209,19 +231,40 @@ impl InPlaceUpgrade {
209231 }
210232}
211233
234+ #[ derive( Clone , Copy , PartialEq ) ]
235+ enum NeedsScope {
236+ Yes ,
237+ No ,
238+ }
239+
240+ impl From < bool > for NeedsScope {
241+ fn from ( value : bool ) -> Self {
242+ if value {
243+ NeedsScope :: Yes
244+ } else {
245+ NeedsScope :: No
246+ }
247+ }
248+ }
249+
212250/// Create the temporary staging directory we will use to install and ensure expected
213251/// subdirectories exist within it
214- fn setup_staging_directory ( manager : PackageManager ) -> Fallible < TempDir > {
252+ fn setup_staging_directory ( manager : PackageManager , needs_scope : NeedsScope ) -> Fallible < TempDir > {
215253 // Workaround to ensure relative symlinks continue to work.
216254 // The final installed location of packages is:
217255 // $VOLTA_HOME/tools/image/packages/{name}/
218256 // To ensure that the temp directory has the same amount of nesting, we use:
219257 // $VOLTA_HOME/tmp/image/packages/{tempdir}/
220258 // This way any relative symlinks will have the same amount of nesting and will remain valid
221259 // even when the directory is persisted.
260+ // We also need to handle the case when the linked package has a scope, which requires another
261+ // level of nesting
222262 let mut staging_root = volta_home ( ) ?. tmp_dir ( ) . to_owned ( ) ;
223263 staging_root. push ( "image" ) ;
224264 staging_root. push ( "packages" ) ;
265+ if needs_scope == NeedsScope :: Yes {
266+ staging_root. push ( "scope" ) ;
267+ }
225268 create_dir_all ( & staging_root) . with_context ( || ErrorKind :: ContainingDirError {
226269 path : staging_root. clone ( ) ,
227270 } ) ?;
0 commit comments