@@ -10,8 +10,10 @@ use postgres::Connection;
1010use rustc_serialize:: json:: ToJson ;
1111use rustwide:: cmd:: { Command , SandboxBuilder } ;
1212use rustwide:: logging:: { self , LogStorage } ;
13+ use rustwide:: toolchain:: ToolchainError ;
1314use rustwide:: { Build , Crate , Toolchain , Workspace , WorkspaceBuilder } ;
1415use std:: borrow:: Cow ;
16+ use std:: collections:: HashSet ;
1517use std:: path:: Path ;
1618use utils:: { copy_doc_dir, parse_rustc_version, CargoMetadata } ;
1719use Metadata ;
@@ -95,12 +97,43 @@ impl RustwideBuilder {
9597 // Ignore errors if detection fails.
9698 let old_version = self . detect_rustc_version ( ) . ok ( ) ;
9799
100+ let mut targets_to_install = TARGETS
101+ . iter ( )
102+ . map ( |t| t. to_string ( ) )
103+ . collect :: < HashSet < _ > > ( ) ;
104+ let installed_targets = match self . toolchain . installed_targets ( & self . workspace ) {
105+ Ok ( targets) => targets,
106+ Err ( err) => {
107+ if let Some ( & ToolchainError :: NotInstalled ) = err. downcast_ref :: < ToolchainError > ( ) {
108+ Vec :: new ( )
109+ } else {
110+ return Err ( err) ;
111+ }
112+ }
113+ } ;
114+
115+ // The extra targets are intentionally removed *before* trying to update.
116+ //
117+ // If a target is installed locally and it goes missing the next update, rustup will block
118+ // the update to avoid leaving the system in a broken state. This is not a behavior we want
119+ // though when we also remove the target from the list managed by docs.rs: we want that
120+ // target gone, and we don't care if it's missing in the next update.
121+ //
122+ // Removing it beforehand works fine, and prevents rustup from blocking the update later in
123+ // the method.
124+ for target in installed_targets {
125+ if !targets_to_install. remove ( & target) {
126+ self . toolchain . remove_target ( & self . workspace , & target) ?;
127+ }
128+ }
129+
98130 self . toolchain . install ( & self . workspace ) ?;
99- for target in TARGETS {
131+
132+ for target in & targets_to_install {
100133 self . toolchain . add_target ( & self . workspace , target) ?;
101134 }
102- self . rustc_version = self . detect_rustc_version ( ) ?;
103135
136+ self . rustc_version = self . detect_rustc_version ( ) ?;
104137 if old_version. as_ref ( ) . map ( |s| s. as_str ( ) ) != Some ( & self . rustc_version ) {
105138 self . add_essential_files ( ) ?;
106139 }
0 commit comments