blob: 6fc96592a885857e7a379d9c3550decd42370437 [file] [log] [blame]
pub mod io;
use crate::environment::Environment;
use crate::utils::io::{delete_directory, get_files_from_dir};
use humansize::{format_size, BINARY};
use std::time::Duration;
use sysinfo::{DiskExt, RefreshKind, System, SystemExt};
pub fn format_env_variables() -> String {
let vars = std::env::vars().map(|(key, value)| format!("{key}={value}")).collect::<Vec<_>>();
vars.join("\n")
}
pub fn print_free_disk_space() -> anyhow::Result<()> {
let sys = System::new_with_specifics(RefreshKind::default().with_disks_list().with_disks());
let available_space: u64 = sys.disks().iter().map(|d| d.available_space()).sum();
let total_space: u64 = sys.disks().iter().map(|d| d.total_space()).sum();
let used_space = total_space - available_space;
log::info!(
"Free disk space: {} out of total {} ({:.2}% used)",
humansize::format_size(available_space, BINARY),
humansize::format_size(total_space, BINARY),
(used_space as f64 / total_space as f64) * 100.0
);
Ok(())
}
pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> {
use std::fmt::Write;
let root = env.build_artifacts().join("stage2");
let mut files = get_files_from_dir(&root.join("bin"), None)?;
files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?);
files.sort_unstable();
let mut output = String::new();
for file in files {
let size = std::fs::metadata(file.as_std_path())?.len();
let size_formatted = format_size(size, BINARY);
let name = format!("{}:", file.file_name().unwrap());
writeln!(output, "{name:<50}{size_formatted:>10}")?;
}
log::info!("Rustc artifact size\n{output}");
Ok(())
}
pub fn clear_llvm_files(env: &Environment) -> anyhow::Result<()> {
// Bootstrap currently doesn't support rebuilding LLVM when PGO options
// change (or any other llvm-related options); so just clear out the relevant
// directories ourselves.
log::info!("Clearing LLVM build files");
delete_directory(&env.build_artifacts().join("llvm"))?;
delete_directory(&env.build_artifacts().join("lld"))?;
Ok(())
}
/// Wraps all output produced within the `func` closure in a CI output group, if we're running in
/// CI.
pub fn with_log_group<F: FnOnce() -> R, R>(group: &str, func: F) -> R {
if is_in_ci() {
println!("::group::{group}");
let result = func();
println!("::endgroup::");
result
} else {
func()
}
}
#[allow(unused)]
pub fn retry_action<F: Fn() -> anyhow::Result<R>, R>(
action: F,
name: &str,
count: u64,
) -> anyhow::Result<R> {
for attempt in 0..count {
match action() {
Ok(result) => return Ok(result),
Err(error) => {
log::error!("Failed to perform action `{name}`, attempt #{attempt}: {error:?}");
std::thread::sleep(Duration::from_secs(5));
}
}
}
Err(anyhow::anyhow!("Failed to perform action `{name}` after {count} retries"))
}
fn is_in_ci() -> bool {
std::env::var("GITHUB_ACTIONS").is_ok()
}