From 499e72c1cba8f7aa0415d3d8b93c57ca98457635 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 14 Jan 2023 15:45:22 +0300 Subject: feat(tvix/cli): track known plain paths in NixCompatIO When adding things to a C++ Nix store, ensure that the path is tracked in the tracker. Since the mechanism for propagating the tracker instance isn't finalised yet, I've opted to take an Rc parameter for it. How exactly that ends up there is going to become clear in the next commits, but for now it's just instantiated in main with Default::default. Change-Id: I90f0b44f2d4f292dedc98ff1aa39041d279b61fd Reviewed-on: https://cl.tvl.fyi/c/depot/+/7833 Tested-by: BuildkiteCI Reviewed-by: flokli --- tvix/cli/src/known_paths.rs | 1 + tvix/cli/src/main.rs | 7 ++++- tvix/cli/src/nix_compat.rs | 64 +++++++++++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/tvix/cli/src/known_paths.rs b/tvix/cli/src/known_paths.rs index 63372c9caaa9..569fb41ba318 100644 --- a/tvix/cli/src/known_paths.rs +++ b/tvix/cli/src/known_paths.rs @@ -29,6 +29,7 @@ pub enum PathType { Plain, } +#[derive(Debug, Default)] pub struct KnownPaths { /// All known paths, and their associated [`PathType`]. paths: HashMap, diff --git a/tvix/cli/src/main.rs b/tvix/cli/src/main.rs index 42297d365bbf..242cece9ecd2 100644 --- a/tvix/cli/src/main.rs +++ b/tvix/cli/src/main.rs @@ -2,9 +2,12 @@ mod known_paths; mod nix_compat; mod refscan; +use std::cell::RefCell; +use std::rc::Rc; use std::{fs, path::PathBuf}; use clap::Parser; +use known_paths::KnownPaths; use rustyline::{error::ReadlineError, Editor}; use tvix_eval::observer::{DisassemblingObserver, TracingObserver}; use tvix_eval::Value; @@ -48,7 +51,9 @@ struct Args { /// evaluation succeeded. fn interpret(code: &str, path: Option, args: &Args, explain: bool) -> bool { let mut eval = tvix_eval::Evaluation::new_impure(code, path); - eval.io_handle = Box::new(nix_compat::NixCompatIO::new()); + let known_paths: Rc> = Default::default(); + + eval.io_handle = Box::new(nix_compat::NixCompatIO::new(known_paths)); eval.nix_path = args.nix_search_path.clone(); let source_map = eval.source_map(); diff --git a/tvix/cli/src/nix_compat.rs b/tvix/cli/src/nix_compat.rs index 75281d90e85b..c3b28c53f6c8 100644 --- a/tvix/cli/src/nix_compat.rs +++ b/tvix/cli/src/nix_compat.rs @@ -5,10 +5,13 @@ //! by piggybacking off functionality that already exists in Nix and //! is still being implemented in Tvix. +use std::cell::RefCell; use std::path::Path; use std::process::Command; +use std::rc::Rc; use std::{io, path::PathBuf}; +use crate::known_paths::KnownPaths; use smol_str::SmolStr; use tvix_eval::{ErrorKind, EvalIO, FileType, StdIO}; @@ -18,12 +21,10 @@ pub struct NixCompatIO { /// Most IO requests are tunneled through to [`tvix_eval::StdIO`] /// instead. underlying: StdIO, -} -impl NixCompatIO { - pub fn new() -> Self { - NixCompatIO { underlying: StdIO } - } + /// Ingested paths must be reported to this known paths tracker + /// for accurate build reference scanning. + known_paths: Rc>, } impl EvalIO for NixCompatIO { @@ -33,7 +34,7 @@ impl EvalIO for NixCompatIO { // Pass path imports through to `nix-store --add` fn import_path(&self, path: &Path) -> Result { - add_to_store(path).map_err(|error| ErrorKind::IO { + self.add_to_store(path).map_err(|error| ErrorKind::IO { error: std::rc::Rc::new(error), path: Some(path.to_path_buf()), }) @@ -53,30 +54,41 @@ impl EvalIO for NixCompatIO { } } -/// Add a path to the Nix store using the `nix-store --add` -/// functionality from C++ Nix. -fn add_to_store(path: &Path) -> Result { - if !path.try_exists()? { - return Err(io::Error::from(io::ErrorKind::NotFound)); +impl NixCompatIO { + pub fn new(known_paths: Rc>) -> Self { + NixCompatIO { + underlying: StdIO, + known_paths, + } } - let mut cmd = Command::new("nix-store"); - cmd.arg("--add"); - cmd.arg(path); + /// Add a path to the Nix store using the `nix-store --add` + /// functionality from C++ Nix. + fn add_to_store(&self, path: &Path) -> Result { + if !path.try_exists()? { + return Err(io::Error::from(io::ErrorKind::NotFound)); + } - let out = cmd.output()?; + let mut cmd = Command::new("nix-store"); + cmd.arg("--add"); + cmd.arg(path); - if !out.status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - String::from_utf8_lossy(&out.stderr), - )); - } + let out = cmd.output()?; + + if !out.status.success() { + return Err(io::Error::new( + io::ErrorKind::Other, + String::from_utf8_lossy(&out.stderr), + )); + } - let out_path_str = String::from_utf8(out.stdout) - .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + let out_path_str = String::from_utf8(out.stdout) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let mut out_path = PathBuf::new(); - out_path.push(out_path_str.trim()); - Ok(out_path) + self.known_paths.borrow_mut().plain(&out_path_str); + + let mut out_path = PathBuf::new(); + out_path.push(out_path_str.trim()); + Ok(out_path) + } } -- cgit 1.4.1