From 7eb36ce0a49db618b9b96e970b3d920b8e7cd774 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 14 Feb 2026 22:15:09 -0500 Subject: [PATCH] Add sqlite for tracking build history. --- Cargo.lock | 166 +++++++++++++++++++++++- Cargo.toml | 6 +- flake.lock | 48 +++++++ flake.nix | 66 ++++++++++ migrations/20250708013159_init.down.sql | 1 + migrations/20250708013159_init.up.sql | 7 + src/command/build/runner.rs | 32 +++-- src/config/root.rs | 7 + src/database/db_handle.rs | 80 ++++++++++++ src/database/migration.rs | 15 +++ src/database/mod.rs | 2 + src/error/error.rs | 14 ++ src/fs_util.rs | 5 +- src/git_util/core.rs | 14 +- src/main.rs | 7 +- src/nix_util/high_level.rs | 2 +- 16 files changed, 442 insertions(+), 30 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 migrations/20250708013159_init.down.sql create mode 100644 migrations/20250708013159_init.up.sql create mode 100644 src/database/db_handle.rs create mode 100644 src/database/migration.rs create mode 100644 src/database/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 45c1488..733cad5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,21 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.21" @@ -204,12 +219,34 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cc" +version = "1.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-link 0.1.3", +] + [[package]] name = "clap" version = "4.5.54" @@ -270,6 +307,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -405,6 +448,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "flume" version = "0.11.1" @@ -702,6 +751,30 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" version = "2.1.1" @@ -893,6 +966,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ + "cc", "pkg-config", "vcpkg", ] @@ -1177,7 +1251,7 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -1523,6 +1597,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.5" @@ -1617,6 +1697,7 @@ checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ "base64 0.22.1", "bytes", + "chrono", "crc", "crossbeam-queue", "either", @@ -1637,8 +1718,11 @@ dependencies = [ "sha2", "smallvec", "thiserror 2.0.18", + "tokio", + "tokio-stream", "tracing", "url", + "uuid", ] [[package]] @@ -1675,6 +1759,7 @@ dependencies = [ "sqlx-postgres", "sqlx-sqlite", "syn 2.0.114", + "tokio", "url", ] @@ -1689,6 +1774,7 @@ dependencies = [ "bitflags 2.11.0", "byteorder", "bytes", + "chrono", "crc", "digest", "dotenvy", @@ -1717,6 +1803,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", + "uuid", "whoami", ] @@ -1730,6 +1817,7 @@ dependencies = [ "base64 0.22.1", "bitflags 2.11.0", "byteorder", + "chrono", "crc", "dotenvy", "etcetera", @@ -1754,6 +1842,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", + "uuid", "whoami", ] @@ -1764,6 +1853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" dependencies = [ "atoi", + "chrono", "flume", "futures-channel", "futures-core", @@ -1779,6 +1869,7 @@ dependencies = [ "thiserror 2.0.18", "tracing", "url", + "uuid", ] [[package]] @@ -2233,6 +2324,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -2327,12 +2428,71 @@ dependencies = [ "wasite", ] +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2366,7 +2526,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2406,7 +2566,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", diff --git a/Cargo.toml b/Cargo.toml index 7c74465..b4fc51d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ opentelemetry-semantic-conventions = { version = "0.12.0", optional = true } serde = { version = "1.0.228", default-features = false, features = ["std", "derive"] } serde_json = { version = "1.0.149", default-features = false, features = ["std"] } sha2 = { version = "0.10.9", default-features = false, features = ["std"] } -sqlx = "0.8.6" +sqlx = { version = "0.8.6", default-features = false, features = ["runtime-tokio", "sqlite", "migrate", "macros", "uuid", "chrono"] } tokio = { version = "1.49.0", default-features = false, features = ["rt", "rt-multi-thread", "fs", "io-util", "process"] } toml = { version = "0.9.11", default-features = false, features = ["display", "parse", "serde", "std"] } tracing = { version = "0.1.37", optional = true } @@ -28,3 +28,7 @@ url = { version = "2.5.8", default-features = false, features = ["std"] } inherits = "release" lto = true strip = "symbols" + +[profile.dev.package.sqlx-macros] +# Faster compile-time verified macros +opt-level = 3 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..5260e65 --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1771008912, + "narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a82ccc39b39b621151d6732718e3e250109076fa", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1771125043, + "narHash": "sha256-ldf/s49n6rOAxl7pYLJGGS1N/assoHkCOWdEdLyNZkc=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "4912f951a26dc8142b176be2c2ad834319dc06e8", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3d47dae --- /dev/null +++ b/flake.nix @@ -0,0 +1,66 @@ +{ + description = "nix_builder development environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; + }; + }; + + outputs = + { + self, + nixpkgs, + rust-overlay, + }: + let + forAllSystems = + func: + builtins.listToAttrs ( + map (system: { + name = system; + value = func system; + }) nixpkgs.lib.systems.flakeExposed + ); + + in + { + devShells = forAllSystems ( + system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { + inherit system overlays; + }; + rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + in + { + default = pkgs.mkShell { + nativeBuildInputs = [ + pkgs.pkg-config + rustToolchain + ]; + buildInputs = with pkgs; [ + sqlx-cli # For sqlx CLI to manage migrations + sqlite # To access the database (sqlite is bundled into the nix_builder binary but this is for manually accessing the db). + ]; + shellHook = '' + cat < + + Generate metadata for query!() macros: + cargo sqlx prepare + EOF + ''; + }; + } + ); + }; +} diff --git a/migrations/20250708013159_init.down.sql b/migrations/20250708013159_init.down.sql new file mode 100644 index 0000000..24de1b2 --- /dev/null +++ b/migrations/20250708013159_init.down.sql @@ -0,0 +1 @@ +DROP TABLE build; diff --git a/migrations/20250708013159_init.up.sql b/migrations/20250708013159_init.up.sql new file mode 100644 index 0000000..4e13e29 --- /dev/null +++ b/migrations/20250708013159_init.up.sql @@ -0,0 +1,7 @@ +CREATE TABLE build ( + id INTEGER NOT NULL PRIMARY KEY, + start_time INTEGER NOT NULL, + end_time INTEGER, + status INTEGER, + target TEXT NOT NULL +) STRICT; diff --git a/src/command/build/runner.rs b/src/command/build/runner.rs index f03e266..d300f90 100644 --- a/src/command/build/runner.rs +++ b/src/command/build/runner.rs @@ -1,18 +1,32 @@ +use crate::Result; use crate::cli::parameters::BuildArgs; use crate::config::Config; use crate::config::TargetConfig; -use crate::error::CustomError; +use crate::database::db_handle::DbHandle; use crate::fs_util::assert_directory; use crate::fs_util::is_git_repo; use crate::git_util::git_force_into_state; use crate::git_util::git_init_at_rev; use crate::nix_util::nixos_build_target; -pub(crate) async fn run_build(args: BuildArgs) -> Result<(), CustomError> { +pub(crate) async fn run_build(args: BuildArgs) -> Result<()> { println!("{:?}", args); let config = Config::load_from_file(args.config).await?; println!("{:?}", config); + let database_path = config.get_database_path()?; + let database_parent = database_path + .parent() + .expect("Database should exist in a folder."); + let database_path = database_path.to_string_lossy(); + assert_directory!( + database_parent, + "Creating database directory {}", + database_parent.to_string_lossy() + ); + + let db_handle = DbHandle::new(Some(database_path)).await?; + for target_name in args.target { let target_config = { let target_config = config.get_target_config(&target_name)?; @@ -30,15 +44,12 @@ pub(crate) async fn run_build(args: BuildArgs) -> Result<(), CustomError> { Ok(()) } -async fn prepare_flake_repo( - config_root: &Config, - target_config: &TargetConfig, -) -> Result<(), CustomError> { +async fn prepare_flake_repo(config_root: &Config, target_config: &TargetConfig) -> Result<()> { let repo_directory = target_config.get_repo_directory(config_root)?; assert_directory!( &repo_directory, "Creating repo directory {}", - (&repo_directory).to_string_lossy() + repo_directory.to_string_lossy() ); if is_git_repo(&repo_directory).await? { @@ -63,16 +74,13 @@ async fn prepare_flake_repo( Ok(()) } -async fn build_target( - config_root: &Config, - target_config: &TargetConfig, -) -> Result<(), CustomError> { +async fn build_target(config_root: &Config, target_config: &TargetConfig) -> Result<()> { let flake_directory = target_config.get_flake_directory(config_root)?; let build_directory = target_config.get_build_directory(config_root)?; assert_directory!( &build_directory, "Creating build directory {}", - (&build_directory).to_string_lossy() + build_directory.to_string_lossy() ); nixos_build_target(build_directory, flake_directory, target_config.get_attr()?).await?; diff --git a/src/config/root.rs b/src/config/root.rs index 1879307..6f6d0be 100644 --- a/src/config/root.rs +++ b/src/config/root.rs @@ -73,4 +73,11 @@ impl Config { let work_dir = current_dir.join("work"); Ok(Cow::Owned(work_dir)) } + + /// The path to the sqlite database where run history is stored. + pub(crate) fn get_database_path(&self) -> Result, CustomError> { + let output_directory = self.get_output_directory()?; + let database_path = output_directory.join("nix_builder.sqlite"); + Ok(Cow::Owned(database_path)) + } } diff --git a/src/database/db_handle.rs b/src/database/db_handle.rs new file mode 100644 index 0000000..8ca54de --- /dev/null +++ b/src/database/db_handle.rs @@ -0,0 +1,80 @@ +use sqlx::Executor; +use sqlx::Pool; +use sqlx::Sqlite; +use sqlx::migrate::MigrateDatabase; +use sqlx::sqlite::SqlitePoolOptions; +use tracing::info; +use tracing::warn; + +use super::migration::run_migrations; +use crate::Result; + +pub(crate) struct DbHandle { + pub(crate) conn: Pool, +} + +impl DbHandle { + pub(crate) async fn new>(db_path: Option

) -> Result { + let db_path = db_path.as_ref().map(|p| p.as_ref()); + let options = SqlitePoolOptions::new() + .max_connections(5) + .test_before_acquire(true) + .after_connect(|conn, _meta| { + Box::pin(async move { + // Enforce foreign keys. + conn.execute("PRAGMA foreign_keys = ON;").await?; + // Allows writes at the same time as reads. + conn.execute("PRAGMA journal_mode = WAL;").await?; + // Do not sync to disk after *every* write. + conn.execute("PRAGMA synchronous = NORMAL;").await?; + // Keep 10k database pages in memory (~40MiB). + conn.execute("PRAGMA cache_size = 10000;").await?; + // Stores temporary tables, indexes, and sorting operations in memory. + conn.execute("PRAGMA temp_store = MEMORY;").await?; + // Use mmap to access database. + conn.execute("PRAGMA mmap_size = 268435456;").await?; + // Clear space of deleted rows at transaction end. + conn.execute("PRAGMA auto_vacuum = FULL;").await?; + + Ok(()) + }) + }) + .after_release(|conn, _meta| { + Box::pin(async move { + // Attempt to optimize the database. (Currently just runs ANALYZE) + conn.execute("PRAGMA optimize;").await?; + // Rebuild the DB file which defragments and clears out deleted pages. + conn.execute("VACUUM;").await?; + Ok(true) + }) + }); + let conn = match db_path { + Some(path) => { + info!("Connecting to sqlite database at {path}"); + if !Sqlite::database_exists(path).await.unwrap_or(false) { + info!("Creating a new sqlite database at {path}"); + Sqlite::create_database(path).await.unwrap(); + } else { + info!("Connecting to existing sqlite database at {path}"); + } + let full_url = format!("sqlite:{path}"); + options.connect(&full_url).await? + } + None => { + warn!("No sqlite_path set in config. Using an in-memory database."); + // We force it to a single connection that never dies or else the data and schema in the in-memory DB is lost. + options + .min_connections(1) + .max_connections(1) + .idle_timeout(None) + .max_lifetime(None) + .connect("sqlite::memory:") + .await? + } + }; + + run_migrations(&conn).await?; + + Ok(DbHandle { conn }) + } +} diff --git a/src/database/migration.rs b/src/database/migration.rs new file mode 100644 index 0000000..d67168b --- /dev/null +++ b/src/database/migration.rs @@ -0,0 +1,15 @@ +use std::ops::Deref; + +use sqlx::Acquire; +use sqlx::migrate::Migrate; + +use crate::Result; + +pub(crate) async fn run_migrations<'a, A>(db: A) -> Result<()> +where + A: Acquire<'a>, + ::Target: Migrate, +{ + sqlx::migrate!("./migrations").run(db).await?; + Ok(()) +} diff --git a/src/database/mod.rs b/src/database/mod.rs new file mode 100644 index 0000000..1e6b5e2 --- /dev/null +++ b/src/database/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod db_handle; +pub(crate) mod migration; diff --git a/src/error/error.rs b/src/error/error.rs index 6cd3515..795d8b9 100644 --- a/src/error/error.rs +++ b/src/error/error.rs @@ -14,6 +14,8 @@ pub(crate) enum CustomError { FromUtf8(#[allow(dead_code)] FromUtf8Error), PathStripPrefix(#[allow(dead_code)] std::path::StripPrefixError), UrlParseError(#[allow(dead_code)] url::ParseError), + Migrate(#[allow(dead_code)] sqlx::migrate::MigrateError), + Sql(#[allow(dead_code)] sqlx::Error), } impl From for CustomError { @@ -81,3 +83,15 @@ impl From for CustomError { CustomError::UrlParseError(value) } } + +impl From for CustomError { + fn from(value: sqlx::migrate::MigrateError) -> Self { + CustomError::Migrate(value) + } +} + +impl From for CustomError { + fn from(value: sqlx::Error) -> Self { + CustomError::Sql(value) + } +} diff --git a/src/fs_util.rs b/src/fs_util.rs index 013fe4f..f147974 100644 --- a/src/fs_util.rs +++ b/src/fs_util.rs @@ -23,10 +23,7 @@ use crate::error::CustomError; pub(crate) async fn is_directory>(dir: D) -> Result { let metadata = tokio::fs::metadata(dir).await; - let result = match metadata { - Ok(metadata) if metadata.is_dir() => true, - _ => false, - }; + let result = matches!(metadata, Ok(metadata) if metadata.is_dir()); Ok(result) } diff --git a/src/git_util/core.rs b/src/git_util/core.rs index 127bac3..d0a0740 100644 --- a/src/git_util/core.rs +++ b/src/git_util/core.rs @@ -15,7 +15,7 @@ where let dest = AsRef::::as_ref(dest.as_ref()); command.arg("-C"); command.arg(dest); - command.args(&["init"]); + command.args(["init"]); command.arg(format!("--initial-branch={}", branch.as_ref())); command.kill_on_drop(true); let output = command.output().await?; @@ -43,7 +43,7 @@ where let mut command = Command::new("git"); command.arg("-C"); command.arg(dest); - command.args(&["remote", "add"]); + command.args(["remote", "add"]); command.arg(name); command.arg(url); command.kill_on_drop(true); @@ -78,7 +78,7 @@ where let mut command = Command::new("git"); command.arg("-C"); command.arg(dest); - command.args(&["fetch"]); + command.args(["fetch"]); if let Some(d) = depth { command.arg(format!("--depth={}", d)); } @@ -118,7 +118,7 @@ where let mut command = Command::new("git"); command.arg("-C"); command.arg(dest); - command.args(&["checkout"]); + command.args(["checkout"]); if force { command.arg("--force"); } @@ -149,7 +149,7 @@ where let mut command = Command::new("git"); command.arg("-C"); command.arg(dest); - command.args(&["remote", "get-url"]); + command.args(["remote", "get-url"]); command.arg(remote.as_ref()); command.kill_on_drop(true); let output = command.output().await?; @@ -181,7 +181,7 @@ where let mut command = Command::new("git"); command.arg("-C"); command.arg(dest); - command.args(&["reset"]); + command.args(["reset"]); if hard { command.arg("--hard"); } @@ -213,7 +213,7 @@ where let mut command = Command::new("git"); command.arg("-C"); command.arg(dest); - command.args(&["clean"]); + command.args(["clean"]); if recurse_into_untracked_directories { command.arg("-d"); } diff --git a/src/main.rs b/src/main.rs index 41507cf..7bdbc67 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,18 +12,21 @@ use self::init_tracing::shutdown_telemetry; mod cli; mod command; mod config; +mod database; mod error; mod fs_util; mod git_util; mod init_tracing; mod nix_util; -fn main() -> Result { +pub(crate) type Result = std::result::Result; + +fn main() -> Result { let rt = tokio::runtime::Runtime::new()?; rt.block_on(async { main_body().await }) } -async fn main_body() -> Result { +async fn main_body() -> Result { init_telemetry().expect("Telemetry should initialize successfully."); let args = Cli::parse(); match args.command { diff --git a/src/nix_util/high_level.rs b/src/nix_util/high_level.rs index e872a37..2dabd54 100644 --- a/src/nix_util/high_level.rs +++ b/src/nix_util/high_level.rs @@ -29,7 +29,7 @@ where // nixos-rebuild build --show-trace --sudo --max-jobs "$JOBS" --flake "$DIR/../../#odo" --log-format internal-json -v "${@}" let mut command = Command::new("nixos-rebuild"); command.current_dir(build_path); - command.args(&[ + command.args([ "build", "--show-trace", "--sudo",