@@ -10,8 +10,10 @@ use postgres::Connection;
10
10
use rustc_serialize:: json:: ToJson ;
11
11
use rustwide:: cmd:: { Command , SandboxBuilder } ;
12
12
use rustwide:: logging:: { self , LogStorage } ;
13
+ use rustwide:: toolchain:: ToolchainError ;
13
14
use rustwide:: { Build , Crate , Toolchain , Workspace , WorkspaceBuilder } ;
14
15
use std:: borrow:: Cow ;
16
+ use std:: collections:: HashSet ;
15
17
use std:: path:: Path ;
16
18
use utils:: { copy_doc_dir, parse_rustc_version, CargoMetadata } ;
17
19
use Metadata ;
@@ -95,12 +97,43 @@ impl RustwideBuilder {
95
97
// Ignore errors if detection fails.
96
98
let old_version = self . detect_rustc_version ( ) . ok ( ) ;
97
99
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
+
98
130
self . toolchain . install ( & self . workspace ) ?;
99
- for target in TARGETS {
131
+
132
+ for target in & targets_to_install {
100
133
self . toolchain . add_target ( & self . workspace , target) ?;
101
134
}
102
- self . rustc_version = self . detect_rustc_version ( ) ?;
103
135
136
+ self . rustc_version = self . detect_rustc_version ( ) ?;
104
137
if old_version. as_ref ( ) . map ( |s| s. as_str ( ) ) != Some ( & self . rustc_version ) {
105
138
self . add_essential_files ( ) ?;
106
139
}
0 commit comments