Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.

Commit dd8c371

Browse files
committed
Use thread-safe buffer instead of file to capture build plan
1 parent 8938495 commit dd8c371

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ curl = "0.4.21"
1717
env_logger = "0.7"
1818
anyhow = "1.0.27"
1919
log = "0.4"
20-
rand = "0.7"
2120
semver = "0.9"
2221
serde = { version = "1.0.84", features = ["derive"] }
2322
serde_json = "1.0.34"
2423

2524
[dev-dependencies]
2625
quickcheck = "0.9"
26+
rand = "0.7"

src/bin/cargo-semver.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,15 @@ use cargo::core::{Package, PackageId, Source, SourceId, Workspace};
88
use cargo::sources::RegistrySource;
99
use curl::easy::Easy;
1010
use log::debug;
11-
use rand::Rng;
1211
use rustc_session::getopts;
1312
use serde::Deserialize;
1413
use std::collections::HashSet;
1514
use std::{
16-
env,
17-
fs::File,
18-
io::BufReader,
15+
env, io,
1916
io::Write,
2017
path::{Path, PathBuf},
2118
process::{Command, Stdio},
19+
sync::{Arc, RwLock},
2220
};
2321

2422
pub type Result<T> = cargo::util::CargoResult<T>;
@@ -503,33 +501,27 @@ impl<'a> WorkInfo<'a> {
503501
format!("-C metadata={}", if current { "new" } else { "old" }),
504502
);
505503

506-
let mut outdir = env::temp_dir();
507-
// The filename is randomized to avoid clashes when multiple cargo-semver instances are running.
508-
outdir.push(&format!(
509-
"cargo_semver_{}_{}_{}",
510-
name,
511-
current,
512-
rand::thread_rng().gen::<u32>()
513-
));
514-
515-
// redirection gang
516-
let outfile = File::create(&outdir)?;
504+
// Capture build plan from a separate Cargo invocation
505+
let output = VecWrite(Arc::new(RwLock::new(Vec::new())));
517506

518-
let mut file_write = cargo::core::Shell::from_write(Box::new(outfile));
507+
let mut file_write = cargo::core::Shell::from_write(Box::new(output.clone()));
519508
file_write.set_verbosity(cargo::core::Verbosity::Quiet);
509+
520510
let old_shell = std::mem::replace(&mut *config.shell(), file_write);
521511

522512
cargo::ops::compile(&self.workspace, &opts)?;
523513

524514
let _ = std::mem::replace(&mut *config.shell(), old_shell);
515+
let plan_output = output.read()?;
525516

526517
// actually compile things now
527518
opts.build_config.build_plan = false;
528519

529520
let compilation = cargo::ops::compile(&self.workspace, &opts)?;
530521
env::remove_var("RUSTFLAGS");
531522

532-
let build_plan: BuildPlan = serde_json::from_reader(BufReader::new(File::open(&outdir)?))?;
523+
let build_plan: BuildPlan = serde_json::from_slice(&plan_output)
524+
.map_err(|_| anyhow::anyhow!("Can't read build plan"))?;
533525

534526
// TODO: handle multiple outputs gracefully
535527
for i in &build_plan.invocations {
@@ -572,3 +564,30 @@ pub fn find_on_crates_io(crate_name: &str) -> Result<crates_io::Crate> {
572564
})
573565
})
574566
}
567+
568+
/// Thread-safe byte buffer that implements `io::Write`.
569+
#[derive(Clone)]
570+
struct VecWrite(Arc<RwLock<Vec<u8>>>);
571+
572+
impl VecWrite {
573+
pub fn read(&self) -> io::Result<std::sync::RwLockReadGuard<'_, Vec<u8>>> {
574+
self.0
575+
.read()
576+
.map_err(|_| io::Error::new(io::ErrorKind::Other, "lock poison"))
577+
}
578+
pub fn write(&self) -> io::Result<std::sync::RwLockWriteGuard<'_, Vec<u8>>> {
579+
self.0
580+
.write()
581+
.map_err(|_| io::Error::new(io::ErrorKind::Other, "lock poison"))
582+
}
583+
}
584+
585+
impl io::Write for VecWrite {
586+
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
587+
let mut lock = Self::write(self)?;
588+
io::Write::write(&mut *lock, data)
589+
}
590+
fn flush(&mut self) -> io::Result<()> {
591+
Ok(())
592+
}
593+
}

0 commit comments

Comments
 (0)