{ description = "Nix flake for the activity logging script"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/25.11"; sudoku-solver.url = "path:./src/sudoku-hs"; }; outputs = { nixpkgs, ... }@inputs: let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; config.allowUnfree = true; overlays = [ inputs.self.overlays.default ]; }; generatePackages = args: let inherit (args) dir ext handler; in ./${dir} |> builtins.readDir |> builtins.attrNames |> builtins.filter (file: builtins.match ".*\\.${ext}$" file != null) |> builtins.map (file: rec { name = builtins.replaceStrings [ ".${ext}" ] [ "" ] file; value = handler ./${dir}/${file} name; }) |> builtins.listToAttrs; in { overlays.default = _final: prev: { python3Packages = prev.python3Packages.override { overrides = _pyself: _pysuper: { webcomix = prev.python3Packages.callPackage ./pkgs_pr/webcomix.nix { }; download = prev.python3Packages.callPackage ./pkgs/download.nix { webcomix = _pyself.webcomix; }; }; }; download = _final.python3Packages.download; # Fix curl-impersonate-ff build issue with CMake 4.0+ requiring CMake >= 3.5 curl-impersonate-ff = prev.curl-impersonate-ff.overrideAttrs (oldAttrs: { postPatch = (oldAttrs.postPatch or "") + '' # Fix brotli CMake build by adding CMAKE_POLICY_VERSION_MINIMUM flag substituteInPlace Makefile.in \ --replace 'cmake -DCMAKE_BUILD_TYPE=Release' 'cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=Release' ''; }); # Also fix curl-impersonate if it has the same issue curl-impersonate = prev.curl-impersonate.overrideAttrs (oldAttrs: { postPatch = (oldAttrs.postPatch or "") + '' # Fix brotli CMake build by adding CMAKE_POLICY_VERSION_MINIMUM flag substituteInPlace Makefile.in \ --replace 'cmake -DCMAKE_BUILD_TYPE=Release' 'cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=Release' ''; }); }; packages.x86_64-linux = let # Handle nix-shell shebangs by extracting packages and using writeShellApplication scriptBin = path: name: let content = builtins.readFile path; # Match the nix-shell package line: #! nix-shell -i bash -p package1 package2 ... nixShellMatch = builtins.match ".*#! nix-shell -i [^ ]+ -p ([^\n]+).*" content; in if nixShellMatch != null then let packagesStr = builtins.head nixShellMatch; # Split by spaces and filter empty strings packages = builtins.filter (s: s != "") (pkgs.lib.splitString " " packagesStr); # Get package references from pkgs runtimeInputs = builtins.map (pkgName: pkgs.${pkgName}) packages; # Remove the nix-shell shebang lines scriptContent = builtins.replaceStrings [ "#!/usr/bin/env nix-shell\n" "#! nix-shell -i bash -p ${packagesStr}\n" ] [ "" "" ] content; in pkgs.writeShellApplication { inherit name; runtimeInputs = runtimeInputs; text = scriptContent; } else pkgs.writeScriptBin name content; pkgsBin = path: _name: let content = builtins.readFile path; in if builtins.match ".*(buildPythonPackage|buildPythonApplication).*" content != null then pkgs.python3Packages.callPackage path { } else pkgs.callPackage path { }; in { citra = pkgs.callPackage ./pkgs/citra/default.nix { branch = "nightly"; }; torzu = pkgs.callPackage ./pkgs/torzu/package.nix { }; pano = pkgs.callPackage ./pkgs/pano/default.nix { }; vdhcoapp = pkgs.callPackage ./pkgs/vdhcoapp/default.nix { }; sudoku-solver = inputs.sudoku-solver.packages.${system}.default; } // generatePackages { dir = "pkgs"; ext = "nix"; handler = pkgsBin; } // generatePackages { dir = "pkgs_pr"; ext = "nix"; handler = pkgsBin; } // generatePackages { dir = "pkgs_wip"; ext = "nix"; handler = pkgsBin; } // generatePackages { dir = "src/scripts"; ext = "sh"; handler = scriptBin; } // generatePackages { dir = "src/scripts"; ext = "py"; handler = scriptBin; }; }; }