diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..e6b69f7 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +if has nix; then + use flake . +fi diff --git a/Cargo.toml b/Cargo.toml index 5303750..59f9a53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "seidr" version = "0.2.0" authors = ["Christina Sørensen"] edition = "2021" -rust-version = "1.69.0" +rust-version = "1.70.0" description = "A Rust GitOps/symlinkfarm orchestrator inspired by GNU Stow." documentation = "https://github.com/cafkafk/seidr" readme = "./README.org" diff --git a/benches/basic_bench.rs b/benches/basic_bench.rs index fafb388..4d24f23 100644 --- a/benches/basic_bench.rs +++ b/benches/basic_bench.rs @@ -1,6 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use seidr::git::Config; use relative_path::RelativePath; +use seidr::git::Config; pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("config loading time", |b| { diff --git a/flake.lock b/flake.lock index e2d15fc..c5599de 100644 --- a/flake.lock +++ b/flake.lock @@ -1,81 +1,5 @@ { "nodes": { - "advisory-db": { - "flake": false, - "locked": { - "lastModified": 1695296241, - "narHash": "sha256-t3SBLTqXyMlloAC0qSTHRAlWweiww6rmp0gSotDy1yo=", - "owner": "rustsec", - "repo": "advisory-db", - "rev": "81594d9fd5b32c3eaa199812475498b47fc98742", - "type": "github" - }, - "original": { - "owner": "rustsec", - "repo": "advisory-db", - "type": "github" - } - }, - "crane": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ], - "rust-overlay": "rust-overlay" - }, - "locked": { - "lastModified": 1695511445, - "narHash": "sha256-mnE14re43v3/Jc50Jv0BKPMtEk7FEtDSligP6B5HwlI=", - "owner": "ipetkov", - "repo": "crane", - "rev": "3de322e06fc88ada5e3589dc8a375b73e749f512", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, - "fenix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ], - "rust-analyzer-src": [] - }, - "locked": { - "lastModified": 1695622936, - "narHash": "sha256-3bnz0FxC/x3K2/E2b2OBG+Iexyh/Fcpq2hZU+lxtLdA=", - "owner": "nix-community", - "repo": "fenix", - "rev": "4fa09c7203bef57254bb1cb1d4bab76fdae34dd5", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems" @@ -99,11 +23,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", "owner": "numtide", "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", "type": "github" }, "original": { @@ -112,13 +36,44 @@ "type": "github" } }, + "naersk": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1694081375, + "narHash": "sha256-vzJXOUnmkMCm3xw8yfPP5m8kypQ3BhAIRe4RRCWpzy8=", + "owner": "nix-community", + "repo": "naersk", + "rev": "3f976d822b7b37fc6fb8e6f157c2dd05e7e94e89", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1695318763, - "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", + "path": "/nix/store/r88zkfh22shcgj0c4zh9jj2q5r1z9wjn-source", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1696419054, + "narHash": "sha256-EdR+dIKCfqL3voZUDYwcvgRDOektQB9KbhBVcE0/3Mo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", + "rev": "7131f3c223a2d799568e4b278380cd9dac2b8579", "type": "github" }, "original": { @@ -128,32 +83,58 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1681358109, + "narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1695644571, + "narHash": "sha256-asS9dCCdlt1lPq0DLwkVBbVoEKuEuz+Zi3DG7pR/RxA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "6500b4580c2a1f3d0f980d32d285739d8e156d92", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { - "advisory-db": "advisory-db", - "crane": "crane", - "fenix": "fenix", - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs" + "flake-utils": "flake-utils", + "naersk": "naersk", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay", + "treefmt-nix": "treefmt-nix" } }, "rust-overlay": { "inputs": { - "flake-utils": [ - "crane", - "flake-utils" - ], - "nixpkgs": [ - "crane", - "nixpkgs" - ] + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1695003086, - "narHash": "sha256-d1/ZKuBRpxifmUf7FaedCqhy0lyVbqj44Oc2s+P5bdA=", + "lastModified": 1696558324, + "narHash": "sha256-TnnP4LGwDB8ZGE7h2n4nA9Faee8xPkMdNcyrzJ57cbw=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "b87a14abea512d956f0b89d0d8a1e9b41f3e20ff", + "rev": "fdb37574a04df04aaa8cf7708f94a9309caebe2b", "type": "github" }, "original": { @@ -191,6 +172,24 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1695822946, + "narHash": "sha256-IQU3fYo0H+oGlqX5YrgZU3VRhbt2Oqe6KmslQKUO4II=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "720bd006d855b08e60664e4683ccddb7a9ff614a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index ab46ca7..d576828 100644 --- a/flake.nix +++ b/flake.nix @@ -1,154 +1,113 @@ { - description = "Build a cargo project"; + description = "Hon hafði um sik hnjóskulinda, ok var þar á skjóðupungr mikill, ok varðveitti hon þar í töfr sín, þau er hon þurfti til fróðleiks at hafa."; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - - crane = { - url = "github:ipetkov/crane"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - fenix = { - url = "github:nix-community/fenix"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.rust-analyzer-src.follows = ""; - }; - flake-utils.url = "github:numtide/flake-utils"; - - advisory-db = { - url = "github:rustsec/advisory-db"; - flake = false; - }; + naersk.url = "github:nix-community/naersk"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + treefmt-nix.url = "github:numtide/treefmt-nix"; + rust-overlay.url = "github:oxalica/rust-overlay"; }; - outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { - inherit system; + outputs = { + self, + flake-utils, + naersk, + nixpkgs, + treefmt-nix, + rust-overlay, + }: + flake-utils.lib.eachDefaultSystem ( + system: let + overlays = [(import rust-overlay)]; + + pkgs = (import nixpkgs) { + inherit system overlays; }; - inherit (pkgs) lib; + toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; - craneLib = crane.lib.${system}; - - # When filtering sources, we want to allow assets other than .rs files - src = lib.cleanSourceWith { - src = ./.; # The original, unfiltered source - filter = path: type: - (lib.hasSuffix "\.yaml" path) || - # (lib.hasSuffix "\.scss" path) || - # Example of a folder for images, icons, etc - #(lib.hasInfix "test" path) || - # Default filter from crane (allow .rs files) - (craneLib.filterCargoSources path type) - ; + naersk' = pkgs.callPackage naersk { + cargo = toolchain; + rustc = toolchain; + clippy = toolchain; }; - # Common arguments can be set here to avoid repeating them later - commonArgs = { - inherit src; - - buildInputs = [ - # test-directory - # Add additional build inputs here - ] ++ lib.optionals pkgs.stdenv.isDarwin [ - # Additional darwin specific inputs can be set here - pkgs.libiconv - ]; - - # Additional environment variables can be set directly - # MY_CUSTOM_VAR = "some value"; - RUST_BACKTRACE = 1; - }; - - craneLibLLvmTools = craneLib.overrideToolchain - (fenix.packages.${system}.complete.withComponents [ - "cargo" - "llvm-tools" - "rustc" - ]); - - # Build *just* the cargo dependencies, so we can reuse - # all of that work (e.g. via cachix) when running in CI - cargoArtifacts = craneLib.buildDepsOnly commonArgs; - - # Build the actual crate itself, reusing the dependency - # artifacts from above. - my-crate = craneLib.buildPackage (commonArgs // { - inherit cargoArtifacts; - }); - in - { - checks = { - # Build the crate as part of `nix flake check` for convenience - inherit my-crate; - - # Run clippy (and deny all warnings) on the crate source, - # again, resuing the dependency artifacts from above. - # - # Note that this is done as a separate derivation so that - # we can block the CI if there are issues here, but not - # prevent downstream consumers from building our crate by itself. - my-crate-clippy = craneLib.cargoClippy (commonArgs // { - inherit cargoArtifacts; - cargoClippyExtraArgs = "--all-targets -- --deny warnings"; - }); - - my-crate-doc = craneLib.cargoDoc (commonArgs // { - inherit cargoArtifacts; - }); - - # Check formatting - my-crate-fmt = craneLib.cargoFmt { - inherit src; - }; - - # Audit dependencies - my-crate-audit = craneLib.cargoAudit { - inherit src advisory-db; - }; - - # Run tests with cargo-nextest - # Consider setting `doCheck = false` on `my-crate` if you do not want - # the tests to run twice - my-crate-nextest = craneLib.cargoNextest (commonArgs // { - inherit cargoArtifacts; - partitions = 1; - partitionType = "count"; - }); - } // lib.optionalAttrs (system == "x86_64-linux") { - # NB: cargo-tarpaulin only supports x86_64 systems - # Check code coverage (note: this will not upload coverage anywhere) - # my-crate-coverage = craneLib.cargoTarpaulin (commonArgs // { - # inherit cargoArtifacts; - # }); - }; + treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix; + buildInputs = with pkgs; [zlib] ++ lib.optionals stdenv.isDarwin [libiconv darwin.apple_sdk.frameworks.Security]; + in rec { + # For `nix fmt` + formatter = treefmtEval.config.build.wrapper; packages = { - default = my-crate; - my-crate-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // { - inherit cargoArtifacts; - }); - }; - - apps.default = flake-utils.lib.mkApp { - drv = my-crate; + # For `nix build` `nix run`, & `nix profile install`: + default = naersk'.buildPackage rec { + pname = "seidr"; + version = "git"; + + src = ./.; + doCheck = true; # run `cargo test` on build + + inherit buildInputs; + + nativeBuildInputs = with pkgs; [cmake pkg-config installShellFiles]; + + # buildNoDefaultFeatures = true; + # buildFeatures = "git"; + + # outputs = [ "out" "man" ]; + + meta = with pkgs.lib; { + description = "A Rust GitOps/symlinkfarm orchestrator inspired by GNU Stow"; + longDescription = '' + A Rust GitOps/symlinkfarm orchestrator inspired by GNU Stow. + Useful for dealing with "dotfiles", and with git support as a + first class feature. Configuration is done through a single yaml + file, giving it a paradigm that should bring joy to those that + use declarative operating systems and package managers. + ''; + homepage = "https://github.com/cafkafk/seidr"; + license = licenses.gpl3; + mainProgram = "seidr"; + maintainers = with maintainers; [cafkafk]; + }; + }; + + # Run `nix build .#check` to check code + check = naersk'.buildPackage { + src = ./.; + mode = "check"; + inherit buildInputs; + }; + + # Run `nix build .#test` to run tests + test = naersk'.buildPackage { + src = ./.; + mode = "test"; + inherit buildInputs; + }; + + # Run `nix build .#clippy` to lint code + clippy = naersk'.buildPackage { + src = ./.; + mode = "clippy"; + inherit buildInputs; + }; }; + # For `nix develop`: devShells.default = pkgs.mkShell { - inputsFrom = builtins.attrValues self.checks.${system}; - - # Additional dev-shell environment variables can be set directly - # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; - - # Extra inputs can be added here - nativeBuildInputs = with pkgs; [ - cargo - rustc - ]; + nativeBuildInputs = with pkgs; [rustup toolchain just convco]; }; - }); + + # For `nix flake check` + checks = { + formatting = treefmtEval.config.build.check self; + build = packages.check; + default = packages.default; + test = packages.test; + lint = packages.clippy; + }; + } + ); } diff --git a/flake.nix.old b/flake.nix.old new file mode 100644 index 0000000..ab46ca7 --- /dev/null +++ b/flake.nix.old @@ -0,0 +1,154 @@ +{ + description = "Build a cargo project"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + crane = { + url = "github:ipetkov/crane"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.rust-analyzer-src.follows = ""; + }; + + flake-utils.url = "github:numtide/flake-utils"; + + advisory-db = { + url = "github:rustsec/advisory-db"; + flake = false; + }; + }; + + outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + }; + + inherit (pkgs) lib; + + craneLib = crane.lib.${system}; + + # When filtering sources, we want to allow assets other than .rs files + src = lib.cleanSourceWith { + src = ./.; # The original, unfiltered source + filter = path: type: + (lib.hasSuffix "\.yaml" path) || + # (lib.hasSuffix "\.scss" path) || + # Example of a folder for images, icons, etc + #(lib.hasInfix "test" path) || + # Default filter from crane (allow .rs files) + (craneLib.filterCargoSources path type) + ; + }; + + # Common arguments can be set here to avoid repeating them later + commonArgs = { + inherit src; + + buildInputs = [ + # test-directory + # Add additional build inputs here + ] ++ lib.optionals pkgs.stdenv.isDarwin [ + # Additional darwin specific inputs can be set here + pkgs.libiconv + ]; + + # Additional environment variables can be set directly + # MY_CUSTOM_VAR = "some value"; + RUST_BACKTRACE = 1; + }; + + craneLibLLvmTools = craneLib.overrideToolchain + (fenix.packages.${system}.complete.withComponents [ + "cargo" + "llvm-tools" + "rustc" + ]); + + # Build *just* the cargo dependencies, so we can reuse + # all of that work (e.g. via cachix) when running in CI + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + + # Build the actual crate itself, reusing the dependency + # artifacts from above. + my-crate = craneLib.buildPackage (commonArgs // { + inherit cargoArtifacts; + }); + in + { + checks = { + # Build the crate as part of `nix flake check` for convenience + inherit my-crate; + + # Run clippy (and deny all warnings) on the crate source, + # again, resuing the dependency artifacts from above. + # + # Note that this is done as a separate derivation so that + # we can block the CI if there are issues here, but not + # prevent downstream consumers from building our crate by itself. + my-crate-clippy = craneLib.cargoClippy (commonArgs // { + inherit cargoArtifacts; + cargoClippyExtraArgs = "--all-targets -- --deny warnings"; + }); + + my-crate-doc = craneLib.cargoDoc (commonArgs // { + inherit cargoArtifacts; + }); + + # Check formatting + my-crate-fmt = craneLib.cargoFmt { + inherit src; + }; + + # Audit dependencies + my-crate-audit = craneLib.cargoAudit { + inherit src advisory-db; + }; + + # Run tests with cargo-nextest + # Consider setting `doCheck = false` on `my-crate` if you do not want + # the tests to run twice + my-crate-nextest = craneLib.cargoNextest (commonArgs // { + inherit cargoArtifacts; + partitions = 1; + partitionType = "count"; + }); + } // lib.optionalAttrs (system == "x86_64-linux") { + # NB: cargo-tarpaulin only supports x86_64 systems + # Check code coverage (note: this will not upload coverage anywhere) + # my-crate-coverage = craneLib.cargoTarpaulin (commonArgs // { + # inherit cargoArtifacts; + # }); + }; + + packages = { + default = my-crate; + my-crate-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // { + inherit cargoArtifacts; + }); + }; + + apps.default = flake-utils.lib.mkApp { + drv = my-crate; + }; + + devShells.default = pkgs.mkShell { + inputsFrom = builtins.attrValues self.checks.${system}; + + # Additional dev-shell environment variables can be set directly + # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; + + # Extra inputs can be added here + nativeBuildInputs = with pkgs; [ + cargo + rustc + ]; + }; + }); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..25df94f --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,11 @@ +[toolchain] +channel = "1.70" +components = [ + "rustfmt", + "rustc", + "rust-src", + "rust-analyzer", + "cargo", + "clippy", +] +profile = "minimal" diff --git a/treefmt.nix b/treefmt.nix new file mode 100644 index 0000000..71e5cf0 --- /dev/null +++ b/treefmt.nix @@ -0,0 +1,11 @@ +{ + projectRootFile = "Cargo.toml"; + programs = { + alejandra.enable = true; # nix + rustfmt.enable = true; # rust + shellcheck.enable = true; # bash/shell + deadnix.enable = true; # find dead nix code + taplo.enable = true; # toml + yamlfmt.enable = true; # yaml + }; +}