@@ -25,6 +25,18 @@ use std::time::Duration;
25
25
use url:: Url ;
26
26
use wait_timeout:: ChildExt ;
27
27
28
+ /// An installed toolchain
29
+ trait InstalledToolchain < ' a > {
30
+ /// What (root) paths are associated with this installed toolchain.
31
+ fn installed_paths ( & self ) -> Result < Vec < InstalledPath < ' a > > > ;
32
+ }
33
+
34
+ /// Installed paths
35
+ enum InstalledPath < ' a > {
36
+ File { name : & ' static str , path : PathBuf } ,
37
+ Dir { path : & ' a Path } ,
38
+ }
39
+
28
40
/// A fully resolved reference to a toolchain which may or may not exist
29
41
pub struct Toolchain < ' a > {
30
42
cfg : & ' a Cfg ,
@@ -59,6 +71,17 @@ impl<'a> Toolchain<'a> {
59
71
dist_handler : Box :: new ( move |n| ( cfg. notify_handler ) ( n. into ( ) ) ) ,
60
72
} )
61
73
}
74
+
75
+ fn as_installed ( & ' a self ) -> Result < Box < dyn InstalledToolchain < ' a > + ' a > > {
76
+ if self . is_custom ( ) {
77
+ let toolchain = CustomToolchain :: new ( self ) ?;
78
+ Ok ( Box :: new ( toolchain) as Box < dyn InstalledToolchain < ' a > > )
79
+ } else {
80
+ let toolchain = DistributableToolchain :: new ( self ) ?;
81
+ Ok ( Box :: new ( toolchain) as Box < dyn InstalledToolchain < ' a > > )
82
+ }
83
+ }
84
+
62
85
pub fn name ( & self ) -> & str {
63
86
& self . name
64
87
}
@@ -99,14 +122,19 @@ impl<'a> Toolchain<'a> {
99
122
( self . cfg . notify_handler ) ( Notification :: ToolchainNotInstalled ( & self . name ) ) ;
100
123
return Ok ( ( ) ) ;
101
124
}
102
- if let Some ( update_hash) = self . update_hash ( ) ? {
103
- utils:: ensure_file_removed ( "update hash" , & update_hash) ?;
125
+ let installed = self . as_installed ( ) ?;
126
+ for path in installed. installed_paths ( ) ? {
127
+ match path {
128
+ InstalledPath :: File { name, path } => utils:: ensure_file_removed ( & name, & path) ?,
129
+ InstalledPath :: Dir { path } => {
130
+ install:: uninstall ( path, & |n| ( self . cfg . notify_handler ) ( n. into ( ) ) ) ?
131
+ }
132
+ }
104
133
}
105
- let result = install:: uninstall ( & self . path , & |n| ( self . cfg . notify_handler ) ( n. into ( ) ) ) ;
106
134
if !self . exists ( ) {
107
135
( self . cfg . notify_handler ) ( Notification :: UninstalledToolchain ( & self . name ) ) ;
108
136
}
109
- result
137
+ Ok ( ( ) )
110
138
}
111
139
// Custom and Distributable. Installed and not installed.
112
140
fn install ( & self , install_method : InstallMethod < ' _ > ) -> Result < UpdateStatus > {
@@ -160,14 +188,6 @@ impl<'a> Toolchain<'a> {
160
188
InstallMethod :: Dist ( ..) => !self . is_custom ( ) ,
161
189
}
162
190
}
163
- // Distributable only probably (once update_hash is only called appropriately). Installed only.
164
- fn update_hash ( & self ) -> Result < Option < PathBuf > > {
165
- if self . is_custom ( ) {
166
- Ok ( None )
167
- } else {
168
- Ok ( Some ( self . cfg . get_hash_file ( & self . name , true ) ?) )
169
- }
170
- }
171
191
172
192
// XXX: Move to Config with a notify handler parameter
173
193
fn download_cfg ( & self ) -> DownloadCfg < ' _ > {
@@ -538,6 +558,23 @@ impl<'a> Toolchain<'a> {
538
558
/// Newtype to facilitate splitting out custom-toolchain specific code.
539
559
pub struct CustomToolchain < ' a > ( & ' a Toolchain < ' a > ) ;
540
560
561
+ impl < ' a > CustomToolchain < ' a > {
562
+ pub fn new ( toolchain : & ' a Toolchain < ' a > ) -> Result < CustomToolchain < ' a > > {
563
+ if toolchain. is_custom ( ) {
564
+ Ok ( CustomToolchain ( & toolchain) )
565
+ } else {
566
+ Err ( format ! ( "{} is not a custom toolchain" , toolchain. name( ) ) . into ( ) )
567
+ }
568
+ }
569
+ }
570
+
571
+ impl < ' a > InstalledToolchain < ' a > for CustomToolchain < ' a > {
572
+ fn installed_paths ( & self ) -> Result < Vec < InstalledPath < ' a > > > {
573
+ let path = & self . 0 . path ;
574
+ Ok ( vec ! [ InstalledPath :: Dir { path } ] )
575
+ }
576
+ }
577
+
541
578
/// Newtype to facilitate splitting out distributable-toolchain specific code.
542
579
pub struct DistributableToolchain < ' a > ( & ' a Toolchain < ' a > ) ;
543
580
@@ -726,12 +763,12 @@ impl<'a> DistributableToolchain<'a> {
726
763
components : & [ & str ] ,
727
764
targets : & [ & str ] ,
728
765
) -> Result < UpdateStatus > {
729
- let update_hash = self . 0 . update_hash ( ) ?;
766
+ let update_hash = self . update_hash ( ) ?;
730
767
let old_date = self . get_manifest ( ) . ok ( ) . and_then ( |m| m. map ( |m| m. date ) ) ;
731
768
self . 0 . install ( InstallMethod :: Dist (
732
769
& self . desc ( ) ?,
733
770
self . 0 . cfg . get_profile ( ) ?,
734
- update_hash . as_ref ( ) . map ( |p| & * * p ) ,
771
+ Some ( & update_hash ) ,
735
772
self . 0 . download_cfg ( ) ,
736
773
force_update,
737
774
allow_downgrade,
@@ -744,11 +781,11 @@ impl<'a> DistributableToolchain<'a> {
744
781
745
782
// Installed or not installed.
746
783
pub fn install_from_dist_if_not_installed ( & self ) -> Result < UpdateStatus > {
747
- let update_hash = self . 0 . update_hash ( ) ?;
784
+ let update_hash = self . update_hash ( ) ?;
748
785
self . 0 . install_if_not_installed ( InstallMethod :: Dist (
749
786
& self . desc ( ) ?,
750
787
self . 0 . cfg . get_profile ( ) ?,
751
- update_hash . as_ref ( ) . map ( |p| & * * p ) ,
788
+ Some ( & update_hash ) ,
752
789
self . 0 . download_cfg ( ) ,
753
790
false ,
754
791
false ,
@@ -884,11 +921,11 @@ impl<'a> DistributableToolchain<'a> {
884
921
885
922
// Installed only.
886
923
pub fn show_dist_version ( & self ) -> Result < Option < String > > {
887
- let update_hash = self . 0 . update_hash ( ) ?;
924
+ let update_hash = self . update_hash ( ) ?;
888
925
889
926
match crate :: dist:: dist:: dl_v2_manifest (
890
927
self . 0 . download_cfg ( ) ,
891
- update_hash . as_ref ( ) . map ( |p| & * * p ) ,
928
+ Some ( & update_hash ) ,
892
929
& self . desc ( ) ?,
893
930
) ? {
894
931
Some ( ( manifest, _) ) => Ok ( Some ( manifest. get_rust_version ( ) ?. to_string ( ) ) ) ,
@@ -903,4 +940,22 @@ impl<'a> DistributableToolchain<'a> {
903
940
None => Ok ( None ) ,
904
941
}
905
942
}
943
+
944
+ // Installed only.
945
+ fn update_hash ( & self ) -> Result < PathBuf > {
946
+ Ok ( self . 0 . cfg . get_hash_file ( & self . 0 . name , true ) ?)
947
+ }
948
+ }
949
+
950
+ impl < ' a > InstalledToolchain < ' a > for DistributableToolchain < ' a > {
951
+ fn installed_paths ( & self ) -> Result < Vec < InstalledPath < ' a > > > {
952
+ let path = & self . 0 . path ;
953
+ Ok ( vec ! [
954
+ InstalledPath :: File {
955
+ name: "update hash" ,
956
+ path: self . update_hash( ) ?,
957
+ } ,
958
+ InstalledPath :: Dir { path } ,
959
+ ] )
960
+ }
906
961
}
0 commit comments