A maildir and Maildir++ library for Zig 0.16: delivery, flags, folders and quota.
0

Configure Feed

Select the types of activity you want to include in your feed.

zig-maildir / flake.nix
6.6 kB 171 lines
1# SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us> 2# SPDX-License-Identifier: MIT 3 4{ 5 description = "zig-maildir"; 6 7 inputs = { 8 nixpkgs = { 9 url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; 10 }; 11 # Mine, not the one in nixpkgs, which is Jari Vetoniemi's original and 12 # takes different options. 13 zon2nix = { 14 url = "github:jcollie/zon2nix"; 15 inputs = { 16 nixpkgs.follows = "nixpkgs"; 17 }; 18 }; 19 }; 20 21 outputs = 22 { 23 nixpkgs, 24 zon2nix, 25 ... 26 }: 27 let 28 inherit (nixpkgs) lib; 29 makePackages = 30 system: 31 import nixpkgs { 32 inherit system; 33 }; 34 forAllSystems = lib.genAttrs lib.systems.flakeExposed; 35 # The virtual machine tests are NixOS ones, so they exist only where 36 # NixOS does. Without this `nix flake check` tries to evaluate them for 37 # Darwin and fails before it has run anything. 38 forLinuxSystems = lib.genAttrs ( 39 lib.filter (system: lib.hasSuffix "-linux" system) lib.systems.flakeExposed 40 ); 41 42 # The devshell's Zig, with one line of its own standard library put 43 # right, because without it `zig build fuzz --fuzz` cannot compile. 44 # 45 # Zig 0.16.0's `compiler/test_runner.zig` reports a failing fuzz input by 46 # asking `std.debug.writeStackTrace` to print what `@errorReturnTrace()` 47 # gave it. Those are two different types: an error return trace is a 48 # `builtin.StackTrace`, a ring buffer with a write index, and that 49 # function takes a `debug.StackTrace`, which is a plain slice and a count 50 # of what was skipped. It is a type error, it is on the path taken only 51 # under `-ffuzz`, and it stops *any* project with a fuzz test in it from 52 # building one. The fix is the function next door: `writeErrorReturnTrace` 53 # takes exactly the type in hand and is what the other three places in 54 # the same file use. 55 # 56 # `--replace-fail` is the whole safety of this: the day Zig ships the fix 57 # the pattern will not be found, the build will fail here rather than 58 # patch something else, and this can go. 59 # 60 # It buys the fuzzer and not its coverage. Nothing in this release 61 # populates the table of program counters, so a bounded run ends with 62 # "corrupted coverage file: pcs_len was zero" and an unbounded one 63 # panics in the build runner's coverage thread; neither is a finding, 64 # and a finding says "input saved to" above the report. The properties 65 # in `tests/fuzz.zig` run as ordinary tests either way, and 66 # `zig build fuzz-run` drives them with a loop of our own. 67 fuzzableZig = 68 pkgs: 69 let 70 # A farm of symlinks rather than a copy: the library is 217 MB, and 71 # exactly one file of it is being changed. 72 library = pkgs.runCommand "zig-0.16.0-lib-fuzz-fix" { } '' 73 cp -rs --no-preserve=mode ${pkgs.zig_0_16}/lib/zig $out 74 chmod -R u+w $out 75 rm $out/compiler/test_runner.zig 76 cp --no-preserve=mode \ 77 ${pkgs.zig_0_16}/lib/zig/compiler/test_runner.zig \ 78 $out/compiler/test_runner.zig 79 substituteInPlace $out/compiler/test_runner.zig \ 80 --replace-fail \ 81 'std.debug.writeStackTrace(trace, stderr)' \ 82 'std.debug.writeErrorReturnTrace(trace, stderr)' 83 ''; 84 in 85 pkgs.symlinkJoin { 86 name = "zig-0.16.0-fuzzable"; 87 paths = [ pkgs.zig_0_16 ]; 88 nativeBuildInputs = [ pkgs.makeWrapper ]; 89 postBuild = '' 90 wrapProgram $out/bin/zig --set ZIG_LIB_DIR ${library} 91 ''; 92 }; 93 in 94 { 95 packages = forAllSystems ( 96 system: 97 let 98 pkgs = makePackages system; 99 in 100 rec { 101 zig-maildir = pkgs.callPackage ./package.nix { }; 102 default = zig-maildir; 103 # The dependency farm on its own, so that a workflow job which runs 104 # `zig build` for something other than the package -- the 105 # documentation -- can be handed it without building the package to 106 # get at it. 107 zig-deps = pkgs.callPackage ./build.zig.zon.nix { }; 108 } 109 ); 110 111 # The virtual machine test, which is here rather than in `zig build 112 # test` because what it tests cannot be reached from a test binary: a 113 # real Dovecot opening the same maildir this library wrote, with its own 114 # idea of what a valid name and a valid flag are. 115 checks = forLinuxSystems ( 116 system: 117 let 118 pkgs = makePackages system; 119 zig-maildir = pkgs.callPackage ./package.nix { }; 120 test = file: pkgs.testers.runNixOSTest (import file { inherit zig-maildir; }); 121 in 122 { 123 inherit zig-maildir; 124 dovecot = test ./tests/nixos/dovecot.nix; 125 } 126 ); 127 128 devShells = forAllSystems ( 129 system: 130 let 131 pkgs = makePackages system; 132 in 133 { 134 default = pkgs.mkShell { 135 name = "zig-maildir"; 136 nativeBuildInputs = [ 137 (fuzzableZig pkgs) 138 pkgs.git-pages-cli 139 pkgs.pinact 140 pkgs.reuse 141 142 # Wrapped so that the Zig it shells out to for `zig env` is the 143 # one this project builds with, rather than whatever happens to 144 # be on the caller's PATH. Without a Zig at all it prints 145 # "unable to execute zig" and writes nothing, leaving the 146 # previous build.zig.zon.nix in place looking untouched. 147 (pkgs.symlinkJoin { 148 name = "zon2nix"; 149 paths = [ zon2nix.packages.${system}.zon2nix ]; 150 nativeBuildInputs = [ pkgs.makeWrapper ]; 151 postBuild = '' 152 wrapProgram $out/bin/zon2nix \ 153 --prefix PATH : ${lib.makeBinPath [ pkgs.zig_0_16 ]} 154 ''; 155 }) 156 ] 157 ++ lib.optionals pkgs.stdenv.hostPlatform.isLinux [ 158 # The other implementations to read what this one writes. 159 # Dovecot is the one whose interpretation of a maildir is the de 160 # facto standard; isync/mbsync and offlineimap each keep state of 161 # their own alongside it and are unforgiving about names. 162 pkgs.dovecot 163 pkgs.isync 164 165 pkgs.kcov 166 ]; 167 }; 168 } 169 ); 170 }; 171}