Skip to content

Commit

Permalink
Merge pull request #254435 from tweag/fix-by-name-check-on-darwin
Browse files Browse the repository at this point in the history
tests.nixpkgs-check-by-name: Fix for symlinked tempdirs
  • Loading branch information
infinisil committed Sep 12, 2023
2 parents e657d37 + 9c9a7e0 commit dc194ec
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
4 changes: 4 additions & 0 deletions pkgs/test/nixpkgs-check-by-name/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ let
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_STORE_DIR=$TEST_ROOT/store
# cargo tests run in parallel by default, which would then run into
# https://github.com/NixOS/nix/issues/2706 unless the store is initialised first
nix-store --init
'';
postCheck = ''
cargo fmt --check
Expand Down
12 changes: 9 additions & 3 deletions pkgs/test/nixpkgs-check-by-name/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ pub fn check_values<W: io::Write>(
// Write the list of packages we need to check into a temporary JSON file.
// This can then get read by the Nix evaluation.
let attrs_file = NamedTempFile::new().context("Failed to create a temporary file")?;
// We need to canonicalise this path because if it's a symlink (which can be the case on
// Darwin), Nix would need to read both the symlink and the target path, therefore need 2
// NIX_PATH entries for restrict-eval. But if we resolve the symlinks then only one predictable
// entry is needed.
let attrs_file_path = attrs_file.path().canonicalize()?;

serde_json::to_writer(&attrs_file, &nixpkgs.package_names).context(format!(
"Failed to serialise the package names to the temporary path {}",
attrs_file.path().display()
attrs_file_path.display()
))?;

// With restrict-eval, only paths in NIX_PATH can be accessed, so we explicitly specify the
Expand All @@ -57,9 +63,9 @@ pub fn check_values<W: io::Write>(
// Pass the path to the attrs_file as an argument and add it to the NIX_PATH so it can be
// accessed in restrict-eval mode
.args(["--arg", "attrsPath"])
.arg(attrs_file.path())
.arg(&attrs_file_path)
.arg("-I")
.arg(attrs_file.path())
.arg(&attrs_file_path)
// Same for the nixpkgs to test
.args(["--arg", "nixpkgsPath"])
.arg(&nixpkgs.path)
Expand Down
36 changes: 36 additions & 0 deletions pkgs/test/nixpkgs-check-by-name/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,42 @@ mod tests {
Ok(())
}

/// Tests symlinked temporary directories.
/// This is needed because on darwin, `/tmp` is a symlink to `/private/tmp`, and Nix's
/// restrict-eval doesn't also allow access to the canonical path when you allow the
/// non-canonical one.
///
/// The error if we didn't do this would look like this:
/// error: access to canonical path '/private/var/folders/[...]/.tmpFbcNO0' is forbidden in restricted mode
#[test]
fn test_symlinked_tmpdir() -> anyhow::Result<()> {
// Create a directory with two entries:
// - actual (dir)
// - symlinked -> actual (symlink)
let temp_root = tempdir()?;
fs::create_dir(temp_root.path().join("actual"))?;
std::os::unix::fs::symlink("actual", temp_root.path().join("symlinked"))?;
let tmpdir = temp_root.path().join("symlinked");

// Then set TMPDIR to the symlinked directory
// Make sure to persist the old value so we can undo this later
let old_tmpdir = env::var("TMPDIR").ok();
env::set_var("TMPDIR", &tmpdir);

// Then run a simple test with this symlinked temporary directory
// This should be successful
test_nixpkgs("symlinked_tmpdir", Path::new("tests/success"), "")?;

// Undo the env variable change
if let Some(old) = old_tmpdir {
env::set_var("TMPDIR", old);
} else {
env::remove_var("TMPDIR");
}

Ok(())
}

fn test_nixpkgs(name: &str, path: &Path, expected_errors: &str) -> anyhow::Result<()> {
let extra_nix_path = Path::new("tests/mock-nixpkgs.nix");

Expand Down

0 comments on commit dc194ec

Please sign in to comment.