Skip to content

Commit fa42232

Browse files
authored
Ensure cargo-kani setup is idempotent (model-checking#1193)
* Ensure cargo-kani setup is idempotent * add test, flip print order for better errors
1 parent d0b74ca commit fa42232

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

.github/workflows/kani.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ jobs:
107107
docker run -w /tmp/kani/tests/cargo-kani/simple-lib kani-latest cargo kani
108108
docker run -w /tmp/kani/tests/cargo-kani/simple-visualize kani-latest cargo kani
109109
docker run -w /tmp/kani/tests/cargo-kani/build-rs-works kani-latest cargo kani
110+
docker run kani-latest cargo-kani setup --use-local-bundle ./kani-latest-x86_64-unknown-linux-gnu.tar.gz
110111
111112
# We can't run macos in a container, so we can only test locally.
112113
# Hopefully any dependency issues won't be unique to macos.

src/lib.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,20 @@ fn setup(use_local_bundle: Option<OsString>) -> Result<()> {
111111
std::fs::create_dir_all(&base_dir)?;
112112

113113
if let Some(pathstr) = use_local_bundle {
114+
println!("[2/6] Installing local Kani bundle: {}", pathstr.to_string_lossy());
114115
let path = Path::new(&pathstr).canonicalize()?;
115-
println!("[2/6] Installing local Kani bundle: {}", path.display());
116-
Command::new("tar").arg("zxf").arg(&path).current_dir(base_dir).run()?;
117-
118-
// when given a local bundle, it's often "-latest" but we expect "-1.0" or something. Hack it up.
119-
let file = path.file_name().expect("has filename").to_string_lossy();
120-
let components: Vec<_> = file.split('-').collect();
121-
let expected_dir = format!("{}-{}", components[0], components[1]);
122-
123-
std::fs::rename(base_dir.join(expected_dir), &kani_dir)?;
116+
// When given a local bundle, it's often "-latest" but we expect "-1.0" or something.
117+
// tar supports "stripping" the first directory from the bundle, so do that and
118+
// extract it directly into the expected (kani_dir) directory (instead of base_dir).
119+
if !kani_dir.exists() {
120+
std::fs::create_dir(&kani_dir)?;
121+
}
122+
Command::new("tar")
123+
.arg("--strip-components=1")
124+
.arg("-zxf")
125+
.arg(&path)
126+
.current_dir(&kani_dir)
127+
.run()?;
124128
} else {
125129
let filename = download_filename();
126130
println!("[2/6] Downloading Kani release bundle: {}", &filename);
@@ -145,7 +149,7 @@ fn setup(use_local_bundle: Option<OsString>) -> Result<()> {
145149

146150
let toolchain = home::rustup_home()?.join("toolchains").join(&toolchain_version);
147151

148-
Command::new("ln").arg("-s").arg(toolchain).arg(kani_dir.join("toolchain")).run()?;
152+
symlink_rust_toolchain(&toolchain, &kani_dir)?;
149153

150154
println!("[4/6] Installing Kani python dependencies...");
151155
let pyroot = kani_dir.join("pyroot");
@@ -201,6 +205,17 @@ fn setup(use_local_bundle: Option<OsString>) -> Result<()> {
201205
Ok(())
202206
}
203207

208+
/// Creates a `kani_dir/toolchain` symlink pointing to `toolchain`.
209+
fn symlink_rust_toolchain(toolchain: &Path, kani_dir: &Path) -> Result<()> {
210+
let path = kani_dir.join("toolchain");
211+
// We want to be idempotent, so if the symlink already exists, delete it first
212+
if path.exists() && path.is_symlink() {
213+
std::fs::remove_file(&path)?;
214+
}
215+
std::os::unix::fs::symlink(toolchain, path)?;
216+
Ok(())
217+
}
218+
204219
/// Executes `kani-driver` in `bin` mode (kani or cargo-kani)
205220
/// augmenting environment variables to accomodate our release environment
206221
fn exec(bin: &str) -> Result<()> {

0 commit comments

Comments
 (0)