Skip to content
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

Improve gc op #123

Open
wants to merge 12 commits into
base: canon
Choose a base branch
from
Open
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
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions Cargo.nix

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ thiserror = "1.0"

# TODO: update to 0.3
structopt.version = "0.2"

# TODO: update to 0.3
structopt.default-features = false

# TODO: update to 0.3
structopt.features = [
# "default",
"suggestions",
Expand Down Expand Up @@ -55,11 +59,14 @@ lazy_static = "1.4.0"
md5 = "0.7.0"
vec1 = ">= 1.1.0, <1.7.0"
human-panic = { path = "vendor/human-panic" }
itertools = "0.12.1"

[dev-dependencies]
# 1.0.0 requires at least rust 1.50
proptest.version = "0.10.1"
# 1.0.0 requires at least rust 1.50
proptest.default-features = false
# 1.0.0 requires at least rust 1.50
proptest.features = [
"std",
# reenable if proptest kills the test runner
Expand Down
11 changes: 3 additions & 8 deletions shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@ let
CARGO_INSTALL_ROOT = "${LORRI_ROOT}/.cargo";

buildInputs = [
pkgs.cargo
pkgs.rustc
pkgs.rustfmt
pkgs.rustPackages.clippy
# please use rustup to install rust, setting it up via nix is a bother
pkgs.rustup
pkgs.git
pkgs.direnv
pkgs.crate2nix
Expand Down Expand Up @@ -80,10 +78,7 @@ in
pkgs.mkShell (
{
name = "lorri";
buildInputs = buildInputs
++ pkgs.lib.optionals isDevelopmentShell [
pkgs.rust-analyzer
];
inherit buildInputs;

inherit BUILD_REV_COUNT RUN_TIME_CLOSURE;

Expand Down
84 changes: 15 additions & 69 deletions src/build_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! evaluate and build a given Nix file.

use crate::builder::{self, BuildError};
use crate::cas::ContentAddressable;
use crate::daemon::LoopHandlerEvent;
use crate::nix::options::NixOptions;
use crate::pathreduction::reduce_paths;
Expand All @@ -17,7 +18,7 @@ use std::path::PathBuf;
/// Build events that can happen.
/// Abstracting over its internal to make different serialize instances possible.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EventI<NixFile, Reason, OutputPath, BuildError> {
pub enum Event {
/// Demarks a stream of events from recent history becoming live
SectionEnd,
/// A build has started
Expand All @@ -32,7 +33,7 @@ pub enum EventI<NixFile, Reason, OutputPath, BuildError> {
/// The shell.nix file for the building project
nix_file: NixFile,
/// the output paths of the build
rooted_output_paths: OutputPath,
rooted_output_paths: builder::OutputPath,
},
/// A build command returned a failing exit status
Failure {
Expand All @@ -43,75 +44,16 @@ pub enum EventI<NixFile, Reason, OutputPath, BuildError> {
},
}

/// Builder events sent back over `BuildLoop.tx`.
pub type Event = EventI<NixFile, Reason, builder::OutputPath<project::RootPath>, BuildError>;

impl<NixFile, Reason, OutputPath, BuildError> EventI<NixFile, Reason, OutputPath, BuildError> {
/// Map over the inner types.
pub fn map<F, G, H, I, NixFile2, Reason2, OutputPaths2, BuildError2>(
self,
nix_file_f: F,
reason_f: G,
output_paths_f: H,
build_error_f: I,
) -> EventI<NixFile2, Reason2, OutputPaths2, BuildError2>
where
F: Fn(NixFile) -> NixFile2,
G: Fn(Reason) -> Reason2,
H: Fn(OutputPath) -> OutputPaths2,
I: Fn(BuildError) -> BuildError2,
{
use EventI::*;
match self {
SectionEnd => SectionEnd,
Started { nix_file, reason } => Started {
nix_file: nix_file_f(nix_file),
reason: reason_f(reason),
},
Completed {
nix_file,
rooted_output_paths,
} => Completed {
nix_file: nix_file_f(nix_file),
rooted_output_paths: output_paths_f(rooted_output_paths),
},
Failure { nix_file, failure } => Failure {
nix_file: nix_file_f(nix_file),
failure: build_error_f(failure),
},
}
}
}

/// Description of the project change that triggered a build.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ReasonI<NixFile> {
/// When a project is presented to Lorri to track, it's built for this reason.
ProjectAdded(NixFile),
/// When a ping is received.
pub enum Reason {
/// We received a ping, requesting us to reevaluate and maybe build the project
PingReceived,
/// When there is a filesystem change, the first changed file is recorded,
/// along with a count of other filesystem events.
FilesChanged(Vec<PathBuf>),
}

impl<NixFile> ReasonI<NixFile> {
/// Map over the inner types.
pub fn map<F, NixFile2>(self, nix_file_f: F) -> ReasonI<NixFile2>
where
F: Fn(NixFile) -> NixFile2,
{
use ReasonI::*;
match self {
ProjectAdded(nix_file) => ProjectAdded(nix_file_f(nix_file)),
PingReceived => PingReceived,
FilesChanged(vec) => FilesChanged(vec),
}
}
}

type Reason = ReasonI<NixFile>;

/// The BuildLoop repeatedly builds the Nix expression in
/// `project` each time a source file influencing
/// a previous build changes.
Expand All @@ -126,6 +68,8 @@ pub struct BuildLoop<'a> {
/// Watches all input files for changes.
/// As new input files are discovered, they are added to the watchlist.
watch: Watch,
/// Content addressable store to save static files in.
cas: ContentAddressable,
nix_gc_root_user_dir: project::NixGcRootUserDir,
logger: slog::Logger,
}
Expand Down Expand Up @@ -168,6 +112,7 @@ impl<'a> BuildLoop<'a> {
project: &'a Project,
extra_nix_options: NixOptions,
nix_gc_root_user_dir: project::NixGcRootUserDir,
cas: ContentAddressable,
logger: slog::Logger,
) -> anyhow::Result<BuildLoop<'a>> {
let mut watch = Watch::try_new(logger.clone()).map_err(|err| anyhow!(err))?;
Expand All @@ -187,6 +132,7 @@ impl<'a> BuildLoop<'a> {
extra_nix_options,
watch,
nix_gc_root_user_dir,
cas,
logger,
})
}
Expand Down Expand Up @@ -303,26 +249,26 @@ impl<'a> BuildLoop<'a> {
/// Start an actual build, asynchronously.
fn start_build(&self) -> Async<Result<builder::RunResult, BuildError>> {
let nix_file = self.project.nix_file.clone();
let cas = self.project.cas.clone();
let cas = self.cas.clone();
let extra_nix_options = self.extra_nix_options.clone();
let logger2 = self.logger.clone();
crate::run_async::Async::run(&self.logger, move || {
builder::run(&nix_file, &cas, &extra_nix_options, &logger2)
builder::instantiate_and_build(&nix_file, &cas, &extra_nix_options, &logger2)
})
}

/// Execute a single build of the environment.
///
/// This will create GC roots and expand the file watch list for
/// the evaluation.
pub fn once(&mut self) -> Result<builder::OutputPath<project::RootPath>, BuildError> {
pub fn once(&mut self) -> Result<builder::OutputPath, BuildError> {
let nix_file = self.project.nix_file.clone();
let cas = self.project.cas.clone();
let cas = self.cas.clone();
let extra_nix_options = self.extra_nix_options.clone();
let logger2 = self.logger.clone();
self.handle_run_result(
crate::run_async::Async::run(&self.logger, move || {
builder::run(&nix_file, &cas, &extra_nix_options, &logger2)
builder::instantiate_and_build(&nix_file, &cas, &extra_nix_options, &logger2)
})
.block(),
)
Expand All @@ -331,7 +277,7 @@ impl<'a> BuildLoop<'a> {
fn handle_run_result(
&mut self,
run_result: Result<builder::RunResult, BuildError>,
) -> Result<builder::OutputPath<project::RootPath>, BuildError> {
) -> Result<builder::OutputPath, BuildError> {
let run_result = run_result?;
let paths = run_result.referenced_paths;

Expand Down
23 changes: 6 additions & 17 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use crate::cas::ContentAddressable;
use crate::nix::{options::NixOptions, StorePath};
use crate::osstrlines;
use crate::project::RootPath;
use crate::watch::WatchPathBuf;
use crate::{DrvFile, NixFile};
use regex::Regex;
Expand Down Expand Up @@ -390,7 +391,7 @@ pub struct RunResult {
///
/// Instruments the nix file to gain extra information,
/// which is valuable even if the build fails.
pub fn run(
pub fn instantiate_and_build(
root_nix_file: &NixFile,
cas: &ContentAddressable,
extra_nix_options: &NixOptions,
Expand Down Expand Up @@ -475,21 +476,9 @@ where

/// Output path generated by `logged-evaluation.nix`
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutputPath<T> {
pub struct OutputPath {
/// Shell path modified to work as a gc root
pub shell_gc_root: T,
}

impl<T> OutputPath<T> {
/// map over the inner type.
pub fn map<F, T2>(self, f: F) -> OutputPath<T2>
where
F: Fn(T) -> T2,
{
OutputPath {
shell_gc_root: f(self.shell_gc_root),
}
}
pub shell_gc_root: RootPath,
}

#[cfg(test)]
Expand Down Expand Up @@ -584,7 +573,7 @@ in {}
print!("{}", nix_drv);

// build, because instantiate doesn’t return the build output (obviously …)
run(
instantiate_and_build(
&crate::NixFile::from(cas.file_from_string(&nix_drv)?),
&cas,
&NixOptions::empty(),
Expand All @@ -605,7 +594,7 @@ in {}
&format!("dep = {};", drv("dep", r#"args = [ "-c" "exit 1" ];"#)),
))?);

if let Err(BuildError::Exit { .. }) = run(
if let Err(BuildError::Exit { .. }) = instantiate_and_build(
&d,
&cas,
&NixOptions::empty(),
Expand Down
3 changes: 3 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pub enum GcSubcommand {
/// Also delete the root of projects that were last built before this amount of time, e.g. 30d.
#[structopt(long = "older-than", parse(try_from_str = "human_friendly_duration"))]
older_than: Option<Duration>,
/// Only print which gc roots would be deleted. No `--json` output yet.
#[structopt(long = "dry-run")]
dry_run: bool,
},
}

Expand Down
Loading
Loading