commit ec1c1c89cdad13c3332f4c2f63a8e41c5baaabeb Author: Nikkuss Date: Sat Nov 8 21:59:42 2025 +0000 init diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7efdf7b --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +/target +/.compose + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml + +/db.* +/storage_chunks +.devenv +result +upload_test +/log +/log2 +/nix-output-monitor +/build.log + +# Added by cargo +# +# already existing elements were commented out + +#/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8850867 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,467 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "color-eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "console" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indicatif" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade6dfcba0dfb62ad59e59e7241ec8912af34fd29e0e743e3db992bd278e8b65" +dependencies = [ + "console", + "portable-atomic", + "unicode-width", + "unit-prefix", + "web-time", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "nix-output" +version = "0.1.0" +dependencies = [ + "color-eyre", + "indicatif", + "serde", + "serde_json", + "serde_repr", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "owo-colors" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "syn" +version = "2.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unit-prefix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..427de6b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,20 @@ +cargo-features = ["codegen-backend"] + +[package] +name = "nix-output" +version = "0.1.0" +edition = "2024" + +[profile.dev] +codegen-backend = "cranelift" +opt-level = 0 +[profile.dev.package."*"] +codegen-backend = "llvm" +opt-level = 3 + +[dependencies] +color-eyre = "0.6.5" +indicatif = "0.18.2" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = { version = "1.0.145", features = ["raw_value"] } +serde_repr = "0.1.20" diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..65330ee --- /dev/null +++ b/flake.lock @@ -0,0 +1,98 @@ +{ + "nodes": { + "crane": { + "locked": { + "lastModified": 1762538466, + "narHash": "sha256-8zrIPl6J+wLm9MH5ksHcW7BUHo7jSNOu0/hA0ohOOaM=", + "owner": "ipetkov", + "repo": "crane", + "rev": "0cea393fffb39575c46b7a0318386467272182fe", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1762363567, + "narHash": "sha256-YRqMDEtSMbitIMj+JLpheSz0pwEr0Rmy5mC7myl17xs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ae814fd3904b621d8ab97418f1d0f2eb0d3716f4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "crane": "crane", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762569282, + "narHash": "sha256-vINZAJpXQTZd5cfh06Rcw7hesH7sGSvi+Tn+HUieJn8=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a35a6144b976f70827c2fe2f5c89d16d8f9179d8", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..29f8e9a --- /dev/null +++ b/flake.nix @@ -0,0 +1,97 @@ +{ + description = "A very basic flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + crane.url = "github:ipetkov/crane"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { + nixpkgs, + crane, + flake-utils, + rust-overlay, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ + (import rust-overlay) + ]; + }; + inherit (pkgs) lib; + craneLib = (crane.mkLib pkgs).overrideToolchain ( + p: + p.rust-bin.nightly.latest.default.override { + extensions = [ + "rustc-codegen-cranelift-preview" + "rust-analyzer" + "rust-src" + ]; + } + ); + src = craneLib.cleanCargoSource ./.; + commonArgs = { + inherit src; + nativeBuildInputs = with pkgs; [ + pkg-config + nix.dev + ]; + strictDeps = true; + }; + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + individualCrateArgs = commonArgs // { + inherit cargoArtifacts; + inherit (craneLib.crateNameFromCargoToml { inherit src; }) version; + }; + + fileSetForCrate = + crate: + lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./Cargo.toml + ./Cargo.lock + ]; + }; + server = craneLib.buildPackage ( + individualCrateArgs + // { + } + ); + in + { + devShells.default = craneLib.devShell { + inherit (commonArgs) nativeBuildInputs; + RUSTFLAGS = "-Clinker=clang -Clink-arg=-fuse-ld=mold -Z macro-backtrace"; + RUST_LOG = "debug,sqlx=warn"; + packages = with pkgs; [ + mold + heaptrack + llvmPackages.clang + llvmPackages.lld + sea-orm-cli + watchexec + cargo-watch + cargo-edit + cargo-nextest + cargo-valgrind + pkg-config + nix.dev + boost.dev + ]; + }; + + } + ); + +} diff --git a/src/action.rs b/src/action.rs new file mode 100644 index 0000000..bcf37a3 --- /dev/null +++ b/src/action.rs @@ -0,0 +1,151 @@ +use std::borrow::Cow; +use std::fmt::Display; +use std::ops::Deref; + +use color_eyre::eyre::Context; +use serde::Deserialize; +use serde_repr::Deserialize_repr; + +use crate::action_raw::RawAction; + +// --- +// --- ActionType +// --- + +#[derive(Clone, Copy, Debug, Deserialize_repr)] +#[repr(u8)] +#[derive(Eq, PartialEq)] +pub enum ActionType { + Unknown = 0, + CopyPath = 100, + FileTransfer = 101, + Realise = 102, + CopyPaths = 103, + Builds = 104, + Build = 105, + OptimiseStore = 106, + VerifyPaths = 107, + Substitute = 108, + QueryPathInfo = 109, + PostBuildHook = 110, + BuildWaiting = 111, +} + +impl Default for ActionType { + fn default() -> Self { + Self::Unknown + } +} + +// --- +// --- BuildStepId +// --- + +#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Hash)] +pub struct BuildStepId(u64); + +impl Deref for BuildStepId { + type Target = u64; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for BuildStepId { + fn from(value: u64) -> Self { + Self(value) + } +} + +impl From for u64 { + fn from(val: BuildStepId) -> Self { + val.0 + } +} + +impl Display for BuildStepId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +// --- +// --- Action +// --- + +#[derive(Debug, Eq, PartialEq)] +pub enum StartFields<'a> { + Unknown, + CopyPath { + path: Cow<'a, str>, + origin: Cow<'a, str>, + destination: Cow<'a, str>, + }, + FileTransfer { + target: Cow<'a, str>, + }, + Realise, + CopyPaths, + Builds, + Build { + target: Cow<'a, str>, + source: Cow<'a, str>, // TODO: check + val1: u64, + val2: u64, + }, + OptimiseStore, + VerifyPaths, + Substitute { + source: Cow<'a, str>, + target: Cow<'a, str>, + }, + QueryPathInfo, + PostBuildHook, + BuildWaiting, +} + +#[derive(Debug, Eq, PartialEq)] +pub enum ResultFields<'a> { + BuildLogLine(Cow<'a, str>), + SetPhase(&'a str), + Progress { + done: u64, + expected: u64, + running: u64, + failed: u64, + }, + SetExpected { + action: ActionType, + expected: u64, + }, +} + +#[derive(Debug, Eq, PartialEq)] +pub enum Action<'a> { + Msg { + level: u8, + msg: Cow<'a, str>, + }, + Start { + start_type: StartFields<'a>, + id: BuildStepId, + level: u8, + parent: BuildStepId, + text: Cow<'a, str>, + }, + Result { + id: BuildStepId, + fields: ResultFields<'a>, + }, + Stop { + id: BuildStepId, + }, +} + +impl<'a> Action<'a> { + pub fn parse(buf: &'a str) -> color_eyre::Result { + let raw: RawAction = serde_json::from_str(buf).context("Could not parse raw JSON")?; + raw.try_into().context("Could not convert raw action") + } +} diff --git a/src/action_raw.rs b/src/action_raw.rs new file mode 100644 index 0000000..16651cd --- /dev/null +++ b/src/action_raw.rs @@ -0,0 +1,174 @@ +use std::borrow::Cow; + +use color_eyre::eyre::{self, Context}; +use serde::Deserialize; +use serde_json::value::RawValue; +use serde_repr::Deserialize_repr; + +use crate::action::{Action, ActionType, BuildStepId, ResultFields, StartFields}; + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum RawActionType { + Msg, + Start, + Result, + Stop, +} + +#[derive(Debug, Deserialize_repr)] +#[repr(u8)] +pub enum RawEnumType { + FileLinked = 100, + BuildLogLine = 101, + UntrustedPath = 102, + CorruptedPath = 103, + SetPhase = 104, + Progress = 105, + SetExpected = 106, + PostBuildLogLine = 107, +} + +#[derive(Debug, Deserialize)] +#[serde(tag = "action", rename_all = "lowercase")] +pub struct RawAction<'a> { + #[serde(rename = "action")] + pub action_type: RawActionType, + pub level: Option, + pub msg: Option>, + pub id: Option, + pub parent: Option, + pub text: Option>, + #[serde(borrow)] + pub fields: Option<&'a RawValue>, + #[serde(rename = "type")] + pub any_type: Option, +} + +impl<'a> TryFrom> for Action<'a> { + type Error = color_eyre::Report; + + fn try_from(val: RawAction<'a>) -> Result { + let missing = |field: &'static str| eyre::eyre!("missing field `{field}`"); + + let action = match val.action_type { + RawActionType::Msg => Action::Msg { + level: val.level.ok_or_else(|| missing("level"))?, + msg: val.msg.ok_or_else(|| missing("msg"))?, + }, + + RawActionType::Start => { + let start_type: ActionType = + serde_json::from_value(val.any_type.ok_or_else(|| missing("type"))?.into()) + .context("invalid type")?; + + let start_type = match start_type { + ActionType::Unknown => StartFields::Unknown, + ActionType::CopyPath => { + let raw_fields = val.fields.ok_or_else(|| missing("fields"))?.get(); + + let (path, origin, destination) = + serde_json::from_str(raw_fields).context("invalid fields")?; + + StartFields::CopyPath { + path, + origin, + destination, + } + } + ActionType::FileTransfer => { + let raw_fields = val.fields.ok_or_else(|| missing("fields"))?.get(); + + let [target] = + serde_json::from_str(raw_fields).context("invalid fields")?; + + StartFields::FileTransfer { target } + } + ActionType::Realise => StartFields::Realise, + ActionType::CopyPaths => StartFields::CopyPaths, + ActionType::Builds => StartFields::Builds, + ActionType::Build => { + let raw_fields = val.fields.ok_or_else(|| missing("fields"))?.get(); + + let (target, source, val1, val2) = + serde_json::from_str(raw_fields).context("invalid fields")?; + + StartFields::Build { + target, + source, + val1, + val2, + } + } + ActionType::OptimiseStore => StartFields::OptimiseStore, + ActionType::VerifyPaths => StartFields::VerifyPaths, + ActionType::Substitute => { + let raw_fields = val.fields.ok_or_else(|| missing("fields"))?.get(); + + let (source, target) = + serde_json::from_str(raw_fields).context("invalid fields")?; + + StartFields::Substitute { source, target } + } + ActionType::QueryPathInfo => StartFields::QueryPathInfo, + ActionType::PostBuildHook => StartFields::PostBuildHook, + ActionType::BuildWaiting => StartFields::BuildWaiting, + }; + + Action::Start { + start_type, + id: val.id.ok_or_else(|| missing("id"))?, + level: val.level.ok_or_else(|| missing("level"))?, + parent: val.parent.ok_or_else(|| missing("parent"))?, + text: val.text.ok_or_else(|| missing("text"))?, + } + } + + RawActionType::Result => { + let raw_fields = val.fields.ok_or_else(|| missing("fields"))?.get(); + + let fields = match val.any_type.ok_or_else(|| missing("type"))? { + 100 => todo!("FileLinked({raw_fields})"), + 101 => { + let [line] = serde_json::from_str(raw_fields).context("invalid fields")?; + ResultFields::BuildLogLine(line) + } + 102 => todo!("UntrustedPath({raw_fields})"), + 103 => todo!("CorruptedPath({raw_fields})"), + 104 => { + let [phase] = serde_json::from_str(raw_fields).context("invalid fields")?; + ResultFields::SetPhase(phase) + } + 105 => { + let (done, expected, running, failed) = + serde_json::from_str(raw_fields).context("invalid fields")?; + + ResultFields::Progress { + done, + expected, + running, + failed, + } + } + 106 => { + let (action, expected) = serde_json::from_str(raw_fields).unwrap(); + ResultFields::SetExpected { action, expected } + } + 107 => todo!("PostBuildLogLine({raw_fields})"), + v => eyre::bail!("Unknown result type `{v}`"), + }; + + Action::Result { + id: val.id.ok_or_else(|| missing("id"))?, + fields, + } + } + + RawActionType::Stop => Action::Stop { + id: val.id.ok_or_else(|| missing("id"))?, + }, + }; + + Ok(action) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..51e6541 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,115 @@ +use std::{collections::HashMap, thread::sleep, time::Duration}; + +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; + +use crate::action::StartFields; + +pub mod action; +pub mod action_raw; +fn main() -> Result<(), color_eyre::Report> { + color_eyre::install().unwrap(); + let lines = std::fs::read_to_string("log2")?; + // let lines = lines.lines().take(1000).collect::>().join("\n"); + + let progress = MultiProgress::new(); + let lines_pb = progress.add(ProgressBar::new(lines.lines().count() as u64)); + // progress.println("Parsing build.log...")?; + // let pb1 = progress.add(ProgressBar::new(lines.lines().count() as u64)); + // pb1.set_style( + // ProgressStyle::default_spinner() + // .template("[{elapsed_precise:>6}] {msg}") + // .unwrap(), + // ); + // pb1.set_message("Processing line2342s\n|\n|\n>"); + // let pb2 = progress.add(ProgressBar::new(lines.lines().count() as u64)); + // pb2.set_style( + // ProgressStyle::default_spinner() + // .template("[{elapsed_precise:>6}] {msg}") + // .unwrap(), + // ); + // pb2.set_message("Processing line2342s\n|\n|\n>"); + // sleep(Duration::from_secs(1)); + + let mut map = HashMap::new(); + + for line in lines.lines() { + lines_pb.inc(1); + let line = line.strip_prefix("@nix ").unwrap_or(line); + // sleep(Duration::from_millis(5)); + let action = action::Action::parse(line)?; + match action { + action::Action::Msg { level, msg } => { + progress.println(format!("MSG (level {level}): {msg}"))?; + } + action::Action::Start { + start_type, + id, + level, + parent, + text, + } => match start_type { + StartFields::CopyPath { + path, + origin, + destination, + } => { + progress.println(format!( + "START (id: {}, level: {}, parent: {}): CopyPath - {} (from: {}, to: {})", + id, level, parent, text, origin, destination + ))?; + } + StartFields::FileTransfer { target } => { + let bar = progress.add(ProgressBar::new(100)); + bar.set_style( + ProgressStyle::default_bar() + .template("{msg} [{bar:40.cyan/blue}] {pos:>3}%") + .unwrap(), + ); + bar.set_message(format!("meow {id} ")); + map.insert(id, bar); + } + _ => {} + }, + action::Action::Stop { id } => { + if let Some(bar) = map.get(&id) { + bar.finish(); + // bar.finish_with_message(format!("Transfer stopped (id: {})", id)); + progress.remove(bar); + map.remove(&id); + } + // progress.println(format!("STOP (id: {})", id))?; + } + action::Action::Result { id, fields } => { + // progress.println(format!("RESULT (id: {}): {:?}", id, fields))?; + match fields { + action::ResultFields::Progress { + done, + expected, + running, + failed, + } => { + sleep(Duration::from_millis(1)); + if let Some(bar) = map.get(&id) { + let percentage = if expected == 0 { + 0 + } else { + (done * 100 / expected) as u64 + }; + bar.set_position(percentage); + // if done >= expected { + // bar.finish_with_message(format!("Completed transfer (id: {})", id)); + // map.remove(&id); + // } + } + } + _ => {} + } + } + _ => { + println!("{action:#?}"); + } + } + } + + Ok(()) +}