Skip to content

Commit 661b76d

Browse files
committed
Fix code that was trying reuse an already installed nightly.
Before, we would just skip attempts to install a current nightly. (And then, we would unconditionally fail the run as documented on issue #54, regardless whether of whether the regression was actually visible on that version, due to it not being installed with the name "bisector-nightly-xxx" that we expect.) This commit fixes that. It makes `install` call out to `rustup toolchain link` to link the current rustc (as reported via `rustc --print sysroot`) up to the new "bisector-nightly-xxx" that we expect. (I also refactored the code to construct `DownloadParams`; that refactoring was more relevant in an earlier version of the code that was linking in a different (buggy) way.)
1 parent 7ac0397 commit 661b76d

File tree

1 file changed

+83
-14
lines changed

1 file changed

+83
-14
lines changed

src/main.rs

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::env;
3131
use std::ffi::OsString;
3232
use std::fmt;
3333
use std::fs;
34+
use std::iter;
3435
use std::io::{self, Read, Write};
3536
use std::path::{Path, PathBuf};
3637
use std::process::{self, Command, Stdio};
@@ -309,19 +310,16 @@ impl DownloadParams {
309310
if cfg.args.alt { "-alt" } else { "" }
310311
);
311312

312-
DownloadParams {
313-
url_prefix: url_prefix,
314-
tmp_dir: cfg.rustup_tmp_path.clone(),
315-
install_dir: cfg.toolchains_path.clone(),
316-
install_cargo: cfg.args.with_cargo,
317-
install_src: cfg.args.with_src,
318-
force_install: cfg.args.force_install,
319-
}
313+
Self::from_cfg_with_url_prefix(cfg, url_prefix)
320314
}
321315

322316
fn for_nightly(cfg: &Config) -> Self {
317+
Self::from_cfg_with_url_prefix(cfg, NIGHTLY_SERVER.to_string())
318+
}
319+
320+
fn from_cfg_with_url_prefix(cfg: &Config, url_prefix: String) -> Self {
323321
DownloadParams {
324-
url_prefix: NIGHTLY_SERVER.to_string(),
322+
url_prefix: url_prefix,
325323
tmp_dir: cfg.rustup_tmp_path.clone(),
326324
install_dir: cfg.toolchains_path.clone(),
327325
install_cargo: cfg.args.with_cargo,
@@ -450,6 +448,8 @@ enum InstallError {
450448
TempDir(#[cause] io::Error),
451449
#[fail(display = "Could not move tempdir into destination: {}", _0)]
452450
Move(#[cause] io::Error),
451+
#[fail(display = "Could not run subcommand {}: {}", command, cause)]
452+
Subcommand { command: String, #[cause] cause: io::Error }
453453
}
454454

455455
#[derive(Debug)]
@@ -702,11 +702,6 @@ impl Toolchain {
702702
}
703703

704704
fn install(&self, client: &Client, dl_params: &DownloadParams) -> Result<(), InstallError> {
705-
if self.is_current_nightly() {
706-
// pre existing installation
707-
return Ok(());
708-
}
709-
710705
debug!("installing {}", self);
711706
let tmpdir = TempDir::new_in(&dl_params.tmp_dir, &self.rustup_name())
712707
.map_err(InstallError::TempDir)?;
@@ -720,6 +715,40 @@ impl Toolchain {
720715
return Ok(());
721716
}
722717

718+
if self.is_current_nightly() {
719+
// make link to pre-existing installation
720+
debug!("installing (via link) {}", self);
721+
722+
let nightly_path: String = {
723+
let cmd = CommandTemplate::new(["rustc", "--print", "sysroot"]
724+
.iter()
725+
.map(|s| s.to_string()));
726+
let stdout = cmd.output()?.stdout;
727+
let output = String::from_utf8_lossy(&stdout);
728+
// the output should be the path, terminated by a newline
729+
let mut path = output.to_string();
730+
let last = path.pop();
731+
assert_eq!(last, Some('\n'));
732+
path
733+
};
734+
735+
let cmd = CommandTemplate::new(["rustup", "toolchain", "link"]
736+
.iter()
737+
.map(|s| s.to_string())
738+
.chain(iter::once(self.rustup_name()))
739+
.chain(iter::once(nightly_path)));
740+
if cmd.status()?.success() {
741+
return Ok(());
742+
} else {
743+
return Err(InstallError::Subcommand {
744+
command: cmd.string(),
745+
cause: io::Error::new(io::ErrorKind::Other, "failed to link via `rustup`"),
746+
});
747+
}
748+
}
749+
750+
debug!("installing via download {}", self);
751+
723752
let rustc_filename = format!("rustc-nightly-{}", self.host);
724753

725754
let location = match self.spec {
@@ -794,6 +823,46 @@ impl Toolchain {
794823
}
795824
}
796825

826+
// A simpler wrapper struct to make up for impoverished `Command` in libstd.
827+
struct CommandTemplate(Vec<String>);
828+
829+
impl CommandTemplate {
830+
fn new(strings: impl Iterator<Item=String>) -> Self {
831+
CommandTemplate(strings.collect())
832+
}
833+
834+
fn command(&self) -> Command {
835+
assert!(self.0.len() > 0);
836+
let mut cmd = Command::new(&self.0[0]);
837+
for arg in &self.0[1..] {
838+
cmd.arg(arg);
839+
}
840+
cmd
841+
}
842+
843+
fn string(&self) -> String {
844+
assert!(self.0.len() > 0);
845+
let mut s = self.0[0].to_string();
846+
for arg in &self.0[1..] {
847+
s.push_str(" ");
848+
s.push_str(arg);
849+
}
850+
s
851+
}
852+
853+
fn status(&self) -> Result<process::ExitStatus, InstallError> {
854+
self.command().status().map_err(|cause| {
855+
InstallError::Subcommand { command: self.string(), cause }
856+
})
857+
}
858+
859+
fn output(&self) -> Result<process::Output, InstallError> {
860+
self.command().output().map_err(|cause| {
861+
InstallError::Subcommand { command: self.string(), cause }
862+
})
863+
}
864+
}
865+
797866
struct Config {
798867
args: Opts,
799868
rustup_tmp_path: PathBuf,

0 commit comments

Comments
 (0)