@@ -23,6 +23,7 @@ extern crate structopt;
23
23
extern crate tar;
24
24
extern crate tee;
25
25
extern crate tempdir;
26
+ extern crate toml;
26
27
extern crate xz2;
27
28
28
29
use std:: fmt;
@@ -42,6 +43,7 @@ use reqwest::{Client, Response};
42
43
use pbr:: { ProgressBar , Units } ;
43
44
use tee:: TeeReader ;
44
45
use tar:: Archive ;
46
+ use toml:: Value ;
45
47
use reqwest:: header:: ContentLength ;
46
48
use xz2:: read:: XzDecoder ;
47
49
use flate2:: read:: GzDecoder ;
@@ -63,6 +65,7 @@ mod least_satisfying;
63
65
use least_satisfying:: { least_satisfying, Satisfies } ;
64
66
65
67
fn get_commits ( start : & str , end : & str ) -> Result < Vec < git:: Commit > , Error > {
68
+ eprintln ! ( "fetching commits from {} to {}" , start, end) ;
66
69
let commits = git:: get_commits_between ( start, end) ?;
67
70
assert_eq ! ( commits. first( ) . expect( "at least one commit" ) . sha, start) ;
68
71
@@ -144,6 +147,48 @@ impl FromStr for Bound {
144
147
}
145
148
}
146
149
150
+ impl Bound {
151
+ fn as_commit ( self ) -> Result < Self , Error > {
152
+ match self {
153
+ Bound :: Commit ( commit) => Ok ( Bound :: Commit ( commit) ) ,
154
+ Bound :: Date ( date) => {
155
+ let date_str = date. format ( "%Y-%m-%d" ) ;
156
+ let url = format ! ( "{}/{}/channel-rust-nightly.toml" , NIGHTLY_SERVER , date_str) ;
157
+
158
+ eprintln ! ( "fetching {}" , url) ;
159
+ let client = Client :: new ( ) ;
160
+ let name = format ! ( "nightly manifest {}" , date_str) ;
161
+ let ( response, mut bar) = download_progress ( & client, & name, & url) ?;
162
+ let mut response = TeeReader :: new ( response, & mut bar) ;
163
+ let mut toml_buf = String :: new ( ) ;
164
+ response. read_to_string ( & mut toml_buf) ?;
165
+
166
+ let manifest = toml_buf. parse :: < Value > ( ) . unwrap ( ) ;
167
+
168
+ let commit = match manifest {
169
+ Value :: Table ( t) => match t. get ( "pkg" ) {
170
+ Some ( & Value :: Table ( ref t) ) => match t. get ( "rust" ) {
171
+ Some ( & Value :: Table ( ref t) ) => match t. get ( "git_commit_hash" ) {
172
+ Some ( & Value :: String ( ref hash) ) => hash. to_owned ( ) ,
173
+ _ => bail ! (
174
+ "not a rustup manifest (no valid git_commit_hash key under rust"
175
+ ) ,
176
+ } ,
177
+ _ => bail ! ( "not a rustup manifest (no rust key under pkg)" ) ,
178
+ } ,
179
+ _ => bail ! ( "not a rustup manifest (missing pkg key)" ) ,
180
+ } ,
181
+ _ => bail ! ( "not a rustup manifest (not a table at root)" ) ,
182
+ } ;
183
+
184
+ eprintln ! ( "converted {} to {}" , date_str, commit) ;
185
+
186
+ Ok ( Bound :: Commit ( commit) )
187
+ }
188
+ }
189
+ }
190
+ }
191
+
147
192
impl Opts {
148
193
fn emit_cargo_output ( & self ) -> bool {
149
194
self . verbosity >= 2
@@ -540,7 +585,7 @@ impl Config {
540
585
}
541
586
542
587
let target = args. target . clone ( ) . unwrap_or_else ( || args. host . clone ( ) ) ;
543
- let args = args;
588
+ let mut args = args;
544
589
545
590
let mut toolchains_path = match env:: var_os ( "RUSTUP_HOME" ) {
546
591
Some ( h) => PathBuf :: from ( h) ,
@@ -586,8 +631,14 @@ impl Config {
586
631
} ;
587
632
588
633
if is_commit == Some ( false ) && args. by_commit {
589
- // FIXME: In theory, we could use the date range to narrow down the commit list...
590
- bail ! ( "cannot bisect by-commit if specifying date range" ) ;
634
+ eprintln ! ( "finding commit range that corresponds to dates specified" ) ;
635
+ match ( args. start , args. end ) {
636
+ ( Some ( b1) , Some ( b2) ) => {
637
+ args. start = Some ( b1. as_commit ( ) ?) ;
638
+ args. end = Some ( b2. as_commit ( ) ?) ;
639
+ }
640
+ _ => unreachable ! ( ) ,
641
+ }
591
642
}
592
643
593
644
Ok ( Config {
@@ -832,6 +883,7 @@ fn toolchains_between(cfg: &Config, a: ToolchainSpec, b: ToolchainSpec) -> Vec<T
832
883
}
833
884
834
885
fn bisect_ci ( cfg : & Config , client : & Client ) -> Result < BisectionResult , Error > {
886
+ eprintln ! ( "bisecting ci builds" ) ;
835
887
let dl_spec = DownloadParams :: for_ci ( cfg) ;
836
888
let start = if let Some ( Bound :: Commit ( ref sha) ) = cfg. args . start {
837
889
sha
@@ -845,6 +897,8 @@ fn bisect_ci(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
845
897
"origin/master"
846
898
} ;
847
899
900
+ eprintln ! ( "starting at {}, ending at {}" , start, end) ;
901
+
848
902
let mut commits = get_commits ( start, end) ?;
849
903
let now = chrono:: Utc :: now ( ) ;
850
904
commits. retain ( |c| now. signed_duration_since ( c. date ) . num_days ( ) < 90 ) ;
@@ -873,6 +927,8 @@ fn bisect_ci(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
873
927
}
874
928
}
875
929
930
+ eprintln ! ( "validated commits found, specifying toolchains" ) ;
931
+
876
932
let toolchains = commits
877
933
. into_iter ( )
878
934
. map ( |commit| {
@@ -890,9 +946,12 @@ fn bisect_ci(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
890
946
} )
891
947
. collect :: < Vec < _ > > ( ) ;
892
948
949
+ eprintln ! ( "testing commits" ) ;
893
950
let found = least_satisfying ( & toolchains, |t| {
951
+ eprintln ! ( "installing {}" , t) ;
894
952
match t. install ( & client, & dl_spec) {
895
953
Ok ( ( ) ) => {
954
+ eprintln ! ( "testing {}" , t) ;
896
955
let outcome = t. test ( & cfg, & dl_spec) ;
897
956
// we want to fail, so a successful build doesn't satisfy us
898
957
let r = match outcome {
0 commit comments