Skip to content

Commit 1f77aff

Browse files
Merge pull request #14 from anp/benchmarking-2
Support `by-commit` with nightly dates, additional logging, some up-front validation
2 parents 29f66a1 + 1c84f2d commit 1f77aff

File tree

5 files changed

+108
-7
lines changed

5 files changed

+108
-7
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ structopt = "0.2.5"
2323
tar = "0.4"
2424
tee = "0.1"
2525
tempdir = "0.3.6"
26+
toml = "0.4"
2627
xz2 = "0.1.3"
2728
chrono = "0.4.0"
2829

src/git.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,23 @@ fn get_repo() -> Result<Repository, Error> {
4646
let loc = Path::new("rust.git");
4747
match (RUST_SRC_REPO, loc.exists()) {
4848
(Some(_), _) | (_, true) => {
49-
let repo = Repository::open(RUST_SRC_REPO.map(Path::new).unwrap_or(loc))?;
49+
let path = RUST_SRC_REPO.map(Path::new).unwrap_or(loc);
50+
eprintln!("opening existing repository at {:?}", path);
51+
let repo = Repository::open(path)?;
5052
{
53+
eprintln!("refreshing repository");
5154
let mut remote = repo.find_remote("origin")
5255
.or_else(|_| repo.remote_anonymous("origin"))?;
5356
remote.fetch(&["master"], None, None)?;
5457
}
5558
Ok(repo)
5659
}
57-
(None, false) => Ok(RepoBuilder::new()
58-
.bare(true)
59-
.clone(RUST_SRC_URL, Path::new("rust.git"))?),
60+
(None, false) => {
61+
eprintln!("cloning rust repository");
62+
Ok(RepoBuilder::new()
63+
.bare(true)
64+
.clone(RUST_SRC_URL, Path::new("rust.git"))?)
65+
}
6066
}
6167
}
6268

@@ -70,7 +76,9 @@ pub fn expand_commit(sha: &str) -> Result<String, Error> {
7076
/// (boundaries inclusive).
7177
pub fn get_commits_between(first_commit: &str, last_commit: &str) -> Result<Vec<Commit>, Error> {
7278
let repo = get_repo()?;
79+
eprintln!("looking up first commit");
7380
let mut first = lookup_rev(&repo, first_commit)?;
81+
eprintln!("looking up second commit");
7482
let last = lookup_rev(&repo, last_commit)?;
7583

7684
// Sanity check -- our algorithm below only works reliably if the
@@ -82,13 +90,16 @@ pub fn get_commits_between(first_commit: &str, last_commit: &str) -> Result<Vec<
8290
None => bail!("No author for {}", c.id()),
8391
}
8492
};
93+
94+
eprintln!("checking that commits are by bors and thus have ci artifacts...");
8595
assert_by_bors(&first)?;
8696
assert_by_bors(&last)?;
8797
// Now find the commits
8898
// We search from the last and always take the first of its parents,
8999
// to only get merge commits.
90100
// This uses the fact that all bors merge commits have the earlier
91101
// merge commit as their first parent.
102+
eprintln!("finding bors merge commits");
92103
let mut res = Vec::new();
93104
let mut current = last;
94105
loop {
@@ -117,5 +128,9 @@ pub fn get_commits_between(first_commit: &str, last_commit: &str) -> Result<Vec<
117128
res.push(Commit::from_git2_commit(&mut first));
118129
// Reverse in order to obtain chronological order
119130
res.reverse();
131+
eprintln!(
132+
"found {} bors merge commits in the specified range",
133+
res.len()
134+
);
120135
Ok(res)
121136
}

src/least_satisfying.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,23 @@ where
1717
let mut predicate = |idx: usize| *cache.entry(idx).or_insert_with(|| predicate(&slice[idx]));
1818
let mut unknown_ranges: Vec<(usize, usize)> = Vec::new();
1919
let mut rm_no = 0; // presume that the slice starts with a no
20+
21+
eprintln!("verifying the start of the range does not reproduce the regression");
22+
match predicate(rm_no) {
23+
Satisfies::No => {
24+
eprintln!("confirmed the start of the range does not reproduce the regression")
25+
}
26+
_ => panic!("the start of the range to test must not reproduce the regression"),
27+
}
28+
2029
let mut lm_yes = slice.len() - 1; // presume that the slice ends with a yes
30+
31+
eprintln!("verifying the end of the range reproduces the regression");
32+
match predicate(lm_yes) {
33+
Satisfies::Yes => eprintln!("confirmed the end of the range reproduces the regression"),
34+
_ => panic!("the end of the range to test must reproduce the regression"),
35+
}
36+
2137
let mut next = (rm_no + lm_yes) / 2;
2238

2339
loop {

src/main.rs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extern crate structopt;
2323
extern crate tar;
2424
extern crate tee;
2525
extern crate tempdir;
26+
extern crate toml;
2627
extern crate xz2;
2728

2829
use std::fmt;
@@ -42,6 +43,7 @@ use reqwest::{Client, Response};
4243
use pbr::{ProgressBar, Units};
4344
use tee::TeeReader;
4445
use tar::Archive;
46+
use toml::Value;
4547
use reqwest::header::ContentLength;
4648
use xz2::read::XzDecoder;
4749
use flate2::read::GzDecoder;
@@ -63,6 +65,7 @@ mod least_satisfying;
6365
use least_satisfying::{least_satisfying, Satisfies};
6466

6567
fn get_commits(start: &str, end: &str) -> Result<Vec<git::Commit>, Error> {
68+
eprintln!("fetching commits from {} to {}", start, end);
6669
let commits = git::get_commits_between(start, end)?;
6770
assert_eq!(commits.first().expect("at least one commit").sha, start);
6871

@@ -144,6 +147,48 @@ impl FromStr for Bound {
144147
}
145148
}
146149

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+
147192
impl Opts {
148193
fn emit_cargo_output(&self) -> bool {
149194
self.verbosity >= 2
@@ -540,7 +585,7 @@ impl Config {
540585
}
541586

542587
let target = args.target.clone().unwrap_or_else(|| args.host.clone());
543-
let args = args;
588+
let mut args = args;
544589

545590
let mut toolchains_path = match env::var_os("RUSTUP_HOME") {
546591
Some(h) => PathBuf::from(h),
@@ -586,8 +631,14 @@ impl Config {
586631
};
587632

588633
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+
}
591642
}
592643

593644
Ok(Config {
@@ -832,6 +883,7 @@ fn toolchains_between(cfg: &Config, a: ToolchainSpec, b: ToolchainSpec) -> Vec<T
832883
}
833884

834885
fn bisect_ci(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
886+
eprintln!("bisecting ci builds");
835887
let dl_spec = DownloadParams::for_ci(cfg);
836888
let start = if let Some(Bound::Commit(ref sha)) = cfg.args.start {
837889
sha
@@ -845,6 +897,8 @@ fn bisect_ci(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
845897
"origin/master"
846898
};
847899

900+
eprintln!("starting at {}, ending at {}", start, end);
901+
848902
let mut commits = get_commits(start, end)?;
849903
let now = chrono::Utc::now();
850904
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> {
873927
}
874928
}
875929

930+
eprintln!("validated commits found, specifying toolchains");
931+
876932
let toolchains = commits
877933
.into_iter()
878934
.map(|commit| {
@@ -890,9 +946,12 @@ fn bisect_ci(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
890946
})
891947
.collect::<Vec<_>>();
892948

949+
eprintln!("testing commits");
893950
let found = least_satisfying(&toolchains, |t| {
951+
eprintln!("installing {}", t);
894952
match t.install(&client, &dl_spec) {
895953
Ok(()) => {
954+
eprintln!("testing {}", t);
896955
let outcome = t.test(&cfg, &dl_spec);
897956
// we want to fail, so a successful build doesn't satisfy us
898957
let r = match outcome {

0 commit comments

Comments
 (0)