run git commands in bootstrap in parallel
this saves about 150ms on many ./x invocations
This commit is contained in:
parent
da935398d5
commit
a269e4da72
3 changed files with 46 additions and 14 deletions
|
@ -545,23 +545,28 @@ impl Build {
|
||||||
.args(["--get-regexp", "path"])
|
.args(["--get-regexp", "path"])
|
||||||
.run_capture(self)
|
.run_capture(self)
|
||||||
.stdout();
|
.stdout();
|
||||||
for line in output.lines() {
|
std::thread::scope(|s| {
|
||||||
// Look for `submodule.$name.path = $path`
|
// Look for `submodule.$name.path = $path`
|
||||||
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
|
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
|
||||||
let submodule = line.split_once(' ').unwrap().1;
|
for line in output.lines() {
|
||||||
self.update_existing_submodule(submodule);
|
let submodule = line.split_once(' ').unwrap().1;
|
||||||
}
|
let config = self.config.clone();
|
||||||
|
s.spawn(move || {
|
||||||
|
Self::update_existing_submodule(&config, submodule);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the given submodule only if it's initialized already; nothing happens otherwise.
|
/// Updates the given submodule only if it's initialized already; nothing happens otherwise.
|
||||||
pub fn update_existing_submodule(&self, submodule: &str) {
|
pub fn update_existing_submodule(config: &Config, submodule: &str) {
|
||||||
// Avoid running git when there isn't a git checkout.
|
// Avoid running git when there isn't a git checkout.
|
||||||
if !self.config.submodules() {
|
if !config.submodules() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
|
if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
|
||||||
self.config.update_submodule(submodule);
|
config.update_submodule(submodule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use super::helpers;
|
use super::helpers;
|
||||||
use crate::Build;
|
use crate::Build;
|
||||||
use crate::utils::helpers::{output, t};
|
use crate::utils::helpers::{start_process, t};
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub enum GitInfo {
|
pub enum GitInfo {
|
||||||
|
@ -56,7 +56,7 @@ impl GitInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok, let's scrape some info
|
// Ok, let's scrape some info
|
||||||
let ver_date = output(
|
let ver_date = start_process(
|
||||||
helpers::git(Some(dir))
|
helpers::git(Some(dir))
|
||||||
.arg("log")
|
.arg("log")
|
||||||
.arg("-1")
|
.arg("-1")
|
||||||
|
@ -65,14 +65,14 @@ impl GitInfo {
|
||||||
.as_command_mut(),
|
.as_command_mut(),
|
||||||
);
|
);
|
||||||
let ver_hash =
|
let ver_hash =
|
||||||
output(helpers::git(Some(dir)).arg("rev-parse").arg("HEAD").as_command_mut());
|
start_process(helpers::git(Some(dir)).arg("rev-parse").arg("HEAD").as_command_mut());
|
||||||
let short_ver_hash = output(
|
let short_ver_hash = start_process(
|
||||||
helpers::git(Some(dir)).arg("rev-parse").arg("--short=9").arg("HEAD").as_command_mut(),
|
helpers::git(Some(dir)).arg("rev-parse").arg("--short=9").arg("HEAD").as_command_mut(),
|
||||||
);
|
);
|
||||||
GitInfo::Present(Some(Info {
|
GitInfo::Present(Some(Info {
|
||||||
commit_date: ver_date.trim().to_string(),
|
commit_date: ver_date().trim().to_string(),
|
||||||
sha: ver_hash.trim().to_string(),
|
sha: ver_hash().trim().to_string(),
|
||||||
short_sha: short_ver_hash.trim().to_string(),
|
short_sha: short_ver_hash().trim().to_string(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,33 @@ pub fn output(cmd: &mut Command) -> String {
|
||||||
String::from_utf8(output.stdout).unwrap()
|
String::from_utf8(output.stdout).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawn a process and return a closure that will wait for the process
|
||||||
|
/// to finish and then return its output. This allows the spawned process
|
||||||
|
/// to do work without immediately blocking bootstrap.
|
||||||
|
#[track_caller]
|
||||||
|
pub fn start_process(cmd: &mut Command) -> impl FnOnce() -> String {
|
||||||
|
let child = match cmd.stderr(Stdio::inherit()).stdout(Stdio::piped()).spawn() {
|
||||||
|
Ok(child) => child,
|
||||||
|
Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let command = format!("{:?}", cmd);
|
||||||
|
|
||||||
|
move || {
|
||||||
|
let output = child.wait_with_output().unwrap();
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
panic!(
|
||||||
|
"command did not execute successfully: {}\n\
|
||||||
|
expected success, got: {}",
|
||||||
|
command, output.status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::from_utf8(output.stdout).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
|
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
|
||||||
pub fn mtime(path: &Path) -> SystemTime {
|
pub fn mtime(path: &Path) -> SystemTime {
|
||||||
fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
|
fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue