From 012244af64ed7885ae7eb829b7bb83286eafe16b Mon Sep 17 00:00:00 2001 From: Leo Gaskin Date: Thu, 11 Mar 2021 20:30:35 +0100 Subject: [PATCH] fix(build_loop): Only regenerate shell_gc_root if store path changes Currently, lorri may regenerate the shell_gc_root link to the project environments store path, even if that store path has not changed. With this commit, lorri will now check if the current and previous store paths are identical and, if so, avoid regenerating the symlink. This is especially interesting as lorri instructs direnv to watch the shell_gc_root symlink, previously causing direnv to be constantly reinvoked for some projects. If merged, this should also fix issue #387. --- src/build_loop.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/build_loop.rs b/src/build_loop.rs index 77bc40d3..c7c6fb15 100644 --- a/src/build_loop.rs +++ b/src/build_loop.rs @@ -5,6 +5,7 @@ use crate::builder; use crate::daemon::LoopHandlerEvent; use crate::error::BuildError; use crate::nix::options::NixOptions; +use crate::nix::StorePath; use crate::pathreduction::reduce_paths; use crate::project::roots; use crate::project::roots::Roots; @@ -63,6 +64,9 @@ pub struct BuildLoop<'a> { watch: Watch, /// Extra options to pass to each nix invocation extra_nix_options: NixOptions, + /// The store path of the last loop iteration is stored so relinking can + /// be avoided when there is no change. + last_store_path: Option, } impl<'a> BuildLoop<'a> { @@ -73,6 +77,7 @@ impl<'a> BuildLoop<'a> { project, watch: Watch::try_new().expect("Failed to initialize watch"), extra_nix_options, + last_store_path: None, } } @@ -199,7 +204,12 @@ impl<'a> BuildLoop<'a> { &self.extra_nix_options, )?; self.register_paths(&run_result.referenced_paths)?; - self.root_result(run_result.result) + if Some(&run_result.result.path) != self.last_store_path.as_ref() { + self.last_store_path = Some(run_result.result.path.clone()); + self.root_result(run_result.result) + } else { + self.root_result_cached() + } } fn register_paths(&mut self, paths: &[PathBuf]) -> Result<(), notify::Error> { @@ -213,6 +223,14 @@ impl<'a> BuildLoop<'a> { Ok(()) } + fn root_result_cached(&self) -> Result { + let roots = Roots::from_project(&self.project); + + Ok(BuildResults { + output_paths: roots.paths(), + }) + } + fn root_result(&mut self, build: builder::RootedPath) -> Result { let roots = Roots::from_project(&self.project);