Skip to content

Have CI check if we need to commit regenerated archives #1590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,13 @@ jobs:
with:
tool: nextest
- name: "Test (nextest)"
env:
GIX_TEST_CREATE_ARCHIVES_EVEN_ON_CI: 1
run: cargo nextest run --all --no-fail-fast
- name: Doctest
run: cargo test --doc
- name: Check that tracked archives are up to date
run: git diff --exit-code # If this fails, the fix is usually to commit a regenerated archive.

test-32bit:
runs-on: ubuntu-latest
Expand Down
49 changes: 27 additions & 22 deletions tests/tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use std::{
collections::BTreeMap,
env,
ffi::OsString,
io::Read,
path::{Path, PathBuf},
Expand Down Expand Up @@ -150,8 +151,8 @@ fn git_version_from_bytes(bytes: &[u8]) -> Result<(u8, u8, u8)> {

/// Set the current working dir to `new_cwd` and return a type that returns to the previous working dir on drop.
pub fn set_current_dir(new_cwd: impl AsRef<Path>) -> std::io::Result<AutoRevertToPreviousCWD> {
let cwd = std::env::current_dir()?;
std::env::set_current_dir(new_cwd)?;
let cwd = env::current_dir()?;
env::set_current_dir(new_cwd)?;
Ok(AutoRevertToPreviousCWD(cwd))
}

Expand All @@ -166,7 +167,7 @@ pub struct AutoRevertToPreviousCWD(PathBuf);

impl Drop for AutoRevertToPreviousCWD {
fn drop(&mut self) {
std::env::set_current_dir(&self.0).unwrap();
env::set_current_dir(&self.0).unwrap();
}
}

Expand Down Expand Up @@ -461,7 +462,7 @@ fn scripted_fixture_read_only_with_args_inner(
crc_digest.update(&std::fs::read(&script_path).unwrap_or_else(|err| {
panic!(
"file {script_path:?} in CWD {:?} could not be read: {err}",
std::env::current_dir().expect("valid cwd"),
env::current_dir().expect("valid cwd"),
)
}));
for arg in &args {
Expand Down Expand Up @@ -548,7 +549,7 @@ fn scripted_fixture_read_only_with_args_inner(
script_location.display()
);
}
let script_absolute_path = std::env::current_dir()?.join(script_path);
let script_absolute_path = env::current_dir()?.join(script_path);
let mut cmd = std::process::Command::new(&script_absolute_path);
let output = match configure_command(&mut cmd, &args, &script_result_directory).output() {
Ok(out) => out,
Expand All @@ -569,7 +570,7 @@ fn scripted_fixture_read_only_with_args_inner(
output.stdout.as_bstr(),
output.stderr.as_bstr()
);
create_archive_if_not_on_ci(
create_archive_if_we_should(
&script_result_directory,
&archive_file_path,
script_identity_for_archive,
Expand All @@ -593,7 +594,7 @@ fn configure_command<'a>(
args: &[String],
script_result_directory: &Path,
) -> &'a mut std::process::Command {
let mut msys_for_git_bash_on_windows = std::env::var_os("MSYS").unwrap_or_default();
let mut msys_for_git_bash_on_windows = env::var_os("MSYS").unwrap_or_default();
msys_for_git_bash_on_windows.push(" winsymlinks:nativestrict");
cmd.args(args)
.stdout(std::process::Stdio::piped())
Expand Down Expand Up @@ -632,6 +633,14 @@ fn write_failure_marker(failure_marker: &Path) {
std::fs::write(failure_marker, []).ok();
}

fn should_skip_all_archive_creation() -> bool {
// On Windows, we fail to remove the meta_dir and can't do anything about it, which means tests will see more
// in the directory than they should which makes them fail. It's probably a bad idea to generate archives on Windows
// anyway. Either Unix is portable OR no archive is created anywhere. This also means that Windows users can't create
// archives, but that's not a deal-breaker.
cfg!(windows) || (is_ci::cached() && env::var_os("GIX_TEST_CREATE_ARCHIVES_EVEN_ON_CI").is_none())
}

fn is_lfs_pointer_file(path: &Path) -> bool {
const PREFIX: &[u8] = b"version https://gix-lfs";
let mut buf = [0_u8; PREFIX.len()];
Expand All @@ -642,14 +651,10 @@ fn is_lfs_pointer_file(path: &Path) -> bool {
.map_or(false, |_| buf.starts_with(PREFIX))
}

/// The `script_identity` will be baked into the soon to be created `archive` as it identitifies the script
/// The `script_identity` will be baked into the soon to be created `archive` as it identifies the script
/// that created the contents of `source_dir`.
fn create_archive_if_not_on_ci(source_dir: &Path, archive: &Path, script_identity: u32) -> std::io::Result<()> {
// on windows, we fail to remove the meta_dir and can't do anything about it, which means tests will see more
// in the directory than they should which makes them fail. It's probably a bad idea to generate archives on windows
// anyway. Either unix is portable OR no archive is created anywhere. This also means that windows users can't create
// archives, but that's not a deal-breaker.
if cfg!(windows) || is_ci::cached() || is_excluded(archive) {
fn create_archive_if_we_should(source_dir: &Path, archive: &Path, script_identity: u32) -> std::io::Result<()> {
if should_skip_all_archive_creation() || is_excluded(archive) {
return Ok(());
}
if is_lfs_pointer_file(archive) {
Expand Down Expand Up @@ -702,7 +707,7 @@ fn is_excluded(archive: &Path) -> bool {
let mut lut = EXCLUDE_LUT.lock();
lut.as_mut()
.and_then(|cache| {
let archive = std::env::current_dir().ok()?.join(archive);
let archive = env::current_dir().ok()?.join(archive);
let relative_path = archive.strip_prefix(cache.base()).ok()?;
cache
.at_path(
Expand Down Expand Up @@ -746,7 +751,7 @@ fn extract_archive(
let mut buf = Vec::new();
#[cfg_attr(feature = "xz", allow(unused_mut))]
let mut input_archive = std::fs::File::open(archive)?;
if std::env::var_os("GIX_TEST_IGNORE_ARCHIVES").is_some() {
if env::var_os("GIX_TEST_IGNORE_ARCHIVES").is_some() {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
Expand Down Expand Up @@ -848,16 +853,16 @@ impl<'a> Env<'a> {

/// Set `var` to `value`.
pub fn set(mut self, var: &'a str, value: impl Into<String>) -> Self {
let prev = std::env::var_os(var);
std::env::set_var(var, value.into());
let prev = env::var_os(var);
env::set_var(var, value.into());
self.altered_vars.push((var, prev));
self
}

/// Unset `var`.
pub fn unset(mut self, var: &'a str) -> Self {
let prev = std::env::var_os(var);
std::env::remove_var(var);
let prev = env::var_os(var);
env::remove_var(var);
self.altered_vars.push((var, prev));
self
}
Expand All @@ -867,8 +872,8 @@ impl<'a> Drop for Env<'a> {
fn drop(&mut self) {
for (var, prev_value) in self.altered_vars.iter().rev() {
match prev_value {
Some(value) => std::env::set_var(var, value),
None => std::env::remove_var(var),
Some(value) => env::set_var(var, value),
None => env::remove_var(var),
}
}
}
Expand Down
Loading