Skip to content

Commit

Permalink
Introduce boilerplate for checking Nix files
Browse files Browse the repository at this point in the history
  • Loading branch information
infinisil committed Jan 8, 2025
1 parent 692d211 commit 22603ba
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 15 deletions.
7 changes: 3 additions & 4 deletions src/eval.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::{env, fs, process};

Expand Down Expand Up @@ -156,7 +157,7 @@ pub fn check_values(
nixpkgs_path: &Path,
nix_file_store: &mut NixFileStore,
package_names: &[String],
) -> validation::Result<ratchet::Nixpkgs> {
) -> validation::Result<BTreeMap<String, ratchet::Package>> {
let work_dir = tempfile::Builder::new()
.prefix("nixpkgs-vet")
.tempdir()
Expand Down Expand Up @@ -255,9 +256,7 @@ pub fn check_values(
.collect_vec()?,
);

Ok(check_result.map(|elems| ratchet::Nixpkgs {
packages: elems.into_iter().collect(),
}))
Ok(check_result.map(|elems| elems.into_iter().collect()))
}

/// Handle the evaluation result for an attribute in `pkgs/by-name`, making it a validation result.
Expand Down
66 changes: 66 additions & 0 deletions src/files.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::problem::npv_170;
use relative_path::RelativePath;
use relative_path::RelativePathBuf;
use rnix::ast::Expr::Str;
use std::collections::BTreeMap;
use std::path::Path;

use crate::nix_file::NixFileStore;
use crate::validation::ResultIteratorExt;
use crate::validation::Validation::Success;
use crate::{nix_file, ratchet, structure, validation};

pub fn check_files(
nixpkgs_path: &Path,
nix_file_store: &mut NixFileStore,
) -> validation::Result<BTreeMap<RelativePathBuf, ratchet::File>> {
process_nix_files(nixpkgs_path, nix_file_store, |nix_file| {
Ok(Success(ratchet::File { }))
})
}

fn collect_nix_files(
base: &Path,
dir: &RelativePath,
files: &mut Vec<RelativePathBuf>,
) -> anyhow::Result<()> {
for entry in structure::read_dir_sorted(&dir.to_path(base))? {
let mut relative_path = dir.to_relative_path_buf();
relative_path.push(entry.file_name().to_string_lossy().into_owned());

let absolute_path = entry.path();

if absolute_path.is_symlink() {
continue;
}
if absolute_path.is_dir() {
collect_nix_files(base, &relative_path, files)?
} else if absolute_path.extension().is_some_and(|x| x == "nix") {
files.push(relative_path)
}
}
Ok(())
}

fn process_nix_files<F: Fn(&nix_file::NixFile) -> validation::Result<ratchet::File>>(
nixpkgs_path: &Path,
nix_file_store: &mut NixFileStore,
f: F,
) -> validation::Result<BTreeMap<RelativePathBuf, ratchet::File>> {
let files = {
let mut files = vec![];
collect_nix_files(nixpkgs_path, &RelativePathBuf::new(), &mut files)?;
files
};

let file_results: Vec<validation::Validation<(RelativePathBuf, ratchet::File)>> = files
.into_iter()
.map(|path| {
let nix_file = nix_file_store.get(&path.to_path(nixpkgs_path))?;
let val = f(nix_file)?.map(|file| (path, file));
Ok::<_, anyhow::Error>(val)
})
.collect_vec()?;

Ok(validation::sequence(file_results).map(|entries| entries.into_iter().collect()))
}
34 changes: 23 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// #![allow(clippy::missing_const_for_fn)]

mod eval;
mod files;
mod location;
mod nix_file;
mod problem;
Expand All @@ -21,6 +22,7 @@ mod validation;

use anyhow::Context as _;
use clap::Parser;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use std::{panic, thread};
Expand Down Expand Up @@ -113,20 +115,30 @@ fn check_nixpkgs(nixpkgs_path: &Path) -> validation::Result<ratchet::Nixpkgs> {
)
})?;

if !nixpkgs_path.join(structure::BASE_SUBPATH).exists() {
// No pkgs/by-name directory, always valid
return Ok(Success(ratchet::Nixpkgs::default()));
}

let mut nix_file_store = NixFileStore::default();
let structure = check_structure(&nixpkgs_path, &mut nix_file_store)?;

// Only if we could successfully parse the structure, we do the evaluation checks
let result = structure.result_map(|package_names| {
eval::check_values(&nixpkgs_path, &mut nix_file_store, package_names.as_slice())
})?;
let package_result = {
if !nixpkgs_path.join(structure::BASE_SUBPATH).exists() {
// No pkgs/by-name directory, always valid
Success(BTreeMap::new())
} else {
let structure = check_structure(&nixpkgs_path, &mut nix_file_store)?;

// Only if we could successfully parse the structure, we do the evaluation checks
structure.result_map(|package_names| {
eval::check_values(&nixpkgs_path, &mut nix_file_store, package_names.as_slice())
})?
}
};

let file_result = files::check_files(&nixpkgs_path, &mut nix_file_store)?;

Ok(result)
Ok(
package_result.and(file_result, |packages, files| ratchet::Nixpkgs {
packages,
files,
}),
)
}

#[cfg(test)]
Expand Down
15 changes: 15 additions & 0 deletions src/ratchet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//!
//! Each type has a `compare` method that validates the ratchet checks for that item.
use relative_path::RelativePath;
use std::collections::BTreeMap;

use relative_path::RelativePathBuf;
Expand All @@ -15,6 +16,7 @@ use crate::validation::{self, Validation, Validation::Success};
pub struct Nixpkgs {
/// The ratchet values for all packages
pub packages: BTreeMap<String, Package>,
pub files: BTreeMap<RelativePathBuf, File>,
}

impl Nixpkgs {
Expand All @@ -27,6 +29,9 @@ impl Nixpkgs {
.into_iter()
.map(|(name, pkg)| Package::compare(&name, from.packages.get(&name), &pkg)),
)
.and_(validation::sequence_(to.files.into_iter().map(
|(name, file)| File::compare(&name, from.files.get(&name), &file),
)))
}
}

Expand Down Expand Up @@ -57,6 +62,16 @@ impl Package {
}
}

pub struct File {
}

impl File {
/// Validates the ratchet checks for a top-level package
pub fn compare(_name: &RelativePath, _optional_from: Option<&Self>, _to: &Self) -> Validation<()> {
Success(())
}
}

/// The ratchet state of a generic ratchet check.
pub enum RatchetState<Ratchet: ToProblem> {
/// The ratchet is loose. It can be tightened more. In other words, this is the legacy state
Expand Down

0 comments on commit 22603ba

Please sign in to comment.