diff --git a/.envrc b/.envrc index 9e83e1de..2294ad52 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,9 @@ -use flake +if [ -n "$(command -v lorri)" ]; then + eval "$(lorri direnv)" +elif [ -n "$(command -v nix)" ]; then + use flake +else + use nix +fi dotenv_if_exists .production.envrc diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc65d2e9..27a02e41 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/magic-nix-cache-action@v7 - - uses: DeterminateSystems/nix-installer-action@v10 + - uses: DeterminateSystems/nix-installer-action@v13 with: extra-conf: | keep-going = true diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index d8651e02..b19e7404 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@v10 + - uses: DeterminateSystems/nix-installer-action@v13 - name: Check flake lockfile uses: DeterminateSystems/flake-checker-action@v5 - name: Check flake outputs diff --git a/.github/workflows/iso.yml b/.github/workflows/iso.yml index 05f42231..34e1fa6c 100644 --- a/.github/workflows/iso.yml +++ b/.github/workflows/iso.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/magic-nix-cache-action@v7 - - uses: DeterminateSystems/nix-installer-action@v10 + - uses: DeterminateSystems/nix-installer-action@v13 - name: Build ISO run: | nix build .#images.${{ matrix.arch }}.bootstrap-install-iso --impure --out-link build-iso-result diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index f234653d..e3e1f570 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/magic-nix-cache-action@v7 - - uses: DeterminateSystems/nix-installer-action@v10 + - uses: DeterminateSystems/nix-installer-action@v13 - env: NIXPKGS_ALLOW_UNFREE: "1" run: nix develop .#docs --impure -c hugo -s ./docs/ diff --git a/.github/workflows/update-firefox-addons.yml b/.github/workflows/update-firefox-addons.yml index 0f5f7669..d88ca417 100644 --- a/.github/workflows/update-firefox-addons.yml +++ b/.github/workflows/update-firefox-addons.yml @@ -18,7 +18,7 @@ jobs: id: metadata run: echo "DATE=$(date +%F)" >> "$GITHUB_OUTPUT" - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@v10 + - uses: DeterminateSystems/nix-installer-action@v13 - env: NIXPKGS_ALLOW_UNFREE: "1" run: nix develop --impure -c mozilla-addons-to-nix pkgs/firefox-addons/firefox-addons.json pkgs/firefox-addons/default.nix diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index 55814a83..51cf9c46 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -14,7 +14,7 @@ jobs: contents: write steps: - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@v10 + - uses: DeterminateSystems/nix-installer-action@v13 - name: Update flake inputs run: | nix flake update --commit-lock-file --commit-lockfile-summary "flake.lock: update inputs" diff --git a/.sops.yaml b/.sops.yaml index 0f1d6ef2..1d430b35 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,6 +1,7 @@ keys: - - &foo-dogsquared DDD7D0BD602E564BAA04FC3514310D9141152B92 + - &foo-dogsquared 7C7F9DC0694508015FE4C9F2DD5E7C08041214EE - &foo-dogsquared-old 8FCE86932583783E515B6FE55F2B001E20ED3763 + - &foo-dogsquared-old-2 DDD7D0BD602E564BAA04FC3514310D9141152B92 - &foo-dogsquared-age age17he74we2sm7q7ufv6x26n83hs42v6gkj984m6kwf9xtjduyccqmqtpv37q - &ni age1jxna9vm7nx4g69s84qgjptxvuzszcypf2rfk4ss2lyhnpe3yxdnqusu6jp - &plover age1yftkhugwrdnlpl45lthrhvvk720zza2nd085sxvjcxg2guavz3kquktplx @@ -10,8 +11,4 @@ creation_rules: - path_regex: configs/nixos/plover/(modules/.+/secrets|secrets/[^/]+)\.(yaml|json|ini|env)$ age: *plover - path_regex: configs/home-manager/foo-dogsquared/(modules/.+/secrets|secrets/[^/]+)\.(yaml|json|inienv)$ - key_groups: - - age: - - *foo-dogsquared-age - - gpg: - - *foo-dogsquared + age: *foo-dogsquared-age diff --git a/README.adoc b/README.adoc index 44326981..bad4ba98 100644 --- a/README.adoc +++ b/README.adoc @@ -10,33 +10,42 @@ This is my NixOS config as a https://www.tweag.io/blog/2020-05-25-flakes/[Nix fl This configuration setup can be described with a list of features: * Contain EVERYTHING! -Unify https://github.com/nix-community/nixos-generators[home-manager] and NixOS configuration (and maybe other environments such as nix-darwin and system-manager in case I have use cases for those) into one flake. +Unify https://github.com/nix-community/home-manager[home-manager] and NixOS configuration (and maybe other environments such as nix-darwin and system-manager in case I have use cases for those) into one flake. Also throw in some NixVim configs in there, some Disko configurations, and make a sticky note about systems-manager and nix-darwin for the near future. This is basically a monorepo for everything Nix-related needs. +* Fully modular configurations for each of the Nix-configurable environments including my NixOS systems, home-manager configurations, and NixVim builds. +Furthermore, they can be attached to a wider-scoped environment provided there is an integration for it. +For specific examples... ++ +-- +** We can have our link:./configs/home-manager[home-manager configurations] to be attached to multiple NixOS systems smoothly. +They are also available as a standalone configuration to be deployed by `home-manager` tool which is nice. + +** We can include link:./configs/nixvim[NixVim configs] into home-manager configs and NixOS systems. +Similar to home-manager configurations, they are also available as a standalone configuration found in `nixvimConfigurations` attribute in the flake output. + +** We can also include link:./configs/disko/[our Disko configurations] to NixOS systems to quickly include filesystem entries. +Once again, also available as a standalone configuration to be usable for `disko` tool. + +All of these is made possible with https://flake.parts[flake-parts] with flake modules encouraging each of the configuration to be as composable as the functional paradigm that Nix encourages. +-- + +* Deploy the same NixOS configuration for more than one system, in multiple output images generated with https://github.com/nix-community/nixos-generators[nixos-generators], and as part of the deployment cluster with https://github.com/serokell/deploy-rs[deploy-rs]. +You can even configure what nixpkgs branch (and home-manager branch) it will use. + +* Features custom desktop configurations as a fully independent desktop session (aka similar to how typical desktop environments are deployed). +You can even test them quickly in a VM by running `nix run github:foo-dogsquared/nixos-config#run-workflow-with-vm -- $WORKFLOW_NAME`. + * Take full advantage of Nix module system with the cluster-wide custom modules footnote:[Most of them are patterned similarly from nixpkgs which made easy to be upstreamed just in case.]. This design bleeds into configuring the NixOS systems and home-manager users by designing https://foo-dogsquared.github.io/nixos-config/04-nixos-modules/04-host-specific-modules/[host-specific modules] and https://foo-dogsquared.github.io/nixos-config/05-home-manager/#_user_specific_modules[user-specific modules], respectively. * Integrate every single component of the Nix ecosystem under the sun (that I use, anyways). Want to declare a NixOS system with two already existing home-manager users as a separate NixOS configuration (`nixosConfigurations`) and as a buildable ISO in the flake output AND have it deployable with deploy-rs? link:./modules/flake-parts/setups/nixos.nix[I wished for it and I got it.] -This is mainly powered by flakes with https://flake.parts/[Flake Parts] framework allowing me to create bloated abstractions on top. +This is mainly powered by flakes with https://flake.parts/[flake-parts] framework allowing me to create bloated abstractions on top. -* Deploy the same NixOS configuration for more than one system and in multiple output images. -This is configured in link:./configs/flake-parts/nixos.nix[`./configs/flake-parts/nixos.nix`] where not only you can deploy them with https://github.com/serokell/deploy-rs[deploy-rs] but build them as generated by https://github.com/nix-community/nixos-generators[nixos-generators]. -You can even configure what nixpkgs branch (and home-manager branch) it will use. - -* Similarly, deploy the same home-manager configuration for more than one system. -This time, it is configured with the link:./configs/flake-parts/home-manager.nix[`./configs/flake-parts/home-manager.nix`] file which you can configure what nixpkgs branch it will use. -You can even include link:./configs/home-manager[those same home-manager users] in NixOS systems smoothly. - -* OK, OK, deploy EVERYTHING for more than one system with as much customizability and integration with other components as possible (I said this already, right?). -Right now, we will quickly list them like so... - -** We have NixVim where we can include link:./configs/nixvim[those same NixVim configs] into home-manager configs and NixOS systems. -** We can also include link:./configs/disko/[our Disko configurations] to NixOS systems to quickly include filesystem entries while being usable in `disko` CLI. - -* It has its own https://foo-dogsquared.github.io/nixos-config[website]. +* It has its own https://foo-dogsquared.github.io/nixos-config[website] fully managed as a separate subproject. Which means that it's cool (or over-the-top, whichever you prefer). It's basically my personal version of nixpkgs: a monorepo of everything I need for Nix-related things unless it sprung into life as its own project footnote:[Speaking of which, I also have some other Nix-related projects stored in this very repo.]. @@ -74,6 +83,8 @@ nix-shell -p disko git disko --mode disko [--arg disk "/dev/sda"] --flake {canonical_flake_url}#external-hdd nixos-install --no-root-passwd --root /mnt --flake {canonical_flake_url}#graphical-installer-x86_64-linux ---- + +Also, the installer configuration also includes Guix which means it's also a Guix System installer. ==== Once you have a live installer in boot, you can then simply install the following commands. @@ -115,10 +126,15 @@ The FlakeHub flake follows a rolling release model so all of the releases are un == Stability promise THERE'S NO STABILITY PROMISE HERE! +YOU KNOW WHY!?! +BECAUSE DEBUGGING IN NIX (whether in nixpkgs' module system or outside of it) IS ONE OF THE MOST PAINFUL EXPERIENCE IT MIGHT AS WELL BE CLASSIFIED AS A TIME MACHINE BECAUSE OF HOW FAR IT SETS YOU BACK, GODDAMN! +MIGHT AS WELL USE THE BETTER ALTERNATIVE CALLED GUIX AND LEARN GUILE SCHEME FROM SCRATCH INSTEAD. footnote:[Seriously though, it is pretty nice and the community especially its developers does have the advantage of hindsight and using a general-purpose programming language. If you're interested in using declarative operating systems (or even just a home environment), I recommend to try it.] + If you're one of the unfortunate users for whatever reason, sorry but I'm afraid there's no such word as "stability" in this project's dictionary (or most Nix projects, really ;p). Not every commit successfully builds because of the way how the project is managed (which is very very badly): * All of the included changes are pushed in one fell swoop over time instead of carefully testing each of them. +* There's barely any testing infrastructure set (at least until I set it up). * NixOS and home-manager configurations are able to be deployed in pure evaluation mode and suddenly it's not (most of the time, it isn't). * Module interfaces change all the time. * Packages can be left unmaintained and vanish at any time. footnote:[The ones I actively maintain are in nixpkgs anyways.] @@ -181,6 +197,9 @@ include::./docs/content/en-US/08-acknowledgement/index.adoc[tag=acknowledgement] == Copyright -This project is licensed under MIT license. +For those who care, this project is licensed under MIT license. I just chose it to make it easier to upstream parts of this project to nixpkgs and to make it easier to copy it without much problems (just don't forget to add attribution as indicated from the license). Please see link:./LICENSE[`./LICENSE`] for the full text. + +However, various subprojects found in here may be under different licenses. +An example of this is the custom GNOME Shell extensions found for my main GNOME configuration which are licensed under GPLv3 only. diff --git a/apps/run-workflow-with-vm/README.adoc b/apps/run-workflow-with-vm/README.adoc index e061a454..e5d96d90 100644 --- a/apps/run-workflow-with-vm/README.adoc +++ b/apps/run-workflow-with-vm/README.adoc @@ -24,8 +24,11 @@ It is expected that the extra configuration folder is structured similarly to th ./extra-config-stuff └── modules ├── home-manager + │ └── default.nix ├── nixvim + │ └── default.nix └── nixos + └── default.nix ---- Once you have an folder containing those extra snippets, you can simply include them like so. @@ -34,3 +37,12 @@ Once you have an folder containing those extra snippets, you can simply include ---- run-workflow-with-vm a-happy-gnome -I extra-config=./extra-config-stuff ---- + +Another thing, this script is using https://github.com/nix-community/nixos-generators[nixos-generators] to build the VM which in turn basically uses nixpkgs' integration of it (at `${pkgs.path}/nixos/modules/virtualisation/build-vm.nix`). +You can extend it either by adding NixOS modules configuring the virtual machine or by adding certain arguments to the script. +This won't be an exhaustive list of niceties as it involves a script that may change but here's some things you can do. + +* You can pass the `SHARED_DIR` environment variable to add a directory to be shared from the host and the guest. +This is useful for testing out spontaneous changes as if you're booting into the system itself. + +* You can pass additional arguments as if you're using `qemu-*` utilities which would be useful for changing graphical drivers and all that jazz. diff --git a/apps/run-workflow-with-vm/configuration.nix b/apps/run-workflow-with-vm/configuration.nix index 8f856aa5..d8c0c1bf 100644 --- a/apps/run-workflow-with-vm/configuration.nix +++ b/apps/run-workflow-with-vm/configuration.nix @@ -26,6 +26,7 @@ import { + @@ -47,6 +48,7 @@ import { config = { # Enable the display manager of choice. + services.displayManager.enable = true; services.xserver.displayManager.gdm.enable = true; # Configure home-manager-related stuff. diff --git a/apps/run-workflow-with-vm/default.nix b/apps/run-workflow-with-vm/default.nix index df8dbca5..b705155a 100644 --- a/apps/run-workflow-with-vm/default.nix +++ b/apps/run-workflow-with-vm/default.nix @@ -2,8 +2,6 @@ , lib , meson , ninja -, nix -, makeWrapper , inputs ? [ ] }: @@ -16,18 +14,12 @@ stdenv.mkDerivation (finalAttrs: { nativeBuildInputs = [ meson ninja - makeWrapper ]; preConfigure = '' mesonFlagsArray+=("-Dinputs=[${lib.concatStringsSep "," inputs}]") ''; - postInstall = '' - wrapProgram $out/bin/${finalAttrs.pname} \ - --prefix PATH ':' '${lib.makeBinPath [ nix ]}' - ''; - meta = with lib; { description = "Quickly run workflow modules with a VM."; license = licenses.gpl3Plus; diff --git a/configs/README.adoc b/configs/README.adoc index 0fb6f4d9..1cf48829 100644 --- a/configs/README.adoc +++ b/configs/README.adoc @@ -12,6 +12,7 @@ Here is the following list of them used in the repo history: * `hosts` for NixOS systems (e.g., `hosts/ni`). * `users` for home-manager configurations (e.g., `users/foo-dogsquared`). * `nixvimConfigs` for NixVim configurations (e.g., `nixvimConfigs/fiesta`). +* `wrapperPackages` for wrapper-manager packages (e.g., `wrappers/archive-setup`). * `flake` for flake-parts (seeing it only has one of them, it is constantly referred to as `flake`). These "codenames" are also used for their environment-specific module structuring (e.g., `hosts.ni.services.backup.enable` for NixOS, `nixvimConfigs.fiesta.setups.tree-sitter` for NixVim, `users.foo-dogsquared.setups.desktop.enable` for home-manager) with the exception of flake-parts where it is basically a free-for-all. diff --git a/configs/flake-parts/default.nix b/configs/flake-parts/default.nix index ebe6f8a8..812e5125 100644 --- a/configs/flake-parts/default.nix +++ b/configs/flake-parts/default.nix @@ -1,17 +1,19 @@ -{ inputs, lib, ... }: { +{ inputs, config, lib, ... }: { imports = [ ./dev.nix ./packages.nix ./templates.nix - # The environment configurations. + # Environment configurations. ./disko.nix ./home-manager.nix ./nixos.nix ./nixvim.nix + ./wrapper-manager.nix # Subprojects. ./bahaghari.nix + ./wrapper-manager-fds.nix ]; _module.args = { @@ -23,6 +25,12 @@ }; defaultOverlays = lib.attrValues inputs.self.overlays; + + defaultSystems = [ "x86_64-linux" ]; + }; + + setups.sharedNixpkgsConfig = { + allowUnfree = true; }; perSystem = { lib, system, ... }: { @@ -31,7 +39,7 @@ # for building NixOS and home-manager systems. pkgs = import inputs.nixpkgs { inherit system; - config.allowUnfree = true; + config = config.setups.sharedNixpkgsConfig; overlays = lib.attrValues inputs.self.overlays ++ [ inputs.nur.overlay ]; diff --git a/configs/flake-parts/dev.nix b/configs/flake-parts/dev.nix index 201231a6..885eb238 100644 --- a/configs/flake-parts/dev.nix +++ b/configs/flake-parts/dev.nix @@ -1,6 +1,10 @@ # All of the development-related shtick for this project is over here. { inputs, ... }: { - flake.lib = import ../../lib { lib = inputs.nixpkgs.lib; }; + flake = { + lib = import ../../lib { lib = inputs.nixpkgs.lib; }; + + foodogsquaredLib = ../../lib; + }; perSystem = { config, lib, pkgs, ... }: { apps = { diff --git a/configs/flake-parts/home-manager.nix b/configs/flake-parts/home-manager.nix index eb045bdc..de49fd21 100644 --- a/configs/flake-parts/home-manager.nix +++ b/configs/flake-parts/home-manager.nix @@ -11,25 +11,33 @@ configs = { # The typical user in desktop environments. foo-dogsquared = { + nixpkgs = { + branch = "nixos-unstable"; + overlays = [ + # Neovim nightly! + inputs.neovim-nightly-overlay.overlays.default + + # Emacs unstable version! + inputs.emacs-overlay.overlays.default + + # Helix master! + inputs.helix-editor.overlays.default + + # Get all of the NUR. + inputs.nur.overlay + ]; + }; + homeManagerBranch = "home-manager-unstable"; systems = [ "aarch64-linux" "x86_64-linux" ]; - overlays = [ - # Neovim nightly! - inputs.neovim-nightly-overlay.overlays.default - - # Emacs unstable version! - inputs.emacs-overlay.overlays.default - - # Helix master! - inputs.helix-editor.overlays.default - - # Get all of the NUR. - inputs.nur.overlay - ]; modules = [ inputs.nur.hmModules.nur inputs.sops-nix.homeManagerModules.sops + inputs.self.homeModules.wrapper-manager ]; - nixvim.instance = "fiesta"; + nixvim = { + instance = "fiesta"; + branch = "nixvim-unstable"; + }; deploy = { autoRollback = true; magicRollback = true; @@ -37,7 +45,11 @@ }; # The typical user in server environments. - plover.systems = [ "x86_64-linux" ]; + plover = { + nixpkgs.branch = "nixos-unstable"; + homeManagerBranch = "home-manager-unstable"; + systems = [ "x86_64-linux" ]; + }; }; # Pretty much the baseline home-manager configuration for the whole diff --git a/configs/flake-parts/nixos.nix b/configs/flake-parts/nixos.nix index 61e9b42e..35a3ec9c 100644 --- a/configs/flake-parts/nixos.nix +++ b/configs/flake-parts/nixos.nix @@ -10,13 +10,17 @@ configs = { # The main desktop. ni = { + nixpkgs.branch = "nixos-unstable"; systems = [ "x86_64-linux" ]; formats = null; modules = [ inputs.disko.nixosModules.disko inputs.sops-nix.nixosModules.sops + inputs.self.nixosModules.wrapper-manager + { wrapper-manager.documentation.manpage.enable = true; } ]; - homeManagerUsers = { + home-manager = { + branch = "home-manager-unstable"; nixpkgsInstance = "global"; users.foo-dogsquared = { userConfig = { @@ -42,6 +46,8 @@ # A remote server. plover = { + nixpkgs.branch = "nixos-unstable"; + home-manager.branch = "home-manager-unstable"; systems = [ "x86_64-linux" ]; formats = null; domain = "foodogsquared.one"; @@ -59,6 +65,8 @@ # TODO: Remove extra newlines that are here for whatever reason. #{{{ void = { + nixpkgs.branch = "nixos-unstable"; + home-manager.branch = "home-manager-unstable"; systems = [ "x86_64-linux" ]; formats = [ "vm" ]; }; @@ -66,13 +74,15 @@ # The barely customized non-graphical installer. bootstrap = { + nixpkgs.branch = "nixos-unstable-small"; systems = [ "aarch64-linux" "x86_64-linux" ]; formats = [ "install-iso" ]; - nixpkgsBranch = "nixos-unstable-small"; }; # The barely customized graphical installer. graphical-installer = { + nixpkgs.branch = "nixos-unstable"; + home-manager.branch = "home-manager-unstable"; systems = [ "aarch64-linux" "x86_64-linux" ]; formats = [ "install-iso-graphical" ]; diskoConfigs = [ "external-hdd" ]; @@ -81,11 +91,15 @@ # The WSL system (that is yet to be used). winnowing = { + nixpkgs = { + branch = "nixos-unstable"; + overlays = [ + inputs.neovim-nightly-overlay.overlays.default + ]; + }; + home-manager.branch = "home-manager-unstable"; systems = [ "x86_64-linux" ]; formats = null; - overlays = [ - inputs.neovim-nightly-overlay.overlays.default - ]; modules = [ # Well, well, well... inputs.nixos-wsl.nixosModules.default @@ -105,6 +119,15 @@ defaultNixConf ../../modules/nixos/profiles/generic.nix ../../modules/nixos/profiles/nix-conf.nix + + { + config.documentation.nixos = { + extraModules = [ + ../../modules/nixos + ../../modules/nixos/_private + ]; + }; + } ]; }; diff --git a/configs/flake-parts/nixvim.nix b/configs/flake-parts/nixvim.nix index f32e1f7d..b2518fcb 100644 --- a/configs/flake-parts/nixvim.nix +++ b/configs/flake-parts/nixvim.nix @@ -1,23 +1,30 @@ -{ inputs, ... }: +{ inputs, lib, ... }: { setups.nixvim.configs = { fiesta = { - nixpkgsBranches = [ - "nixos-unstable" - ]; - neovimPackages = p: with p; [ - neovim-nightly + components = [ + { + nixpkgsBranch = "nixos-unstable"; + nixvimBranch = "nixvim-unstable"; + neovimPackage = pkgs: pkgs.neovim; + overlays = [ + inputs.neovim-nightly-overlay.overlays.default + ]; + } ]; }; trovebelt = { - nixpkgsBranches = [ - "nixos-unstable" - ]; - neovimPackages = p: with p; [ - neovim-nightly - ]; + components = lib.cartesianProduct { + nixpkgsBranch = [ "nixos-unstable" ]; + nixvimBranch = [ "nixvim-unstable" ]; + neovimPackage = [ (pkgs: pkgs.neovim) ]; + overlays = [ + [ inputs.neovim-nightly-overlay.overlays.default ] + [ ] + ]; + }; }; }; diff --git a/configs/flake-parts/wrapper-manager-fds.nix b/configs/flake-parts/wrapper-manager-fds.nix new file mode 100644 index 00000000..6347a785 --- /dev/null +++ b/configs/flake-parts/wrapper-manager-fds.nix @@ -0,0 +1,10 @@ +{ lib, ... }: + +{ + flake = { + wrapperManagerLib = ../../subprojects/wrapper-manager-fds/lib; + wrapperManagerModules = ../../subprojects/wrapper-manager-fds/modules/wrapper-manager; + homeModules.wrapper-manager = ../../subprojects/wrapper-manager-fds/modules/env/home-manager; + nixosModules.wrapper-manager = ../../subprojects/wrapper-manager-fds/modules/env/nixos; + }; +} diff --git a/configs/flake-parts/wrapper-manager.nix b/configs/flake-parts/wrapper-manager.nix new file mode 100644 index 00000000..297aba01 --- /dev/null +++ b/configs/flake-parts/wrapper-manager.nix @@ -0,0 +1,19 @@ +{ lib, ... }: + +{ + setups.wrapper-manager = { + configs = { + archive-setup = { + systems = [ "x86_64-linux" ]; + nixpkgs.branch = "nixos-unstable"; + }; + + dotfiles-wrapped = { + systems = [ "x86_64-linux" ]; + nixpkgs.branch = "nixos-unstable"; + }; + }; + }; + + flake.wrapperManagerModules.default = ../../modules/wrapper-manager; +} diff --git a/configs/home-manager/foo-dogsquared/config/tridactyl/tridactylrc b/configs/home-manager/foo-dogsquared/config/tridactyl/tridactylrc index 7189bdb1..2afaadf7 100644 --- a/configs/home-manager/foo-dogsquared/config/tridactyl/tridactylrc +++ b/configs/home-manager/foo-dogsquared/config/tridactyl/tridactylrc @@ -109,12 +109,20 @@ autocontain -s github\.com Work autocontain -s gitlab\.com Work autocontain -s app\.netlify\.com Work autocontain -s archive\.softwareheritage\.com Work +autocontain -s sourcegraph\.com Work " So does most freelancing sites. autocontain -s upwork\.com Work autocontain -s monster\.com Work autocontain -s foundit\.com(\.ph?) Work autocontain -s fiverr\.com Work +autocontain -s (ph\.?)linkedin\.com Work +autocontain -s jobstreet\.com(\.ph?) Work +autocontain -s (ph\.?)jobstreet\.com(\.ph?) Work + +autocontain -s mxroute\.com Work +autocontain -s mailbox\.org Work +autocontain -s cloud\.google\.com Work " Shopping, shopping, shopping! autocontain -s yelp\.com Shopping diff --git a/configs/home-manager/foo-dogsquared/config/yt-dlp/audio.conf b/configs/home-manager/foo-dogsquared/config/yt-dlp/audio.conf index 6a3b5ff2..9d944c23 100644 --- a/configs/home-manager/foo-dogsquared/config/yt-dlp/audio.conf +++ b/configs/home-manager/foo-dogsquared/config/yt-dlp/audio.conf @@ -6,7 +6,7 @@ --format bestaudio --audio-format opus ---output '%(album_artist,artist)s/%(album,playlist)s/%(track_number,playlist_index)d-%(track,title)s.%(ext)s' +--output '%(album_artists.0,artists.0)s/%(album,playlist)s/%(track_number,playlist_index)d-%(track,title)s.%(ext)s' --download-archive archive # Add all sorts of metadata. diff --git a/configs/home-manager/foo-dogsquared/default.nix b/configs/home-manager/foo-dogsquared/default.nix index b736244d..6a731eb8 100644 --- a/configs/home-manager/foo-dogsquared/default.nix +++ b/configs/home-manager/foo-dogsquared/default.nix @@ -1,7 +1,8 @@ -{ config, lib, pkgs, foodogsquaredLib, bahaghariLib, ... }: +{ config, lib, pkgs, foodogsquaredLib, bahaghariLib, ... }@attrs: let inherit (bahaghariLib.tinted-theming) importScheme; + userCfg = config.users.foo-dogsquared; in { imports = [ ./modules ]; @@ -19,16 +20,62 @@ in nixvim.enable = true; email.enable = true; email.thunderbird.enable = true; - research.enable = true; vs-code.enable = true; + + custom-homepage = { + enable = true; + sections = lib.mkMerge [ + # Merge the upstream since any new files will be overridden. It also + # allows us to attach data to it such as new links to the hardcoded + # sections. + (lib.importTOML "${config.users.foo-dogsquared.programs.custom-homepage.package.src}/data/foodogsquared-homepage/links.toml") + + { + services = { + name = "Local services"; + flavorText = "For your local productivity"; + textOnly = true; + weight = (-50); + + icon = { + iconset = "material-design-icons"; + name = "room-service"; + }; + }; + } + + (lib.mkIf config.services.archivebox.webserver.enable { + services.links = lib.singleton { + url = "http://localhost:${builtins.toString config.state.ports.archivebox-webserver.value}"; + text = "Archive webserver"; + }; + + YOHOOHOOHOOHOO.links = lib.mkBefore (lib.singleton { + url = "http://localhost:${builtins.toString config.state.ports.archivebox-webserver.value}"; + text = "ArchiveBox webserver"; + }); + }) + + (lib.mkIf (attrs.nixosConfig.suites.filesystem.setups.archive.enable or false) { + YOHOOHOOHOOHOO.links = lib.mkBefore (lib.singleton { + url = "file://${attrs.nixosConfig.state.paths.archive}"; + text = "Personal archive"; + }); + }) + ]; + }; }; + services.backup.enable = true; + setups = { desktop.enable = true; development.enable = true; fonts.enable = true; music.enable = true; music.mpd.enable = true; + music.spotify.enable = true; + research.enable = true; }; }; @@ -39,12 +86,6 @@ in # The keyfile required to decrypt the secrets. sops.age.keyFile = "${config.xdg.configHome}/age/user"; - sops.secrets = foodogsquaredLib.sops-nix.getSecrets ./secrets/secrets.yaml { - davfs2-credentials = { - path = "${config.home.homeDirectory}/.davfs2/davfs2.conf"; - }; - }; - # Add our own projects directory since most programs can't decide where it is # properly. xdg.userDirs.extraConfig.XDG_PROJECTS_DIR = "${config.home.homeDirectory}/Projects"; @@ -65,6 +106,17 @@ in kanidm.source = ./config/kanidm/config; }; + # Holding these in for whatever reason. + state.packages = { + diff = pkgs.diffoscope; + pager = config.programs.bat.package; + editor = + if userCfg.programs.nixvim.enable then + config.programs.nixvim.finalPackage + else + config.programs.neovim.package; + }; + # Automating some files to be fetched on activation. home.mutableFile = { # ...my gopass secrets,... diff --git a/configs/home-manager/foo-dogsquared/files/homepage/.gitignore b/configs/home-manager/foo-dogsquared/files/homepage/.gitignore new file mode 100644 index 00000000..da21e6ac --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/.gitignore @@ -0,0 +1,16 @@ + +### Hugo ### +# Generated files by hugo +/public/ +/resources/_gen/ +/assets/jsconfig.json +hugo_stats.json + +# Executable may be added to repository +hugo.exe +hugo.darwin +hugo.linux + +# Temporary lock file while building +/.hugo_build.lock + diff --git a/configs/home-manager/foo-dogsquared/files/homepage/LICENSE b/configs/home-manager/foo-dogsquared/files/homepage/LICENSE new file mode 100644 index 00000000..228f9b3e --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/configs/home-manager/foo-dogsquared/files/homepage/Makefile b/configs/home-manager/foo-dogsquared/files/homepage/Makefile new file mode 100644 index 00000000..eab585dd --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/Makefile @@ -0,0 +1,7 @@ +.PHONY: build +build: + hugo --destination public + +.PHONY: serve +serve: + hugo serve diff --git a/configs/home-manager/foo-dogsquared/files/homepage/README.adoc b/configs/home-manager/foo-dogsquared/files/homepage/README.adoc new file mode 100644 index 00000000..34e12812 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/README.adoc @@ -0,0 +1,33 @@ += foodogsquared's custom homepage +:toc: + +My custom homepage intended to be deployed alongside my home-manager configuration. +In theory, you could deploy this outside of the home-manager config but that's on you (READ: anyone that is not foodogsquared) to figure out. +It should be fairly easy to do that though since all you need is the following list of components to successfully build the website: + +* GNU Make for its build automation. +This is structured in this way to make building consistent either with Nix and non-Nix'd environments. + +* https://gohugo.io/[Hugo] is the site generator mainly designed to be deployed with one binary. + +* https://foo-dogsquared.github.io/panapton[Panapton] to compile the stylesheet with my custom scheme. +In place of this, you could use other Base16 builders but you'll have to recreate the stylesheet template for that particular builder. + +There are some design constraints when developing this website. + +* This homepage is pretty much designed to be completely possible to use entirely offline. +As such, it has a design constraint of using less (zero as much as possible) remote resources such as a CDN. +Usage of third-party libraries are fine as long as it is bundled nicely (we'll probably use something like https://bun.sh/[Bun] for this). + +* We cannot use anything within the site generator requiring a network access mostly because we're relying on the Nix which has sandboxing by default including networking isolation. footnote:[While we can remove it ourselves, it isn't really good practice.] +As a neat side effect, it also strengthens the previous goal of keeping it as offline as possible. + + +[#development] +== Development + +It is recommended to set up the development environment with https://nixos.org/[Nix package manager]. +In case it isn't possible to use it, you'll have to install the following tools. + +* Hugo v0.130.0 and above +* https://treefmt.com/[treefmt] diff --git a/configs/home-manager/foo-dogsquared/files/homepage/assets/scss/main.scss b/configs/home-manager/foo-dogsquared/files/homepage/assets/scss/main.scss new file mode 100644 index 00000000..a91dcd96 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/assets/scss/main.scss @@ -0,0 +1,71 @@ +:root { + height: 100%; + font-size: 1.1em; + + --background: var(--base00); + --foreground: var(--base05); + --accent-color: var(--base0C); +} + +body { + min-height: 100%; + margin: 0; + background: var(--background); + font-family: "Source Sans Pro", sans-serif; +} + +#links { + --width: 30ch; + --gap: 0.5em; + --header-font-size: 1.5em; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(var(--width), 1fr)); + grid-template-rows: max-content; + gap: var(--gap); + margin: calc(var(--gap) * 2); + + section[id^="section-"] { + background: var(--foreground); + color: var(--background); + + border: var(--gap) solid var(--accent-color); + padding: calc(var(--gap) * 2); + text-align: center; + + .nav-icon { + color: currentColor; + fill: currentColor; + + svg { + --size: calc(var(--header-font-size) * 2); + width: var(--size); + height: var(--size); + } + } + + .nav-header { + font-size: var(--header-font-size); + font-weight: bolder; + } + + .flavor-text { + font-size: 0.9em; + font-style: italic; + display: inline-block; + width: 100%; + } + + nav { + display: flex; + flex-direction: column; + } + + a { + color: var(--background); + + &:hover { + color: var(--accent-color); + } + } + } +} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/heroicon.svg b/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/heroicon.svg new file mode 100644 index 00000000..e1d6a967 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/heroicon.svg @@ -0,0 +1,9 @@ +{{- /* +This template applies an ID to an SVG from the Heroicons set to be used with `` element. +*/ -}} +{{- $match := "^\\s*" }} +{{- $name := default .id .name }} +{{- $icon := resources.Get (printf "svg/heroicons/24/solid/%s.svg" .id) }} +{{- $replaceWith := printf `` $name }} + +{{- replaceRE $match $replaceWith $icon.Content | safeHTML -}} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/simple-icon.svg b/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/simple-icon.svg new file mode 100644 index 00000000..d2f6bc6f --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/simple-icon.svg @@ -0,0 +1,9 @@ +{{- /* +This template applies an ID to an SVG from the Simple Icons set to be used with `` element. +*/ -}} +{{- $match := "\\s*(.*)\\s*" }} +{{- $name := default .id .name }} +{{- $icon := resources.Get (printf "svg/simple-icons/%s.svg" .id) }} +{{- $replaceWith := printf `${2}` $name }} + +{{- replaceRE $match $replaceWith $icon.Content | safeHTML }} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/theme.scss b/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/theme.scss new file mode 100644 index 00000000..ff6f6ece --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/assets/templates/theme.scss @@ -0,0 +1,102 @@ +{{ $data := newScratch }} + +{{/* + Create an automatic way of generating system color schemes, if set by the user. + + * If either only one is set, generate an appropriate color scheme with the given color scheme. + For example, if there is only a given dark theme, the theme will generate a light color scheme. + * If given neither, go with the fallback themes. +*/}} +{{ $themes := (index $.Site.Data "foodogsquared-homepage").themes }} +{{ $hasLight := $themes._light }} +{{ $hasDark := $themes._dark }} +{{ $hasSystemTheme := or $hasLight $hasDark }} + +{{/* + Take note how the other half get its colors. It's not exactly a color + string but it is a SASS expression to be evaluated and put into string + interpolation in SASS. +*/}} +{{ if (and $hasLight (not $hasDark)) }} + {{- warnf "No given dark theme. Generating one from the light theme..." }} + {{ $palette := $hasLight.palette }} + {{ $darkTheme := dict + "scheme" (printf "%s (light)" $hasLight.scheme) + "base00" $palette.base07 + "base01" $palette.base06 + "base02" $palette.base05 + "base03" $palette.base04 + "base04" $palette.base03 + "base05" $palette.base02 + "base06" $palette.base01 + "base07" $palette.base00 + "base08" (print "{lighten(saturate(#" $palette.base08 ", 10%), 15%)}") + "base09" (print "{lighten(saturate(#" $palette.base09 ", 10%), 15%)}") + "base0A" (print "{lighten(saturate(#" $palette.base0A ", 10%), 15%)}") + "base0B" (print "{lighten(saturate(#" $palette.base0B ", 10%), 15%)}") + "base0C" (print "{lighten(saturate(#" $palette.base0C ", 10%), 15%)}") + "base0D" (print "{lighten(saturate(#" $palette.base0D ", 10%), 15%)}") + "base0E" (print "{lighten(saturate(#" $palette.base0E ", 10%), 15%)}") + "base0F" (print "{lighten(saturate(#" $palette.base0F ", 10%), 15%)}") + }} + {{ $themes = merge $themes (dict "_dark" $darkTheme) }} +{{ else if (and $hasDark (not $hasLight)) }} + {{- warnf "No given light theme. Generating one from the dark theme..." }} + {{ $palette := $hasDark.palette }} + {{ $lightTheme := dict + "scheme" (printf "%s (light)" $hasDark.scheme) + "base00" $palette.base07 + "base01" $palette.base06 + "base02" $palette.base05 + "base03" $palette.base04 + "base04" $palette.base03 + "base05" $palette.base02 + "base06" $palette.base01 + "base07" $palette.base00 + "base08" (print "{darken(saturate(#" $palette.base08 ", 10%), 15%)}") + "base09" (print "{darken(saturate(#" $palette.base09 ", 10%), 15%)}") + "base0A" (print "{darken(saturate(#" $palette.base0A ", 10%), 15%)}") + "base0B" (print "{darken(saturate(#" $palette.base0B ", 10%), 15%)}") + "base0C" (print "{darken(saturate(#" $palette.base0C ", 10%), 15%)}") + "base0D" (print "{darken(saturate(#" $palette.base0D ", 10%), 15%)}") + "base0E" (print "{darken(saturate(#" $palette.base0E ", 10%), 15%)}") + "base0F" (print "{darken(saturate(#" $palette.base0F ", 10%), 15%)}") + }} + {{ $themes = merge $themes (dict "_light" $lightTheme) }} +{{ end }} + +{{- range $name, $scheme := $themes }} + // This is a template for a colorscheme based from a Base16 data file from + // https://github.com/chriskempson/base16. + @mixin createColorScheme { + {{ $palette := $scheme.palette }} + {{- range $i := seq 0 15 }} + {{- $hex := upper (printf "%02x" $i) }} + {{- $key := printf "base%s" $hex }} + + // TODO: Make a better way to interpolate the color strings. + {{/* We're just taking advantage the fact that the SASS color functions + returns the colors in the same format we needed. */}} + {{- $color := printf "#%s" (index $palette $key) }} + --{{ $key }}: {{ $color }}; + {{- end }} + } + + {{- if eq $name "_light" }} + @media (prefers-color-scheme: light) { + :root, ::backdrop { + @include createColorScheme + } + } + {{- else if eq $name "_dark" }} + @media (prefers-color-scheme: dark) { + :root, ::backdrop { + @include createColorScheme + } + } + {{- end }} + + [data-theme="{{ .name }}"]:root, [data-theme="{{ .name }}"]::backdrop { + @include createColorScheme; + } +{{- end }} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/config/_default/config.toml b/configs/home-manager/foo-dogsquared/files/homepage/config/_default/config.toml new file mode 100644 index 00000000..fc33450e --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/config/_default/config.toml @@ -0,0 +1,5 @@ +baseURL = "./" +defaultContentLanguage = "en" +title = "foodogsquared's homepage" +timeZone = "UTC" +disableKinds = [ "taxonomy", "sitemap", "robotstxt", "rss" ] diff --git a/configs/home-manager/foo-dogsquared/files/homepage/config/_default/module.toml b/configs/home-manager/foo-dogsquared/files/homepage/config/_default/module.toml new file mode 100644 index 00000000..df32a123 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/config/_default/module.toml @@ -0,0 +1,13 @@ +[[imports]] +path = "github.com/foo-dogsquared/hugo-mod-simple-icons" + +[[imports]] +path = "github.com/Templarian/MaterialDesign" + +[[imports.mounts]] +source = "svg/" +target = "assets/svg/material-design-icons/" + +[[imports.mounts]] +source = "meta.json" +target = "data/icons/material-design-icons/meta.json" diff --git a/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/links.toml b/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/links.toml new file mode 100644 index 00000000..1f6da5f2 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/links.toml @@ -0,0 +1,91 @@ +[quicklinks] +name = "Quicklinks" +flavorText = "For the quick-wilting brain" +textOnly = true +weight = -100 +links = [ + { url = "org-protocol://wiki-open-up-b4-u-todo-anything?where=latest", text = "YOUR GODFORSAKEN TODO LIST" }, + { url = "org-protocol://wiki-open-journal?when=today", text = "Open journal for today" }, + { url = "org-protocol://roam-node?node=41da43fe-a8a9-4a2e-a361-05a11ce8b318", text = "Open todo for today" }, + { url = "https://search.brave.com", text = "Brave Search" }, + { url = "https://login.tailscale.com", text = "Tailscale" }, + { url = "https://devdocs.io", text = "Devdocs" }, +] +icon.iconset = "material-design-icons" +icon.name = "fast-forward" + +[applications] +name = "Applications" +flavorText = "Self-hosting is not the answer to everything, btw" +weight = -1 +textOnly = false +links = [ + { url = "https://start.foodogsquared.one", text = "The other homepage" }, + { url = "https://code.foodogsquared.one", icon = "gitea", text = "Personal forge" }, + { url = "https://pass.foodogsquared.one", icon = "bitwarden", text = "Password manager" }, + { url = "https://monitoring.foodogsquared.one", icon = "grafana", text = "Monitoring application" }, +] +icon.iconset = "material-design-icons" +icon.name = "developer-board" + +[dev] +name = "Software dev" +flavorText = "...is just standing on a house of cards" +textOnly = true +weight = -25 +links = [ + { url = "https://github.com", text = "GitHub" }, + { url = "https://sourcegraph.com", text = "SourceGraph" }, + { url = "https://devdocs.io", text = "Devdocs" }, + { url = "https://vscode.dev", text = "Online Visual Studio Code" }, + { url = "https://cloud.oracle.com", text = "Oracle Cloud" }, + { url = "https://cloud.hetzner.com", text = "Hetzner Cloud" }, + { url = "https://portal.azure.com", text = "Azure Cloud" }, + { url = "https://manpages.debian.org", text = "Debian Manpages" }, +] +grid.row = 2 +icon.iconset = "simple-icons" +icon.name = "github" + +[design] +name = "Design" +flavorText = "No matter how hard I try, it's pretty crap" +textOnly = true +links = [ + { url = "https://app.diagrams.net/", text = "lazy way of drawing things" }, + { url = "https://figma.com", text = "Figma..." }, + { url = "https://www.awwwards.com/", text = "Awwwards" }, + { url = "https://dribbble.com", text = "Dribbble" }, + { url = "https://simpleicons.org/", text = "Simple Icons" }, + { url = "https://pictogrammers.com/library/mdi/", text = "Material Design Icons" }, +] +icon.iconset = "material-design-icons" +icon.name = "pencil-ruler" + +[music] +name = "Music" +flavorText = "Jammin' and groovin'" +textOnly = true +links = [ + { url = "https://music.youtube.com", text = "YouTube Music" }, + { url = "https://open.spotify.com", text = "Spotify" }, + { url = "https://www.last.fm", text = "last.fm" }, + { url = "https://modarchive.org/", text = "The Mod Archive" }, +] +icon.iconset = "material-design-icons" +icon.name = "music" + +[YOHOOHOOHOOHOO] +name = "YOHOOHOOHOOHOO" +flavorText = "Fly away, glum blue sea" +textOnly = true +weight = 100 +links = [ + { url = "https://libgen.is/", text = "Library Genesis" }, + { url = "https://sci-hub.se/", text = "sci-hub" }, + { url = "https://archive.org", text = "Internet Archive" }, + { url = "https://annas-archive.se/", text = "Anna's Archive" }, + { url = "https://archive.softwareheritage.org", text = "Software Heritage" }, +] +icon.iconset = "material-design-icons" +icon.name = "skull-crossbones" diff --git a/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/themes/_dark.yaml b/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/themes/_dark.yaml new file mode 100644 index 00000000..69d7bbcf --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/themes/_dark.yaml @@ -0,0 +1,22 @@ +system: "base16" +name: "Bark on a tree" +author: "Gabriel Arazas (https://foodogsquared.one)" +description: "Rusty theme resembling forestry inspired from Nord theme." +variant: "dark" +palette: + base00: "2b221f" + base01: "412c26" + base02: "5c362c" + base03: "a45b43" + base04: "e1bcb2" + base05: "f5ecea" + base06: "fefefe" + base07: "eb8a65" + base08: "d03e68" + base09: "df937a" + base0A: "afa644" + base0B: "85b26e" + base0C: "eb914a" + base0D: "c67f62" + base0E: "8b7ab9" + base0F: "7f3F83" diff --git a/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/themes/_light.yaml b/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/themes/_light.yaml new file mode 100644 index 00000000..6f1e31f1 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/data/foodogsquared-homepage/themes/_light.yaml @@ -0,0 +1,22 @@ +system: "base16" +name: "Albino bark on a tree" +author: "Gabriel Arazas (https://foodogsquared.one)" +description: "Bright rusty theme resembling forestry inspired from Nord theme." +variant: "light" +palette: + base00: "f0f0f0" + base01: "e1e3e2" + base02: "dacec7" + base03: "9d5c4c" + base04: "54352c" + base05: "392c26" + base06: "2b220f" + base07: "cb6d48" + base08: "b52b52" + base09: "d56f17" + base0A: "b0a52e" + base0B: "5c963e" + base0C: "e46403" + base0D: "954c2f" + base0E: "6751a5" + base0F: "55195a" diff --git a/configs/home-manager/foo-dogsquared/files/homepage/default.nix b/configs/home-manager/foo-dogsquared/files/homepage/default.nix new file mode 100644 index 00000000..dd2fae86 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/default.nix @@ -0,0 +1,5 @@ +{ pkgs ? import { + overlays = [ (import ../../../../../overlays).default ]; +} }: + +pkgs.callPackage ./package.nix { } diff --git a/configs/home-manager/foo-dogsquared/files/homepage/go.mod b/configs/home-manager/foo-dogsquared/files/homepage/go.mod new file mode 100644 index 00000000..6af77ff6 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/go.mod @@ -0,0 +1,9 @@ +module foodogsquared.one/nixos-homepage + +go 1.22.5 + +require ( + github.com/Templarian/MaterialDesign v0.0.0-20240619144146-ce55b68ba730 // indirect + github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20240829051824-890465b5b17e // indirect + github.com/simple-icons/simple-icons v0.0.0-20240828075807-7197fd28e247 // indirect +) diff --git a/configs/home-manager/foo-dogsquared/files/homepage/go.sum b/configs/home-manager/foo-dogsquared/files/homepage/go.sum new file mode 100644 index 00000000..bf5c99d7 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/go.sum @@ -0,0 +1,6 @@ +github.com/Templarian/MaterialDesign v0.0.0-20240619144146-ce55b68ba730 h1:x7myofnw5/5o02a3XMH0IKqGF1uTVdP7TSxEPiX3zKE= +github.com/Templarian/MaterialDesign v0.0.0-20240619144146-ce55b68ba730/go.mod h1:ERpxhfm8YCuNFFEBv+hLM4M4VOrfV5g/mpVMNEfj0MQ= +github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20240829051824-890465b5b17e h1:h4Abw0MZnXP2hFavjEEcXY+lCPJtNejp6CXntXwW8fA= +github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20240829051824-890465b5b17e/go.mod h1:rcVWEdpC9uuXK5ydiewUfaEcoKIZv+l91hphiKrxVq4= +github.com/simple-icons/simple-icons v0.0.0-20240828075807-7197fd28e247 h1:eKjM/xegyBg3XIb+p55bnnB6bD32e0GbCA/1/9vq8aY= +github.com/simple-icons/simple-icons v0.0.0-20240828075807-7197fd28e247/go.mod h1:oOgUUt8yVYOso/wEBi2ojfZP2MU/xxiNccIpaE+jCvE= diff --git a/configs/home-manager/foo-dogsquared/files/homepage/layouts/index.html b/configs/home-manager/foo-dogsquared/files/homepage/layouts/index.html new file mode 100644 index 00000000..d34cd6a3 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/layouts/index.html @@ -0,0 +1,37 @@ + + + + + {{ partial "head.html" . -}} + + + + + + + diff --git a/configs/home-manager/foo-dogsquared/files/homepage/layouts/partials/head.html b/configs/home-manager/foo-dogsquared/files/homepage/layouts/partials/head.html new file mode 100644 index 00000000..0429c43f --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/layouts/partials/head.html @@ -0,0 +1,11 @@ +{{ hugo.Generator }} + + + + +{{ $site := resources.Get "scss/main.scss" | resources.ToCSS }} +{{ $themes := resources.Get "templates/theme.scss" | resources.ExecuteAsTemplate "css/themes.css" . | resources.ToCSS }} + +{{ $stylesheets := slice | append $site $themes | resources.Concat "css/main.css" }} + +{{ .Site.Title }} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/layouts/partials/icon.html b/configs/home-manager/foo-dogsquared/files/homepage/layouts/partials/icon.html new file mode 100644 index 00000000..76d6e813 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/layouts/partials/icon.html @@ -0,0 +1,13 @@ +{{- /* + A partial for easily using icons from Simple Icons set. +*/ -}} +{{ if eq .iconset "simple-icons" }} + {{- $res := resources.ExecuteAsTemplate (printf "svg/brands/%s.svg" .name) + (dict "id" .name + "name" .name) + (resources.Get "templates/simple-icon.svg") }} + {{ $res.Content | safeHTML }} +{{ else if eq .iconset "material-design-icons" }} + {{- $res := resources.Get (printf "svg/material-design-icons/%s.svg" .name) }} + {{ $res.Content | safeHTML }} +{{ end }} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/package.nix b/configs/home-manager/foo-dogsquared/files/homepage/package.nix new file mode 100644 index 00000000..ae2edc3d --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/package.nix @@ -0,0 +1,22 @@ +{ + buildHugoSite, + lib, +}: + +buildHugoSite { + pname = "foodogsquared-hm-startpage"; + version = "0.3.0"; + src = lib.cleanSource ./.; + + vendorHash = "sha256-Mi61QK1yKWIneZ+i79fpJqP9ew5r5vnv7ptr9YGq0Uk="; + + preBuild = '' + install -Dm0644 ${../tinted-theming/base16/bark-on-a-tree.yaml} ./data/foodogsquared-homepage/themes/_dark.yaml + install -Dm0644 ${../tinted-theming/base16/albino-bark-on-a-tree.yaml} ./data/foodogsquared-homepage/themes/_light.yaml + ''; + + meta = with lib; { + description = "foodogsquared's homepage"; + license = licenses.gpl3Only; + }; +} diff --git a/configs/home-manager/foo-dogsquared/files/homepage/shell.nix b/configs/home-manager/foo-dogsquared/files/homepage/shell.nix new file mode 100644 index 00000000..476048f5 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/files/homepage/shell.nix @@ -0,0 +1,14 @@ +{ pkgs ? import { + overlays = [ (import ../../../../../overlays).default ]; +} }: + +let + site = pkgs.callPackage ./package.nix { }; +in +pkgs.mkShell { + inputsFrom = [ site ]; + packages = with pkgs; [ + treefmt + npins + ]; +} diff --git a/configs/home-manager/foo-dogsquared/modules/default.nix b/configs/home-manager/foo-dogsquared/modules/default.nix index fec67e08..b8f556a1 100644 --- a/configs/home-manager/foo-dogsquared/modules/default.nix +++ b/configs/home-manager/foo-dogsquared/modules/default.nix @@ -8,16 +8,19 @@ ./programs/doom-emacs.nix ./programs/email.nix ./programs/git.nix + ./programs/jujutsu.nix ./programs/keys.nix ./programs/nixvim - ./programs/research.nix + ./programs/custom-homepage.nix ./programs/shell.nix ./programs/terminal-multiplexer.nix ./programs/vs-code.nix + ./services/backup ./setups/desktop.nix ./setups/development.nix ./setups/fonts.nix ./setups/music.nix + ./setups/research.nix ]; } diff --git a/configs/home-manager/foo-dogsquared/modules/dotfiles.nix b/configs/home-manager/foo-dogsquared/modules/dotfiles.nix index f1e146dc..5031385c 100644 --- a/configs/home-manager/foo-dogsquared/modules/dotfiles.nix +++ b/configs/home-manager/foo-dogsquared/modules/dotfiles.nix @@ -6,7 +6,7 @@ let projectsDir = config.xdg.userDirs.extraConfig.XDG_PROJECTS_DIR; - dotfiles = "${projectsDir}/dotfiles"; + dotfiles = "${projectsDir}/packages/dotfiles"; dotfiles' = config.lib.file.mkOutOfStoreSymlink config.home.mutableFile."${dotfiles}".path; getDotfiles = path: "${dotfiles'}/${path}"; in diff --git a/configs/home-manager/foo-dogsquared/modules/programs/browsers.nix b/configs/home-manager/foo-dogsquared/modules/programs/browsers.nix index 420ac40e..56ef3676 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/browsers.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/browsers.nix @@ -10,6 +10,8 @@ in firefox.enable = lib.mkEnableOption "foo-dogsquared's Firefox setup"; brave.enable = lib.mkEnableOption "foo-dogsquared's Brave setup"; misc.enable = lib.mkEnableOption "foo-dogsquared's miscellaneous browsers setup"; + + plugins.firenvim.enable = lib.mkEnableOption "setting up Firenvim"; }; config = lib.mkMerge [ @@ -110,6 +112,7 @@ in ] ++ (with pkgs.firefox-addons; [ get-rss-feed-url google-container + microsoft-container regretsreporter simple-translate sourcegraph-for-firefox @@ -128,6 +131,8 @@ in # Some quality of lifes. "browser.search.widget.inNavBar" = true; "browser.search.openintab" = true; + "browser.startup.homepage" = + lib.mkIf userCfg.programs.custom-homepage.enable "file://${userCfg.programs.custom-homepage.finalPackage}/index.html"; # Some privacy settings... "privacy.donottrackheader.enabled" = true; @@ -195,7 +200,19 @@ in }; # Configuring Tridactyl. - xdg.configFile.tridactyl.source = ../../config/tridactyl; + xdg.configFile."tridactyl/tridactylrc".source = pkgs.concatTextFile { + name = "tridactyl-config"; + files = [ + ../../config/tridactyl/tridactylrc + + (pkgs.writeTextFile { + name = "tridactyl-nix-generated"; + text = '' + set newtab file://${userCfg.programs.custom-homepage.finalPackage}/index.html + ''; + }) + ]; + }; # Configuring Bleachbit for Firefox cleaning. services.bleachbit.cleaners = [ @@ -215,7 +232,7 @@ in (lib.mkIf cfg.misc.enable { home.packages = with pkgs; [ google-chrome - nyxt + #nyxt ]; services.bleachbit.cleaners = [ @@ -229,5 +246,25 @@ in "google_chrome.vacuum" ]; }) + + (lib.mkIf cfg.plugins.firenvim.enable + (let + supportedBrowsers = [ + "brave" + "chromium" + "google-chrome" + "vivaldi" + ]; + enableSupportedBrowser = acc: name: acc // { + programs.${name}.extensions = [ + { id = "egpjdkipkomnmjhjmdamaniclmdlobbo"; } + ]; + }; + in + lib.foldl' enableSupportedBrowser { } supportedBrowsers // { + programs.firefox.profiles.personal.extensions = with pkgs.nur.repos.rycee.firefox-addons; [ + firenvim + ]; + })) ]; } diff --git a/configs/home-manager/foo-dogsquared/modules/programs/custom-homepage.nix b/configs/home-manager/foo-dogsquared/modules/programs/custom-homepage.nix new file mode 100644 index 00000000..dcc1034b --- /dev/null +++ b/configs/home-manager/foo-dogsquared/modules/programs/custom-homepage.nix @@ -0,0 +1,122 @@ +{ config, lib, pkgs, ... }: + +let + userCfg = config.users.foo-dogsquared; + cfg = userCfg.programs.custom-homepage; + + settingsFormat = pkgs.formats.toml { }; + themesSettingsFormat = pkgs.formats.yaml { }; +in +{ + options.users.foo-dogsquared.programs.custom-homepage = { + enable = lib.mkEnableOption "addition of custom homepage"; + + sections = lib.mkOption { + type = with lib.types; attrsOf settingsFormat.type; + description = '' + List of additional sections with their settings to be configured + alongside the hardcoded sections. + ''; + default = { }; + example = lib.literalExpression '' + { + services = { + name = "Local services"; + flavorText = "for the local productivity"; + textOnly = true; + + links = lib.singleton { + url = "localhost:''${builtins.toString config.services.mopidy.settings.port}"; + text = "Music streaming server"; + }; + }; + } + ''; + }; + + themes = lib.mkOption { + type = with lib.types; attrsOf path; + description = '' + Set of [Tinted Theming Base16 + palettes](https://github.com/tinted-theming) to be exported to the + homepage. + + ::: {.note} + As such, they are assumed to be all YAML files. + ::: + ''; + default = { }; + example = lib.literalExpression '' + { + _dark = ./files/base16/bark-on-a-tree.yml; + _light = ./files/base16/albino-bark-on-a-tree.yml; + + catpuccin-mocha = (pkgs.formats.yaml { }).generate "catpuccin-mocha-base16" { + system = "base16"; + name = "Catppuccin Mocha"; + author = "https://github.com/catppuccin/catppuccin"; + variant = "dark"; + palette = { + base00 = "1e1e2e"; + base01 = "181825"; + base02 = "313244"; + base03 = "45475a"; + base04 = "585b70"; + base05 = "cdd6f4"; + base06 = "f5e0dc"; + base07 = "b4befe"; + base08 = "f38ba8"; + base09 = "fab387"; + base0A = "f9e2af"; + base0B = "a6e3a1"; + base0C = "94e2d5"; + base0D = "89b4fa"; + base0E = "cba6f7"; + base0F = "f2cdcd"; + }; + }; + } + ''; + }; + + package = lib.mkOption { + type = lib.types.package; + description = '' + The package derivation of the website. + ''; + default = pkgs.callPackage ../../files/homepage/package.nix { }; + }; + + finalPackage = lib.mkOption { + type = lib.types.package; + description = '' + Output derivation containing the website with all of its modifications. + ''; + readOnly = true; + }; + }; + + config = { + users.foo-dogsquared.programs.custom-homepage.finalPackage = + let + data = lib.mapAttrs (n: v: + settingsFormat.generate "fds-homepage-section-${n}" v) cfg.sections; + + installDataDir = lib.foldlAttrs (acc: n: v: '' + ${acc} + install -Dm0644 ${v} './data/foodogsquared-homepage/links/${n}.toml' + '') "" data; + + installThemes = lib.foldlAttrs (acc: n: v: '' + ${acc} + install -Dm0644 ${v} './data/foodogsquared-homepage/themes/${n}}.yaml + '') "" cfg.themes; + in + cfg.package.overrideAttrs (prevAttrs: { + preBuild = (prevAttrs.preBuild or "") + '' + ${installDataDir} + ${installThemes} + ''; + }); + }; +} diff --git a/configs/home-manager/foo-dogsquared/modules/programs/doom-emacs.nix b/configs/home-manager/foo-dogsquared/modules/programs/doom-emacs.nix index f13437af..0d0273bb 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/doom-emacs.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/doom-emacs.nix @@ -71,10 +71,19 @@ in socketActivation.enable = true; }; + # Add org-protocol support. + xdg.desktopEntries.org-protocol = { + name = "Org protocol"; + exec = "emacsclient %u"; + icon = "emacs-icon"; + mimeType = [ "x-scheme-handler/org-protocol" ]; + }; + xdg.mimeApps.defaultApplications = { "application/json" = [ "emacs.desktop" ]; "text/org" = [ "emacs.desktop" ]; "text/plain" = [ "emacs.desktop" ]; + "x-scheme-handler/org-protocol" = [ "org-protocol.desktop" ]; }; }; } diff --git a/configs/home-manager/foo-dogsquared/modules/programs/email.nix b/configs/home-manager/foo-dogsquared/modules/programs/email.nix index 9d0a6f0e..e2ef9121 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/email.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/email.nix @@ -68,6 +68,7 @@ in (lib.mkIf cfg.thunderbird.enable { programs.thunderbird = { enable = true; + package = pkgs.thunderbird-foodogsquared; profiles.personal = { isDefault = true; settings = { diff --git a/configs/home-manager/foo-dogsquared/modules/programs/git.nix b/configs/home-manager/foo-dogsquared/modules/programs/git.nix index 09baa04f..25220c62 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/git.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/git.nix @@ -45,6 +45,8 @@ in "https://git.savannah.nongnu.org/git/".insteadOf = [ "sv:" "savannah:" ]; }; + pull.rebase = "interactive"; + status = { showPatch = true; showStash = true; diff --git a/configs/home-manager/foo-dogsquared/modules/programs/jujutsu.nix b/configs/home-manager/foo-dogsquared/modules/programs/jujutsu.nix new file mode 100644 index 00000000..f154ea51 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/modules/programs/jujutsu.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +let + userCfg = config.users.foo-dogsquared; + cfg = userCfg.programs.jujutsu; +in +{ + options.users.foo-dogsquared.programs.jujutsu.enable = + lib.mkEnableOption "foo-dogsquared's Jujutsu configuration"; + + config = lib.mkIf cfg.enable { + programs.jujutsu = { + enable = true; + settings = { + user.name = config.accounts.email.accounts.personal.realName; + user.email = config.accounts.email.accounts.personal.address; + + ui.diff-editor = "diffedit3"; + + "merge-tools.diffoscope" = { + merge-args = [ "$left" "$right" ]; + program = lib.getExe' pkgs.diffoscope "diffoscope"; + }; + + "merge-tools.diffedit3" = { + merge-args = [ "$left" "$right" "$output" ]; + program = lib.getExe' pkgs.diffedit3 "diffedit3"; + }; + }; + }; + }; +} diff --git a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/dap.nix b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/dap.nix index 47b61594..3538342a 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/dap.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/dap.nix @@ -29,5 +29,5 @@ # Enable a bunch of pre-configured configurations. plugins.dap.extensions.dap-go.enable = true; plugins.dap.extensions.dap-python.enable = true; - plugins.rustaceanvim.enable = true; + plugins.rustaceanvim.enable = false; } diff --git a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/lsp.nix b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/lsp.nix index 82a12492..63069362 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/lsp.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/lsp.nix @@ -2,6 +2,7 @@ { plugins.lsp.enable = true; + plugins.lsp.inlayHints = true; # Enable all of the LSP servers that I'll likely use. plugins.lsp.servers = { @@ -11,14 +12,14 @@ cssls.enable = true; # For CSS. denols.enable = true; # For Deno runtime. dockerls.enable = true; # For Dockerfiles. - emmet_ls.enable = true; # For emmet support. + emmet-ls.enable = true; # For emmet support. eslint.enable = true; # For JavaScript. html.enable = true; # For HTML. jsonls.enable = true; # There's one for JSON? lemminx.enable = true; # And for XML? ltex.enable = true; # And for LanguageTool, too? lua-ls.enable = true; # For Lua. - nil_ls.enable = true; # For Nix. + nixd.enable = true; # For Nix. nushell.enable = true; # For Nushell. pyright.enable = true; # For Python. diff --git a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/misc.nix b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/misc.nix index 582aae96..382f0486 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/misc.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/misc.nix @@ -1,4 +1,8 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, hmConfig, ... }: + +let + userConfig = hmConfig.users.foo-dogsquared; +in { extraPlugins = builtins.map (path: @@ -12,7 +16,15 @@ ]); # Light your browser on fire, bebe. - plugins.firenvim.enable = true; + plugins.firenvim = { + enable = userConfig.programs.browsers.plugins.firenvim.enable; + settings = { + localSettings.".*" = { + selector = "textarea"; + content = "text"; + }; + }; + }; plugins.legendary-nvim = { enable = true; diff --git a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/note-taking.nix b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/note-taking.nix index 5b510b33..363fce3d 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/nixvim/note-taking.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/nixvim/note-taking.nix @@ -2,7 +2,7 @@ { # The main star of the show. - plugins.neorg.enable = true; + plugins.neorg.enable = false; # Set it up, set it up, set it up. plugins.neorg.extraOptions = { diff --git a/configs/home-manager/foo-dogsquared/modules/programs/vs-code.nix b/configs/home-manager/foo-dogsquared/modules/programs/vs-code.nix index 8a831c3a..90bb458a 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/vs-code.nix +++ b/configs/home-manager/foo-dogsquared/modules/programs/vs-code.nix @@ -9,8 +9,9 @@ in lib.mkEnableOption "foo-dogsquared's Visual Studio Code setup"; config = lib.mkIf cfg.enable { + suites.editors.vscode.enable = true; programs.vscode = { - extensions = with pkgs; [ + extensions = with pkgs.vscode-extensions; [ # Additional language support. bbenoist.nix graphql.vscode-graphql diff --git a/configs/home-manager/foo-dogsquared/modules/services/backup/default.nix b/configs/home-manager/foo-dogsquared/modules/services/backup/default.nix new file mode 100644 index 00000000..43fb804b --- /dev/null +++ b/configs/home-manager/foo-dogsquared/modules/services/backup/default.nix @@ -0,0 +1,127 @@ +{ config, lib, foodogsquaredLib, pkgs, ... }@attrs: + +let + userCfg = config.users.foo-dogsquared; + cfg = userCfg.services.backup; + + pathPrefix = "borg-backup"; + getPath = path: + config.sops.secrets."${pathPrefix}/${path}".path; + isFilesystemSet = setupName: + attrs.nixosConfig.suites.filesystem.setups.${setupName}.enable or false; + + hetznerBoxesUser = "u332477"; + hetznerBoxesServer = "${hetznerBoxesUser}.your-storagebox.de"; + + borgmaticCommonConfig = module: lib.mkMerge [ + module + + { + archive_name_format = lib.mkDefault "{fqdn}-home-manager-personal-{now}"; + patterns = lib.mkBefore [ + "R ${config.home.homeDirectory}" + "! ${config.xdg.dataHome}" + "! ${config.xdg.cacheHome}" + "- ${config.xdg.configHome}" + "- ${config.xdg.userDirs.download}" + "+ ${config.xdg.userDirs.extraConfig.XDG_PROJECTS_DIR}" + "+ ${config.xdg.userDirs.documents}" + "+ ${config.xdg.userDirs.music}" + "+ ${config.xdg.userDirs.pictures}" + "+ ${config.xdg.userDirs.templates}" + "+ ${config.xdg.userDirs.videos}" + ]; + exclude_if_present = [ + ".nobackup" + ".exclude.bak" + ]; + exclude_patterns = [ + "node_modules/" + "*.pyc" + "result*/" + "*/.vim*.tmp" + "target/" + ]; + + store_config_files = true; + + # Most of these retention settings are meant to have overlaps in the + # periodic backups. + keep_hourly = 48; + keep_daily = 14; + keep_weekly = 8; + keep_monthly = 12; + keep_yearly = 4; + + check_last = 4; + } + ]; + + checkRemovableMountScript = pkgs.writeShellScript "check-for-removable-storage" '' + { findmnt "$(dirname "$1")" > /dev/null && [ -d "$1" ]; } || exit 75 + ''; +in +{ + options.users.foo-dogsquared.services.backup.enable = + lib.mkEnableOption "preferred backup service"; + + config = lib.mkIf cfg.enable { + sops.secrets = foodogsquaredLib.sops-nix.getSecrets ./secrets.yaml ( + foodogsquaredLib.sops-nix.attachSopsPathPrefix pathPrefix { + "repos/remote-hetzner-boxes-personal/password" = { }; + "repos/local-external-hdd-personal/password" = { }; + "repos/local-archive-personal/password" = { }; + }); + + programs.borgmatic.enable = true; + programs.borgmatic.backups = lib.mkMerge [ + { + remote-hetzner-boxes-personal = { + initService.enable = true; + initService.startAt = "04:30"; + settings = borgmaticCommonConfig { + encryption_passcommand = "cat ${getPath "repos/remote-hetzner-boxes-personal/password"}"; + repositories = lib.singleton { + path = "ssh://${hetznerBoxesUser}@${hetznerBoxesServer}:23/./borg/users/${config.home.username}"; + label = "remote-hetzner-boxes"; + }; + }; + }; + } + + (lib.mkIf (isFilesystemSet "external-hdd") { + local-external-hdd-personal = { + initService.enable = true; + initService.startAt = "04:30"; + settings = let + removablePath = "${attrs.nixosConfig.state.paths.external-hdd}/Backups"; + in borgmaticCommonConfig { + encryption_passcommand = "cat ${getPath "repos/local-external-hdd-personal/password"}"; + repositories = lib.singleton { + path = removablePath; + label = "local-external-hdd"; + }; + before_backup = lib.singleton "${checkRemovableMountScript} ${removablePath}"; + }; + }; + }) + + (lib.mkIf (isFilesystemSet "archive") { + local-archive-personal = { + initService.enable = true; + initService.startAt = "04:30"; + settings = let + removablePath = "${attrs.nixosConfig.state.paths.archive}/Backups"; + in borgmaticCommonConfig { + encryption_passcommand = "cat ${getPath "repos/local-archive-personal/password"}"; + repositories = lib.singleton { + path = removablePath; + label = "local-archive"; + }; + before_backup = lib.singleton "${checkRemovableMountScript} ${removablePath}"; + }; + }; + }) + ]; + }; +} diff --git a/configs/home-manager/foo-dogsquared/modules/services/backup/secrets.yaml b/configs/home-manager/foo-dogsquared/modules/services/backup/secrets.yaml new file mode 100644 index 00000000..d24db788 --- /dev/null +++ b/configs/home-manager/foo-dogsquared/modules/services/backup/secrets.yaml @@ -0,0 +1,27 @@ +repos: + remote-hetzner-boxes-personal: + password: ENC[AES256_GCM,data:VAwukJ6oP0ZuYQGEdS3JVyGHIIUKhcK3Z3bSfoLdwWVP+SU1078YLjusWg==,iv:wMiWIEZknA0c+OFdI+3+yw0Y9WXkqTWOpkn0FnXjYxI=,tag:VKFvr8Ik+eVaMajJPbn09g==,type:str] + local-external-hdd-personal: + password: ENC[AES256_GCM,data:o5zV5Q+Bg+hXVtb7w+IE6mMSFG0GKbsl9Y5GZR2yiHTmUdvH2r7p3CoDFJAV1Us=,iv:HxtXlYOyV1kDhzBPBjNDGwH1ciYbQtcnTZzrgwiSjLw=,tag:ApoenU3Tmg1nltJgNCTlkg==,type:str] + local-archive-personal: + password: ENC[AES256_GCM,data:01UTj28FJegt2USisJ7YPk8zjzUcVhg6VdWzmNJrbJHqzKwA90B1eH6hL4Q2BPQC1tRks2MxPQ==,iv:ScV3wpC2pp3ZCRqmVhPy4R3QMpOd4yEl3h9DwimKi1I=,tag:y8XuQ5vBM0rzmDMD/NKjZw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age17he74we2sm7q7ufv6x26n83hs42v6gkj984m6kwf9xtjduyccqmqtpv37q + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCOTB1YzlhMWdXNnl2L0l6 + dllncG9uN0lzNUtJdmh3SjdzSEhZd001Q0FnCkFDZ2lYb2ZWZi9vTG5OditUOE50 + U08yZGZCaEkzU0pNcFI1WDEwNTlqdHcKLS0tIHRWdEVuM2VqaGYrclllMHJFazls + dGgwbzdJd0xCOHh1eFBTMTkwbnFIOTAKBUjwZqUsUM8qRvRtg0KHm8VNddGPRwJG + 4EwQfN16XVASb44X03c1wKlP4Pdch3Vkxvxo/UzawuZS92TRbZkQVA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-09-07T06:24:59Z" + mac: ENC[AES256_GCM,data:Yf1vU6+oQR1Ao+1haKxKvLmYkjPFr9RnzlOk8wrMs+bHwkpO979rz/PsOhvVGoJMas4fHiIsnpsx3efSf9Kg5UrGb40pJ/uZTWGr9LpeMczD7WyqK/3l9XSbIWAzRqZ6lp5JEBqLqmbwPHOVBI64bakHmQLNklNIGMYVd+hk5gw=,iv:rh3qSSbc2Sv6VottndPLr/bqAnEc+tjxVvQ7MEu0IqI=,tag:nSrREELrPM8mgar5A7tBpA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.0 diff --git a/configs/home-manager/foo-dogsquared/modules/setups/desktop.nix b/configs/home-manager/foo-dogsquared/modules/setups/desktop.nix index 9d311a69..1453aa8f 100644 --- a/configs/home-manager/foo-dogsquared/modules/setups/desktop.nix +++ b/configs/home-manager/foo-dogsquared/modules/setups/desktop.nix @@ -10,6 +10,8 @@ in lib.mkEnableOption "a set of usual desktop productivity services"; config = lib.mkIf cfg.enable { + state.ports.activitywatch.value = 5600; + # Install all of the desktop stuff. suites.desktop = { enable = true; @@ -29,6 +31,7 @@ in # Self-inflicted telemetry. services.activitywatch = { enable = true; + settings.server.port = config.state.ports.activitywatch.value; watchers = { aw-watcher-afk.package = pkgs.activitywatch; aw-watcher-window.package = pkgs.activitywatch; @@ -60,7 +63,7 @@ in topdirs = "~/Downloads ~/Documents ~/library"; "skippedNames+" = let - inherit (config.state) ignoreDirectories; + inherit (config.state.paths) ignoreDirectories; in lib.concatStringsSep " " ignoreDirectories; @@ -73,5 +76,10 @@ in }; }; }; + + users.foo-dogsquared.programs.custom-homepage.sections.services.links = lib.singleton { + url = "http://localhost:${builtins.toString config.state.ports.activitywatch.value}"; + text = "Telemetry server"; + }; }; } diff --git a/configs/home-manager/foo-dogsquared/modules/setups/development.nix b/configs/home-manager/foo-dogsquared/modules/setups/development.nix index 4d4e1c9d..aecf6633 100644 --- a/configs/home-manager/foo-dogsquared/modules/setups/development.nix +++ b/configs/home-manager/foo-dogsquared/modules/setups/development.nix @@ -10,7 +10,7 @@ in config = lib.mkIf cfg.enable (lib.mkMerge [ { - state.ignoreDirectories = [ + state.paths.ignoreDirectories = [ "node_modules" # For Node projects. "result" # For Nix builds. "target" # For Rust builds. @@ -19,6 +19,7 @@ in users.foo-dogsquared.programs = { shell.enable = lib.mkDefault true; git.enable = lib.mkDefault true; + jujutsu.enable = lib.mkDefault true; keys.gpg.enable = true; keys.ssh.enable = true; terminal-multiplexer.enable = lib.mkDefault true; @@ -42,6 +43,7 @@ in regex-cli # Save some face of confusion for yourself. dt # Get that functional gawk. recode # Convert between different encodings. + go-migrate # Go potential migraines. ]; } diff --git a/configs/home-manager/foo-dogsquared/modules/setups/music.nix b/configs/home-manager/foo-dogsquared/modules/setups/music.nix index a1efdb1f..ecf6a31d 100644 --- a/configs/home-manager/foo-dogsquared/modules/setups/music.nix +++ b/configs/home-manager/foo-dogsquared/modules/setups/music.nix @@ -1,12 +1,12 @@ -{ config, lib, pkgs, ... }@attrs: +{ config, lib, pkgs, foodogsquaredLib, ... }@attrs: let + inherit (foodogsquaredLib.trivial) unitsToInt; userCfg = config.users.foo-dogsquared; cfg = userCfg.setups.music; - ytdlpAudio = pkgs.writeScriptBin "yt-dlp-audio" '' - ${pkgs.yt-dlp}/bin/yt-dlp --config-location "${../../config/yt-dlp/audio.conf}" $@ - ''; + isFilesystemSet = setupName: + attrs.nixosConfig.suites.filesystem.setups.${setupName}.enable or false; musicDir = config.xdg.userDirs.music; playlistsDir = "${musicDir}/playlists"; @@ -15,16 +15,25 @@ in options.users.foo-dogsquared.setups.music = { enable = lib.mkEnableOption "foo-dogsquared's music setup"; mpd.enable = lib.mkEnableOption "foo-dogsquared's MPD server setup"; + spotify.enable = lib.mkEnableOption "music streaming setup with Spotify"; }; config = lib.mkIf cfg.enable (lib.mkMerge [ { home.packages = with pkgs; [ songrec # SHAZAM! - ytdlpAudio # My custom script for downloading music with yt-dlp. picard # Graphical beets. ]; + wrapper-manager.packages.music-setup = { + wrappers.yt-dlp-audio = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ../../config/yt-dlp/audio.conf + ]; + }; + }; + # Enable the desktop audio profile for extra auditorial goodies. suites.desktop.audio = { enable = lib.mkDefault true; @@ -92,9 +101,49 @@ in "vlc.memory_dump" "vlc.mru" ]; + + # Set every music-related services from the encompassing NixOS + # configuration. + users.foo-dogsquared.programs.custom-homepage.sections = lib.mkMerge [ + (lib.mkIf (attrs.nixosConfig.services.gonic.enable or false) (let + subsonicLink = { + url = "http://localhost:${builtins.toString attrs.nixosConfig.state.ports.gonic.value}"; + text = "Jukebox server"; + }; + in { + services.links = lib.singleton subsonicLink; + music.links = lib.mkBefore [ (subsonicLink // { text = "Subsonic music server"; }) ]; + })) + ]; } + (lib.mkIf cfg.spotify.enable { + home.packages = with pkgs; [ spotify ]; + + state.ports.spotifyd.value = attrs.nixosConfig.services.spotifyd.value or 9009; + + services.mopidy.extensionPackages = [ pkgs.mopidy-spotify ]; + }) + + (lib.mkIf (cfg.spotify.enable && !(attrs.nixosConfig.services.spotifyd.enable or false)) { + services.spotifyd = { + enable = true; + settings.global = { + use_mpris = true; + device_name = "My laptop"; + bitrate = 320; + device_type = "computer"; + zeroconf_port = config.state.ports.spotifyd.value; + + cache_path = "${config.xdg.cacheHome}/spotifyd"; + max_cache_size = unitsToInt { size = 4; prefix = "G"; }; + }; + }; + }) + (lib.mkIf cfg.mpd.enable { + state.ports.mopidy.value = 6680; + services.mopidy = { enable = true; extensionPackages = with pkgs; [ @@ -110,7 +159,7 @@ in settings = { http = { hostname = "127.0.0.1"; - port = 6680; + port = config.state.ports.mopidy.value; default_app = "iris"; }; @@ -120,10 +169,10 @@ in "$XDG_MUSIC_DIR|Music" "~/library/music|Library" ] - ++ lib.optional (attrs?nixosConfig.suites.filesystem.setups.external-hdd.enable) - "/mnt/external-storage/Music|External storage" - ++ lib.optional (attrs?nixosConfig.suites.filesystem.setups.archive.enable) - "/mnt/archives/Music|Archive"; + ++ lib.optional (isFilesystemSet "external-hdd") + "${attrs.nixosConfig.state.paths.external-hdd}/Music|External storage" + ++ lib.optional (isFilesystemSet "archive") + "${attrs.nixosConfig.state.paths.archive}/Music|Archive"; }; internetarchive = { @@ -154,6 +203,17 @@ in enable = true; mpdMusicDir = musicDir; }; + + # Set this to the custom homepage. + users.foo-dogsquared.programs.custom-homepage.sections = let + mopidyLink = { + url = "http://localhost:${builtins.toString config.state.ports.mopidy.value}"; + text = "Music streaming server"; + }; + in { + services.links = lib.singleton mopidyLink; + music.links = lib.mkBefore [ (mopidyLink // { text = "Mopidy server"; }) ]; + }; }) ]); } diff --git a/configs/home-manager/foo-dogsquared/modules/programs/research.nix b/configs/home-manager/foo-dogsquared/modules/setups/research.nix similarity index 67% rename from configs/home-manager/foo-dogsquared/modules/programs/research.nix rename to configs/home-manager/foo-dogsquared/modules/setups/research.nix index b2f20916..14f6f879 100644 --- a/configs/home-manager/foo-dogsquared/modules/programs/research.nix +++ b/configs/home-manager/foo-dogsquared/modules/setups/research.nix @@ -2,14 +2,16 @@ let userCfg = config.users.foo-dogsquared; - cfg = userCfg.programs.research; + cfg = userCfg.setups.research; in { - options.users.foo-dogsquared.programs.research.enable = + options.users.foo-dogsquared.setups.research.enable = lib.mkEnableOption "foo-dogsquared's usual toolbelt for research"; config = lib.mkIf cfg.enable (lib.mkMerge [ { + state.ports.syncthing.value = 8384; + home.packages = with pkgs; [ anki # Rise, rinse, and repeat. #archivebox # The ultimate archiving solution created by a pirate! @@ -18,6 +20,7 @@ in gallery-dl # More potential for your image collection. internetarchive # All of the potential vintage collection of questionable materials at your fingertips. kiwix # Offline reader for your fanon wiki. + localsend # Local network syncing. monolith # Archive webpages into a single file. qbittorrent # The pirate's toolkit for downloading Linux ISOs. sherlock # Make a profile of your *target*. @@ -26,20 +29,35 @@ in zotero # It's actually good at archiving despite not being a researcher myself. ]; - services.syncthing.enable = true; + services.syncthing = { + enable = true; + extraOptions = [ + "--gui-address=http://localhost:${builtins.toString config.state.ports.syncthing.value}" + ]; + }; xdg.mimeApps.defaultApplications = { "application/vnd.anki" = [ "anki.desktop" ]; }; + + users.foo-dogsquared.programs.custom-homepage.sections.services.links = + lib.singleton { + url = "http://localhost:${builtins.toString config.state.ports.syncthing.value}"; + text = "Local sync server"; + }; } (lib.mkIf userCfg.programs.shell.enable { programs.atuin.settings.history_filter = [ "^curl" + "^wget" "^monolith" "^sherlock" "^yt-dlp" + "^yt-dl" "^gallery-dl" + "^archivebox" + "^fanficfare" ]; }) ]); diff --git a/configs/home-manager/foo-dogsquared/secrets/secrets.yaml b/configs/home-manager/foo-dogsquared/secrets/secrets.yaml deleted file mode 100644 index 97adcba2..00000000 --- a/configs/home-manager/foo-dogsquared/secrets/secrets.yaml +++ /dev/null @@ -1,27 +0,0 @@ -davfs2-credentials: ENC[AES256_GCM,data:pl0rlf8q5/QKp/N7QiYHz/Ol8Lu6QSwIWUTYkkZ0zKO4uhWubICZyJu3Yc4bsn19DCEA7ch8wZ+zHVU8YgMHyesc5OeB5FBjmGCFEqmlM0QwCY3lhy1LirBhqzUf4/x0vIIrgO4d2fI=,iv:H2IYE2cHLzaZ/ni+t0BaSAcdHAmE2PCBlq93R6qQBhY=,tag:DewKYU/tvgtXH3gmcp6TCQ==,type:str] -sops: - shamir_threshold: 2 - key_groups: - - hc_vault: [] - age: - - recipient: age1say65zc678yc03tx4zexp20c9gvskvwrm4390j4x2jkepn97duhq9ptuj9 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmN3FtZ3hTRVdDbDFTbTZt - ZHRKZ1lDUlU0c042RXRqRXFZbUhibnFnb0JrCkZnTDAyZ2xZYXZML0E2Nmg0Mk13 - d1dWa0t0ZHdGZ0xPMHVhc241QzFmSFkKLS0tIGZLSW5NZlNlOXVOQ1d5dzJZZGcy - MmZMcjlmYUQybVU2UVpTOWh2a3p2N1UKtAer0EZBUwgftHd5ITbzy/X8VaeMfH1O - RG0uA9kZOOXkW8yFu23VvUjp0F+SQhQoxKde4qXLbpIMS30juOHYlE8= - -----END AGE ENCRYPTED FILE----- - - hc_vault: [] - age: [] - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] - age: [] - lastmodified: "2023-07-28T15:02:44Z" - mac: ENC[AES256_GCM,data:RI4HgCcLAK/0kS3FOQUJ4AvjGWwziJYvj4ymjWscujsPqQVqhCf35wIoTJ9Wa7Fb6gMM+5ws6LgUj0W3Evu56qi5ej022kyWbO4opOopJGXhZzUzUkX3w2rayDpCu0M9H3EM0AGUvqj8dScFV7GhEFKFeGJ0re9U7ZFXLCfanRs=,iv:lMRuV1/UiIJ3ftK48AGgo6uVdIyWJO9YcbSy57xOC+0=,tag:9RdYy95TwZmhHzNDQMnA6w==,type:str] - pgp: [] - unencrypted_suffix: _unencrypted - version: 3.7.3 diff --git a/configs/nixos/bootstrap/default.nix b/configs/nixos/bootstrap/default.nix index f9b68e51..77a69bef 100644 --- a/configs/nixos/bootstrap/default.nix +++ b/configs/nixos/bootstrap/default.nix @@ -1,4 +1,4 @@ -{ lib, config, pkgs, foodogsquaredModulesPath, ... }: +{ lib, config, pkgs, foodogsquaredLib, foodogsquaredModulesPath, ... }: # Since this will be exported as an installer ISO, you'll have to keep in mind # about the added imports from nixos-generators. In this case, it simply adds @@ -23,9 +23,10 @@ system.stateVersion = "23.11"; } - (lib.mkIf (config.formatAttr == "isoImage") { + (lib.mkIf (foodogsquaredLib.nixos.isFormat config "isoImage") { isoImage = { isoBaseName = config.networking.hostName; + edition = "minimal"; squashfsCompression = "zstd -Xcompression-level 11"; diff --git a/configs/nixos/graphical-installer/default.nix b/configs/nixos/graphical-installer/default.nix index 51780ca9..95a9c224 100644 --- a/configs/nixos/graphical-installer/default.nix +++ b/configs/nixos/graphical-installer/default.nix @@ -32,9 +32,11 @@ # Use my desktop environment configuration without the apps just to make the # closure size smaller. - workflows.workflows.a-happy-gnome = { - enable = true; - extraApps = [ ]; + workflows = { + enable = [ "a-happy-gnome" ]; + workflows.a-happy-gnome = { + extraApps = lib.mkForce [ ]; + }; }; # Install the web browser of course. What would be a graphical installer @@ -62,10 +64,10 @@ } (lib.mkIf - (foodogsquaredLib.isFormat "graphicalIsoImage") { + (foodogsquaredLib.nixos.isFormat config "isoImage") { isoImage = { isoBaseName = config.networking.hostName; - edition = "A Happy GNOME"; + edition = "a-happy-gnome"; squashfsCompression = "zstd -Xcompression-level 12"; }; diff --git a/configs/nixos/ni/default.nix b/configs/nixos/ni/default.nix index 0d44ff49..e2c199dc 100644 --- a/configs/nixos/ni/default.nix +++ b/configs/nixos/ni/default.nix @@ -26,6 +26,13 @@ }; }; + state.paths = { + cacheDir = "/var/cache"; + dataDir = "/var/lib"; + logDir = "/var/log"; + runtimeDir = "/run"; + }; + # Enable the display manager of choice. services.xserver.displayManager.gdm.enable = true; diff --git a/configs/nixos/ni/hardware-configuration.nix b/configs/nixos/ni/hardware-configuration.nix index 20e8db10..2c5c51d0 100644 --- a/configs/nixos/ni/hardware-configuration.nix +++ b/configs/nixos/ni/hardware-configuration.nix @@ -20,4 +20,12 @@ powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + boot.initrd.services.udev.rules = '' + KERNELS=="input0", SUBSYSTEMS=="input", ATTRS{id/product}=="0001", ATTRS{id/vendor}=="0001", ATTRS{id/version}=="ab83", ENV{LIBINPUT_IGNORE_DEVICE}="1" + ''; + + services.udev.extraRules = '' + KERNELS=="input0", SUBSYSTEMS=="input", ATTRS{id/product}=="0001", ATTRS{id/vendor}=="0001", ATTRS{id/version}=="ab83", ENV{LIBINPUT_IGNORE_DEVICE}="1" + ''; } diff --git a/configs/nixos/ni/modules/hardware/qol.nix b/configs/nixos/ni/modules/hardware/qol.nix index 01b3a4aa..5bc6e263 100644 --- a/configs/nixos/ni/modules/hardware/qol.nix +++ b/configs/nixos/ni/modules/hardware/qol.nix @@ -19,14 +19,10 @@ in browsing = true; drivers = with pkgs; [ gutenprint - hplip splix ]; }; - # Make your CPU more useful. - services.auto-cpufreq.enable = true; - # Extend the life of an SSD. services.fstrim.enable = true; }; diff --git a/configs/nixos/ni/modules/networking/setup.nix b/configs/nixos/ni/modules/networking/setup.nix index e1888383..df43bd4e 100644 --- a/configs/nixos/ni/modules/networking/setup.nix +++ b/configs/nixos/ni/modules/networking/setup.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, foodogsquaredLib, ... }: let hostCfg = config.hosts.ni; @@ -7,6 +7,17 @@ in { options.hosts.ni.networking = { enable = lib.mkEnableOption "networking setup"; + + enableCommonSetup = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to enable opening TCP ports and configuring network-related + settings typically used for easy networking with clients. + ''; + example = false; + }; + setup = lib.mkOption { type = lib.types.enum [ "networkd" "networkmanager" ]; description = '' @@ -19,7 +30,14 @@ in risk. ::: ''; - default = "networkmanager"; + default = + if config.networking.useNetworkd + then "networkd" + else "networkmanager"; + defaultText = '' + When networkd is enabled, `networkd`, otherwise `networkmanager` as the + general fallback value. + ''; example = "networkd"; }; }; @@ -139,5 +157,27 @@ in interfaces = [ "enp1s0" "wlp2s0" ]; }; }) + + (lib.mkIf cfg.enableCommonSetup { + state.ports = { + http = { + value = 80; + protocols = [ "tcp" ]; + openFirewall = true; + }; + https = { + value = 443; + protocols = [ "tcp" ]; + openFirewall = true; + }; + + # This is for user-specific services that would need to be exposed to + # the local network. + userland = { + value = foodogsquaredLib.nixos.makeRange 20000 30000; + openFirewall = true; + }; + }; + }) ]); } diff --git a/configs/nixos/ni/modules/services/backup/secrets.yaml b/configs/nixos/ni/modules/services/backup/secrets.yaml index 8f87f4a2..b73f8f53 100644 --- a/configs/nixos/ni/modules/services/backup/secrets.yaml +++ b/configs/nixos/ni/modules/services/backup/secrets.yaml @@ -1,7 +1,7 @@ patterns: home: ENC[AES256_GCM,data:8wCxREEfMlZseot2UuN2JmOaoaWVbO++q21/WRIDu8Z2emC5ii93mY5Kl1CdgtgoXOWSF+HWmQB7g7pbilTDykKA0wue3UnGjxR9ST2uyJaFFpytAIDpOi/wV5zNEI76kg+Ly8N6LjVkLUhTF1qB9fhwGcFzxdFkSUlY2CTWloYGmABY+H3v8vgWbGy+MgKgw7FmzjmqJGpYosi1tqkNctOCDi8ExZG9slD60JYIrIstxmTWqPp2HpzHojeW5cSevTjNx0YY7JZQzOtog4a4AD7Ztrj7nhdS0qfeS7r6RjZrGpkC3d+nUPtEoqwH37xp+G3KvpiQTnVl4qwVBIezUWNPnXJ/eL4lySiue+0qhKVCdaG3/EaObP4vIOUv/8C1N7JVYlhq/Fqmgfukee3v33xjWWKxvN/IrxgKyzOT4a0YTuLYqIj4JaHu5O3lziFDYTuFtKPvIpj0MCbfB+NccE23BuPR6Dgj2mY5V2Gwjwi7R5NMd2I=,iv:aekk7RIqluAAB5+owNECPjZc6LhnBGBsN6eCTAoLklA=,tag:nvNepYWZLgNZUNylkeSBIQ==,type:str] keys: ENC[AES256_GCM,data:xxuamNHPWLpQyERawROxaRdUek6HoDypPK9zw9WGRJthk+7vtCWhyZLLndz0j0ST0H5mU9L9rwDJ4GiyKvPgAyk4iP4=,iv:FclOzefSaDDc+VXq/EMdKX95GfzInPvdKdaBqkNTQRI=,tag:p/0upm4ef/ESx0m9MUPROg==,type:str] - root: ENC[AES256_GCM,data:mrQjyFN6g17dVQ3fGZ8pZ5pcQjgdTTCFrRH7iH/wfRgtXGQ2QCWsQeHes/8b/49gNxQTMYjUuoG66L9HMNS6OQU5gu8jaDXLQdXj2q8pZmOnEA0n1gKv7h6aB3F/NAJuEvTeN93cALraQshpxA2bhb8+icc67lZVWM2c7sNqr9Le6VdPn86wL6uWqmaMH1oIsVqogWHGr+Of1Yc6HB9gdfbI,iv:89L4Rd824Qg5b8OxMoYS4i4XcY0jcCTivDctPCGKxJo=,tag:vQz0M4D5utmR48zEHKLhIg==,type:str] + root: ENC[AES256_GCM,data:MAwmT4t6GA9bK0lPKk/Qkv+keavU2VpVfmKaNqZ+7dLXJjEoEXi6LImbTlAL3bsn1RUPtb1yRWmdcD9wETOjOm7SuufG/HtxI1sJpZnmkUPJV+2I1ll5krEWp1/M1vQHNTgQ2gbJU99riORN4W0EDOeQEg2vMvzALRYW5LRrL/InDqfqzbqUSodb0Uwnt5IL9yQEJIOrIaqxeVRA9zLA6m9ri5dkYIk70hg7QyzDEGA1pzsp81odE6wHAP6yhg==,iv:Kiq7uDRVFwLSOFoEU4xOhsvmSMivO/5fQUc96zmzmD0=,tag:FCHnoIoNpMxsS2gacda/tw==,type:str] repos: archives: password: ENC[AES256_GCM,data:FuPW5dgbt20+eOT4ulV653amUocILnSgc2sBYaeusXw=,iv:WZJYpYdWQzs8G23P4Zflhlxe/H1tShPvMjmFEiLHl4A=,tag:lZUC9JBIwhcEiBpPajaKUw==,type:str] @@ -25,8 +25,8 @@ sops: emJQY1B4UHQvVDJxQlVlUjZXcW5hV2MKAqRYMFGWoXALeUeDoFCYFvCT8pIIRGk4 xMZwLHvRWuZW+15DYGrfrA9+DOS6SZYEYQeApMFVWUdYMU/Xn6KZig== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-04-24T13:05:10Z" - mac: ENC[AES256_GCM,data:tFWcvgXTkz39GuHsRqQioWGfppmODVKvtoOJIth/B52QduspHkK8wMzWDbeBdtA9EaUkL1vv9BOs9G8e42cFBsDH8WWcJsv5L9E3Vciq4n3ihe4wkEIebe//UPGDRwvXXyJAGn14WVROigFYGj7f7tBXfNFaHyEtYm279ta3Qtw=,iv:AksshYcfgoaNiQYNSIy5yfO1rQDysqayKNnvRR60Tl8=,tag:DhxMJ0o7XoY/UP/UXQtSxQ==,type:str] + lastmodified: "2024-06-19T04:49:56Z" + mac: ENC[AES256_GCM,data:d/PpeuvmhHLNivielvfuSfUIQWuSYPd/CJrnuSWoWQxorZG9V7g3UnqMmb7mfISLj3HpC0Xgo1R/wV03hdaRoT2/JwG0Gl4ya9FJiO5jKiwkKVC5cFPvh26aRWTG9/qCzkymL+GC2vyqsvsYTXkq42Ef43tUmxGoFDGsbHzoAlw=,iv:LFIvVqBi4pQEhleaWdcfQI4jGzFksTlRXMgFfHbaaTM=,tag:fsNrZ4h0YmPhCP1XyD9LiQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.8.1 diff --git a/configs/nixos/ni/modules/services/download-media/data/jobs.schema.json b/configs/nixos/ni/modules/services/download-media/data/jobs.schema.json index 87f32058..0c91ea01 100644 --- a/configs/nixos/ni/modules/services/download-media/data/jobs.schema.json +++ b/configs/nixos/ni/modules/services/download-media/data/jobs.schema.json @@ -9,12 +9,17 @@ "required": true, "properties": { "extraArgs": { + "$comment": "Extra arguments to be passed to the associated service.", "type": "array", "items": { "type": "string" }, "uniqueItems": true }, + "downloadPath": { + "$comment": "Job-specific download path of the associated service.", + "type": "string" + }, "subscriptions": { "$comment": "While it is easy to think this could be an object, some exports and applications allow the data to have the same name but points to different URLs. For example, NewPipe has support for multiple services other than YouTube which the same creator could have accounts on multiple platforms. Overriding it would be troublesome in case I want to follow the same creator on multiple platforms.", "type": "array", @@ -28,11 +33,16 @@ "type": "string" } }, - "required": [ "name", "url" ] + "required": [ + "name", + "url" + ] } } }, - "required": [ "subscriptions" ] + "required": [ + "subscriptions" + ] } } } diff --git a/configs/nixos/ni/modules/services/download-media/default.nix b/configs/nixos/ni/modules/services/download-media/default.nix index 38f7fa4b..4006b192 100644 --- a/configs/nixos/ni/modules/services/download-media/default.nix +++ b/configs/nixos/ni/modules/services/download-media/default.nix @@ -29,8 +29,7 @@ in # Write the subtitle file with the preferred languages. "--write-subs" - "--sub-langs" - "en.*,ja,ko,zh.*,fr,pt.*" + "--sub-langs" "en.*,ja,ko,zh.*,fr,pt.*" # Write the description in a separate file. "--write-description" @@ -44,15 +43,12 @@ in "(webm,mkv,mp4)[height<=?1280]" # Prefer MKV whenever possible for video formats. - "--merge-output-format" - "mkv" + "--merge-output-format" "mkv" # Don't download any videos that are originally live streams. - "--match-filters" - "!was_live" + "--match-filters" "!was_live" - "--audio-quality" - "1" + "--audio-quality" "1" # Not much error since it will always fail. "--no-abort-on-error" @@ -60,9 +56,17 @@ in "--ignore-no-formats-error" ]; - ytdlpArchiveVariant = pkgs.writeScriptBin "yt-dlp-archive-variant" '' - ${pkgs.yt-dlp}/bin/yt-dlp ${lib.escapeShellArgs ytdlpArgs} $@ - ''; + galleryDlArgs = [ + # Write metadata to separate JSON files. + "--write-metadata" + + # The config file that contains the secrets for various services. + # We're putting as a separate config file instead of configuring it + # in the service properly since secrets decrypted by sops-nix cannot + # be read in Nix. + "--config" + "${config.sops.secrets."${pathPrefix}/secrets-config".path}" + ]; # Given an attribute set of jobs that contains a list of objects with # their names and URL, create an attrset suitable for declaring the @@ -93,25 +97,27 @@ in lib.listToAttrs jobsList; in { - environment.systemPackages = [ ytdlpArchiveVariant ]; - sops.secrets = foodogsquaredLib.sops-nix.getSecrets ./secrets.yaml (lib.attachSopsPathPrefix pathPrefix { "secrets-config" = { }; }); + # This is to make an exception for Archivebox. + nixpkgs.config.permittedInsecurePackages = [ + "python3.12-django-3.1.14" + ]; + suites.filesystem.setups.archive.enable = true; services.yt-dlp = { enable = true; - archivePath = "${mountName}/yt-dlp-service"; + downloadPath = "${mountName}/yt-dlp-service"; # This is applied on all jobs. It is best to be minimal as much as # possible for this. extraArgs = ytdlpArgs ++ [ # Make a global list of successfully downloaded videos as a cache for yt-dlp. - "--download-archive" - "${config.services.yt-dlp.archivePath}/videos" + "--download-archive" "videos" ]; jobs = mkJobs { @@ -148,22 +154,12 @@ in services.gallery-dl = { enable = true; - archivePath = "${mountName}/gallery-dl-service"; + downloadPath = "${mountName}/gallery-dl-service"; - extraArgs = [ + extraArgs = galleryDlArgs ++ [ # Record all downloaded files in an archive file. "--download-archive" - "${config.services.gallery-dl.archivePath}/photos" - - # Write metadata to separate JSON files. - "--write-metadata" - - # The config file that contains the secrets for various services. - # We're putting as a separate config file instead of configuring it - # in the service properly since secrets decrypted by sops-nix cannot - # be read in Nix. - "--config" - "${config.sops.secrets."${pathPrefix}/secrets-config".path}" + "${config.services.gallery-dl.downloadPath}/photos" ]; settings.extractor = { @@ -203,6 +199,18 @@ in }; }; }; + + wrapper-manager.packages.download-media-variants = { + wrappers."yt-dlp-${pathPrefix}" = { + arg0 = lib.getExe' config.services.yt-dlp.package "yt-dlp"; + prependArgs = ytdlpArgs; + }; + + wrappers."gallery-dl-${pathPrefix}" = { + arg0 = lib.getExe' config.services.gallery-dl.package "gallery-dl"; + prependArgs = galleryDlArgs; + }; + }; } ); } diff --git a/configs/nixos/ni/modules/setups/music.nix b/configs/nixos/ni/modules/setups/music.nix index 153eac39..9aebcfcd 100644 --- a/configs/nixos/ni/modules/setups/music.nix +++ b/configs/nixos/ni/modules/setups/music.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, foodogsquaredLib, ... }: let hostCfg = config.hosts.ni; @@ -9,18 +9,31 @@ in lib.mkEnableOption "music streaming and organizing setup"; config = lib.mkIf cfg.enable { + state.ports = rec { + gonic = { + value = 4747; + protocols = [ "tcp" ]; + openFirewall = true; + }; + uxplay = { + value = 10001; + openFirewall = true; + }; + uxplayClients = { + value = foodogsquaredLib.nixos.makeRange' uxplay.value 10; + openFirewall = true; + }; + }; + # My portable music streaming server. services.gonic = { enable = true; settings = rec { - listen-addr = "localhost:4747"; + listen-addr = "localhost:${builtins.toString config.state.ports.gonic.value}"; cache-path = "/var/cache/gonic"; music-path = [ "/srv/Music" - ] - ++ lib.optionals config.suites.filesystem.setups.external-hdd.enable [ - "/mnt/external-storage/Music" ]; podcast-path = "${cache-path}/podcasts"; playlists-path = "${cache-path}/playlists"; @@ -31,5 +44,14 @@ in scan-at-start-enabled = true; }; }; + + # My AirPlay mirroring server. + services.uxplay = { + enable = true; + extraArgs = [ + "-p" (builtins.toString config.state.ports.uxplay.value) + "-reset" "30" + ]; + }; }; } diff --git a/configs/nixos/plover/.terraform.lock.hcl b/configs/nixos/plover/.terraform.lock.hcl index e3153cc7..05ca9cfd 100644 --- a/configs/nixos/plover/.terraform.lock.hcl +++ b/configs/nixos/plover/.terraform.lock.hcl @@ -2,23 +2,39 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/hetznercloud/hcloud" { - version = "1.40.0" - constraints = "1.40.0" + version = "1.48.1" + constraints = "1.48.1" hashes = [ - "h1:73wGxI4xen4QdT5D1HBhcn1Ll1itFu1b6r4ggflG2OM=", - "zh:0451768ebac9c01b2cc9b3fa63014baa6d1d92e4b5cda9f98a15c320eabc62bd", - "zh:399a3c8fd13e69d8ac836ff5cb3e49eaa13f8d588390862d3c84e5221b85a5ec", - "zh:3f1e2310eaf0945e8df20e841437119b4f1a4fbcbf5c8ef9f66d086a6206df2e", - "zh:5088bd924089c49717fd90fd4893df6caccf978b53bdad79762383c519987290", - "zh:50c178c74bc5aaba5f5d5a0fd51257136b6f2cc0b44bc02b0603f656daad8ee7", - "zh:6a25d234eef37ca727bf20aebeb6a2d3cabbc6338b5e53e98aed222def4b1c86", - "zh:7489d6b14b49916d7181e444880ad1f3914606beda0b7c21485e969ba43f84eb", - "zh:8ded3bfeb885a61a6895e400d1476d15500f2a1a67da440ddd4b1ee2fad0407d", - "zh:b34e3430d48c48edbd49064e500e84765ce03d97c01d855db71c738e1928b97d", - "zh:c36241fc84663e90fd693a74773a22a459c55edae71141f13aba58a267cb09ab", - "zh:c5add5e07edf1876486f4ecfa103f3e500040b4801b8cdf68a91224d3bc6c636", - "zh:ebced845b6be85ca6cf3435eec84514146a48ab6438c700f2e48b7e86d89ff37", - "zh:f543dce13d3c28bf1327452a3922acda70742fc53fefe9628666391f448de99e", - "zh:fa1e04522a1fdf8383f93ec5ffd18424abe99a5ce4a1a8af7e4cd28fce43bb1a", + "h1:fa9fxdSV9DG+HDcXyRbcGfb6Dk94SBP3TamHb1yOYiI=", + "zh:086cce10cb005f25f85183c59e639d6675e91e919934c80f660ca1cc4b9bc09b", + "zh:111d185707168b90c7ed3d245b522b2bd508f0bd4275496a1acdc9c0adaa85f2", + "zh:1acba3f30150282d283c46cd7ce25e9afb8b027fd2f594d41de9131d25a42b27", + "zh:1f8858aa81f93d52550502a11c7ea4e9370316ab098f6b75a09ffe75da6129ee", + "zh:20e01e6e6f99f57b3c1ef2a9de5d617c0139d3f3934eeb5e6c5976ae8b831a48", + "zh:2a8489a586a7bdadc42bbc9e3cb7b9deaefdf8020e3f2caba2678877d5d64d52", + "zh:31d8017529b0429bc9e873ec5d358ab9b75af2ba0ae24f21abcd4d09f36b7ee9", + "zh:407b4d7f1407e7e4a51b6f4dcdb0c7fbf81f2f1e25a7275f34054009419125a2", + "zh:42cf7cf867d199054713d4e6060e4b578eff16f0f537e9aaa5fd990c3eab8bc6", + "zh:460ac856ff952c5d41525949b93cfb7ee642f900594eff965494f11999d7496b", + "zh:d09e527d23f62564c82bc24e286cf2cb8cb0ed6cdc6f4c66adf2145cfa62adac", + "zh:d465356710444ac70dea4883252efc429b73e79fc6dc94f075662b838476680e", + "zh:d476c8eca307e30a20eed54c0735b062a6f3066b4ac63eebecd38ab8f40c16f4", + "zh:e0e9b2f6d5e28dbd01fa1ec3147aa88062d6223c5146532a3dcd1d3bb827e1e9", + ] +} + +provider "registry.opentofu.org/timohirt/hetznerdns" { + version = "2.2.0" + constraints = "2.2.0" + hashes = [ + "h1:HyskQAglrOueur79gSCBgx9MNDOs0tz39aNYQiFgxz8=", + "zh:5bb0ab9f62be3ed92070235e507f3c290491d51391ef4edcc70df53b65a83019", + "zh:5ccdfac7284f5515ac3cff748336b77f21c64760e429e811a1eeefa8ebb86e12", + "zh:687c35665139ae37c291e99085be2e38071f6b355c4e1e8957c5a6a3bcdf9caf", + "zh:6de27f0d0d1513b3a4b7e81923b4a8506c52759bd466e2b4f8156997b0478931", + "zh:85770a9199a4c2d16ca41538d7a0f7a7bfc060678104a1faac19213e6f0a800c", + "zh:a5ff723774a9ccfb27d5766c5e6713537f74dd94496048c89c5d64dba597e59e", + "zh:bf9ab76fd37cb8aebb6868d73cbe8c08cee36fc25224cc1ef5949efa3c34b06c", + "zh:db998fe3bdcd4902e99fa470bb3f355883170cf4c711c8da0b5f1f4510f1be41", ] } diff --git a/configs/nixos/plover/default.nix b/configs/nixos/plover/default.nix index 49d6f45b..26c68174 100644 --- a/configs/nixos/plover/default.nix +++ b/configs/nixos/plover/default.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, foodogsquaredLib, foodogsquaredModulesPath, ... }: +{ config, lib, pkgs, foodogsquaredLib, foodogsquaredUtils, foodogsquaredModulesPath, ... }: { imports = [ @@ -8,8 +8,8 @@ ./modules/profiles/hetzner-cloud-cx21.nix # The users for this host. - (foodogsquaredLib.getUser "nixos" "admin") - (foodogsquaredLib.getUser "nixos" "plover") + (foodogsquaredUtils.getUser "nixos" "admin") + (foodogsquaredUtils.getUser "nixos" "plover") "${foodogsquaredModulesPath}/profiles/headless.nix" "${foodogsquaredModulesPath}/profiles/hardened.nix" @@ -32,11 +32,43 @@ fail2ban.enable = true; # The self-hosted services. - atuin.enable = true; - gitea.enable = true; grafana.enable = true; - vaultwarden.enable = true; - wireguard.enable = true; + }; + + # We're using our own VPN configuration for this one. + suites.vpn.enable = true; + + state.network = { + ipv4 = lib.mkDefault "65.109.224.213"; + ipv6 = lib.mkDefault "2a01:4f9:c012:607a::1"; + + interfaces = { + lan = { + ipv4 = "10.0.0.2"; + ipv6 = ""; + }; + }; + + secondaryNameservers = [ + # ns1.first-ns.de + "213.239.242.238" + "2a01:4f8:0:a101::a:1" + + # robotns2.second-ns.de + "213.133.105.6" + "2a01:4f8:d0a:2004::2" + + # robotns3.second-ns.com + "193.47.99.3" + "2001:67c:192c::add:a3" + ]; + }; + + state.paths = { + dataDir = "/var/lib"; + cacheDir = "/var/cache"; + logDir = "/var/log"; + runtimeDir = "/run"; }; # Offline SSH!?! @@ -61,7 +93,7 @@ email = "admin+acme@foodogsquared.one"; dnsProvider = "rfc2136"; dnsResolver = "1.1.1.1"; - credentialsFile = config.sops.secrets."lego/env".path; + credentialsFile = config.sops.secrets."lego/env".path or "/var/lib/secrets/acme.env"; }; # Enable generating new DH params. diff --git a/configs/nixos/plover/disko.nix b/configs/nixos/plover/disko.nix index a05b808f..b7b8ef20 100644 --- a/configs/nixos/plover/disko.nix +++ b/configs/nixos/plover/disko.nix @@ -1,47 +1,59 @@ -{ config, lib, ... }: +{ disk ? "/dev/sda", ... }: { disko.devices = { - disk.sda = { - device = [ "/dev/sda" ]; + disk.primary = { + device = disk; type = "disk"; content = { type = "gpt"; - partitions = [ - { - name = "boot"; + partitions = { + boot = { start = "0"; end = "1MiB"; - part-type = "primary"; - flags = [ "bios_grub" ]; - } + type = "EF02"; + }; - { - name = "ESP"; + # You can't really have a btrfs-layered boot so this'll have to do. + ESP = { + priority = 1; start = "1MiB"; end = "256MiB"; - bootable = true; + type = "EF00"; content = { type = "filesystem"; - format = "vfat"; mountpoint = "/boot"; + format = "vfat"; }; - flags = [ "esp" ]; - } + }; - { - name = "root"; + root = { start = "256MiB"; end = "100%"; - part-type = "primary"; - bootable = true; + type = "8300"; content = { - type = "filesystem"; - format = "ext4"; - mountpoint = "/"; + type = "btrfs"; + extraArgs = [ "-f" ]; + + subvolumes = [ + { + "/root" = { + mountOptions = [ "compress=zstd" ]; + mountpoint = "/"; + }; + "/home" = { + mountOptions = [ "compress=zstd" ]; + mountpoint = "/home"; + }; + "/nix" = { + mountOptions = [ "compress=zstd" "noatime" "noacl" ]; + mountpoint = "/nix"; + }; + } + ]; }; - } - ]; + }; + }; }; }; }; diff --git a/configs/nixos/plover/files/hcloud/hcloud-user-data.yml b/configs/nixos/plover/files/hcloud/hcloud-user-data.yml deleted file mode 100644 index 73320c21..00000000 --- a/configs/nixos/plover/files/hcloud/hcloud-user-data.yml +++ /dev/null @@ -1,6 +0,0 @@ -#cloud-config - -runcmd: - - curl https://raw.githubusercontent.com/elitak/nixos-infect/e6c879494717cf3a3a54deb0d8630133127f810b/nixos-infect | NIX_CHANNEL=nixos-unstable bash 2>&1 | tee /tmp/infect.log - - e2label /dev/sda1 nixos - - fatlabel /dev/sda15 boot diff --git a/configs/nixos/plover/files/wireguard/wireguard-public-key-phone b/configs/nixos/plover/files/wireguard/wireguard-public-key-phone deleted file mode 100644 index 4565039b..00000000 --- a/configs/nixos/plover/files/wireguard/wireguard-public-key-phone +++ /dev/null @@ -1 +0,0 @@ -MBqt2HPZFGRkIXjv5sIPhGjDytGCWC3K9uTHIa7Xtlc= diff --git a/configs/nixos/plover/files/wireguard/wireguard-public-key-plover b/configs/nixos/plover/files/wireguard/wireguard-public-key-plover deleted file mode 100644 index 1fb33599..00000000 --- a/configs/nixos/plover/files/wireguard/wireguard-public-key-plover +++ /dev/null @@ -1 +0,0 @@ -zXYsuKGj0F/MJmTyHyTj3EIzMnrof7FzK/tx3w/xTEk= diff --git a/configs/nixos/plover/main.tf b/configs/nixos/plover/main.tf index e7765634..425609c0 100644 --- a/configs/nixos/plover/main.tf +++ b/configs/nixos/plover/main.tf @@ -2,14 +2,33 @@ variable "hcloud_token" { sensitive = true } +variable "hcloud_dns_token" { + sensitive = true +} + provider "hcloud" { token = var.hcloud_token } +provider "hetznerdns" { + apitoken = var.hcloud_dns_token +} + +resource "hetznerdns_zone" "main" { + name = "foodogsquared.one" + ttl = 3600 +} + +resource "hetznerdns_primary_server" "main" { + address = hcloud_server.plover.ipv4_address + port = 53 + zone_id = hetznerdns_zone.main.id +} + resource "hcloud_server" "plover" { name = "plover" image = "debian-12" - server_type = "cx21" + server_type = "cx22" location = "hel1" datacenter = "hel1-dc2" @@ -18,8 +37,6 @@ resource "hcloud_server" "plover" { delete_protection = true rebuild_protection = true - user_data = file("${path.module}/files/hcloud/hcloud-user-data.yml") - public_net { ipv4_enabled = true ipv6_enabled = true @@ -27,11 +44,7 @@ resource "hcloud_server" "plover" { network { network_id = hcloud_network.plover.id - ip = "172.27.0.1" - alias_ips = [ - "172.27.0.2", - "172.27.0.3" - ] + ip = "10.0.0.1" } depends_on = [ @@ -46,12 +59,13 @@ resource "hcloud_ssh_key" "foodogsquared" { resource "hcloud_network" "plover" { name = "plover" - ip_range = "172.16.0.0/12" + ip_range = "10.0.0.0/8" + delete_protection = true } resource "hcloud_network_subnet" "plover-subnet" { network_id = hcloud_network.plover.id type = "cloud" network_zone = "eu-central" - ip_range = "172.27.0.0/16" + ip_range = "10.0.0.0/12" } diff --git a/configs/nixos/plover/modules/default.nix b/configs/nixos/plover/modules/default.nix index 1e099ed6..4c128820 100644 --- a/configs/nixos/plover/modules/default.nix +++ b/configs/nixos/plover/modules/default.nix @@ -11,7 +11,7 @@ ./services/database.nix # The primary DNS server that is completely hidden. - ./services/dns-server.nix + ./services/dns-server # The single-sign on setup. ./services/idm.nix @@ -22,9 +22,6 @@ # The firewall of choice. ./services/firewall.nix - # The VPN setup of choice. - ./services/wireguard.nix - # The rest of the self-hosted applications. ./services/atuin.nix ./services/fail2ban.nix diff --git a/configs/nixos/plover/modules/hardware/networks.nix b/configs/nixos/plover/modules/hardware/networks.nix index f6393471..1b7b9dbb 100644 --- a/configs/nixos/plover/modules/hardware/networks.nix +++ b/configs/nixos/plover/modules/hardware/networks.nix @@ -9,69 +9,6 @@ rec { # The thing is generated using a ULA generator. privateIPv6Prefix = "fd89:c181:8016"; - # These blocks should be used sparingly with how wide these blocks cover. - # Plus, they shouldn't be treated as subnets. - clientNetworks = [ - "172.24.0.0/13" - "10.128.0.0/9" - "fd00::/8" - ]; - serverNetworks = [ - "172.16.0.0/13" - "10.0.0.0/9" - "fc00::/8" - ]; - - interfaces = - let - ploverInternalNetworkGateway = "172.16.0.1"; - ipv6Gateway = "fe80::1"; - in - { - # This is the public-facing interface. Any interface name with a prime - # symbol means it's a public-facing interface. - wan = { - ifname = "ens3"; - # The gateways for the public addresses are retrieved from the following - # pages: - # - # * https://docs.hetzner.com/cloud/networks/faq/#are-any-ip-addresses-reserved - # * https://docs.hetzner.com/robot/dedicated-server/ip/additional-ip-adresses/#gateway - IPv4 = { - address = "65.109.224.213"; - gateway = "172.31.1.1"; - }; - IPv6 = { - address = "2a01:4f9:c012:607a::1"; - gateway = ipv6Gateway; - }; - }; - - lan = { - ifname = "ens10"; - IPv4 = { - address = "172.27.0.1"; - gateway = ploverInternalNetworkGateway; - }; - IPv6 = { - address = "${privateIPv6Prefix}::1"; - gateway = ipv6Gateway; - }; - }; - - wireguard0 = { - ifname = "wireguard0"; - IPv4 = { - address = "172.28.0.1"; - gateway = ploverInternalNetworkGateway; - }; - IPv6 = { - address = "${wireguardIPv6Prefix}::1"; - gateway = ipv6Gateway; - }; - }; - }; - # Wireguard-related things. wireguardPort = 51820; @@ -80,36 +17,4 @@ rec { # This IPv6 network prefix should have /64 for the entire Wireguard network. wireguardIPv6Prefix = "${privateIPv6Prefix}:ffff"; - - # These are all fixed IP addresses. However, they should be assigned in /16 - # and /64 for IPv4 and IPv6 block respectively. - wireguardPeers = { - server = with interfaces.wireguard0; { - IPv4 = IPv4.address; - IPv6 = IPv6.address; - }; - desktop = { - IPv4 = "${wireguardIPv4Prefix}.2"; - IPv6 = "${wireguardIPv6Prefix}::2"; - }; - phone = { - IPv4 = "${wireguardIPv4Prefix}.3"; - IPv6 = "${wireguardIPv6Prefix}::3"; - }; - }; - - secondaryNameServers = { - "ns1.first-ns.de." = { - IPv4 = [ "213.239.242.238" ]; - IPv6 = [ "2a01:4f8:0:a101::a:1" ]; - }; - "robotns2.second-ns.de." = { - IPv4 = [ "213.133.105.6" ]; - IPv6 = [ "2a01:4f8:d0a:2004::2" ]; - }; - "robotns3.second-ns.com." = { - IPv4 = [ "193.47.99.3" ]; - IPv6 = [ "2001:67c:192c::add:a3" ]; - }; - }; } diff --git a/configs/nixos/plover/modules/services/database.nix b/configs/nixos/plover/modules/services/database.nix index 5d39b2f4..000c1149 100644 --- a/configs/nixos/plover/modules/services/database.nix +++ b/configs/nixos/plover/modules/services/database.nix @@ -14,38 +14,20 @@ in config = lib.mkIf cfg.enable (lib.mkMerge [ { + state.ports.postgresql.value = 5432; + services.postgresql = { enable = true; package = pkgs.postgresql_16; enableTCPIP = true; - # Create per-user schema as documented from Usage Patterns. This is to make - # use of the secure schema usage pattern they encouraged to do. - # - # Now, you just have to keep in mind about applications making use of them. - # Most of them should have the setting to set the schema to be used. If - # not, then screw them (or just file an issue and politely ask for the - # feature). - initialScript = - let - # This will be run once anyways so it is acceptable to create users - # "forcibly". - perUserSchemas = lib.lists.map - (user: '' - CREATE USER ${user.name}; - CREATE SCHEMA AUTHORIZATION ${user.name}; - '') - config.services.postgresql.ensureUsers; - in - pkgs.writeText "plover-initial-postgresql-script" '' - ${lib.concatStringsSep "\n" perUserSchemas} - ''; - settings = let credsDir = path: "/run/credentials/postgresql.service/${path}"; in { + port = config.state.ports.postgresql.value; + # Still doing the secure schema usage pattern. search_path = ''"$user"''; diff --git a/configs/nixos/plover/modules/services/dns-server.nix b/configs/nixos/plover/modules/services/dns-server/default.nix similarity index 80% rename from configs/nixos/plover/modules/services/dns-server.nix rename to configs/nixos/plover/modules/services/dns-server/default.nix index b9d37f38..8c2bc4f4 100644 --- a/configs/nixos/plover/modules/services/dns-server.nix +++ b/configs/nixos/plover/modules/services/dns-server/default.nix @@ -8,29 +8,23 @@ let cfg = hostCfg.services.dns-server; inherit (config.networking) domain fqdn; - inherit (import ../hardware/networks.nix) interfaces clientNetworks serverNetworks secondaryNameServers; - secondaryNameServersIPs = lib.foldl' - (total: addresses: total ++ addresses.IPv4 ++ addresses.IPv6) - [ ] - (lib.attrValues secondaryNameServers); - domainZone = pkgs.substituteAll { - src = ../../config/dns/${domain}.zone; - ploverWANIPv4 = interfaces.wan.IPv4.address; - ploverWANIPv6 = interfaces.wan.IPv6.address; + zonesDir = "/etc/bind/zones"; + getZoneFile = domain: "${zonesDir}/${domain}.zone"; + + zonefile = pkgs.substituteAll { + src = ../setups/dns/zones/${domain}.zone; + ploverWANIPv4 = config.state.network.ipv4; + ploverWANIPv6 = config.state.network.ipv6; }; fqdnZone = pkgs.substituteAll { - src = ../../config/dns/${fqdn}.zone; - ploverLANIPv4 = interfaces.lan.IPv4.address; - ploverLANIPv6 = interfaces.lan.IPv6.address; + src = ../setups/dns/zones/${fqdn}.zone; + ploverWANIPv4 = config.state.network.ipv4; + ploverWANIPv6 = config.state.network.ipv6; }; - zonesDir = "/etc/bind/zones"; - zoneFile = domain: "${zonesDir}/${domain}.zone"; - dnsSubdomain = "ns1.${domain}"; - dnsOverHTTPSPort = 8443; in { options.hosts.plover.services.dns-server.enable = @@ -38,6 +32,12 @@ in config = lib.mkIf cfg.enable (lib.mkMerge [ { + state.ports = { + dns.value = 53; + dnsOverHTTPS.value = 8443; + dnsOverTLS.value = 853; + }; + sops.secrets = let dnsFileAttribute = { @@ -46,10 +46,7 @@ in mode = "0400"; }; in - foodogsquaredLib.sops-nix.getSecrets ../../secrets/secrets.yaml { - "dns/${domain}/mailbox-security-key" = dnsFileAttribute; - "dns/${domain}/mailbox-security-key-record" = dnsFileAttribute; - "dns/${domain}/keybase-verification-key" = dnsFileAttribute; + foodogsquaredLib.sops-nix.getSecrets ./secrets.yaml { "dns/${domain}/rfc2136-key" = dnsFileAttribute // { reloadUnits = [ "bind.service" ]; }; @@ -69,16 +66,18 @@ in listenOn = [ "127.0.0.1" - interfaces.lan.IPv4.address - interfaces.wan.IPv4.address + config.state.network.ipv4 ]; listenOnIpv6 = [ "::1" - interfaces.lan.IPv6.address - interfaces.wan.IPv6.address + config.state.network.ipv6 ]; + extraConfig = '' + include "${config.state.paths.dataDir}/dns/*-dnskeys.conf"; + ''; + # Welp, since the template is pretty limited, we'll have to go with our # own. This is partially based from the NixOS Bind module except without # the template for filling in zones since we use views. @@ -110,7 +109,7 @@ in endpoints { "/dns-query"; }; }; - acl trusted { ${lib.concatStringsSep "; " (clientNetworks ++ serverNetworks)}; localhost; }; + acl trusted { ${lib.concatStringsSep "; " [ "10.0.0.0/8" ]}; localhost; }; acl cachenetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} }; acl badnetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} }; @@ -124,7 +123,8 @@ in listen-on-v6 tls ${dnsSubdomain} { ${listenInterfacesIpv6} }; # DNS-over-HTTPS. - https-port ${builtins.toString dnsOverHTTPSPort}; + tls-port ${builtins.toString config.state.ports.dnsOverTLS.value}; + https-port ${builtins.toString config.state.ports.dnsOverHTTPS.value}; listen-on tls ${dnsSubdomain} http ${dnsSubdomain} { ${listenInterfaces} }; listen-on-v6 tls ${dnsSubdomain} http ${dnsSubdomain} { ${listenInterfacesIpv6} }; @@ -147,14 +147,14 @@ in zone "${fqdn}" { type primary; - file "${zoneFile fqdn}"; + file "${getZoneFile fqdn}"; }; zone "${domain}" { type primary; - file "${zoneFile domain}"; - allow-transfer { ${lib.concatStringsSep "; " secondaryNameServersIPs}; }; + file "${getZoneFile domain}"; + allow-transfer { ${lib.concatStringsSep "; " config.state.network.secondaryNameservers}; }; update-policy { grant rfc2136key.${domain}. zonesub TXT; }; @@ -182,22 +182,15 @@ in path = with pkgs; [ replace-secret ]; preStart = let - domainZone' = zoneFile domain; - fqdnZone' = zoneFile fqdn; - secretPath = path: config.sops.secrets."dns/${path}".path; - rndc = lib.getExe' config.services.bind.package "rndc"; + domainZone' = getZoneFile domain; + fqdnZone' = getZoneFile fqdn; in lib.mkAfter '' # Install the domain zone. - { - install -Dm0600 '${domainZone}' '${domainZone'}' - replace-secret '#mailboxSecurityKey#' '${secretPath "${domain}/mailbox-security-key"}' '${domainZone'}' - replace-secret '#mailboxSecurityKeyRecord#' '${secretPath "${domain}/mailbox-security-key-record"}' '${domainZone'}' - #${rndc} sync "${domain}" IN external - } + [ -f ${lib.escapeShellArg domainZone'} ] && install -Dm0600 ${zonefile} ${lib.escapeShellArg domainZone'} # Install the internal DNS zones. - install -Dm0600 '${fqdnZone}' '${fqdnZone'}' + [ -f ${lib.escapeShellArg fqdnZone'} ] && install -Dm0600 '${fqdnZone}' ${lib.escapeShellArg fqdnZone'} ''; serviceConfig = { @@ -287,6 +280,23 @@ in security.dhparams.params.bind.bits = 4096; } + (lib.mkIf hostCfg.setups.monitoring.enable { + state.ports.bindStatistics.value = 9423; + + services.bind.extraConfig = '' + statistics-channels { + inet 127.0.0.1 port ${builtins.toString config.state.ports.bindStatistics.value} allow { 127.0.0.1; }; + }; + ''; + + services.prometheus.exporters = { + bind = { + enable = true; + bindURI = "http://127.0.0.1/${builtins.toString config.state.ports.bindStatistics.value}"; + }; + }; + }) + (lib.mkIf hostCfg.services.reverse-proxy.enable { # Making this with nginx. services.nginx.upstreams.local-dns = { @@ -294,7 +304,7 @@ in zone dns 64k; ''; servers = { - "127.0.0.1:${builtins.toString dnsOverHTTPSPort}" = { }; + "127.0.0.1:${builtins.toString config.state.ports.dnsOverHTTPS.value}" = { }; }; }; @@ -329,23 +339,19 @@ in proxy_pass dns_servers; } ''; - }) # Set up the firewall. Take note the ports with the transport layer being # accepted in Bind. (lib.mkIf hostCfg.services.firewall.enable { - networking.firewall = - let - ports = [ - 53 # DNS - 853 # DNS-over-TLS/DNS-over-QUIC - ]; - in - { - allowedUDPPorts = ports; - allowedTCPPorts = ports; - }; + networking.firewall = { + allowedUDPPorts = [ config.state.ports.dns.value ]; + allowedTCPPorts = with config.state.ports; [ + dns.value + dnsOverHTTPS.value + dnsOverTLS.value + ]; + }; }) # Add the following to be backed up. diff --git a/configs/nixos/plover/modules/services/dns-server/secrets.yaml b/configs/nixos/plover/modules/services/dns-server/secrets.yaml new file mode 100644 index 00000000..6adfb201 --- /dev/null +++ b/configs/nixos/plover/modules/services/dns-server/secrets.yaml @@ -0,0 +1,23 @@ +dns: + foodogsquared.one: + rfc2136-key: ENC[AES256_GCM,data:wrYDf+kxNmRnEQdSyqNPtJCHHTnmoSUfZd+zgOKOxGJuggOKVLKinyQTqbHNlBr8Ww3mQSxJQHuUmlUlmBFadWD6jli/89V3g3Yf8Dfmp04dZqxxyeVf4tAfZPYxhvMYv3b3Vf8iwPVo+6wLp/sUjISj32zsUNqXv62Z,iv:HYWW6kCUrBfE9tK3TbocVgFNgemz4lMSrwXork7EYtQ=,tag:f40LfresTPzzBojGrRuS7g==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1yftkhugwrdnlpl45lthrhvvk720zza2nd085sxvjcxg2guavz3kquktplx + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArNXRmbXB6YWJxa0w1R3Rh + ZzVjMHNtdStETXkraEhrbVVIQWtRT1FEbWcwCiszSmFTR2s4RUI1SlJWL3RMTHN2 + a1Qva1Z5TC9PU3hSd2xHczdaZkdnelEKLS0tIE1kQ2FhV3hOY3lHbEx1SUlLSi9X + NHY2MWtSZEtKUkdJa1dnT0VhQWN1dUUKbi24Rv2vAT5teHt9dKltJyKjLpLDuYDw + SxoVKJ6zgEnkwhByAQwHKwwd6fSgPicl2b0kNGUJrooHlwHEUqsDMw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-09-19T13:08:29Z" + mac: ENC[AES256_GCM,data:K7u79dy6X9UtX/nlAuFLUgeU01j12BzGdibdDMmuCc0GEE6+SsByDxf9t1CK1eOlUyJZr1978cjvaYLR3DAv7gTnicBT4r0T6UM6qF0uD4OvlFAKOPz9oUf972NIjAHE2OO4gTHUbOPtIjFGrZSHXmFzQIbG8QAmNmKTPTGF2Fo=,iv:HFsc7i4CtbZCYEAdhbb7tt5D0xDj54oU7DkSDUAmcLY=,tag:m055t7fHlIUUvVKs39LhOA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.0 diff --git a/configs/nixos/plover/config/dns/foodogsquared.one.zone b/configs/nixos/plover/modules/services/dns-server/zones/foodogsquared.one.zone similarity index 71% rename from configs/nixos/plover/config/dns/foodogsquared.one.zone rename to configs/nixos/plover/modules/services/dns-server/zones/foodogsquared.one.zone index 86b023d9..0ccfb782 100644 --- a/configs/nixos/plover/config/dns/foodogsquared.one.zone +++ b/configs/nixos/plover/modules/services/dns-server/zones/foodogsquared.one.zone @@ -4,7 +4,7 @@ $TTL 12h $ORIGIN foodogsquared.one. @ 3600 IN SOA ns1 hostmaster ( - 2023100801 ; serial number + 2024091701 ; serial number 1h ; refresh 15m ; update retry 3w ; expiry @@ -15,29 +15,22 @@ $ORIGIN foodogsquared.one. 3600 IN NS robotns3.second-ns.com. ; Setting up the mail-related DNS entries. -; For future references, please the see the following document at -; https://kb.mailbox.org/en/private/e-mail-article/using-e-mail-addresses-of-your-domain -@ IN MX 10 mxext1.mailbox.org. - IN MX 10 mxext2.mailbox.org. - IN MX 20 mxext3.mailbox.org. - IN TXT v=spf1 include:mailbox.org ~all +; https://mxroutedocs.com/ +@ IN MX 10 heracles.mxrouting.net. + IN MX 20 heracles-relay.mxrouting.net. + IN TXT "v=spf1 include:mxlogin.com -all" + +; Protect the validity of my emails sent by me!!!! +x._domainkey 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyLlrgdsO4jLncMoGAowlE14oB9R2ESxNLRBtkzc24LOPJ1CwEIE+5AHZd+ZRMwiD7fdXcyCH7/E1BRXWT+TtLnKnBgf5I0z6EbPqiPPb6nmpDWrbZzA2mdKetAKz0kFJC8oYK7lQF7Bdh57y/HWksoH6yjl1E88m8tEQ/thlyABGjqzV+txgmc1BryFu23KasqI2c4We/KgvsoSSAaUHkjpAMCuJck/P0G9mJWyTHrnZN2gCotyenLBZew0BIbiA2XYp6dQW4sU+MawfZ0E1KA0lem0SRYCB+sGD248uj4xVo9sIiCVyO9EQXy/YCZTeuTQHf1+QeFzI82vIrlv63QIDAQAB" + +; Protect my domain email from spoofing. +_dmarc 400 IN TXT "v=DMARC1;p=none;rua=mailto:postmaster@foodogsquared.one;ruf=mailto:admin@foodogsquared.one" + + ; Keybase verification key. @ 3600 IN TXT #keybaseVerificationKey# -; This is something that is needed for mailbox.org to verify it is indeed in my -; domain. -#mailboxSecurityKey# 3600 IN TXT #mailboxSecurityKeyRecord# - -; Protect the validity of my emails sent by me!!!! -MBO0001._domainkey IN CNAME MBO0001._domainkey.mailbox.org. -MBO0002._domainkey IN CNAME MBO0002._domainkey.mailbox.org. -MBO0003._domainkey IN CNAME MBO0003._domainkey.mailbox.org. -MBO0004._domainkey IN CNAME MBO0004._domainkey.mailbox.org. - -; Protect my domain email from spoofing. -_dmarc 400 IN TXT v=DMARC1;p=none;rua=mailto:postmaster@foodogsquared.one;ruf=mailto:admin@foodogsquared.one - ; This will make PGP clients find my public key for the email. _hkps._tcp IN SRV 1 1 443 pgp.mailbox.org. diff --git a/configs/nixos/plover/config/dns/plover.foodogsquared.one.zone b/configs/nixos/plover/modules/services/dns-server/zones/plover.foodogsquared.one.zone similarity index 100% rename from configs/nixos/plover/config/dns/plover.foodogsquared.one.zone rename to configs/nixos/plover/modules/services/dns-server/zones/plover.foodogsquared.one.zone diff --git a/configs/nixos/plover/modules/services/fail2ban.nix b/configs/nixos/plover/modules/services/fail2ban.nix index 5cd84a96..4cb3ac00 100644 --- a/configs/nixos/plover/modules/services/fail2ban.nix +++ b/configs/nixos/plover/modules/services/fail2ban.nix @@ -20,11 +20,7 @@ in overalljails = true; }; extraPackages = with pkgs; [ ipset ]; - ignoreIP = [ - # VPN clients. - "${interfaces.wireguard0.IPv4.address}/13" - "${interfaces.wireguard0.IPv6.address}/64" - ]; + ignoreIP = [ "10.0.0.0/8" ]; # We're going to be unforgiving with this one since we only have key # authentication and password authentication is disabled anyways. diff --git a/configs/nixos/plover/modules/services/idm.nix b/configs/nixos/plover/modules/services/idm.nix index 69e2d11d..da06cbc1 100644 --- a/configs/nixos/plover/modules/services/idm.nix +++ b/configs/nixos/plover/modules/services/idm.nix @@ -5,7 +5,7 @@ let cfg = hostCfg.services.idm; authDomain = "auth.${config.networking.domain}"; - port = 9443; + port = config.state.ports.kanidm.value; certsDir = config.security.acme.certs."${authDomain}".directory; @@ -16,6 +16,7 @@ in config = lib.mkIf cfg.enable (lib.mkMerge [ { + state.ports.kanidm.value = 9443; hosts.plover.services.vouch-proxy.enable = lib.mkDefault true; services.kanidm = { diff --git a/configs/nixos/plover/modules/services/monitoring.nix b/configs/nixos/plover/modules/services/monitoring.nix index 50d2aba0..9e6e2a61 100644 --- a/configs/nixos/plover/modules/services/monitoring.nix +++ b/configs/nixos/plover/modules/services/monitoring.nix @@ -4,7 +4,6 @@ let hostCfg = config.hosts.plover; cfg = hostCfg.services.monitoring; - bindStatsPort = 8053; prometheusExports = config.services.prometheus.exporters; in { @@ -17,14 +16,6 @@ in enable = true; exporters = { - bind = { - enable = true; - bindURI = "http://127.0.0.1/${builtins.toString bindStatsPort}"; - }; - - nginx.enable = true; - nginxlog.enable = true; - node = { enable = true; enabledCollectors = [ "systemd" ]; @@ -40,14 +31,6 @@ in } ]; }; - - # Requiring this for Prometheus being able to monitor my services. - services.nginx.statusPage = true; - services.bind.extraConfig = '' - statistics-channels { - inet 127.0.0.1 port ${builtins.toString bindStatsPort} allow { 127.0.0.1; }; - }; - ''; } ]); } diff --git a/configs/nixos/plover/modules/services/reverse-proxy.nix b/configs/nixos/plover/modules/services/reverse-proxy.nix index 17621c57..281112d3 100644 --- a/configs/nixos/plover/modules/services/reverse-proxy.nix +++ b/configs/nixos/plover/modules/services/reverse-proxy.nix @@ -83,5 +83,15 @@ in nginx-bad-request.settings = { enabled = true; }; }; }) + + (lib.mkIf hostCfg.services.monitoring.enable { + # Requiring this for Prometheus being able to monitor my services. + services.nginx.statusPage = true; + + services.prometheus.exporters = { + nginx.enable = true; + nginxlog.enable = true; + }; + }) ]); } diff --git a/configs/nixos/plover/modules/services/wireguard.nix b/configs/nixos/plover/modules/services/wireguard.nix deleted file mode 100644 index 2834712b..00000000 --- a/configs/nixos/plover/modules/services/wireguard.nix +++ /dev/null @@ -1,117 +0,0 @@ -{ config, lib, pkgs, foodogsquaredLib, ... }: - -# Take note this service is heavily based on the hardware networking setup of -# this host so better stay focused on the hardware configuration on this host. -let - hostCfg = config.hosts.plover; - cfg = hostCfg.services.wireguard; - - inherit (import ../hardware/networks.nix) interfaces wireguardPort wireguardPeers; - - wireguardIFName = interfaces.wireguard0.ifname; - - desktopPeerAddresses = with wireguardPeers.desktop; [ "${IPv4}/32" "${IPv6}/128" ]; - phonePeerAddresses = with wireguardPeers.phone; [ "${IPv4}/32" "${IPv6}/128" ]; -in -{ - options.hosts.plover.services.wireguard.enable = - lib.mkEnableOption "Wireguard VPN setup"; - - config = lib.mkIf cfg.enable (lib.mkMerge [ - { - environment.systemPackages = [ pkgs.wireguard-tools ]; - - sops.secrets = - let - systemdNetworkdPermission = { - group = config.users.users.systemd-network.group; - reloadUnits = [ "systemd-networkd.service" ]; - mode = "0640"; - }; - in - foodogsquaredLib.sops-nix.getSecrets ../../secrets/secrets.yaml { - "wireguard/private-key" = systemdNetworkdPermission; - "wireguard/preshared-keys/ni" = systemdNetworkdPermission; - "wireguard/preshared-keys/phone" = systemdNetworkdPermission; - }; - - # Since we're using systemd-networkd to configure interfaces, we can control - # how each interface can handle things such as IP masquerading so no need for - # modifying sysctl settings like 'ipv4.ip_forward' or similar. - systemd.network = { - wait-online.ignoredInterfaces = [ wireguardIFName ]; - - netdevs."99-${wireguardIFName}" = { - netdevConfig = { - Name = wireguardIFName; - Kind = "wireguard"; - }; - - wireguardConfig = { - PrivateKeyFile = config.sops.secrets."wireguard/private-key".path; - ListenPort = wireguardPort; - }; - - wireguardPeers = [ - # Desktop workstation. - { - wireguardPeerConfig = { - PublicKey = lib.readFile ../../../ni/files/wireguard/wireguard-public-key-ni; - PresharedKeyFile = config.sops.secrets."wireguard/preshared-keys/ni".path; - AllowedIPs = lib.concatStringsSep "," desktopPeerAddresses; - }; - } - - # Phone. - { - wireguardPeerConfig = { - PublicKey = lib.readFile ../../files/wireguard/wireguard-public-key-phone; - PresharedKeyFile = config.sops.secrets."wireguard/preshared-keys/phone".path; - AllowedIPs = lib.concatStringsSep "," phonePeerAddresses; - }; - } - ]; - }; - - networks."99-${wireguardIFName}" = with interfaces.wireguard0; { - matchConfig.Name = ifname; - - address = [ - "${IPv4.address}/14" - "${IPv6.address}/64" - ]; - - routes = [ - { routeConfig.Gateway = IPv4.gateway; } - ]; - }; - }; - } - - (lib.mkIf hostCfg.services.firewall.enable { - networking.firewall = { - # Allow the UDP traffic for the Wireguard service. - allowedUDPPorts = [ wireguardPort ]; - - # IP forwarding for specific interfaces. - filterForward = true; - extraForwardRules = '' - iifname ${wireguardIFName} accept comment "IP forward from Wireguard interface to LAN" - ''; - }; - - networking.nftables.ruleset = '' - table ip wireguard-${wireguardIFName} { - chain prerouting { - type nat hook prerouting priority filter; policy accept; - } - - chain postrouting { - type nat hook postrouting priority srcnat; policy accept; - iifname ${wireguardIFName} snat to ${interfaces.lan.IPv4.address} comment "Make packets from Wireguard interface appear as coming from the LAN interface" - } - } - ''; - }) - ]); -} diff --git a/configs/nixos/plover/versions.tf b/configs/nixos/plover/versions.tf index b57a4e2b..5f5c1832 100644 --- a/configs/nixos/plover/versions.tf +++ b/configs/nixos/plover/versions.tf @@ -2,7 +2,12 @@ terraform { required_providers { hcloud = { source = "hetznercloud/hcloud" - version = "1.40.0" + version = "1.48.1" + } + + hetznerdns = { + source = "timohirt/hetznerdns" + version = "2.2.0" } } } diff --git a/configs/nixvim/fiesta/default.nix b/configs/nixvim/fiesta/default.nix index 0be24c7d..9fe1eb20 100644 --- a/configs/nixvim/fiesta/default.nix +++ b/configs/nixvim/fiesta/default.nix @@ -1,10 +1,11 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, helpers, ... }: { imports = [ ./modules ]; config = { nixvimConfigs.fiesta.setups = { + devenvs.enable = true; snippets.enable = true; ui.enable = true; completion.enable = true; @@ -41,8 +42,7 @@ { mode = "n"; key = "bd"; - action = "vim.cmd.bdelete"; - lua = true; + action = helpers.mkRaw "vim.cmd.bdelete"; options.desc = "Delete current buffer"; } ]; diff --git a/configs/nixvim/fiesta/modules/default.nix b/configs/nixvim/fiesta/modules/default.nix index ec9461f2..1ad0ea51 100644 --- a/configs/nixvim/fiesta/modules/default.nix +++ b/configs/nixvim/fiesta/modules/default.nix @@ -3,6 +3,7 @@ ./setups/completion.nix ./setups/debugging.nix ./setups/desktop-utils.nix + ./setups/devenvs.nix ./setups/fuzzy-finder.nix ./setups/lsp.nix ./setups/note-taking.nix diff --git a/configs/nixvim/fiesta/modules/setups/debugging.nix b/configs/nixvim/fiesta/modules/setups/debugging.nix index b95d2f39..1356fb42 100644 --- a/configs/nixvim/fiesta/modules/setups/debugging.nix +++ b/configs/nixvim/fiesta/modules/setups/debugging.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, helpers, ... }: let nixvimCfg = config.nixvimConfigs.fiesta; @@ -14,7 +14,10 @@ in plugins.dap.extensions.dap-virtual-text.enable = true; plugins.debugprint = { enable = true; - settings.ignore_treesitter = false; + settings = { + variable_below_alwaysprompt = null; + variable_above_alwaysprompt = null; + }; }; keymaps = @@ -24,24 +27,23 @@ in { mode = "n"; key = "${bindingPrefix}${binding}"; - lua = true; } // settings; in lib.mapAttrsToList mkDAPBinding { "b" = { options.desc = "Toggle breakpoint"; - action = "require('dap').toggle_breakpoint"; + action = helpers.mkRaw "require('dap').toggle_breakpoint"; }; "B" = { options.desc = "Set breakpoint"; - action = "require('dap').set_breakpoint"; + action = helpers.mkRaw "require('dap').set_breakpoint"; }; "Bp" = { options.desc = "Set breakpoint with log message"; - action = '' + action = helpers.mkRaw '' function() require('dap').set_breakpoint(nil, nil, vim.fn.input('Log point message: ')) end @@ -50,92 +52,92 @@ in "n" = { options.desc = "Continue"; - action = "require('dap').continue"; + action = helpers.mkRaw "require('dap').continue"; }; # You know, like a comma is supposed to do. I got nothing on this one # but this is the best choice for now. "," = { options.desc = "Pause"; - action = "require('dap').pause"; + action = helpers.mkRaw "require('dap').pause"; }; "d" = { options.desc = "Terminate"; - action = "require('dap').terminate"; + action = helpers.mkRaw "require('dap').terminate"; }; "l" = { options.desc = "Step over"; - action = "require('dap').step_over"; + action = helpers.mkRaw "require('dap').step_over"; }; "j" = { options.desc = "Step into"; - action = "require('dap').step_into"; + action = helpers.mkRaw "require('dap').step_into"; }; "J" = { options.desc = "Go up"; - action = "require('dap').up"; + action = helpers.mkRaw "require('dap').up"; }; "k" = { options.desc = "Step out"; - action = "require('dap').step_out"; + action = helpers.mkRaw "require('dap').step_out"; }; "K" = { options.desc = "Go down"; - action = "require('dap').down"; + action = helpers.mkRaw "require('dap').down"; }; "rs" = { options.desc = "Restart session"; - action = "require('dap').restart"; + action = helpers.mkRaw "require('dap').restart"; }; "rr" = { options.desc = "Open debugging REPL"; - action = "require('dap').repl.open"; + action = helpers.mkRaw "require('dap').repl.open"; }; "rl" = { options.desc = "Run last configuration"; - action = "require('dap').run_last"; + action = helpers.mkRaw "require('dap').run_last"; }; "ph" = { options.desc = "View the value under the cursor"; - action = "require('dap.ui.widgets').hover"; + action = helpers.mkRaw "require('dap.ui.widgets').hover"; mode = [ "n" "v" ]; }; "pp" = { options.desc = "See value in preview window"; - action = "require('dap.ui.widgets').preview"; + action = helpers.mkRaw "require('dap.ui.widgets').preview"; mode = [ "n" "v" ]; }; } ++ lib.mapAttrsToList mkDAPBinding { "" = { options.desc = "Continue"; - action = "require('dap').continue"; + action = helpers.mkRaw "require('dap').continue"; }; "" = { options.desc = "Step over"; - action = "require('dap').step_over"; + action = helpers.mkRaw "require('dap').step_over"; }; "" = { options.desc = "Step into"; - action = "require('dap').step_into"; + action = helpers.mkRaw "require('dap').step_into"; }; "" = { options.desc = "Step out"; - action = "require('dap').step_out"; + action = helpers.mkRaw "require('dap').step_out"; }; }; }; diff --git a/configs/nixvim/fiesta/modules/setups/devenvs.nix b/configs/nixvim/fiesta/modules/setups/devenvs.nix new file mode 100644 index 00000000..c979134b --- /dev/null +++ b/configs/nixvim/fiesta/modules/setups/devenvs.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +let + nixvimCfg = config.nixvimConfigs.fiesta; + cfg = nixvimCfg.setups.devenvs; +in +{ + options.nixvimConfigs.fiesta.setups.devenvs.enable = + lib.mkEnableOption "integration for typical devenvs"; + + config = lib.mkIf cfg.enable { + plugins.direnv.enable = true; + plugins.nvim-remote-containers.enable = true; + }; +} diff --git a/configs/nixvim/fiesta/modules/setups/fuzzy-finder.nix b/configs/nixvim/fiesta/modules/setups/fuzzy-finder.nix index 37433a71..8c0f49c3 100644 --- a/configs/nixvim/fiesta/modules/setups/fuzzy-finder.nix +++ b/configs/nixvim/fiesta/modules/setups/fuzzy-finder.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, helpers, ... }: let nixvimCfg = config.nixvimConfigs.fiesta; @@ -31,26 +31,23 @@ in lib.mapAttrsToList mkTelescopeKeymap ({ "A" = { options.desc = "Resume from last use"; - action = "require('telescope.builtin').resume"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').resume"; }; "b" = { options.desc = "List buffers"; - action = "require('telescope.builtin').buffers"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').buffers"; }; "f" = { options.desc = "Find files"; - action = '' + action = helpers.mkRaw '' function() require('telescope.builtin').find_files { hidden = true } end ''; - lua = true; }; "F" = { options.desc = "Find files in current directory"; - action = '' + action = helpers.mkRaw '' function() require('telescope.builtin').find_files { cwd = require('telescope.utils').buffer_dir(), @@ -58,34 +55,28 @@ in } end ''; - lua = true; }; "g" = { options.desc = "Find files tracked by Git"; - action = "require('telescope.builtin').git_files"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').git_files"; }; "G" = { options.desc = "Live grep for the whole project"; - action = "require('telescope.builtin').live_grep"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').live_grep"; }; "h" = { options.desc = "Find section from help tags"; - action = "require('telescope.builtin').help_tags"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').help_tags"; }; "m" = { options.desc = "Find manpage entries"; - action = "require('telescope.builtin').man_pages"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').man_pages"; }; } // lib.optionalAttrs nixvimCfg.setups.treesitter.enable { "t" = { options.desc = "List symbols from treesitter queries"; - action = "require('telescope.builtin').treesitter"; - lua = true; + action = helpers.mkRaw "require('telescope.builtin').treesitter"; }; }); }; diff --git a/configs/nixvim/fiesta/modules/setups/lsp.nix b/configs/nixvim/fiesta/modules/setups/lsp.nix index 6b3f5432..b01438fb 100644 --- a/configs/nixvim/fiesta/modules/setups/lsp.nix +++ b/configs/nixvim/fiesta/modules/setups/lsp.nix @@ -15,7 +15,10 @@ in }; config = lib.mkIf cfg.enable { - plugins.lsp.enable = true; + plugins.lsp = { + enable = true; + inlayHints = true; + }; # Keymaps for moving around in the buffer. plugins.lsp.keymaps.lspBuf = { diff --git a/configs/nixvim/fiesta/modules/setups/snippets/default.nix b/configs/nixvim/fiesta/modules/setups/snippets/default.nix index 88f9a2ef..648fb614 100644 --- a/configs/nixvim/fiesta/modules/setups/snippets/default.nix +++ b/configs/nixvim/fiesta/modules/setups/snippets/default.nix @@ -1,11 +1,10 @@ -{ config, lib, ... }: +{ config, lib, helpers, ... }: let nixvimCfg = config.nixvimConfigs.fiesta; cfg = nixvimCfg.setups.snippets; luasnipKeymapConfig = { - lua = true; mode = [ "i" "s" ]; }; in @@ -40,7 +39,7 @@ in (luasnipKeymapConfig // { key = ""; options.desc = "Jump to next node"; - action = '' + action = helpers.mkRaw '' function() ls = require("luasnip") if ls.jumpable(1) then @@ -53,7 +52,7 @@ in (luasnipKeymapConfig // { key = ""; options.desc = "Jump to previous node"; - action = '' + action = helpers.mkRaw '' function() ls = require("luasnip") if ls.jumpable(-1) then @@ -66,7 +65,7 @@ in (luasnipKeymapConfig // { key = ""; options.desc = "Expand or jump to next node"; - action = '' + action = helpers.mkRaw '' function() ls = require("luasnip") if ls.expand_or_jumpable() then @@ -79,7 +78,7 @@ in (luasnipKeymapConfig // { key = ""; options.desc = "Show extra choices"; - action = '' + action = helpers.mkRaw '' function() require("luasnip.extras.select_choice")() end diff --git a/configs/nixvim/fiesta/modules/setups/treesitter.nix b/configs/nixvim/fiesta/modules/setups/treesitter.nix index a9341cc0..4d1379c5 100644 --- a/configs/nixvim/fiesta/modules/setups/treesitter.nix +++ b/configs/nixvim/fiesta/modules/setups/treesitter.nix @@ -43,8 +43,10 @@ in # Enable all of its useful features. folding = true; - indent = true; - incrementalSelection.enable = true; + settings = { + indent.enable = true; + incremental_selection.enable = true; + }; }; # Enable some more context for me. @@ -94,7 +96,7 @@ in }] ++ ( let - motions = lib.cartesianProductOfSets { + motions = lib.cartesianProduct { region = [ "Start" "End" ]; jumpDirection = [ "Previous" "Next" ]; variant = [ "outer" "inner" ]; @@ -213,7 +215,7 @@ in [{ enable = true; }] ++ ( let - motions = lib.cartesianProductOfSets { + motions = lib.cartesianProduct { jumpDirection = [ "Previous" "Next" ]; variant = [ "outer" ]; }; diff --git a/configs/nixvim/fiesta/modules/setups/ui.nix b/configs/nixvim/fiesta/modules/setups/ui.nix index f71a45bf..41f79ed2 100644 --- a/configs/nixvim/fiesta/modules/setups/ui.nix +++ b/configs/nixvim/fiesta/modules/setups/ui.nix @@ -31,7 +31,7 @@ in # Show them hidden suckers. opts.list = true; opts.listchars = { - tab = "↦ *"; + tab = "↦ "; trail = "·"; nbsp = "%"; }; diff --git a/configs/nixvim/trovebelt/modules/setups/debugging.nix b/configs/nixvim/trovebelt/modules/setups/debugging.nix index d0eb385d..7ebf5386 100644 --- a/configs/nixvim/trovebelt/modules/setups/debugging.nix +++ b/configs/nixvim/trovebelt/modules/setups/debugging.nix @@ -21,7 +21,6 @@ in lldb = { command = "lldb-dap"; - name = "lldb"; }; dart = { diff --git a/configs/nixvim/trovebelt/modules/setups/lsp.nix b/configs/nixvim/trovebelt/modules/setups/lsp.nix index 003686f0..d2290fc0 100644 --- a/configs/nixvim/trovebelt/modules/setups/lsp.nix +++ b/configs/nixvim/trovebelt/modules/setups/lsp.nix @@ -31,7 +31,7 @@ in "efm" # For whatever. "elixirls" # For Elixir. "elmls" # For Elm. - "emmet_ls" # For Emmet support. + "emmet-ls" # For Emmet support. "eslint" # For JavaScript. "gdscript" # For Godot. "gopls" # For Go. @@ -45,7 +45,7 @@ in "kotlin-language-server" # For Kotlin. "lemminx" # For XML. "lua-ls" # For Lua. - "nil_ls" # For Nix. + "nil-ls" # For Nix. "nushell" # For Nushell. "perlpls" # For Perl. "phpactor" # For PHP. diff --git a/configs/nixvim/trovebelt/modules/setups/treesitter.nix b/configs/nixvim/trovebelt/modules/setups/treesitter.nix index 6eb39e9c..2a55c7ea 100644 --- a/configs/nixvim/trovebelt/modules/setups/treesitter.nix +++ b/configs/nixvim/trovebelt/modules/setups/treesitter.nix @@ -20,17 +20,21 @@ in # Enable all of its useful features. folding = true; - indent = true; - incrementalSelection.enable = true; + settings = { + indent.enable = true; + incremental_selection.enable = true; + }; }; # Enable some more context for me. plugins.treesitter-context = { enable = true; - lineNumbers = true; - maxLines = 7; - mode = "cursor"; - separator = "*"; + settings = { + separator = "*"; + mode = "cursor"; + line_numbers = true; + max_lines = 7; + }; }; # Some niceties for refactoring. diff --git a/configs/nixvim/trovebelt/modules/setups/ui.nix b/configs/nixvim/trovebelt/modules/setups/ui.nix index f2e41c46..8b28a9bc 100644 --- a/configs/nixvim/trovebelt/modules/setups/ui.nix +++ b/configs/nixvim/trovebelt/modules/setups/ui.nix @@ -13,24 +13,24 @@ in colorschemes = lib.mkDefault { gruvbox.enable = true; }; # Make it so that terminal GUI colors are au natural. - options.termguicolors = true; + opts.termguicolors = true; # Show locations you're supposed to be copying from the internet (or your # own code). - options.number = true; + opts.number = true; # Make it easy to count. - options.relativenumber = true; + opts.relativenumber = true; # Make it easy to identify your cursor. - options.cursorline = true; + opts.cursorline = true; # Conceal all of the hidden weapons (or distractions). - options.conceallevel = 1; + opts.conceallevel = 1; # Show them hidden suckers. - options.list = true; - options.listchars = { + opts.list = true; + opts.listchars = { tab = "↦ *"; trail = "·"; nbsp = "%"; diff --git a/configs/wrapper-manager/archive-setup/config/yt-dlp/audio.conf b/configs/wrapper-manager/archive-setup/config/yt-dlp/audio.conf new file mode 100644 index 00000000..a91d94e8 --- /dev/null +++ b/configs/wrapper-manager/archive-setup/config/yt-dlp/audio.conf @@ -0,0 +1,14 @@ +# Don't overwrite for cautious individuals. +--no-overwrite + +# To make sure all audio-related. +--extract-audio +--format bestaudio +--audio-format opus + +--output '%(album_artists.0,artists.0)s/%(album,playlist)s/%(track_number,playlist_index)d-%(track,title)s.%(ext)s' +--download-archive music-archive + +# Add all sorts of metadata. +--embed-thumbnail +--add-metadata diff --git a/configs/wrapper-manager/archive-setup/config/yt-dlp/video.conf b/configs/wrapper-manager/archive-setup/config/yt-dlp/video.conf new file mode 100644 index 00000000..89ff7431 --- /dev/null +++ b/configs/wrapper-manager/archive-setup/config/yt-dlp/video.conf @@ -0,0 +1,18 @@ +# Don't overwrite for cautious individuals. +--no-overwrite + +--output '%(uploader,artist,creator|Unknown)s/%(release_date>%F,upload_date>%F|Unknown)s-%(title)s.%(ext)s' +--format '(webm,mkv,mp4)[height<=?1280]' +--download-archive video-archive + +# Don't download past live streams. +--match-filters '!was_live' + +# Add all sorts of metadata. +--embed-thumbnail +--embed-chapters +--add-metadata + +# Add some metadata into sidecar files or something. +--write-info-json +--write-descriptions diff --git a/configs/wrapper-manager/archive-setup/default.nix b/configs/wrapper-manager/archive-setup/default.nix new file mode 100644 index 00000000..ec74aa59 --- /dev/null +++ b/configs/wrapper-manager/archive-setup/default.nix @@ -0,0 +1,17 @@ +{ lib, pkgs, ... }: + +{ + wrappers.yt-dlp-audio = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/audio.conf + ]; + }; + + wrappers.yt-dlp-video = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/video.conf + ]; + }; +} diff --git a/configs/wrapper-manager/dotfiles-wrapped/default.nix b/configs/wrapper-manager/dotfiles-wrapped/default.nix new file mode 100644 index 00000000..9c5d28ac --- /dev/null +++ b/configs/wrapper-manager/dotfiles-wrapped/default.nix @@ -0,0 +1,76 @@ +# All of the programs with my outside dotfiles from +# https://github.com/foo-dogsquared/dotfiles. Pretty nifty for me to have, +# yeah? This should work on both NixOS and non-NixOS system considering that +# parts from the config are conditionally setting up NixGL wrapping. Though, +# you have to use NixOS systems in order to actually use it. We probably should +# have a specialized launcher for this. +let + sources = import ./npins; +in +{ lib, pkgs, wrapperManagerLib, ... }@moduleArgs: + +let + inherit (sources) dotfiles nixgl; + + getDotfiles = path: "${dotfiles}/${path}"; + isInNonNixOS = !(moduleArgs ? nixosConfig); + + wrapNixGL = arg0: + if isInNonNixOS then { + nixgl.enable = true; + nixgl.wraparound.arg0 = arg0; + } else { + inherit arg0; + }; +in +{ + # This wrapper needs runtime expansion which is not possible with binary + # wrappers. + build.isBinary = false; + + nixgl.src = nixgl; + + wrappers.wezterm = lib.mkMerge [ + { + env.WEZTERM_CONFIG_FILE.value = getDotfiles "wezterm/wezterm.lua"; + } + + (wrapNixGL (lib.getExe' pkgs.wezterm "wezterm")) + ]; + + wrappers.kitty = lib.mkMerge [ + { + env.KITTY_CONFIG_DIRECTORY.value = getDotfiles "kitty"; + } + + (wrapNixGL (lib.getExe' pkgs.kitty "kitty")) + ]; + + wrappers.nvim = { + env.VIM.value = getDotfiles "nvim"; + arg0 = lib.getExe' pkgs.neovim "nvim"; + }; + + # Trying to create a portable Doom Emacs. + wrappers.emacs = lib.mkMerge [ + { + env.EMACSDIR.value = builtins.toString sources.doom-emacs; + env.DOOMDIR.value = getDotfiles "emacs"; + env.DOOMPROFILELOADFILE.value = lib.escapeShellArg "$XDG_CACHE_HOME/doom/profiles.el"; + + # TODO: This will be removed in Doom Emacs 3.0 as far as I can tell so we'll + # remove it once that happens. + env.DOOMLOCALDIR.value = lib.escapeShellArg "$XDG_CONFIG_HOME/emacs/"; + + pathAdd = wrapperManagerLib.getBin [ + sources.doom-emacs + ]; + } + + (wrapNixGL (lib.getExe' pkgs.emacs "emacs")) + ]; + + build.extraSetup = '' + install -Dm0755 ${getDotfiles "bin"}/* -t $out/bin + ''; +} diff --git a/configs/wrapper-manager/dotfiles-wrapped/npins/default.nix b/configs/wrapper-manager/dotfiles-wrapped/npins/default.nix new file mode 100644 index 00000000..5e7d086e --- /dev/null +++ b/configs/wrapper-manager/dotfiles-wrapped/npins/default.nix @@ -0,0 +1,80 @@ +# Generated by npins. Do not modify; will be overwritten regularly +let + data = builtins.fromJSON (builtins.readFile ./sources.json); + version = data.version; + + mkSource = + spec: + assert spec ? type; + let + path = + if spec.type == "Git" then + mkGitSource spec + else if spec.type == "GitRelease" then + mkGitSource spec + else if spec.type == "PyPi" then + mkPyPiSource spec + else if spec.type == "Channel" then + mkChannelSource spec + else + builtins.throw "Unknown source type ${spec.type}"; + in + spec // { outPath = path; }; + + mkGitSource = + { + repository, + revision, + url ? null, + hash, + branch ? null, + ... + }: + assert repository ? type; + # At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository + # In the latter case, there we will always be an url to the tarball + if url != null then + (builtins.fetchTarball { + inherit url; + sha256 = hash; # FIXME: check nix version & use SRI hashes + }) + else + assert repository.type == "Git"; + let + urlToName = + url: rev: + let + matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url; + + short = builtins.substring 0 7 rev; + + appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else ""; + in + "${if matched == null then "source" else builtins.head matched}${appendShort}"; + name = urlToName repository.url revision; + in + builtins.fetchGit { + url = repository.url; + rev = revision; + inherit name; + # hash = hash; + }; + + mkPyPiSource = + { url, hash, ... }: + builtins.fetchurl { + inherit url; + sha256 = hash; + }; + + mkChannelSource = + { url, hash, ... }: + builtins.fetchTarball { + inherit url; + sha256 = hash; + }; +in +if version == 3 then + builtins.mapAttrs (_: mkSource) data.pins +else + throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`" diff --git a/configs/wrapper-manager/dotfiles-wrapped/npins/sources.json b/configs/wrapper-manager/dotfiles-wrapped/npins/sources.json new file mode 100644 index 00000000..f43b17f8 --- /dev/null +++ b/configs/wrapper-manager/dotfiles-wrapped/npins/sources.json @@ -0,0 +1,41 @@ +{ + "pins": { + "doom-emacs": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "doomemacs", + "repo": "doomemacs" + }, + "branch": "master", + "revision": "0f30e1eca5f7cb9220d2d1caf4fef7214a86c339", + "url": "https://github.com/doomemacs/doomemacs/archive/0f30e1eca5f7cb9220d2d1caf4fef7214a86c339.tar.gz", + "hash": "004xf0681rizdavl0krpx015h9zyb12ma4gq11nazcy8547qg3kl" + }, + "dotfiles": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "foo-dogsquared", + "repo": "dotfiles" + }, + "branch": "master", + "revision": "c0c64c9f9dae40c7041933851894e14601b56ba7", + "url": "https://github.com/foo-dogsquared/dotfiles/archive/c0c64c9f9dae40c7041933851894e14601b56ba7.tar.gz", + "hash": "1sm00fxajqhrccbxl5647na4fw9cha6w8jvarg5p4kvs3rrwh5p2" + }, + "nixgl": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "nixGL" + }, + "branch": "main", + "revision": "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a", + "url": "https://github.com/nix-community/nixGL/archive/310f8e49a149e4c9ea52f1adf70cdc768ec53f8a.tar.gz", + "hash": "1crnbv3mdx83xjwl2j63rwwl9qfgi2f1lr53zzjlby5lh50xjz4n" + } + }, + "version": 3 +} \ No newline at end of file diff --git a/docs/README.adoc b/docs/README.adoc deleted file mode 100644 index 0243003a..00000000 --- a/docs/README.adoc +++ /dev/null @@ -1,6 +0,0 @@ -= Project documentation -:toc: - - -It's the documentation for my project rendered with Hugo and written with Asciidoctor format. -There are some things you need to be diff --git a/docs/config/_default/languages.toml b/docs/config/_default/languages.toml deleted file mode 100644 index 18010f4e..00000000 --- a/docs/config/_default/languages.toml +++ /dev/null @@ -1,4 +0,0 @@ -[en-US] -languageName = "English" -languageCode = "en-US" -contentDir = "content/en-US" diff --git a/docs/content/en-US/04-nixos-modules/01-workflows/index.adoc b/docs/content/en-US/04-nixos-modules/01-workflows/index.adoc deleted file mode 100644 index 500aba2e..00000000 --- a/docs/content/en-US/04-nixos-modules/01-workflows/index.adoc +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Workflows ---- -= Workflows - -Workflows are all-encompassing NixOS modules for dictating how you interact with your computer/device/whatever. -Basically, this is where certain things are set such as your GNOME desktop environment settings, your dolled up standalone window manager setup, or an oddball audio-only desktop interface. -They are located in `./nixos/modules/workflows` at the project root. - -Workflows are defined under the namespace `workflows` where each workflow module is set to be declared and to be enabled at `workflows.workflows..enable`. -For example, here's how I would enable my imaginary GNOME desktop workflow. - -[source, nix] ----- -{ config, lib, pkgs, ... }: - -{ - workflows.workflows.a-happy-gnome.enable = true; -} ----- - -Take note you cannot enable more than two workflows at any given time. - -[source, nix] ----- -{ config, lib, pkgs, ... }: - -{ - # This would cause an assertion error. - workflows.workflows = { - a-happy-gnome.enable = true; - knome.enable = true; - }; -} ----- - -You can get around this by setting `workflows.disableLimit` to `true`. -However, this shouldn't be taken lightly as workflow modules are very vast in scope and are expected to set system settings that can affect your hardware including... - -* Enabling (and/or disabling) system services such as the preferred network manager. -* Modifying the list of installed applications. -* Setting up programs with custom configurations which could cause conflicts with the defaults (upstream or from nixpkgs) or with another workflow module. - -[chat, foodogsquared] -==== -By organizing the workflow modules this way, you can easily create your desktop rices without overlapping system settings. -Bless the Nix module system! -==== - -[chat, foodogsquared, state=cheeky] -==== -Whether those rices are worth posting to Unix ricing communities is up to you though. -==== - -[chat, Ezran, state=disappointed, role=reversed] -==== -Whippersnappers with your "riced"-up systems... -==== - - - - -== Designing a workflow module - -There are a few guidelines to designing a workflow module which is already laid out in its respective README but as a reminder, let's list it here. - -* All workflow modules should be under `workflows.workflows.` namespace with an `enable` option. - -* No usage of the private modules. -It is a public module, after all so it'll make things messier. -While we can conditionally set the configuration, it is pretty useless since we have the xref:../03-disko/index.adoc[host-specific module structure]. - -* No locale-related settings. -Each user may have its own set of preferred locales and their setup so it is pretty much prohibited from setting any. -The only related parts a workflow module can set is their preferred input method engine (IME) of choice. -The rest of the locale settings is best configured from the host or its individual users. diff --git a/docs/default.nix b/docs/default.nix new file mode 100644 index 00000000..422948f5 --- /dev/null +++ b/docs/default.nix @@ -0,0 +1,143 @@ +{ pkgs ? import { overlays = [ (import ../overlays).default ]; } }: + +let + inherit (pkgs) lib nixosOptionsDoc; + + mkOptionsDoc = args@{ class, modules, includeModuleSystemArguments ? false, ... }: + let + modulesEval = + if class == "nixos" + then lib.evalModules { + modules = modules ++ lib.singleton { + imports = [ + "${pkgs.path}/nixos/modules/misc/extra-arguments.nix" + + # One of the modules requires this to be included. + "${pkgs.path}/nixos/modules/config/xdg/mime.nix" + ]; + _module.check = false; + _module.args.pkgs = pkgs; + fileSystems."/".device = "nodev"; + }; + } + else if class == "homeManager" + then + let + hmLib = import lib; + in + lib.evalModules { + modules = modules ++ lib.singleton { + _module.check = false; + _module.args.pkgs = pkgs; + lib = hmLib.hm; + }; + } + else if class == "wrapperManager" then + let + wrapper-manager = import ../subprojects/wrapper-manager-fds { }; + in + wrapper-manager.lib.eval { + inherit pkgs; + modules = modules ++ lib.singleton { + _module.check = false; + }; + } + else + lib.evalModules { + modules = modules ++ lib.singleton { + _module.check = false; + _module.args.pkgs = pkgs; + }; + }; + + inherit (modulesEval) options; + in + nixosOptionsDoc ({ + options = + if includeModuleSystemArguments + then options + else builtins.removeAttrs options [ "_module" ]; + } + // builtins.removeAttrs args [ "modules" "class" "includeModuleSystemArguments" ]); + + mkManpage = { optionsJSON, asciidocHeader }: + pkgs.runCommand "wrapper-manager-reference-manpage" + { + nativeBuildInputs = with pkgs; [ + nixos-render-docs + asciidoctor + ]; + } + '' + mkdir -p $out/share/man/man5 + asciidoctor --attribute is-wider-scoped --backend manpage \ + ${asciidocHeader} --out-file header.5 + nixos-render-docs options manpage --revision ${pkgs.lib.version} \ + --header ./header.5 --footer ${./manpages/footer.5} \ + ${optionsJSON}/share/doc/nixos/options.json \ + $out/share/man/man5/wrapper-manager.nix.5 + ''; +in +{ + nixos = rec { + optionsDoc = mkOptionsDoc { + modules = [ ../modules/nixos ../modules/nixos/_private ]; + class = "nixos"; + }; + + outputs.manpage = mkManpage { + inherit (optionsDoc) optionsJSON; + asciidocHeader = ./manpages/nixos-header.adoc; + }; + }; + + home-manager = rec { + optionsDoc = mkOptionsDoc { + modules = [ ../modules/home-manager ../modules/home-manager/_private ]; + class = "homeManager"; + }; + + outputs.manpage = mkManpage { + inherit (optionsDoc) optionsJSON; + asciidocHeader = ./manpages/home-manager-header.adoc; + }; + }; + + nixvim = rec { + optionsDoc = mkOptionsDoc { + modules = [ ../modules/nixvim ../modules/nixvim/_private ]; + class = "nixvim"; + }; + + outputs.manpage = mkManpage { + inherit (optionsDoc) optionsJSON; + asciidocHeader = ./manpages/nixvim-header.adoc; + }; + }; + + wrapper-manager = rec { + optionsDoc = mkOptionsDoc { + modules = [ ../modules/wrapper-manager ../modules/wrapper-manager/_private ]; + class = "wrapperManager"; + }; + + outputs.manpage = mkManpage { + inherit (optionsDoc) optionsJSON; + asciidocHeader = ./manpages/wrapper-manager-header.adoc; + }; + }; + + flake-parts = rec { + optionsDoc = mkOptionsDoc { + modules = [ ../modules/flake-parts ]; + class = "flakeParts"; + }; + + outputs.manpage = mkManpage { + inherit (optionsDoc) optionsJSON; + asciidocHeader = ./manpages/flake-parts-header.adoc; + }; + }; + + website = pkgs.callPackage ./website/package.nix { }; +} diff --git a/docs/go.mod b/docs/go.mod deleted file mode 100644 index c4ffd29a..00000000 --- a/docs/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module foo-dogsquared-nixos-config-site - -go 1.20 - -require ( - github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.0 // indirect - github.com/foo-dogsquared/website v0.0.0-20230708113620-9c0c493becff // indirect -) diff --git a/docs/go.sum b/docs/go.sum deleted file mode 100644 index c48a2b26..00000000 --- a/docs/go.sum +++ /dev/null @@ -1,9 +0,0 @@ -github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20230426231746-ef27600d22f3/go.mod h1:11iN6ArO6sro187xxOeDYAFMENfUNd+Vopn+qqVkCbw= -github.com/foo-dogsquared/hugo-mod-web-feeds v0.0.3-0.20220613123653-e0bc8e58159d/go.mod h1:V7UXom6wuFrWj1lBUCXQA3HguwfDhQA+tQNxyRxdClk= -github.com/foo-dogsquared/hugo-theme-contentful v1.2.1-0.20220513103455-d83c3f8c6954/go.mod h1:BL7L5CENEhUx+miRRaOZ9SVC92j9MAMztirBWtTpiPc= -github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.0 h1:N+U5CshaEko6batgTHa6GBfl2bg/1RbG1dAX6EkndVM= -github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.0/go.mod h1:BpUC3zBnnsil2SkU6bULvcDvAEs6FdDDEM8uB0oCpho= -github.com/foo-dogsquared/website v0.0.0-20230708113620-9c0c493becff h1:SmB7yEWR04EWeZ47oQnCBQtD9ZqAOQv9aQjESyfYBDo= -github.com/foo-dogsquared/website v0.0.0-20230708113620-9c0c493becff/go.mod h1:Wce+DpoP9bp3tTaXFeghknBeJEpnDZ4roiR8qwArSXQ= -github.com/refactoringui/heroicons v2.0.17+incompatible/go.mod h1:82HsLWQga7MkEl5aK8TctxPPIBlXrsyWcVTB57uipuk= -github.com/simple-icons/simple-icons v0.0.0-20230423030844-cd4f7d2bf53c/go.mod h1:oOgUUt8yVYOso/wEBi2ojfZP2MU/xxiNccIpaE+jCvE= diff --git a/docs/layouts/_default/baseof.html b/docs/layouts/_default/baseof.html deleted file mode 100644 index 9de7dd68..00000000 --- a/docs/layouts/_default/baseof.html +++ /dev/null @@ -1,19 +0,0 @@ - - - {{ partial "precontent.html" . }} - - {{ partial "head.html" . -}} - {{ partial "head-extended.html" . }} - - - -
- {{ partial "header.html" . }} - - {{ block "main" . }}{{ end }} - {{ partial "footer.html" . }} -
- - diff --git a/docs/manpages/footer.5 b/docs/manpages/footer.5 new file mode 100644 index 00000000..fe3169d5 --- /dev/null +++ b/docs/manpages/footer.5 @@ -0,0 +1,3 @@ +.SH "AUTHORS" +.PP +foodogsquared diff --git a/docs/manpages/wrapper-manager-header.adoc b/docs/manpages/wrapper-manager-header.adoc new file mode 100644 index 00000000..b70ee48e --- /dev/null +++ b/docs/manpages/wrapper-manager-header.adoc @@ -0,0 +1,11 @@ += foodogsquared-wrapper-manager-extra-modules(5) +:doctype: manpage +:manmanual: foodogsquared's wrapper-manager extra module +:mansource: foodogsquared's wrapper-manager extra module + + +== Name + +wrapper-manager-foodogsquared-modules.nix - foodogsquared's extra *wrapper-manager.nix(5)* modules + +== Options diff --git a/docs/shell.nix b/docs/shell.nix deleted file mode 100644 index 3fe9701d..00000000 --- a/docs/shell.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ pkgs ? import { } }: - -with pkgs; - -let - asciidoctorWrapper = writeShellScriptBin "asciidoctor" '' - ${lib.getBin gems}/bin/asciidoctor -T ${./assets/templates/asciidoctor} $@ - ''; - - gems = bundlerEnv { - name = "nixos-config-project-docs"; - ruby = ruby_3_1; - gemdir = ./.; - }; -in -mkShell { - packages = [ - asciidoctorWrapper - gems - gems.wrappedRuby - bundix - - hugo - go - nodePackages.prettier - vscode-langservers-extracted - ]; -} diff --git a/docs/.gitignore b/docs/website/.gitignore similarity index 100% rename from docs/.gitignore rename to docs/website/.gitignore diff --git a/docs/Gemfile b/docs/website/Gemfile similarity index 100% rename from docs/Gemfile rename to docs/website/Gemfile diff --git a/docs/Gemfile.lock b/docs/website/Gemfile.lock similarity index 100% rename from docs/Gemfile.lock rename to docs/website/Gemfile.lock diff --git a/docs/LICENSE b/docs/website/LICENSE similarity index 100% rename from docs/LICENSE rename to docs/website/LICENSE diff --git a/docs/website/Makefile b/docs/website/Makefile new file mode 100644 index 00000000..d6d2a84a --- /dev/null +++ b/docs/website/Makefile @@ -0,0 +1,2 @@ +update: + hugo mod get ./... && hugo mod tidy diff --git a/docs/website/README.adoc b/docs/website/README.adoc new file mode 100644 index 00000000..d9cf032a --- /dev/null +++ b/docs/website/README.adoc @@ -0,0 +1,17 @@ += Project documentation +:toc: + + +It's the documentation for my project rendered with Hugo and written with Asciidoctor format. +There are some things you need to be aware of. + +* This is basically an extended theme using https://github.com/foo-dogsquared/website[my website]. +It is built on top of it so every single change will have to be adapted to it including the assets (especially). + +* This heavily uses my https://github.com/foo-dogsquared/asciidoctor-foodogsquared-extensions[own set of Asciidoctor extensions]. + +* This uses my custom Asciidoctor templates. +Unfortunately, this is not doable with Hugo so it is done primarily with a hack that shadows the original `asciidoctor` executable with a custom script of the same name. + +* This also uses nixpkgs with their Ruby packaging infrastructure. +You can see more details about developing and maintaining them in https://nixos.org/manual/nixpkgs/stable/#sec-language-ruby[the respective manual]. diff --git a/docs/assets/scss/extend.scss b/docs/website/assets/scss/extend.scss similarity index 100% rename from docs/assets/scss/extend.scss rename to docs/website/assets/scss/extend.scss diff --git a/docs/assets/templates/asciidoctor/admonition.html.erb b/docs/website/assets/templates/asciidoctor/admonition.html.erb similarity index 100% rename from docs/assets/templates/asciidoctor/admonition.html.erb rename to docs/website/assets/templates/asciidoctor/admonition.html.erb diff --git a/docs/assets/templates/asciidoctor/paragraph.html.erb b/docs/website/assets/templates/asciidoctor/paragraph.html.erb similarity index 100% rename from docs/assets/templates/asciidoctor/paragraph.html.erb rename to docs/website/assets/templates/asciidoctor/paragraph.html.erb diff --git a/docs/config/_default/config.toml b/docs/website/config/_default/config.toml similarity index 85% rename from docs/config/_default/config.toml rename to docs/website/config/_default/config.toml index fe47a94c..1ba298a6 100644 --- a/docs/config/_default/config.toml +++ b/docs/website/config/_default/config.toml @@ -1,5 +1,5 @@ baseURL = 'https://foo-dogsquared.github.io/nixos-config' -defaultContentLanguage = 'en-US' +defaultContentLanguage = 'en' title = "foodogsquared's NixOS config" timeZone = "UTC" diff --git a/docs/website/config/_default/languages.toml b/docs/website/config/_default/languages.toml new file mode 100644 index 00000000..efec485e --- /dev/null +++ b/docs/website/config/_default/languages.toml @@ -0,0 +1,4 @@ +[en] +languageName = "English" +languageCode = "en" +contentDir = "content/en" diff --git a/docs/config/_default/markup.toml b/docs/website/config/_default/markup.toml similarity index 100% rename from docs/config/_default/markup.toml rename to docs/website/config/_default/markup.toml diff --git a/docs/config/_default/module.toml b/docs/website/config/_default/module.toml similarity index 100% rename from docs/config/_default/module.toml rename to docs/website/config/_default/module.toml diff --git a/docs/content/en-US/01-introduction/index.adoc b/docs/website/content/en/01-introduction/index.adoc similarity index 100% rename from docs/content/en-US/01-introduction/index.adoc rename to docs/website/content/en/01-introduction/index.adoc diff --git a/docs/content/en-US/02-lay-of-the-land/01-prerequisites/index.adoc b/docs/website/content/en/02-lay-of-the-land/01-prerequisites/index.adoc similarity index 100% rename from docs/content/en-US/02-lay-of-the-land/01-prerequisites/index.adoc rename to docs/website/content/en/02-lay-of-the-land/01-prerequisites/index.adoc diff --git a/docs/content/en-US/02-lay-of-the-land/02-project-structure/index.adoc b/docs/website/content/en/02-lay-of-the-land/02-project-structure/index.adoc similarity index 100% rename from docs/content/en-US/02-lay-of-the-land/02-project-structure/index.adoc rename to docs/website/content/en/02-lay-of-the-land/02-project-structure/index.adoc diff --git a/docs/content/en-US/02-lay-of-the-land/03-whats-in-my-flake/index.adoc b/docs/website/content/en/02-lay-of-the-land/03-whats-in-my-flake/index.adoc similarity index 100% rename from docs/content/en-US/02-lay-of-the-land/03-whats-in-my-flake/index.adoc rename to docs/website/content/en/02-lay-of-the-land/03-whats-in-my-flake/index.adoc diff --git a/docs/content/en-US/02-lay-of-the-land/04-channels-support/index.adoc b/docs/website/content/en/02-lay-of-the-land/04-channels-support/index.adoc similarity index 100% rename from docs/content/en-US/02-lay-of-the-land/04-channels-support/index.adoc rename to docs/website/content/en/02-lay-of-the-land/04-channels-support/index.adoc diff --git a/docs/content/en-US/02-lay-of-the-land/05-what-should-not-be-here/index.adoc b/docs/website/content/en/02-lay-of-the-land/05-what-should-not-be-here/index.adoc similarity index 100% rename from docs/content/en-US/02-lay-of-the-land/05-what-should-not-be-here/index.adoc rename to docs/website/content/en/02-lay-of-the-land/05-what-should-not-be-here/index.adoc diff --git a/docs/content/en-US/02-lay-of-the-land/06-the-ci-server/index.adoc b/docs/website/content/en/02-lay-of-the-land/06-the-ci-server/index.adoc similarity index 100% rename from docs/content/en-US/02-lay-of-the-land/06-the-ci-server/index.adoc rename to docs/website/content/en/02-lay-of-the-land/06-the-ci-server/index.adoc diff --git a/docs/content/en-US/03-project-specific-setup/01-declarative-host-management/index.adoc b/docs/website/content/en/03-project-specific-setup/01-declarative-host-management/index.adoc similarity index 100% rename from docs/content/en-US/03-project-specific-setup/01-declarative-host-management/index.adoc rename to docs/website/content/en/03-project-specific-setup/01-declarative-host-management/index.adoc diff --git a/docs/content/en-US/03-project-specific-setup/02-declarative-user-management/index.adoc b/docs/website/content/en/03-project-specific-setup/02-declarative-user-management/index.adoc similarity index 100% rename from docs/content/en-US/03-project-specific-setup/02-declarative-user-management/index.adoc rename to docs/website/content/en/03-project-specific-setup/02-declarative-user-management/index.adoc diff --git a/docs/content/en-US/03-project-specific-setup/03-secrets-management/assets/attach-sops-prefix.nix b/docs/website/content/en/03-project-specific-setup/03-secrets-management/assets/attach-sops-prefix.nix similarity index 100% rename from docs/content/en-US/03-project-specific-setup/03-secrets-management/assets/attach-sops-prefix.nix rename to docs/website/content/en/03-project-specific-setup/03-secrets-management/assets/attach-sops-prefix.nix diff --git a/docs/content/en-US/03-project-specific-setup/03-secrets-management/assets/get-secrets.nix b/docs/website/content/en/03-project-specific-setup/03-secrets-management/assets/get-secrets.nix similarity index 100% rename from docs/content/en-US/03-project-specific-setup/03-secrets-management/assets/get-secrets.nix rename to docs/website/content/en/03-project-specific-setup/03-secrets-management/assets/get-secrets.nix diff --git a/docs/content/en-US/03-project-specific-setup/03-secrets-management/index.adoc b/docs/website/content/en/03-project-specific-setup/03-secrets-management/index.adoc similarity index 100% rename from docs/content/en-US/03-project-specific-setup/03-secrets-management/index.adoc rename to docs/website/content/en/03-project-specific-setup/03-secrets-management/index.adoc diff --git a/docs/content/en-US/03-project-specific-setup/04-custom-firefox-addons/index.adoc b/docs/website/content/en/03-project-specific-setup/04-custom-firefox-addons/index.adoc similarity index 100% rename from docs/content/en-US/03-project-specific-setup/04-custom-firefox-addons/index.adoc rename to docs/website/content/en/03-project-specific-setup/04-custom-firefox-addons/index.adoc diff --git a/docs/website/content/en/04-nixos-modules/01-workflows/index.adoc b/docs/website/content/en/04-nixos-modules/01-workflows/index.adoc new file mode 100644 index 00000000..000f8c24 --- /dev/null +++ b/docs/website/content/en/04-nixos-modules/01-workflows/index.adoc @@ -0,0 +1,56 @@ +--- +title: Workflows +--- += Workflows + +Workflows are all-encompassing NixOS modules for dictating how you interact with your computer/device/whatever. +Basically, this is where certain things are set such as your GNOME desktop environment settings, your dolled up standalone window manager setup, or an oddball audio-only desktop interface. + +[NOTE] +==== +Take note that they are considered as private modules so if you're not foodogsquared, you shouldn't use it. +==== + +The workflow namespace mainly contains the `enable` option where you can enable more than one workflows like in the following code. + +[source, nix] +---- +{ config, lib, pkgs, ... }: + +{ + workflows.enable = [ + "a-happy-gnome" + "beepeedobolyuessemm" + ]; +} +---- + +However, enabling workflows shouldn't be taken lightly as they are quite pervasive with what they can configure. + +* Enabling (and/or disabling) system services such as the preferred network manager. + +* Modifying the list of installed applications. +This is especially more prevalent when you enable more than workflow module. + +* Setting up programs with custom configurations which could cause conflicts with the defaults (upstream or from nixpkgs) or with another workflow module. + +Additionally, you can make your workflow module configurable by setting up options in `workflows.workflows.` namespace. + +[chat, foodogsquared] +==== +By organizing the workflow modules this way, you can easily create your desktop rices without overlapping system settings. +Bless the Nix module system! +==== + +[chat, foodogsquared, state=cheeky] +==== +Whether those rices are worth posting to Unix ricing communities is up to you though. +==== + +[chat, Ezran, state=disappointed, role=reversed] +==== +Whippersnappers with your "riced"-up systems... +==== + + +include::../../../../../modules/nixos/_private/workflows/README.adoc#design-constraints[] diff --git a/docs/content/en-US/04-nixos-modules/02-disko/index.adoc b/docs/website/content/en/04-nixos-modules/02-disko/index.adoc similarity index 100% rename from docs/content/en-US/04-nixos-modules/02-disko/index.adoc rename to docs/website/content/en/04-nixos-modules/02-disko/index.adoc diff --git a/docs/content/en-US/04-nixos-modules/03-host-specific-modules/index.adoc b/docs/website/content/en/04-nixos-modules/03-host-specific-modules/index.adoc similarity index 100% rename from docs/content/en-US/04-nixos-modules/03-host-specific-modules/index.adoc rename to docs/website/content/en/04-nixos-modules/03-host-specific-modules/index.adoc diff --git a/docs/content/en-US/05-home-manager/index.adoc b/docs/website/content/en/05-home-manager/index.adoc similarity index 100% rename from docs/content/en-US/05-home-manager/index.adoc rename to docs/website/content/en/05-home-manager/index.adoc diff --git a/docs/content/en-US/06-using-parts-of-my-configuration/index.adoc b/docs/website/content/en/06-using-parts-of-my-configuration/index.adoc similarity index 100% rename from docs/content/en-US/06-using-parts-of-my-configuration/index.adoc rename to docs/website/content/en/06-using-parts-of-my-configuration/index.adoc diff --git a/docs/content/en-US/07-faq/index.adoc b/docs/website/content/en/07-faq/index.adoc similarity index 100% rename from docs/content/en-US/07-faq/index.adoc rename to docs/website/content/en/07-faq/index.adoc diff --git a/docs/content/en-US/08-acknowledgement/index.adoc b/docs/website/content/en/08-acknowledgement/index.adoc similarity index 100% rename from docs/content/en-US/08-acknowledgement/index.adoc rename to docs/website/content/en/08-acknowledgement/index.adoc diff --git a/docs/content/en-US/09-copyright/index.adoc b/docs/website/content/en/09-copyright/index.adoc similarity index 100% rename from docs/content/en-US/09-copyright/index.adoc rename to docs/website/content/en/09-copyright/index.adoc diff --git a/docs/content/en-US/_index.adoc b/docs/website/content/en/_index.adoc similarity index 100% rename from docs/content/en-US/_index.adoc rename to docs/website/content/en/_index.adoc diff --git a/docs/content/en-US/menu.adoc b/docs/website/content/en/menu.adoc similarity index 100% rename from docs/content/en-US/menu.adoc rename to docs/website/content/en/menu.adoc diff --git a/docs/gemset.nix b/docs/website/gemset.nix similarity index 100% rename from docs/gemset.nix rename to docs/website/gemset.nix diff --git a/docs/website/go.mod b/docs/website/go.mod new file mode 100644 index 00000000..c0744f71 --- /dev/null +++ b/docs/website/go.mod @@ -0,0 +1,8 @@ +module foo-dogsquared-nixos-config-site + +go 1.20 + +require ( + github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20240518105144-dd35649b15e2 // indirect + github.com/foo-dogsquared/website v0.0.0-20240609010936-d1a9857559b8 // indirect +) diff --git a/docs/website/go.sum b/docs/website/go.sum new file mode 100644 index 00000000..7bc1e35c --- /dev/null +++ b/docs/website/go.sum @@ -0,0 +1,10 @@ +github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20231025231637-36998f86bbf2/go.mod h1:8HnVc0SlzI7LCEU4sITYS5MQTq0Bct/nFr/7LdsHYVQ= +github.com/foo-dogsquared/hugo-mod-web-feeds v0.0.3-0.20220613123653-e0bc8e58159d/go.mod h1:V7UXom6wuFrWj1lBUCXQA3HguwfDhQA+tQNxyRxdClk= +github.com/foo-dogsquared/hugo-theme-contentful v1.2.1-0.20220513103455-d83c3f8c6954/go.mod h1:BL7L5CENEhUx+miRRaOZ9SVC92j9MAMztirBWtTpiPc= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20231028090155-ee19cd7714b4/go.mod h1:RgD3YpinFJyZhtn0iVLNs8eRa0nSs2VA+o1jBpe4zBs= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20240518105144-dd35649b15e2 h1:BvkVSiI6jXUhUyuRnBY6gSnmb2Th/7FaEwBStbw36Qk= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20240518105144-dd35649b15e2/go.mod h1:RgD3YpinFJyZhtn0iVLNs8eRa0nSs2VA+o1jBpe4zBs= +github.com/foo-dogsquared/website v0.0.0-20240609010936-d1a9857559b8 h1:a7HWbiHMkcgz6T2lpm4gXHFTljuQ66uHH6YyZdZqeKA= +github.com/foo-dogsquared/website v0.0.0-20240609010936-d1a9857559b8/go.mod h1:zJw9MC6Ajnx5Bom/52LR9Xib40toK9d2tG9FeVqJN3U= +github.com/refactoringui/heroicons v2.0.18+incompatible/go.mod h1:82HsLWQga7MkEl5aK8TctxPPIBlXrsyWcVTB57uipuk= +github.com/simple-icons/simple-icons v0.0.0-20231022005333-fdbaaa2d5f99/go.mod h1:oOgUUt8yVYOso/wEBi2ojfZP2MU/xxiNccIpaE+jCvE= diff --git a/docs/website/layouts/_default/baseof.html b/docs/website/layouts/_default/baseof.html new file mode 100644 index 00000000..a6f2f890 --- /dev/null +++ b/docs/website/layouts/_default/baseof.html @@ -0,0 +1,22 @@ + + +{{ partial "precontent.html" . }} + + + {{ partial "head.html" . -}} + {{ partial "head-extended.html" . }} + + + + +
+ {{ partial "header.html" . }} + + {{ block "main" . }}{{ end }} + {{ partial "footer.html" . }} +
+ + + diff --git a/docs/layouts/index.html b/docs/website/layouts/index.html similarity index 100% rename from docs/layouts/index.html rename to docs/website/layouts/index.html diff --git a/docs/layouts/partials/chapters.html b/docs/website/layouts/partials/chapters.html similarity index 100% rename from docs/layouts/partials/chapters.html rename to docs/website/layouts/partials/chapters.html diff --git a/docs/layouts/partials/head-extended.html b/docs/website/layouts/partials/head-extended.html similarity index 100% rename from docs/layouts/partials/head-extended.html rename to docs/website/layouts/partials/head-extended.html diff --git a/docs/website/package.nix b/docs/website/package.nix new file mode 100644 index 00000000..27867b6d --- /dev/null +++ b/docs/website/package.nix @@ -0,0 +1,34 @@ +{ + lib, + buildHugoSite, + bundlerEnv, + ruby_3_1, + writeShellScriptBin, +}: + +let + gems = bundlerEnv { + name = "foodogsquared-docs-gemset"; + ruby = ruby_3_1; + gemdir = ./.; + }; + + asciidoctorWrapper = writeShellScriptBin "asciidoctor" '' + ${lib.getExe' gems "asciidoctor"} -T ${./assets/templates/asciidoctor} $@ + ''; +in +buildHugoSite { + pname = "foodogsquared-docs"; + version = "2024-09-03"; + + src = lib.cleanSource ./.; + + vendorHash = ""; + + buildInputs = [ asciidoctorWrapper gems ]; + + meta = with lib; { + description = "foodogsquared's NixOS configuration docs"; + license = licenses.mit; + }; +} diff --git a/docs/website/shell.nix b/docs/website/shell.nix new file mode 100644 index 00000000..204560a6 --- /dev/null +++ b/docs/website/shell.nix @@ -0,0 +1,18 @@ +{ pkgs ? import { + overlays = [ (import ../../overlays).default ]; +} }: + + +let + site = pkgs.callPackage ./package.nix { }; +in +pkgs.mkShell { + inputsFrom = [ site ]; + + packages = with pkgs; [ + bundix + + nodePackages.prettier + vscode-langservers-extracted + ]; +} diff --git a/docs/static/favicon.png b/docs/website/static/favicon.png similarity index 100% rename from docs/static/favicon.png rename to docs/website/static/favicon.png diff --git a/docs/static/icons/avatars/ezran/angry.avif b/docs/website/static/icons/avatars/ezran/angry.avif similarity index 100% rename from docs/static/icons/avatars/ezran/angry.avif rename to docs/website/static/icons/avatars/ezran/angry.avif diff --git a/docs/static/icons/avatars/ezran/curious.avif b/docs/website/static/icons/avatars/ezran/curious.avif similarity index 100% rename from docs/static/icons/avatars/ezran/curious.avif rename to docs/website/static/icons/avatars/ezran/curious.avif diff --git a/docs/static/icons/avatars/ezran/default.avif b/docs/website/static/icons/avatars/ezran/default.avif similarity index 100% rename from docs/static/icons/avatars/ezran/default.avif rename to docs/website/static/icons/avatars/ezran/default.avif diff --git a/docs/static/icons/avatars/ezran/disappointed.avif b/docs/website/static/icons/avatars/ezran/disappointed.avif similarity index 100% rename from docs/static/icons/avatars/ezran/disappointed.avif rename to docs/website/static/icons/avatars/ezran/disappointed.avif diff --git a/docs/static/icons/avatars/ezran/proud.avif b/docs/website/static/icons/avatars/ezran/proud.avif similarity index 100% rename from docs/static/icons/avatars/ezran/proud.avif rename to docs/website/static/icons/avatars/ezran/proud.avif diff --git a/docs/static/icons/avatars/ezran/skeptical.avif b/docs/website/static/icons/avatars/ezran/skeptical.avif similarity index 100% rename from docs/static/icons/avatars/ezran/skeptical.avif rename to docs/website/static/icons/avatars/ezran/skeptical.avif diff --git a/docs/static/icons/avatars/foodogsquared/cheeky.avif b/docs/website/static/icons/avatars/foodogsquared/cheeky.avif similarity index 100% rename from docs/static/icons/avatars/foodogsquared/cheeky.avif rename to docs/website/static/icons/avatars/foodogsquared/cheeky.avif diff --git a/docs/static/icons/avatars/foodogsquared/curious.avif b/docs/website/static/icons/avatars/foodogsquared/curious.avif similarity index 100% rename from docs/static/icons/avatars/foodogsquared/curious.avif rename to docs/website/static/icons/avatars/foodogsquared/curious.avif diff --git a/docs/static/icons/avatars/foodogsquared/default.avif b/docs/website/static/icons/avatars/foodogsquared/default.avif similarity index 100% rename from docs/static/icons/avatars/foodogsquared/default.avif rename to docs/website/static/icons/avatars/foodogsquared/default.avif diff --git a/docs/static/icons/avatars/foodogsquared/despair.avif b/docs/website/static/icons/avatars/foodogsquared/despair.avif similarity index 100% rename from docs/static/icons/avatars/foodogsquared/despair.avif rename to docs/website/static/icons/avatars/foodogsquared/despair.avif diff --git a/docs/static/icons/avatars/foodogsquared/disappointed.avif b/docs/website/static/icons/avatars/foodogsquared/disappointed.avif similarity index 100% rename from docs/static/icons/avatars/foodogsquared/disappointed.avif rename to docs/website/static/icons/avatars/foodogsquared/disappointed.avif diff --git a/docs/static/icons/avatars/foodogsquared/nervous.avif b/docs/website/static/icons/avatars/foodogsquared/nervous.avif similarity index 100% rename from docs/static/icons/avatars/foodogsquared/nervous.avif rename to docs/website/static/icons/avatars/foodogsquared/nervous.avif diff --git a/docs/static/nix-snowflake-with-fds.svg b/docs/website/static/nix-snowflake-with-fds.svg similarity index 100% rename from docs/static/nix-snowflake-with-fds.svg rename to docs/website/static/nix-snowflake-with-fds.svg diff --git a/docs/static/nix-snowflake.svg b/docs/website/static/nix-snowflake.svg similarity index 100% rename from docs/static/nix-snowflake.svg rename to docs/website/static/nix-snowflake.svg diff --git a/flake.lock b/flake.lock index 43bb4f28..a707b4ba 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ "utils": "utils" }, "locked": { - "lastModified": 1715699772, - "narHash": "sha256-sKhqIgucN5sI/7UQgBwsonzR4fONjfMr9OcHK/vPits=", + "lastModified": 1718194053, + "narHash": "sha256-FaGrf7qwZ99ehPJCAwgvNY5sLCqQ3GDiE/6uLhxxwSY=", "owner": "serokell", "repo": "deploy-rs", - "rev": "b3ea6f333f9057b77efd9091119ba67089399ced", + "rev": "3867348fa92bc892eba5d9ddb2d7a97b9e127a8a", "type": "github" }, "original": { @@ -45,18 +45,38 @@ }, "devshell": { "inputs": { - "flake-utils": "flake-utils_6", "nixpkgs": [ - "nixvim", + "nixvim-stable", "nixpkgs" ] }, "locked": { - "lastModified": 1713532798, - "narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=", + "lastModified": 1722113426, + "narHash": "sha256-Yo/3loq572A8Su6aY5GP56knpuKYRvM2a1meP9oJZCw=", "owner": "numtide", "repo": "devshell", - "rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40", + "rev": "67cce7359e4cd3c45296fb4aaf6a19e2a9c757ae", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "devshell_2": { + "inputs": { + "nixpkgs": [ + "nixvim-unstable", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722113426, + "narHash": "sha256-Yo/3loq572A8Su6aY5GP56knpuKYRvM2a1meP9oJZCw=", + "owner": "numtide", + "repo": "devshell", + "rev": "67cce7359e4cd3c45296fb4aaf6a19e2a9c757ae", "type": "github" }, "original": { @@ -72,11 +92,11 @@ ] }, "locked": { - "lastModified": 1715722685, - "narHash": "sha256-SaccIpa1ToibLs3iULKUZEIBi8aOWVE2RSsLikjl4Tc=", + "lastModified": 1723426710, + "narHash": "sha256-yrS9al6l3fYfFfvovnyBWnyELDQOdfKyai4K/jKgoBw=", "owner": "nix-community", "repo": "disko", - "rev": "d62af72c2262ee6b9bd143901e21dbb3503555f7", + "rev": "0d510fe40b56ed74907a021d7e1ffd0042592914", "type": "github" }, "original": { @@ -94,11 +114,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1715736973, - "narHash": "sha256-yRaLc2e3t3+AeYqUA+dp8j3f8ZU3U8lGasJu0aVeVkg=", + "lastModified": 1723597543, + "narHash": "sha256-iCH3XzX1uDJGLtnXzP5yAFiID7oeTdqV7gyunPLtskQ=", "owner": "nix-community", "repo": "emacs-overlay", - "rev": "e25b6be33695d35ceb5059b37af4da3ba7af8e4d", + "rev": "8dd2e6a5281ec2be00c2115ad0b2483be8db9d4b", "type": "github" }, "original": { @@ -170,20 +190,6 @@ } }, "flake-compat_4": { - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "revCount": 57, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_5": { "flake": false, "locked": { "lastModified": 1696426674, @@ -199,16 +205,60 @@ "type": "github" } }, + "flake-compat_5": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flake-compat_6": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_7": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1714641030, - "narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -225,11 +275,11 @@ ] }, "locked": { - "lastModified": 1714641030, - "narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -262,16 +312,16 @@ "flake-parts_4": { "inputs": { "nixpkgs-lib": [ - "nixvim", + "nixvim-stable", "nixpkgs" ] }, "locked": { - "lastModified": 1714641030, - "narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -280,18 +330,24 @@ "type": "github" } }, - "flake-root": { + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": [ + "nixvim-unstable", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1713493429, - "narHash": "sha256-ztz8JQkI08tjKnsTpfLqzWoKFQF4JGu2LRz8bkdnYUk=", - "owner": "srid", - "repo": "flake-root", - "rev": "bc748b93b86ee76e2032eecda33440ceb2532fcd", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { - "owner": "srid", - "repo": "flake-root", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, @@ -385,47 +441,139 @@ "type": "github" } }, - "flake-utils_6": { + "git-hooks": { "inputs": { - "systems": "systems_7" + "flake-compat": "flake-compat_3", + "gitignore": "gitignore", + "nixpkgs": [ + "neovim-nightly-overlay", + "nixpkgs" + ], + "nixpkgs-stable": [ + "neovim-nightly-overlay", + "nixpkgs" + ] }, "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "lastModified": 1723202784, + "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "c7012d0c18567c889b948781bc74a501e92275d1", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "cachix", + "repo": "git-hooks.nix", "type": "github" } }, - "flake-utils_7": { + "git-hooks_2": { "inputs": { - "systems": "systems_8" + "flake-compat": "flake-compat_6", + "gitignore": "gitignore_2", + "nixpkgs": [ + "nixvim-stable", + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixvim-stable", + "nixpkgs" + ] }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1723202784, + "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "c7012d0c18567c889b948781bc74a501e92275d1", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "git-hooks_3": { + "inputs": { + "flake-compat": [ + "nixvim-unstable", + "flake-compat" + ], + "gitignore": "gitignore_3", + "nixpkgs": [ + "nixvim-unstable", + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixvim-unstable", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723202784, + "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "c7012d0c18567c889b948781bc74a501e92275d1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", "type": "github" } }, "gitignore": { "inputs": { "nixpkgs": [ - "nixvim", - "pre-commit-hooks", + "neovim-nightly-overlay", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "nixvim-stable", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_3": { + "inputs": { + "nixpkgs": [ + "nixvim-unstable", + "git-hooks", "nixpkgs" ] }, @@ -453,11 +601,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1715676857, - "narHash": "sha256-SSohpqbkPgyzLGT89hDxBD9WC88tm+eN5wGOZ6cupEc=", + "lastModified": 1723549983, + "narHash": "sha256-8lya0y9tR3dtVk++nUjVaPbSb5+Ah+vKgcX+3R556BQ=", "owner": "helix-editor", "repo": "helix", - "rev": "e76020ddb93eeb051de606c24f92189c3fc55547", + "rev": "f65ec32a1c2e09b3b32b521617f4a3ef19bc71c5", "type": "github" }, "original": { @@ -475,11 +623,11 @@ ] }, "locked": { - "lastModified": 1713898448, - "narHash": "sha256-6q6ojsp/Z9P2goqnxyfCSzFOD92T3Uobmj8oVAicUOs=", + "lastModified": 1719226092, + "narHash": "sha256-YNkUMcCUCpnULp40g+svYsaH1RbSEj6s4WdZY/SHe38=", "owner": "hercules-ci", "repo": "hercules-ci-effects", - "rev": "c0302ec12d569532a6b6bd218f698bc402e93adc", + "rev": "11e4b8dc112e2f485d7c97e1cee77f9958f498f5", "type": "github" }, "original": { @@ -495,16 +643,16 @@ ] }, "locked": { - "lastModified": 1715381426, - "narHash": "sha256-wPuqrAQGdv3ISs74nJfGb+Yprm23U/rFpcHFFNWgM94=", + "lastModified": 1720042825, + "narHash": "sha256-A0vrUB6x82/jvf17qPCpxaM+ulJnD8YZwH9Ci0BsAzE=", "owner": "nix-community", "repo": "home-manager", - "rev": "ab5542e9dbd13d0100f8baae2bc2d68af901f4b4", + "rev": "e1391fb22e18a36f57e6999c7a9f966dc80ac073", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-23.11", + "ref": "release-24.05", "repo": "home-manager", "type": "github" } @@ -516,11 +664,11 @@ ] }, "locked": { - "lastModified": 1715486357, - "narHash": "sha256-4pRuzsHZOW5W4CsXI9uhKtiJeQSUoe1d2M9mWU98HC4=", + "lastModified": 1723399884, + "narHash": "sha256-97wn0ihhGqfMb8WcUgzzkM/TuAxce2Gd20A8oiruju4=", "owner": "nix-community", "repo": "home-manager", - "rev": "44677a1c96810a8e8c4ffaeaad10c842402647c1", + "rev": "086f619dd991a4d355c07837448244029fc2d9ab", "type": "github" }, "original": { @@ -529,46 +677,23 @@ "type": "github" } }, - "neovim-flake": { - "inputs": { - "flake-utils": "flake-utils_4", - "nixpkgs": [ - "neovim-nightly-overlay", - "nixpkgs" - ] - }, - "locked": { - "dir": "contrib", - "lastModified": 1715728713, - "narHash": "sha256-DmODP02EhM3+O2hHKB+AVJc+5qykxDh8nz7POO6zGrI=", - "owner": "neovim", - "repo": "neovim", - "rev": "7acf39ddab8ebdb63ebf78ec980149d20783fd4b", - "type": "github" - }, - "original": { - "dir": "contrib", - "owner": "neovim", - "repo": "neovim", - "type": "github" - } - }, "neovim-nightly-overlay": { "inputs": { "flake-compat": "flake-compat_2", "flake-parts": "flake-parts_2", + "git-hooks": "git-hooks", "hercules-ci-effects": "hercules-ci-effects", - "neovim-flake": "neovim-flake", + "neovim-src": "neovim-src", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1715731444, - "narHash": "sha256-Mdj0NXU5yZCyX8LWigox+ab67RQGcYpmbuw3NQr6L9E=", + "lastModified": 1723528508, + "narHash": "sha256-4++qlOlqMoZz3h/g48f+TY3r75h+EBToRNmgcVWKpsE=", "owner": "nix-community", "repo": "neovim-nightly-overlay", - "rev": "5c17e8ef097ee948586858a25e05bc48145a2956", + "rev": "f019c7b0e7f478e4aaf2b406785a8d6ec6d1957d", "type": "github" }, "original": { @@ -577,19 +702,56 @@ "type": "github" } }, + "neovim-src": { + "flake": false, + "locked": { + "lastModified": 1723504195, + "narHash": "sha256-Tt+UtP3iSQATu2CUgFgtPkobASE7Rbf2AWZeLH8fthU=", + "owner": "neovim", + "repo": "neovim", + "rev": "9768e88f3891b5594eb2d556bd3bdf40c61d46e1", + "type": "github" + }, + "original": { + "owner": "neovim", + "repo": "neovim", + "type": "github" + } + }, "nix-darwin": { "inputs": { "nixpkgs": [ - "nixvim", + "nixvim-stable", "nixpkgs" ] }, "locked": { - "lastModified": 1713946171, - "narHash": "sha256-lc75rgRQLdp4Dzogv5cfqOg6qYc5Rp83oedF2t0kDp8=", + "lastModified": 1722924007, + "narHash": "sha256-+CQDamNwqO33REJLft8c26NbUi2Td083hq6SvAm2xkU=", "owner": "lnl7", "repo": "nix-darwin", - "rev": "230a197063de9287128e2c68a7a4b0cd7d0b50a7", + "rev": "91010a5613ffd7ee23ee9263213157a1c422b705", + "type": "github" + }, + "original": { + "owner": "lnl7", + "repo": "nix-darwin", + "type": "github" + } + }, + "nix-darwin_2": { + "inputs": { + "nixpkgs": [ + "nixvim-unstable", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722924007, + "narHash": "sha256-+CQDamNwqO33REJLft8c26NbUi2Td083hq6SvAm2xkU=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "91010a5613ffd7ee23ee9263213157a1c422b705", "type": "github" }, "original": { @@ -605,11 +767,11 @@ ] }, "locked": { - "lastModified": 1715483403, - "narHash": "sha256-WMDuQj7J5jbpXI/X/E6FZRKgBFGcaSTvYyVxPnKE6KU=", + "lastModified": 1723352546, + "narHash": "sha256-WTIrvp0yV8ODd6lxAq4F7EbrPQv0gscBnyfn559c3k8=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "f9027322f48b427da23746aa359a6510dfcd0228", + "rev": "ec78079a904d7d55e81a0468d764d0fffb50ac06", "type": "github" }, "original": { @@ -620,11 +782,11 @@ }, "nixlib": { "locked": { - "lastModified": 1712450863, - "narHash": "sha256-K6IkdtMtq9xktmYPj0uaYc8NsIqHuaAoRBaMgu9Fvrw=", + "lastModified": 1722732880, + "narHash": "sha256-do2Mfm3T6SR7a5A804RhjQ+JTsF5hk4JTPGjCTRM/m8=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "3c62b6a12571c9a7f65ab037173ee153d539905f", + "rev": "8bebd4c74f368aacb047f0141db09ec6b339733c", "type": "github" }, "original": { @@ -641,11 +803,11 @@ ] }, "locked": { - "lastModified": 1713783234, - "narHash": "sha256-3yh0nqI1avYUmmtqqTW3EVfwaLE+9ytRWxsA5aWtmyI=", + "lastModified": 1723444610, + "narHash": "sha256-WzhuUR2ZwafNzBh0VAbk3+320xd2sNWdZdjZa0S9ydY=", "owner": "nix-community", "repo": "nixos-generators", - "rev": "722b512eb7e6915882f39fff0e4c9dd44f42b77e", + "rev": "a220fc3a6e144f12f0c3dc3e4d01d44c2e6b0b85", "type": "github" }, "original": { @@ -656,27 +818,27 @@ }, "nixos-stable": { "locked": { - "lastModified": 1715542476, - "narHash": "sha256-FF593AtlzQqa8JpzrXyRws4CeKbc5W86o8tHt4nRfIg=", + "lastModified": 1723556749, + "narHash": "sha256-+CHVZnTnIYRLYsARInHYoWkujzcRkLY/gXm3s5bE52o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "44072e24566c5bcc0b7aa9178a0104f4cfffab19", + "rev": "4a92571f9207810b559c9eac203d1f4d79830073", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "nixos-24.05", "repo": "nixpkgs", "type": "github" } }, "nixos-unstable": { "locked": { - "lastModified": 1715534503, - "narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=", + "lastModified": 1723362943, + "narHash": "sha256-dFZRVSgmJkyM0bkPpaYRtG/kRMRTorUIDj8BxoOt1T4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2057814051972fa1453ddfb0d98badbea9b83c06", + "rev": "a58bc8ad779655e790115244571758e8de055e3d", "type": "github" }, "original": { @@ -686,20 +848,36 @@ "type": "github" } }, + "nixos-unstable-small": { + "locked": { + "lastModified": 1723599198, + "narHash": "sha256-kFB8EB7ne/ujWIa7pY6UmcwbGfwUCL6NTGJrglWva40=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5a1fae64da2be3d09a8f289c6257146997827d1d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable-small", + "repo": "nixpkgs", + "type": "github" + } + }, "nixos-wsl": { "inputs": { - "flake-compat": "flake-compat_3", - "flake-utils": "flake-utils_5", + "flake-compat": "flake-compat_4", + "flake-utils": "flake-utils_4", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1715612368, - "narHash": "sha256-rpXM1gGZY1KacCvKLx5Hnzxp+iLRVVVrt70KiMKvalo=", + "lastModified": 1723124175, + "narHash": "sha256-w+rlZdbj4kn70uPJl4WrPDFoGEy0A9oJqw684nvZ9dY=", "owner": "nix-community", "repo": "NixOS-WSL", - "rev": "0802ef2739396a18d56c2fd088b95006671f6f48", + "rev": "be1a6b2e4ddc34b9b6a297e7df2f2a2ecee24690", "type": "github" }, "original": { @@ -710,55 +888,55 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1714640452, - "narHash": "sha256-QBx10+k6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94=", + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" } }, "nixpkgs-stable": { "locked": { - "lastModified": 1715542476, - "narHash": "sha256-FF593AtlzQqa8JpzrXyRws4CeKbc5W86o8tHt4nRfIg=", + "lastModified": 1723556749, + "narHash": "sha256-+CHVZnTnIYRLYsARInHYoWkujzcRkLY/gXm3s5bE52o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "44072e24566c5bcc0b7aa9178a0104f4cfffab19", + "rev": "4a92571f9207810b559c9eac203d1f4d79830073", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "nixos-24.05", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-stable_2": { "locked": { - "lastModified": 1715458492, - "narHash": "sha256-q0OFeZqKQaik2U8wwGDsELEkgoZMK7gvfF6tTXkpsqE=", + "lastModified": 1721524707, + "narHash": "sha256-5NctRsoE54N86nWd0psae70YSLfrOek3Kv1e8KoXe/0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8e47858badee5594292921c2668c11004c3b0142", + "rev": "556533a23879fc7e5f98dd2e0b31a6911a213171", "type": "github" }, "original": { "owner": "NixOS", - "ref": "release-23.11", + "ref": "release-24.05", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-unstable": { "locked": { - "lastModified": 1715653339, - "narHash": "sha256-7lR9tpVXviSccl07GXI0+ve/natd24HAkuy1sQp0OlI=", + "lastModified": 1723572004, + "narHash": "sha256-U5gKtbKuPahB02iGeGHFPlKr/HqrvSsHlEDEXoVyaPc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "abd6d48f8c77bea7dc51beb2adfa6ed3950d2585", + "rev": "19674872444bb3e0768249e724d99c8649c3bd78", "type": "github" }, "original": { @@ -768,28 +946,58 @@ "type": "github" } }, - "nixvim": { + "nixvim-stable": { "inputs": { "devshell": "devshell", - "flake-compat": "flake-compat_4", + "flake-compat": "flake-compat_5", "flake-parts": "flake-parts_4", - "flake-root": "flake-root", + "git-hooks": "git-hooks_2", "home-manager": [ - "home-manager" + "home-manager-stable" ], "nix-darwin": "nix-darwin", "nixpkgs": [ - "nixpkgs" + "nixos-stable" ], - "pre-commit-hooks": "pre-commit-hooks", "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1715582453, - "narHash": "sha256-pW8a12PHt/PUphG8Tn0nb+mfbTS7JS4YbThGPepCcb0=", + "lastModified": 1723536338, + "narHash": "sha256-1bSEOtZBsAeCkg5vdDbDgOT3z91K8L/KE2s7J9hLYHw=", "owner": "nix-community", "repo": "nixvim", - "rev": "4530a35bad28a0e8b21905b0817a225e6387811c", + "rev": "0b6aa80acbcb8387f2a4affb3dd22960ac2899aa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "nixos-24.05", + "repo": "nixvim", + "type": "github" + } + }, + "nixvim-unstable": { + "inputs": { + "devshell": "devshell_2", + "flake-compat": "flake-compat_7", + "flake-parts": "flake-parts_5", + "git-hooks": "git-hooks_3", + "home-manager": [ + "home-manager-unstable" + ], + "nix-darwin": "nix-darwin_2", + "nixpkgs": [ + "nixos-unstable" + ], + "nuschtosSearch": "nuschtosSearch", + "treefmt-nix": "treefmt-nix_2" + }, + "locked": { + "lastModified": 1723481641, + "narHash": "sha256-9djT72/Ab2E3SpUbB3l0WmqZQ5mj05+LIVoorcjCWgE=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "dbf6f7bc997dc3a9ab1f014ea075600357226950", "type": "github" }, "original": { @@ -800,11 +1008,11 @@ }, "nur": { "locked": { - "lastModified": 1715737563, - "narHash": "sha256-w9F9oOfEMXxqx7AOSM65ZNhc1yGLwQL8AcqUIITgAeA=", + "lastModified": 1723601917, + "narHash": "sha256-/t6ZtVSLNO01KtI0E+NirfGwvQ1m4XCIt8YTrjJVok8=", "owner": "nix-community", "repo": "NUR", - "rev": "39593093fd61ec424b3eb73ea0662711aea2dbb7", + "rev": "f88e52b6f36d876b2228ad7fc7d2f538d99c493d", "type": "github" }, "original": { @@ -813,31 +1021,25 @@ "type": "github" } }, - "pre-commit-hooks": { + "nuschtosSearch": { "inputs": { - "flake-compat": "flake-compat_5", - "flake-utils": "flake-utils_7", - "gitignore": "gitignore", + "flake-utils": "flake-utils_5", "nixpkgs": [ - "nixvim", - "nixpkgs" - ], - "nixpkgs-stable": [ - "nixvim", + "nixvim-unstable", "nixpkgs" ] }, "locked": { - "lastModified": 1714478972, - "narHash": "sha256-q//cgb52vv81uOuwz1LaXElp3XAe1TqrABXODAEF6Sk=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "2849da033884f54822af194400f8dff435ada242", + "lastModified": 1723367906, + "narHash": "sha256-v1qA4WBGDI2uH/TVqRwuXSBP341W681psbzYJ8zrjog=", + "owner": "NuschtOS", + "repo": "search", + "rev": "6ca2c3ae05a915c160512bd41f6810f456c9b30d", "type": "github" }, "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", + "owner": "NuschtOS", + "repo": "search", "type": "github" } }, @@ -860,12 +1062,17 @@ "nixos-generators": "nixos-generators", "nixos-stable": "nixos-stable", "nixos-unstable": "nixos-unstable", + "nixos-unstable-small": "nixos-unstable-small", "nixos-wsl": "nixos-wsl", "nixpkgs": [ "nixos-unstable" ], "nixpkgs-unstable": "nixpkgs-unstable", - "nixvim": "nixvim", + "nixvim": [ + "nixvim-unstable" + ], + "nixvim-stable": "nixvim-stable", + "nixvim-unstable": "nixvim-unstable", "nur": "nur", "sops-nix": "sops-nix" } @@ -903,11 +1110,11 @@ "nixpkgs-stable": "nixpkgs-stable_2" }, "locked": { - "lastModified": 1715482972, - "narHash": "sha256-y1uMzXNlrVOWYj1YNcsGYLm4TOC2aJrwoUY1NjQs9fM=", + "lastModified": 1723501126, + "narHash": "sha256-N9IcHgj/p1+2Pvk8P4Zc1bfrMwld5PcosVA0nL6IGdE=", "owner": "Mic92", "repo": "sops-nix", - "rev": "b6cb5de2ce57acb10ecdaaf9bbd62a5ff24fa02e", + "rev": "be0eec2d27563590194a9206f551a6f73d52fa34", "type": "github" }, "original": { @@ -1006,49 +1213,40 @@ "type": "github" } }, - "systems_7": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_8": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "treefmt-nix": { "inputs": { "nixpkgs": [ - "nixvim", + "nixvim-stable", "nixpkgs" ] }, "locked": { - "lastModified": 1714058656, - "narHash": "sha256-Qv4RBm4LKuO4fNOfx9wl40W2rBbv5u5m+whxRYUMiaA=", + "lastModified": 1723454642, + "narHash": "sha256-S0Gvsenh0II7EAaoc9158ZB4vYyuycvMGKGxIbERNAM=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "c6aaf729f34a36c445618580a9f95a48f5e4e03f", + "rev": "349de7bc435bdff37785c2466f054ed1766173be", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { + "inputs": { + "nixpkgs": [ + "nixvim-unstable", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723454642, + "narHash": "sha256-S0Gvsenh0II7EAaoc9158ZB4vYyuycvMGKGxIbERNAM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "349de7bc435bdff37785c2466f054ed1766173be", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 232c1b79..1299d2b5 100644 --- a/flake.nix +++ b/flake.nix @@ -23,7 +23,7 @@ # ...except we allow other configurations to use other nixpkgs branch so # that may not matter anyways. - nixos-stable.url = "github:NixOS/nixpkgs/nixos-23.11"; + nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.05"; nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; nixos-unstable-small.url = "github:NixOS/nixpkgs/nixos-unstable-small"; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; @@ -34,16 +34,22 @@ # Managing home configurations. home-manager.follows = "home-manager-unstable"; - home-manager-stable.url = "github:nix-community/home-manager/release-23.11"; + home-manager-stable.url = "github:nix-community/home-manager/release-24.05"; home-manager-stable.inputs.nixpkgs.follows = "nixpkgs"; home-manager-unstable.url = "github:nix-community/home-manager"; home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs"; # Make a Neovim distro. - nixvim.url = "github:nix-community/nixvim"; - nixvim.inputs.nixpkgs.follows = "nixpkgs"; - nixvim.inputs.home-manager.follows = "home-manager"; + nixvim.follows = "nixvim-unstable"; + + nixvim-stable.url = "github:nix-community/nixvim/nixos-24.05"; + nixvim-stable.inputs.nixpkgs.follows = "nixos-stable"; + nixvim-stable.inputs.home-manager.follows = "home-manager-stable"; + + nixvim-unstable.url = "github:nix-community/nixvim"; + nixvim-unstable.inputs.nixpkgs.follows = "nixos-unstable"; + nixvim-unstable.inputs.home-manager.follows = "home-manager-unstable"; # This is what AUR strives to be. nur.url = "github:nix-community/NUR"; @@ -84,7 +90,9 @@ nix-index-database.url = "github:nix-community/nix-index-database"; nix-index-database.inputs.nixpkgs.follows = "nixpkgs"; - # Make a default.nix compatible stuff. + # Make a default.nix compatible stuff. Take note, we're giving this a + # unique suffix since there are other flake inputs that uses the same flake + # and we want our `default.nix` to refer to our version. flake-compat-fds.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; # Someone had the idea to make the flake outputs be configured as a Nix diff --git a/lib/README.adoc b/lib/README.adoc new file mode 100644 index 00000000..a810d16f --- /dev/null +++ b/lib/README.adoc @@ -0,0 +1,12 @@ += foodogsquared custom nixpkgs library +:toc: + + +This is my custom library set of functions to be included within each of the environment. +They are included in each of the environment as `foodogsquaredLib` module argument. +It is similarly structured from nixpkgs (though it is directly copied after I've implemented how Bahaghari structures their library set) where it is an extensible fixed point making it easy to use after adding new functions into the set AND extend it if you want to through the `$LIB.extend` function. +The structure is even copied from nixpkgs where each of the subset is in the fixed point also stored with the same name. + +The only exception to this are the environment-specific subsets where they are only intended to be imported into NixOS, home-manager, and the like. +This is in the link:./env-specific[`./env-specific` directory]. +Furthermore, env-specific subsets have a lesser restriction of allowing the configuration object to be included in there (though it is discouraged to use it but that's on a case-by-case basis). diff --git a/lib/builders/default.nix b/lib/builders/default.nix new file mode 100644 index 00000000..0ece6780 --- /dev/null +++ b/lib/builders/default.nix @@ -0,0 +1,8 @@ +{ pkgs, lib, self }: + +{ + makeXDGMimeAssociationList = pkgs.callPackage ./xdg/make-association-list.nix { }; + makeXDGPortalConfiguration = pkgs.callPackage ./xdg/make-portal-config.nix { }; + makeXDGDesktopEntry = pkgs.callPackage ./xdg/make-desktop-entry.nix { }; + buildHugoSite = pkgs.callPackage ./hugo-build-site { }; +} diff --git a/lib/builders/hugo-build-site/default.nix b/lib/builders/hugo-build-site/default.nix new file mode 100644 index 00000000..a9d63e05 --- /dev/null +++ b/lib/builders/hugo-build-site/default.nix @@ -0,0 +1,330 @@ +# Copyright (c) 2003-2024 Eelco Dolstra and the Nixpkgs/NixOS contributors +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +{ + hugo, + go, + cacert, + git, + lib, + stdenv, +}: + +# A modified Go builder for generating a website with Hugo. Since it relies on +# Hugo modules (which is basically wrapper around Go modules), this can be used +# for Hugo projects that heavily uses them. +# +# Take note, this doesn't work for Hugo projects with remote resources +# right in the content since Hugo allows network access when generating +# the website. +{ + name ? "${args'.pname}-${args'.version}", + + nativeBuildInputs ? [ ], + passthru ? { }, + + # A function to override the goModules derivation + overrideModAttrs ? (_oldAttrs: { }), + + # path to go.mod and go.sum directory + modRoot ? "./", + + # vendorHash is the SRI hash of the vendored dependencies + # + # if vendorHash is null, then we won't fetch any dependencies and + # rely on the vendor folder within the source. + vendorHash ? throw ( + if args' ? vendorSha256 then + "buildHugoSite: Expect vendorHash instead of vendorSha256" + else + "buildHugoSite: vendorHash is missing" + ), + + # Whether to delete the vendor folder supplied with the source. + deleteVendor ? false, + + # Whether to fetch (go mod download) and proxy the vendor directory. + # This is useful if your code depends on c code and go mod tidy does not + # include the needed sources to build or if any dependency has case-insensitive + # conflicts which will produce platform dependant `vendorHash` checksums. + proxyVendor ? false, + + # We want parallel builds by default + enableParallelBuilding ? true, + + # Do not enable this without good reason + # IE: programs coupled with the compiler + allowGoReference ? false, + + CGO_ENABLED ? go.CGO_ENABLED, + + meta ? { }, + + ldflags ? [ ], + + GOFLAGS ? [ ], + + ... +}@args': + +let + args = removeAttrs args' [ + "overrideModAttrs" + "vendorSha256" + "vendorHash" + ]; + + GO111MODULE = "on"; + GOTOOLCHAIN = "local"; + + hugoModules = + if (vendorHash == null) then + "" + else + (stdenv.mkDerivation { + name = "${name}-hugo-modules"; + + nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ + hugo + go + git + cacert + ]; + + inherit (args) src; + inherit (go) GOOS GOARCH; + inherit GO111MODULE GOTOOLCHAIN; + + # The following inheritence behavior is not trivial to expect, and some may + # argue it's not ideal. Changing it may break vendor hashes in Nixpkgs and + # out in the wild. In anycase, it's documented in: + # doc/languages-frameworks/go.section.md + prePatch = args.prePatch or ""; + patches = args.patches or [ ]; + patchFlags = args.patchFlags or [ ]; + postPatch = args.postPatch or ""; + preBuild = args.preBuild or ""; + postBuild = args.modPostBuild or ""; + sourceRoot = args.sourceRoot or ""; + setSourceRoot = args.setSourceRoot or ""; + env = args.env or { }; + + impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ + "GIT_PROXY_COMMAND" + "SOCKS_SERVER" + "GOPROXY" + ]; + + configurePhase = + args.modConfigurePhase or '' + runHook preConfigure + export GOCACHE=$TMPDIR/go-cache + export GOPATH="$TMPDIR/go" + cd "${modRoot}" + runHook postConfigure + ''; + + buildPhase = + args.modBuildPhase or ( + '' + runHook preBuild + '' + + lib.optionalString deleteVendor '' + if [ ! -d _vendor ]; then + echo "_vendor folder does not exist, 'deleteVendor' is not needed" + exit 10 + else + rm -rf _vendor + fi + '' + + '' + if [ -d _vendor ]; then + echo "_vendor folder exists, please set 'vendorHash = null;' in your expression" + exit 10 + fi + + ${ + if proxyVendor then + '' + mkdir -p "''${GOPATH}/pkg/mod/cache/download" + hugo mod vendor + '' + else + '' + if (( "''${NIX_DEBUG:-0}" >= 1 )); then + hugoModVendorFlags+=(-v) + fi + hugo mod vendor "''${hugoModVendorFlags[@]}" + '' + } + + mkdir -p _vendor + + runHook postBuild + '' + ); + + installPhase = + args.modInstallPhase or '' + runHook preInstall + + ${ + if proxyVendor then + '' + rm -rf "''${GOPATH}/pkg/mod/cache/download/sumdb" + cp -r --reflink=auto "''${GOPATH}/pkg/mod/cache/download" $out + '' + else + '' + cp -r --reflink=auto _vendor $out + '' + } + + if ! [ "$(ls -A $out)" ]; then + echo "_vendor folder is empty, please set 'vendorHash = null;' in your expression" + exit 10 + fi + + runHook postInstall + ''; + + dontFixup = true; + + outputHashMode = "recursive"; + outputHash = vendorHash; + # Handle empty vendorHash; avoid + # error: empty hash requires explicit hash algorithm + outputHashAlgo = if vendorHash == "" then "sha256" else null; + }).overrideAttrs + overrideModAttrs; + + package = stdenv.mkDerivation ( + args + // { + nativeBuildInputs = [ + hugo + git + go + ] ++ nativeBuildInputs; + + inherit (go) GOOS GOARCH; + + GOFLAGS = + GOFLAGS + ++ + lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) + "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS" + (lib.optional (!proxyVendor) "-mod=vendor") + ++ + lib.warnIf (builtins.elem "-trimpath" GOFLAGS) + "`-trimpath` is added by default to GOFLAGS by buildHugoSite when allowGoReference isn't set to true" + (lib.optional (!allowGoReference) "-trimpath"); + inherit + CGO_ENABLED + enableParallelBuilding + GO111MODULE + GOTOOLCHAIN + ; + + # If not set to an explicit value, set the buildid empty for reproducibility. + ldflags = ldflags ++ lib.optional (!lib.any (lib.hasPrefix "-buildid=") ldflags) "-buildid="; + + configurePhase = + args.configurePhase or ( + '' + runHook preConfigure + + export GOCACHE=$TMPDIR/go-cache + export GOPATH="$TMPDIR/go" + export GOPROXY=off + export GOSUMDB=off + cd "$modRoot" + '' + + lib.optionalString (vendorHash != null) '' + ${ + if proxyVendor then + '' + export GOPROXY=file://${hugoModules} + '' + else + '' + rm -rf _vendor + cp -r --reflink=auto ${hugoModules} _vendor + '' + } + '' + + '' + + # currently pie is only enabled by default in pkgsMusl + # this will respect the `hardening{Disable,Enable}` flags if set + if [[ $NIX_HARDENING_ENABLE =~ "pie" ]]; then + export GOFLAGS="-buildmode=pie $GOFLAGS" + fi + + runHook postConfigure + '' + ); + + buildPhase = + args.buildPhase or '' + runHook preBuild + hugo "''${buildFlags[@]}" --destination public + runHook postBuild + ''; + + doCheck = args.doCheck or true; + checkPhase = + args.checkPhase or '' + runHook preCheck + + runHook postCheck + ''; + + installPhase = + args.installPhase or '' + runHook preInstall + + mkdir -p $out + cp -r public/* $out + + runHook postInstall + ''; + + strictDeps = true; + + disallowedReferences = lib.optional (!allowGoReference) go; + + passthru = passthru // { + inherit + go + hugo + hugoModules + vendorHash + ; + }; + + meta = { + # Add default meta information + platforms = go.meta.platforms or lib.platforms.all; + } // meta; + } + ); +in +package diff --git a/lib/builders/xdg/make-association-list.nix b/lib/builders/xdg/make-association-list.nix new file mode 100644 index 00000000..588b9997 --- /dev/null +++ b/lib/builders/xdg/make-association-list.nix @@ -0,0 +1,38 @@ +{ lib, writeTextFile }: + +/* Create an XDG MIME Association listing. This should also take care of + generating desktop-specific mimeapps.list if `desktopName` is given. The + given desktop name is already assumed to be in suitable casing which is + typically in lowercase ASCII. +*/ +{ + # An optional string containing the name of the desktop to be associated + # with. + desktopName ? "", + + # Applications to be put in `Added Associations`. This is not set when the + # database is desktop-specific (when the `desktopName` is non-empty.) + addedAssociations ? { }, + + # Associations to be put in `Removed Associations` in the file. Similar to + # `addedAssociations`, this will not be added when it is desktop-specific. + removedAssociations ? { }, + + # Set of applications to be opened associated with the MIME type. + defaultApplications ? { }, +}: + +writeTextFile { + name = "xdg-mime-associations${lib.optionalString (desktopName != "") "-${desktopName}"}"; + text = + # Non-desktop-specific mimeapps.list are only allowed to specify + # default applications. + lib.generators.toINI { } ({ + "Default Applications" = defaultApplications; + } // (lib.optionalAttrs (desktopName == "") { + "Added Associations" = addedAssociations; + "Removed Associations" = removedAssociations; + })); + destination = "/share/applications/${lib.optionalString (desktopName != "") "${desktopName}-"}mimeapps.list"; +} + diff --git a/lib/builders/xdg/make-desktop-entry.nix b/lib/builders/xdg/make-desktop-entry.nix new file mode 100644 index 00000000..a2448764 --- /dev/null +++ b/lib/builders/xdg/make-desktop-entry.nix @@ -0,0 +1,39 @@ +{ lib, writeTextFile, desktop-file-utils }: + +/* Create an XDG desktop entry file. Unlike the `makeDesktopItem`, it doesn't + have a required schema as long as it is valid data to be converted to. + Furthermore, the validation process can be disabled in case you want to + create something like an entry for a desktop session. +*/ +{ + # Name of the desktop entry. Only used as part of the package name and the + # default value of the destination path. + name, + + # Nix-representable data to be exported as the desktop entry. + config, + + # Add a validation check for the exported desktop entry. + validate ? true, + + # Destination path relative to the output path. + destination ? "/share/applications/${name}.desktop", +}: + +writeTextFile { + name = "xdg-desktop-entry-${name}"; + text = lib.generators.toINI { + listsAsDuplicateKeys = false; + mkKeyValue = lib.generators.mkKeyValueDefault { + mkValueString = v: + if lib.isList v then lib.concatStringsSep ";" v + else lib.generators.mkValueStringDefault { } v; + } "="; + } config; + inherit destination; + checkPhase = + lib.optionalString validate + '' + ${lib.getExe' desktop-file-utils "desktop-file-validate"} "$target" + ''; +} diff --git a/lib/builders/xdg/make-portal-config.nix b/lib/builders/xdg/make-portal-config.nix new file mode 100644 index 00000000..7a0eff78 --- /dev/null +++ b/lib/builders/xdg/make-portal-config.nix @@ -0,0 +1,17 @@ +{ lib, writeTextFile }: + +/* Create an XDG Portals configuration with the given desktop name and its + configuration. Similarly, the given desktop name is assumed to be already + in its suitable form of a lowercase ASCII. +*/ +{ + desktopName ? "common", + + # Nix-representable data to be exported as the portal configuration. + config, +}: +writeTextFile { + name = "xdg-portal-config${lib.optionalString (desktopName != "common") "-${desktopName}"}"; + text = lib.generators.toINI { } config; + destination = "/share/xdg-desktop-portal/${lib.optionalString (desktopName != "common") "${desktopName}-"}portals.conf"; +} diff --git a/lib/data.nix b/lib/data.nix new file mode 100644 index 00000000..8bffae7f --- /dev/null +++ b/lib/data.nix @@ -0,0 +1,67 @@ +# Anything that has to do with interacting with data especially with external +# ones (that is, anything that is not represented as a Nix object). +# Unfortunately, most of these functions are surely going to use packages found +# in nixpkgs so expect a lot of them are used as an IFD. +{ pkgs, lib, self }: + +{ + /* Import the YAML file and return it as a Nix object. Unfortunately, this is + implemented as an import-from-derivation (IFD) so it will not be pretty. + + Type: importYAML :: Path -> Attrs + + Example: + importYAML ./your-mom.yaml + => { name = "Yor Mum"; age = 56; world = "Herown"; } + */ + importYAML = path: + let + dataDrv = pkgs.runCommand "convert-yaml-to-json" { } '' + ${lib.getExe' pkgs.yaml2json "yaml2json"} < "${path}" > "$out" + ''; + in lib.importJSON dataDrv; + + /* Render a Tera template given a parameter set powered by `tera-cli`. Also + typically used as an IFD. + + Type: renderTeraTemplate :: Attrs -> Path + + Example: + renderTeraTemplate { path = ./template.tera; context = { hello = 34; }; } + => /nix/store/HASH-tera-render-template + */ + renderTeraTemplate = { template, context, extraArgs ? { } }: + let + extraArgs' = lib.cli.toGNUCommandLineShell { } extraArgs; + + # Take note we're generating the context file in this way since tera-cli + # can only detect them through its file extension and doesn't have a way + # of explicitly reading files as JSON, YAML, etc. + settingsFormat = pkgs.formats.json { }; + contextFile = settingsFormat.generate "tera-context.json" context; + in pkgs.runCommand "tera-render-template" { + nativeBuildInputs = with pkgs; [ tera-cli ]; + } '' + tera --out "$out" ${extraArgs'} --template "${template}" "${contextFile}" + ''; + + /* Render a Mustache template given a parameter set powered by `mustache-go`. + Also typically used as an IFD. + + Type: renderMustacheTemplate :: Attrs -> Path + + Example: + renderMustacheTemplate { path = ./template.mustache; context = { hello = 34; }; } + => /nix/store/HASH-mustache-render-template + */ + renderMustacheTemplate = { template, context, extraArgs ? { } }: + let + extraArgs' = lib.cli.toGNUCommandLineShell { } extraArgs; + in pkgs.runCommand "mustache-render-template" { + nativeBuildInputs = with pkgs; [ mustache-go ]; + context = builtins.toJSON context; + passAsFile = [ "template" "context" ]; + } '' + mustache "$contextPath" "${template}" ${extraArgs'} > $out + ''; +} diff --git a/lib/default.nix b/lib/default.nix index 2c42167b..ff2b993c 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,13 +1,32 @@ # The entrypoint for our custom library set. +# +# Take note, this is modularly included as part of the environment so we cannot +# have any functions or references that could make the evaluation go in an +# infinite recursion such as a function that generates a valid nixpkgs module. +# If you have to add those functions, you'll have to add them in configUtils. { pkgs }: +let + inherit (pkgs) lib; +in pkgs.lib.makeExtensible (self: let - inherit (pkgs) lib; callLib = file: import file { inherit pkgs lib self; }; in { + builders = callLib ./builders; trivial = callLib ./trivial.nix; + data = callLib ./data.nix; + math = callLib ./math.nix; + fetchers = callLib ./fetchers; - inherit (self.trivial) countAttrs getConfig getUser; + inherit (self.builders) makeXDGMimeAssociationList + makeXDGPortalConfiguration makeXDGDesktopEntry; + inherit (self.trivial) countAttrs filterAttrs'; + inherit (self.data) importYAML renderTeraTemplate renderMustacheTemplate; + inherit (self.fetchers) fetchInternetArchive; + } // lib.optionalAttrs (builtins ? fetchTree) { + flake = callLib ./flake.nix; + + inherit (self.flake) importFlakeMetadata fetchTree fetchInput; }) diff --git a/lib/env-builders.nix b/lib/env-builders.nix new file mode 100644 index 00000000..a502cfbc --- /dev/null +++ b/lib/env-builders.nix @@ -0,0 +1,137 @@ +# This shouldn't be a part of the foodogsquared's library set. These are simply +# environment builders used to build consistent environments throughout flake- +# and non-flake-based Nix environments. Much of the things here are unofficial +# and basically redoing what the upstream projects are doing so maintenance is +# pretty much higher here. +# +# Anyways, all we're doing here is to see how much of a pain to use those Nix +# projects especially those that are entirely relying on flakes. +# +# Despite named similarly to npins `sources` convention, it should also work +# for flake-based setups as long as the inputs attrset from the flake output +# function is the one that is passed. +{ lib, foodogsquaredLib, sources }: + +let + # A set of nixos-generators modules including our custom ones. + nixosGeneratorModules = + let + officialFormats = builtins.readDir "${sources.nixos-generators}/formats"; + unofficialFormats = builtins.readDir ../modules/nixos-generators; + formats = officialFormats // unofficialFormats; + in + lib.mapAttrs' (n: _: lib.nameValuePair (lib.removeSuffix ".nix" n) { + imports = [ + "${sources.nixos-generators}/format-module.nix" + ( + if (lib.hasAttr n officialFormats) + then "${sources.nixos-generators}/formats/${n}" + else "${../modules/nixos-generators}/${n}" + ) + ]; + }) formats; +in +rec { + mkNixosSystem = { + pkgs, + lib ? pkgs.lib, + system, + extraModules ? [ ], + specialArgs ? { }, + }: + let + nixosModules = ../modules/nixos; + + # Evaluating the system ourselves (which is trivial) instead of relying + # on nixpkgs.lib.nixosSystem flake output. + nixosSystem = args: import "${pkgs.path}/nixos/lib/eval-config.nix" args; + in + (lib.makeOverridable nixosSystem) { + inherit pkgs; + specialArgs = specialArgs // { + foodogsquaredUtils = import ./utils/nixos.nix { inherit lib; }; + foodogsquaredModulesPath = builtins.toString nixosModules; + }; + modules = extraModules ++ [ + nixosModules + ../modules/nixos/_private + ({ lib, ... }: { + nixpkgs.hostPlatform = lib.mkForce system; + }) + ]; + + # Since we're setting it through nixpkgs.hostPlatform, we'll have to pass + # this as null. + system = null; + }; + + # A very very thin wrapper around `mkNixosSystem` to build with the given format. + mkNixosImage = { + pkgs, + system, + lib ? pkgs.lib, + extraModules ? [ ], + specialArgs ? { }, + format ? "iso", + }: + let + extraModules' = extraModules ++ [ nixosGeneratorModules.${format} ]; + nixosSystem = mkNixosSystem { + inherit pkgs lib system specialArgs; + extraModules = extraModules'; + }; + in + nixosSystem.config.system.build.${nixosSystem.config.formatAttr}; + + mkHome = { + pkgs, + homeManagerSrc, + lib ? pkgs.lib, + modules ? [ ], + specialArgs ? { }, + }: + let + homeModules = ../modules/home-manager; + in + import "${homeManagerSrc}/modules" { + inherit pkgs lib; + check = true; + extraSpecialArgs = specialArgs // { + foodogsquaredModulesPath = builtins.toString homeModules; + }; + configuration = { lib, ... }: { + imports = modules ++ [ + homeModules + ../modules/home-manager/_private + ]; + + config = { + programs.home-manager.path = homeManagerSrc; + inherit (pkgs) overlays; + nixpkgs.config = lib.mkDefault pkgs.config; + }; + }; + }; + + mkWrapper = { + pkgs, + lib ? pkgs.lib, + wrapperManagerSrc, + modules ? [ ], + specialArgs ? { }, + }: + let + wrapperManagerModules = ../modules/wrapper-manager; + wrapperManager = import wrapperManagerSrc { }; + in + wrapperManager.lib.build { + inherit pkgs lib; + specialArgs = specialArgs // { + foodogsquaredModulesPath = builtins.toString wrapperManagerModules; + }; + modules = modules ++ [ + wrapperManagerModules + ../modules/wrapper-manager/_private + ]; + }; +} diff --git a/lib/home-manager.nix b/lib/env-specific/home-manager.nix similarity index 100% rename from lib/home-manager.nix rename to lib/env-specific/home-manager.nix diff --git a/lib/env-specific/nixos.nix b/lib/env-specific/nixos.nix new file mode 100644 index 00000000..979e43fd --- /dev/null +++ b/lib/env-specific/nixos.nix @@ -0,0 +1,69 @@ +# All of the functions suitable only for NixOS. +{ pkgs, lib, self }: + +{ + # Checks if the NixOS configuration is part of the nixos-generator build. + # Typically, we just check if there's a certain attribute that is imported + # from it. + hasNixosFormat = config: + lib.hasAttrByPath [ "formatAttr" ] config; + + # Checks if the NixOS config is being built for a particular format. + isFormat = config: format: + (config.formatAttr or "") == format; + + # Create a separate environment similar to NixOS `system.path`. This is + # typically used to create isolated environments for custom desktop sessions + # which makes it possible to have them installed side-by-side with their own + # set of applications and everything (except for overlapping NixOS services + # that will just add them into the NixOS environment itself). + mkNixoslikeEnvironment = config: args: + pkgs.buildEnv (args // { + inherit (config.environment) pathsToLink extraOutputsToInstall; + ignoreCollisions = true; + postBuild = + '' + # Remove wrapped binaries, they shouldn't be accessible via PATH. + find $out/bin -maxdepth 1 -name ".*-wrapped" -type l -delete + + if [ -x $out/bin/glib-compile-schemas -a -w $out/share/glib-2.0/schemas ]; then + $out/bin/glib-compile-schemas $out/share/glib-2.0/schemas + fi + + ${config.environment.extraSetup} + ''; + }); + + # Given an environment (built with `pkgs.buildEnv`), create a systemd + # environment attrset meant to be used as part of the desktop service. + mkSystemdDesktopEnvironment = env: { + PATH = "${lib.getBin env}\${PATH:+:$PATH}"; + XDG_DATA_DIRS = "${env}/share\${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"; + XDG_CONFIG_DIRS = "${env}/etc/xdg\${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS}"; + }; + + # Create a range object (as [start, end) in notation) that is typically used + # in module options that accept them. + makeRange = start: range: + { from = start; to = start + range; }; + + # Create a range object (as [start + 1, end + 1] in notation) that is typically used + # in module options that accept them except that the starting port is included. + makeRange' = start: range: + let + start' = start + 1; + in + { from = start'; to = start' + range; }; + + /* + A specific function that checks if specific filesystem setups are set. + */ + isFilesystemSet = config: setupName: + config.suites.filesystem.setups.${setupName}.enable or false; + + /* + Get the path from the state variable. + */ + getFilesystem = config: setupName: + config.state.paths.${setupName}; +} diff --git a/lib/nixvim.nix b/lib/env-specific/nixvim.nix similarity index 100% rename from lib/nixvim.nix rename to lib/env-specific/nixvim.nix diff --git a/lib/sops.nix b/lib/env-specific/sops.nix similarity index 100% rename from lib/sops.nix rename to lib/env-specific/sops.nix diff --git a/lib/env-specific/wrapper-manager.nix b/lib/env-specific/wrapper-manager.nix new file mode 100644 index 00000000..c59e9996 --- /dev/null +++ b/lib/env-specific/wrapper-manager.nix @@ -0,0 +1,88 @@ +{ pkgs, lib, self }: + +rec { + /* Given a Blender package and its addons to be wrapped, create a derivation + containing all of the addons properly placed as a system resource folder. + */ + wrapBlenderAddons = { blenderPackage, addons }: + let + blenderVersion = lib.versions.majorMinor blenderPackage.version; + in + pkgs.runCommand "blender-system-resources" + { + passAsFile = [ "paths" ]; + paths = addons ++ [ blenderPackage ]; + nativeBuildInputs = with pkgs; [ outils ]; + } '' + mkdir -p $out + for i in $(cat $pathsPath); do + resourcesPath="$i/share/blender" + if [ -d $i/share/blender/${blenderVersion} ]; then + resourcesPath="$i/share/blender/${blenderVersion}"; + fi + lndir -silent $resourcesPath $out + done + ''; + + makeBlenderWrapper = module@{ blenderPackage, blenderArgs ? [ ] , addons ? [ ], ... }: + let + blenderAddons = wrapBlenderAddons { inherit blenderPackage addons; }; + in + lib.mkMerge [ + { + arg0 = lib.getExe' blenderPackage "blender"; + prependArgs = lib.mkBefore blenderArgs; + } + + (lib.mkIf (builtins.length addons > 0) { + env.BLENDER_SYSTEM_RESOURCES.value = blenderAddons; + }) + + (lib.removeAttrs module [ "blenderPackage" "blenderArgs" "addons" ]) + ]; + + /* Create a configuration module for quickly wrapping with Boxxy. + */ + makeBoxxyWrapper = module@{ boxxyArgs, wraparound, wraparoundArgs ? [], ... }: + lib.mkMerge [ + { + arg0 = lib.getExe' pkgs.boxxy "boxxy"; + prependArgs = lib.mkBefore (boxxyArgs ++ [ "--" wraparound ] ++ wraparoundArgs); + } + + (builtins.removeAttrs module [ "boxxyArgs" "wraparound" "wraparoundArgs" ]) + ]; + + /* Given the path to the source code, the attribute path, and the executable + name, return the store path to one of its executables. + */ + getNixglExecutable = { src, variant ? [ "auto" "nixGLDefault" ], nixglProgram ? "nixGL" }: + let + nixgl = import src { inherit pkgs; }; + nixglPkg = lib.getAttrFromPath variant nixgl; + in + lib.getExe' nixglPkg nixglProgram; + + /* Create a configuration module for quickly wrapping with NixGL. + */ + makeNixglWrapper = { + nixglSrc, + nixglArgs, + nixglVariant, + nixglExecutable, + wraparound, + wraparoundArgs ? [], + ... + }@module: + lib.mkMerge [ + { + arg0 = getNixglExecutable nixglSrc nixglVariant nixglExecutable; + prependArgs = lib.mkBefore (nixglArgs ++ [ "--" wraparound ] ++ wraparoundArgs); + } + + (builtins.removeAttrs module [ + "nixglArgs" "nixglVariant" "nixglExecutable" + "wraparound" "wraparoundArgs" + ]) + ]; +} diff --git a/lib/fetchers/default.nix b/lib/fetchers/default.nix new file mode 100644 index 00000000..e4eceb31 --- /dev/null +++ b/lib/fetchers/default.nix @@ -0,0 +1,5 @@ +{ pkgs, lib, self }: + +{ + fetchInternetArchive = pkgs.callPackage ./fetch-internet-archive { }; +} diff --git a/lib/fetchers/fetch-internet-archive/default.nix b/lib/fetchers/fetch-internet-archive/default.nix new file mode 100644 index 00000000..ba96a68f --- /dev/null +++ b/lib/fetchers/fetch-internet-archive/default.nix @@ -0,0 +1,27 @@ +{ stdenvNoCC, lib, fetchzip, fetchurl, curl }: + +{ + id, + file ? "", + formats ? [ ], + hash ? "", + name ? "internet-archive-${id}", +}@args: + +let + isFormatIndiciated = formats != [ ]; + url = + if isFormatIndiciated + then "https://archive.org/compress/${lib.escapeURL id}/formats=${lib.concatStringsSep "," formats}" + else "https://archive.org/download/${lib.escapeURL id}/${lib.escapeURL file}"; + + args' = lib.removeAttrs args [ "id" "file" "formats" ] // { + inherit url hash name; + }; + + fetcher = + if isFormatIndiciated + then fetchzip + else fetchurl; +in + fetcher args' diff --git a/lib/flake.nix b/lib/flake.nix new file mode 100644 index 00000000..95f8196a --- /dev/null +++ b/lib/flake.nix @@ -0,0 +1,27 @@ +# No, this is not a flake of the library set, it is a library subset for +# flake-related shtick. This should be used VERY RARELY in most parts of the +# configuration because they are set up to be usable both in flakes- and +# non-flakes-enabled environment. +# +# Take note it has a very strict design constraint of not relying on the +# `inputs` attribute of the flake output. Instead, we're relying on the +# builtins and the flake lockfile for this. +# +# Because Nix under the hood is a bit of a mess especially relating with +# flakes, we'll have to thoroughly document which versions this is working. So +# far, it is working on flake format version 7. AAAAAND also because apparently +# it requires flakes to be enabled to use `builtins.fetchTree`, this is pretty +# much a flakes-only subset. +# +# If anything else is pretty much in despair, we could always ste- I mean... +# copy edolstra's flake-compat implementation. +rec { + importFlakeMetadata = flakeLockfile: + builtins.fromJSON (builtins.readFile flakeLockfile); + + fetchTree = metadata: inputName: + builtins.fetchTree metadata.nodes.${inputName}.locked; + + fetchInput = metadata: inputName: + (fetchTree metadata inputName).outPath; +} diff --git a/lib/math.nix b/lib/math.nix new file mode 100644 index 00000000..ef868753 --- /dev/null +++ b/lib/math.nix @@ -0,0 +1,37 @@ +# Math subset. +{ pkgs, lib, self }: + +rec { + /* Returns the absolute value of the given number. + + Example: + abs -4 + => 4 + + abs (1 / 5) + => 0.2 + */ + abs = number: + if number < 0 then -(number) else number; + /* Exponentiates the given base with the exponent. + + Example: + pow 2 3 + => 8 + + pow 6 4 + => 1296 + */ + pow = base: exponent: + # Just to be a contrarian, I'll just make this as a tail recursive function + # instead lol. + let + absValue = abs exponent; + iter = product: counter: maxCount: + if counter > maxCount + then product + else iter (product * base) (counter + 1) maxCount; + value = iter 1 1 absValue; + in + if exponent < 0 then (1 / value) else value; +} diff --git a/lib/nixos.nix b/lib/nixos.nix deleted file mode 100644 index 2320024d..00000000 --- a/lib/nixos.nix +++ /dev/null @@ -1,14 +0,0 @@ -# All of the functions suitable only for NixOS. -{ pkgs, lib, self }: - -{ - # Checks if the NixOS configuration is part of the nixos-generator build. - # Typically, we just check if there's a certain attribute that is imported - # from it. - hasNixosFormat = config: - lib.hasAttrByPath [ "formatAttr" ] config; - - # Checks if the NixOS config is being built for a particular format. - isFormat = config: format: - (config.formatAttr or "") == format; -} diff --git a/lib/trivial.nix b/lib/trivial.nix index ca39f8bc..82f0f084 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -1,6 +1,17 @@ { pkgs, lib, self }: -{ +rec { + /* Force a numerical value to be a floating value. + + Example: + toFloat 5698 + => 5698.0 + + toFloat 9859.55 + => 9859.55 + */ + toFloat = x: x / 1.0; + /* Count the attributes with the given predicate. Examples: @@ -14,26 +25,169 @@ lib.count (attr: pred attr.name attr.value) (lib.mapAttrsToList lib.nameValuePair attrs); - /* Returns the file path of the given config of the given environment. - - Type: getConfig :: String -> String -> Path + /* Filters and groups the attribute set into two separate attribute where it + either accepted or denied from a given predicate function. Example: - getConfig "home-manager" "foo-dogsquared" - => ../configs/home-manager/foo-dogsquared + filterAttrs' (n: v: v == 4) { a = 4; b = 2; c = 6; } + => { ok = { a = 4; }; notOk = { b = 2; c = 6; }; } */ - getConfig = type: config: ../configs/${type}/${config}; + filterAttrs' = f: attrs: + lib.foldlAttrs (acc: name: value: let + isOk = f name value; + in { + ok = acc.ok // lib.optionalAttrs isOk { ${name} = value; }; + notOk = acc.notOk // lib.optionalAttrs (!isOk) { ${name} = value; }; + }) + { ok = { }; notOk = { }; } + attrs; - - /* Returns the file path of the given user subpart of the given - environment. Only certain environments such as NixOS have this type of - setup. - - Type: getConfig :: String -> String -> Path + /* Convenient function for converting bits to bytes. Example: - getUser "nixos" "foo-dogsquared" - => ../configs/nixos/_users/foo-dogsquared + bitsToBytes 1600 + => 200 */ - getUser = type: user: ../configs/${type}/_users/${user}; + bitsToBytes = x: x / 8.0; + + /* Gives the exponent with the associated SI prefix. + + Example: + SIPrefixExponent "M" + => 6 + + SIPrefixExponent "Q" + => 30 + */ + SIPrefixExponent = c: + let + prefixes = { + Q = 30; + R = 27; + Y = 24; + Z = 21; + E = 18; + P = 15; + T = 12; + G = 9; + M = 6; + k = 3; + h = 2; + da = 1; + d = -1; + c = -2; + m = -3; + "μ" = -6; + n = -9; + p = -12; + f = -15; + a = -18; + z = -21; + y = -24; + r = -27; + q = -30; + }; + in + prefixes.${c}; + + /* Gives the multiplier for the metric units. + + Example: + metricPrefixMultiplier "M" + => 1000000 + + metricPrefixMultiplier "G" + => 1000000000 + */ + metricPrefixMultiplier = c: + self.math.pow 10 (SIPrefixExponent c); + + /* Gives the exponent with the associated binary prefix. + + As an implementation detail, we don't follow the proper IEC unit prefixes + and instead mapping this to the SI prefix for convenience. + + Example: + SIPrefixExponent "M" + => 6 + + SIPrefixExponent "Q" + => 30 + */ + binaryPrefixExponent = c: + let + prefixes = { + Y = 80; + Z = 70; + E = 60; + P = 50; + T = 40; + G = 30; + M = 20; + K = 10; + }; + in + prefixes.${c}; + + /* Gives the multiplier for the given byte unit. Essentially returns the + value in number of bytes. + + Example: + binaryPrefixMultiplier "M" + => 1048576 + + binaryPrefixMultiplier "G" + => 1.099511628×10¹² + */ + binaryPrefixMultiplier = c: + self.math.pow 2 (binaryPrefixExponent c); + + /* Parse the given string containing the size into its appropriate value. + Returns the value in number of bytes. + + Example: + parseBytesSizeIntoInt "4GiB" + => 4294967296 + + parseBytesSizeIntoInt "2 MB" + => 2000000 + + parseBytesSizeIntoInt "2 Mb" + => 250000 + */ + parseBytesSizeIntoInt = str: + let + matches = builtins.match "([[:digit:]]+)[[:space:]]*([[:alpha:]]{1})(i?[B|b])" str; + numeral = lib.toInt (lib.lists.head matches); + prefix = lib.lists.elemAt matches 1; + suffix = lib.lists.last matches; + isBinary = lib.hasPrefix "i" suffix; + + multiplier = + let + multiplierFn = if isBinary then binaryPrefixMultiplier else metricPrefixMultiplier; + in + multiplierFn prefix; + bitDivider = if lib.hasSuffix "b" suffix then 8 else 1; + in + numeral * multiplier / bitDivider; + + /* + Given an attrset of unit size object, return the size in bytes. + + Example: + unitsToInt { size = 4; prefix = "G"; type = "binary"; } + => 4294967296 + + unitsToInt { size = 4; prefix = "G"; type = "metric"; } + => 4000000000 + */ + unitsToInt = { size, prefix, type ? "binary" }: + let + multiplierFn = + if type == "binary" then binaryPrefixMultiplier + else if type == "metric" then metricPrefixMultiplier + else builtins.throw "no multiplier type ${type}"; + in + size * (multiplierFn prefix); } diff --git a/lib/utils/nixos.nix b/lib/utils/nixos.nix index 644d6c08..e35b9df8 100644 --- a/lib/utils/nixos.nix +++ b/lib/utils/nixos.nix @@ -5,12 +5,6 @@ mapHomeManagerUser = user: settings: let homeDirectory = "/home/${user}"; - defaultUserConfig = { - extraGroups = lib.mkDefault [ "wheel" ]; - createHome = lib.mkDefault true; - home = lib.mkDefault homeDirectory; - isNormalUser = lib.mkForce true; - }; in ({ lib, ... }: { home-manager.users."${user}" = { ... }: { @@ -25,9 +19,35 @@ }; users.users."${user}" = lib.mkMerge [ - defaultUserConfig + { + extraGroups = lib.mkDefault [ "wheel" ]; + createHome = lib.mkDefault true; + home = lib.mkDefault homeDirectory; + isNormalUser = lib.mkForce true; + } settings ]; }); + /* Returns the file path of the given config of the given environment. + + Type: getConfig :: String -> String -> Path + + Example: + getConfig "home-manager" "foo-dogsquared" + => ../configs/home-manager/foo-dogsquared + */ + getConfig = type: config: ../../configs/${type}/${config}; + + /* Returns the file path of the given user subpart of the given + environment. Only certain environments such as NixOS have this type of + setup. + + Type: getConfig :: String -> String -> Path + + Example: + getUser "nixos" "foo-dogsquared" + => ../configs/nixos/_users/foo-dogsquared + */ + getUser = type: user: ../../configs/${type}/_users/${user}; } diff --git a/modules/flake-parts/default.nix b/modules/flake-parts/default.nix index 2d6467da..0f0f450a 100644 --- a/modules/flake-parts/default.nix +++ b/modules/flake-parts/default.nix @@ -13,6 +13,7 @@ ./home-modules.nix ./nixvim-modules.nix ./nixvim-configurations.nix + ./wrapper-manager-packages.nix ./setups ]; } diff --git a/modules/flake-parts/disko-configurations.nix b/modules/flake-parts/disko-configurations.nix index 335e4055..1f35a20b 100644 --- a/modules/flake-parts/disko-configurations.nix +++ b/modules/flake-parts/disko-configurations.nix @@ -9,7 +9,7 @@ description = '' A set of [disko](https://github.com/nix-community/disko) configurations readily available as part of the flake output to be - used by {program}`disko`. Could be useful as backup initialization + used by {command}`disko`. Could be useful as backup initialization scripts for individual storage drives. ''; }; diff --git a/modules/flake-parts/setups/default.nix b/modules/flake-parts/setups/default.nix index 221dd419..4a861015 100644 --- a/modules/flake-parts/setups/default.nix +++ b/modules/flake-parts/setups/default.nix @@ -1,8 +1,43 @@ +# The declarative environment management modules. Basically the backbone of my +# flake. Most of the modules here should have some things integrated within +# each other such as the ability to easily declare home-manager users (or a +# NixVim instance) into a NixOS system from already existing declared +# home-manager users (or NixVim instances) in the flake config. +{ lib, ... }: + { imports = [ ./disko.nix ./nixos.nix ./nixvim.nix ./home-manager.nix + ./wrapper-manager.nix ]; + + options.setups = { + configDir = lib.mkOption { + type = lib.types.path; + default = ../../../configs; + description = '' + The directory containing configurations of various environments. The + top-level directories are expected to be the name of the environment + with their configurations inside. + ''; + example = lib.literalExpression '' + ''${inputs.my-flake}/configs + ''; + }; + + sharedNixpkgsConfig = lib.mkOption { + type = with lib.types; attrsOf anything; + description = '' + Shared configuration of the nixpkgs instance to be passed to all of the + module environments based from the nixpkgs module system. + ''; + default = { }; + example = { + allowUnfree = true; + }; + }; + }; } diff --git a/modules/flake-parts/setups/disko.nix b/modules/flake-parts/setups/disko.nix index ed5b27d4..ec48026d 100644 --- a/modules/flake-parts/setups/disko.nix +++ b/modules/flake-parts/setups/disko.nix @@ -4,10 +4,11 @@ # that. Take note we don't consider integrating this with declarative NixOS # setups since their Disko scripts are already gettable in # `config.system.build.diskoScript` along with its variants (e.g., `noDeps`). -{ config, lib, ... }: +{ config, lib, inputs, ... }: let cfg = config.setups.disko; + partsConfig = config; diskoConfigType = { name, config, ... }: { options = { @@ -39,8 +40,42 @@ in }; }; + options.setups.nixos.configs = + let + diskoIntegrationModule = { config, lib, name, ... }: { + options = { + diskoConfigs = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + example = [ "external-hdd" ]; + description = '' + A list of declarative Disko configurations to be included alongside + the NixOS configuration. + ''; + }; + }; + + config = lib.mkIf (config.diskoConfigs != [ ]) ( + let + diskoConfigs = + builtins.map (name: import "${partsConfig.setups.configDir}/disko/${name}") config.diskoConfigs; + in + { + modules = lib.singleton { + imports = + [ inputs.disko.nixosModules.disko ] + ++ (lib.lists.flatten diskoConfigs); + }; + } + ); + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule diskoIntegrationModule); + }; + config = { flake.diskoConfigurations = - lib.mapAttrs (name: _: import ../../../configs/disko/${name}) cfg.configs; + lib.mapAttrs (name: _: import "${partsConfig.setups.configDir}/disko/${name}") cfg.configs; }; } diff --git a/modules/flake-parts/setups/home-manager.nix b/modules/flake-parts/setups/home-manager.nix index f4457ab0..9f447b1f 100644 --- a/modules/flake-parts/setups/home-manager.nix +++ b/modules/flake-parts/setups/home-manager.nix @@ -1,28 +1,28 @@ # This is the declarative user management converted into a flake-parts module. -{ config, lib, inputs, ... }: +# Take note, it reinforces mandatory import of home-manager to its composed +# environments such as NixOS. +{ config, options, lib, inputs, ... }: let cfg = config.setups.home-manager; - homeManagerModules = ../../home-manager; partsConfig = config; + homeManagerModules = ../../home-manager; # A thin wrapper around the home-manager configuration function. mkHome = - { system - , nixpkgsBranch ? "nixpkgs" + { pkgs + , lib ? pkgs.lib + , system , homeManagerBranch ? "home-manager" , extraModules ? [ ] + , specialArgs ? { } }: - let - pkgs = inputs.${nixpkgsBranch}.legacyPackages.${system}; - in inputs.${homeManagerBranch}.lib.homeManagerConfiguration { - extraSpecialArgs = { + extraSpecialArgs = specialArgs // { foodogsquaredModulesPath = builtins.toString homeManagerModules; }; - inherit pkgs; - lib = pkgs.lib; + inherit pkgs lib; modules = extraModules; }; @@ -35,16 +35,16 @@ let type = with lib.types; functionTo (attrsOf anything); default = homeenv: { home = { - sshUser = username; - user = username; + sshUser = homeenv.name; + user = homeenv.name; path = inputs.deploy.lib.${homeenv.system}.activate.home-manager homeenv.config; }; }; defaultText = lib.literalExpression '' homeenv: { home = { - sshUser = "$USERNAME"; - user = "$USERNAME"; + sshUser = "''${homeenv.name}"; + user = "''${homeenv.name}"; path = .lib.''${homeenv.system}.activate.home-manager homeenv.config; }; } @@ -69,36 +69,6 @@ let configType = { config, name, lib, ... }: { options = { - overlays = lib.mkOption { - type = with lib.types; listOf (functionTo raw); - default = [ ]; - example = lib.literalExpression '' - [ - inputs.neovim-nightly-overlay.overlays.default - inputs.emacs-overlay.overlays.default - ] - ''; - description = '' - A list of overlays to be applied for that host. - ''; - }; - - nixpkgsBranch = lib.mkOption { - type = lib.types.str; - default = "nixpkgs"; - example = "nixos-unstable-small"; - description = '' - The nixpkgs branch to be used for evaluating the NixOS configuration. - By default, it will use the `nixpkgs` flake input. - - ::: {.note} - This is based from your flake inputs and not somewhere else. If you - want to have support for multiple nixpkgs branch, simply add them as - a flake input. - ::: - ''; - }; - homeManagerBranch = lib.mkOption { type = lib.types.str; default = "home-manager"; @@ -135,39 +105,33 @@ let config = { modules = [ - ../../../configs/home-manager/${config.configName} + "${partsConfig.setups.configDir}/home-manager/${config.configName}" ( let setupConfig = config; in { config, lib, ... }: { - nixpkgs.overlays = setupConfig.overlays; + nixpkgs.overlays = setupConfig.nixpkgs.overlays; home.username = lib.mkForce name; home.homeDirectory = lib.mkForce setupConfig.homeDirectory; } ) - - (lib.mkIf (config.nixvim.instance != null) - ({ lib, ... }: { - imports = [ - inputs.nixvim.homeManagerModules.nixvim - ]; - - config.programs.nixvim = { ... }: { - enable = lib.mkDefault true; - imports = - partsConfig.setups.nixvim.configs.${config.nixvim.instance}.modules - ++ partsConfig.setups.nixvim.sharedModules - ++ config.nixvim.additionalModules; - }; - })) ]; + + nixpkgs.config = cfg.sharedNixpkgsConfig; }; }; in { options.setups.home-manager = { + sharedNixpkgsConfig = options.setups.sharedNixpkgsConfig // { + description = '' + nixpkgs configuration to be shared among home-manager configurations + defined here. + ''; + }; + sharedModules = lib.mkOption { type = with lib.types; listOf deferredModule; default = [ ]; @@ -197,15 +161,12 @@ in }; configs = lib.mkOption { - type = with lib.types; attrsOf (submoduleWith { - specialArgs = { inherit (config) systems; }; - modules = [ - (import ./shared/nix-conf.nix { inherit inputs; }) - ./shared/nixvim-instance-options.nix - ./shared/config-options.nix - configType - ]; - }); + type = with lib.types; attrsOf (submodule [ + (import ./shared/nix-conf.nix { inherit inputs; }) + (import ./shared/config-options.nix { inherit (config) systems; }) + ./shared/nixpkgs-options.nix + configType + ]); default = { }; description = '' An attribute set of metadata for the declarative home-manager setups. @@ -218,7 +179,7 @@ in inputs.nur.hmModules.nur inputs.nixvim.homeManagerModules.nixvim ]; - overlays = [ + nixpkgs.overlays = [ inputs.neovim-nightly-overlay.overlays.default inputs.emacs-overlay.overlays.default inputs.helix-editor.overlays.default @@ -232,7 +193,178 @@ in }; }; + # Setting up all of the integrations for the wider-scoped environments. + options.setups.nixos.configs = lib.mkOption { + type = with lib.types; attrsOf (submodule [ + ./shared/home-manager-users.nix + + ({ config, lib, name, ... }: let + inherit (config.home-manager) nixpkgsInstance; + setupConfig = config; + + hasHomeManagerUsers = config.home-manager.users != { }; + isNixpkgs = state: hasHomeManagerUsers && nixpkgsInstance == state; + homeManagerUserType = { name, config, lib, ... }: { + options = { + userConfig = lib.mkOption { + type = with lib.types; attrsOf anything; + description = '' + The configuration applied for individual users set in the + wider-scoped environment. + ''; + }; + }; + + config = + let + hmUserConfig = partsConfig.setups.home-manager.configs.${name}; + in + { + userConfig = { + isNormalUser = lib.mkDefault true; + createHome = lib.mkDefault true; + home = lib.mkForce hmUserConfig.homeDirectory; + }; + + additionalModules = [ + ({ lib, ... }: { + home.homeDirectory = lib.mkForce hmUserConfig.homeDirectory; + home.username = lib.mkForce name; + }) + ]; + }; + }; + in { + options.home-manager = { + users = lib.mkOption { + type = with lib.types; attrsOf (submodule homeManagerUserType); + }; + + nixpkgsInstance = lib.mkOption { + type = lib.types.enum [ "global" "separate" "none" ]; + default = "global"; + description = '' + Indicates how to manage the nixpkgs instance (or instances) + of the holistic system. This will also dictate how to import + overlays from + {option}`setups.home-manager.configs..overlays`. + + * `global` enforces to use one nixpkgs instance for all + home-manager users and imports all of the overlays into the + nixpkgs instance of the NixOS system. + + * `separate` enforces the NixOS system to use individual + nixpkgs instance for all home-manager users and imports the + overlays to the nixpkgs instance of the home-manager user. + + * `none` leave the configuration alone and do not import + overlays at all where you have to set them yourself. This is + the best option if you want more control over each individual + NixOS and home-manager configuration. + + The default value is set to `global` which is the encouraged + practice with this module. + ''; + }; + }; + + # Mapping the declarative home-manager users (if it has one) into NixOS + # users. + config = { + modules = [ + # For declarative NixOS systems, importing home-manager module is + # mandatory. + inputs.${config.home-manager.branch}.nixosModules.home-manager + + # Set the home-manager-related settings. + ({ lib, ... }: { + home-manager.sharedModules = partsConfig.setups.home-manager.sharedModules; + + # These are just the recommended options for home-manager that may be + # the default value in the future but this is how most of the NixOS + # setups are already done so... + home-manager.useUserPackages = lib.mkDefault true; + home-manager.useGlobalPkgs = lib.mkDefault true; + }) + + (lib.mkIf hasHomeManagerUsers ({ lib, pkgs, ... }: { + config = lib.mkMerge [ + { + users.users = + lib.mapAttrs + (name: hmUser: hmUser.userConfig) + setupConfig.home-manager.users; + + home-manager.users = + lib.mapAttrs + (name: hmUser: { + imports = + partsConfig.setups.home-manager.configs.${name}.modules + ++ hmUser.additionalModules; + }) + setupConfig.home-manager.users; + } + + (lib.mkIf (isNixpkgs "global") { + home-manager.useGlobalPkgs = lib.mkForce true; + + # Disable all options that are going to be blocked once + # `home-manager.useGlobalPkgs` is used. + home-manager.users = + lib.mapAttrs + (name: _: { + nixpkgs.overlays = lib.mkForce null; + nixpkgs.config = lib.mkForce null; + }) + setupConfig.home-manager.users; + + # Then apply all of the user overlays into the nixpkgs instance + # of the NixOS system. + nixpkgs.overlays = + let + hmUsersOverlays = + lib.mapAttrsToList + (name: _: + partsConfig.setups.home-manager.configs.${name}.nixpkgs.overlays) + setupConfig.home-manager.users; + + overlays = lib.lists.flatten hmUsersOverlays; + in + # Most of the overlays are going to be imported from a + # variable anyways. This should massively reduce the step + # needed for nixpkgs to do its thing. + # + # Though, it becomes unpredictable due to the way how the + # overlay list is constructed. However, this is much more + # preferable than letting a massive list with duplicated + # overlays from different home-manager users to be applied. + # + # Anyways, all I'm saying is that this is a massive hack + # because it isn't correct. + lib.lists.unique overlays; + }) + + (lib.mkIf (isNixpkgs "separate") { + home-manager.useGlobalPkgs = lib.mkForce false; + home-manager.users = + lib.mapAttrs + (name: _: { + nixpkgs.overlays = + partsConfig.setups.home-manager.configs.${name}.nixpkgs.overlays; + }) + setupConfig.home-manager.users; + }) + ]; + })) + ]; + }; + }) + ]); + }; + config = lib.mkIf (cfg.configs != { }) { + setups.home-manager.sharedNixpkgsConfig = config.setups.sharedNixpkgsConfig; + # Import our own home-manager modules. setups.home-manager.sharedModules = [ homeManagerModules @@ -250,9 +382,19 @@ in lib.listToAttrs (builtins.map (system: + let + nixpkgs = inputs.${metadata.nixpkgs.branch}; + + # We won't apply the overlays here since it is set + # modularly. + pkgs = import nixpkgs { + inherit system; + inherit (metadata.nixpkgs) config; + }; + in lib.nameValuePair system (mkHome { - inherit (metadata) nixpkgsBranch homeManagerBranch; - inherit system; + inherit pkgs system; + inherit (metadata) homeManagerBranch; extraModules = cfg.sharedModules ++ cfg.standaloneConfigModules diff --git a/modules/flake-parts/setups/nixos.nix b/modules/flake-parts/setups/nixos.nix index cbb1625f..4c50e5a6 100644 --- a/modules/flake-parts/setups/nixos.nix +++ b/modules/flake-parts/setups/nixos.nix @@ -1,31 +1,30 @@ # This is the declarative host management converted into a flake-parts module. -# It also enforces a structure for declarative NixOS setups such as a mandatory -# inclusion of the home-manager NixOS module, a deploy-rs node, a hostname and -# an optional domain, and deploy-rs-related options so it isn't really made to -# be generic or anything like that. -{ config, lib, inputs, ... }: +# It also enforces a structure for declarative NixOS setups such a deploy-rs +# node, a hostname and an optional domain, and deploy-rs-related options so it +# isn't really made to be generic or anything like that. +{ config, options, lib, inputs, ... }: let cfg = config.setups.nixos; + partsConfig = config; nixosModules = ../../nixos; - # This is used on a lot of the Nix modules below. - partsConfig = config; - # A thin wrapper around the NixOS configuration function. - mkHost = { extraModules ? [ ], nixpkgsBranch ? "nixpkgs", system }: + mkHost = { + pkgs, + lib ? pkgs.lib, + system, + extraModules ? [ ], + specialArgs ? { }, + }: let - nixpkgs = inputs.${nixpkgsBranch}; - - # Just to be sure, we'll use everything with the given nixpkgs' stdlib. - lib = nixpkgs.lib; - # Evaluating the system ourselves (which is trivial) instead of relying # on nixpkgs.lib.nixosSystem flake output. - nixosSystem = args: import "${nixpkgs}/nixos/lib/eval-config.nix" args; + nixosSystem = args: import "${pkgs.path}/nixos/lib/eval-config.nix" args; in (lib.makeOverridable nixosSystem) { - specialArgs = { + inherit pkgs; + specialArgs = specialArgs // { foodogsquaredUtils = import ../../../lib/utils/nixos.nix { inherit lib; }; foodogsquaredModulesPath = builtins.toString nixosModules; }; @@ -55,17 +54,17 @@ let inputs.nixos-generators.nixosModules // customFormats; # A very very thin wrapper around `mkHost` to build with the given format. - mkImage = - { system - , nixpkgsBranch ? "nixpkgs" - , extraModules ? [ ] - , format ? "iso" - }: + mkImage = { + pkgs, + system, + extraModules ? [ ], + format ? "iso", + }: let extraModules' = extraModules ++ [ nixosGeneratorsModulesSet.${format} ]; image = mkHost { - inherit nixpkgsBranch system; + inherit pkgs system; extraModules = extraModules'; }; in @@ -112,46 +111,9 @@ let }; }; - homeManagerUserType = { name, config, lib, ... }: { - options = { - userConfig = lib.mkOption { - type = with lib.types; attrsOf anything; - description = '' - The configuration applied for {option}`users.users.` in the - NixOS configuration. - ''; - }; - - additionalModules = lib.mkOption { - type = with lib.types; listOf deferredModule; - description = '' - A list of additional home-manager modules to be added with the - user. - ''; - }; - }; - - config = - let - hmUserConfig = partsConfig.setups.home-manager.configs.${name}; - in - { - userConfig = { - isNormalUser = lib.mkDefault true; - createHome = lib.mkDefault true; - home = lib.mkForce hmUserConfig.homeDirectory; - }; - - additionalModules = [ - ({ lib, ... }: { - home.homeDirectory = lib.mkForce hmUserConfig.homeDirectory; - home.username = lib.mkForce name; - }) - ]; - }; - }; - - configType = { config, name, lib, ... }: { + configType = { options, config, name, lib, ... }: let + setupConfig = config; + in { options = { formats = lib.mkOption { type = with lib.types; nullOr (listOf str); @@ -164,20 +126,6 @@ let ''; }; - overlays = lib.mkOption { - type = with lib.types; listOf (functionTo raw); - default = [ ]; - example = lib.literalExpression '' - [ - inputs.neovim-nightly-overlay.overlays.default - inputs.emacs-overlay.overlays.default - ] - ''; - description = '' - A list of overlays to be applied for that host. - ''; - }; - hostname = lib.mkOption { type = lib.types.nonEmptyStr; default = name; @@ -192,109 +140,6 @@ let description = "The domain of the NixOS system."; }; - nixpkgsBranch = lib.mkOption { - type = lib.types.str; - default = "nixpkgs"; - description = '' - The nixpkgs branch to be used for evaluating the NixOS configuration. - By default, it will use the `nixpkgs` flake input. - - ::: {.note} - This is based from your flake inputs and not somewhere else. If you - want to have support for multiple nixpkgs branch, simply add them as - a flake input. - ::: - ''; - example = "nixos-unstable-small"; - }; - - homeManagerBranch = lib.mkOption { - type = lib.types.str; - default = "home-manager"; - example = "home-manager-stable"; - description = '' - The home-manager branch to be used for the NixOS module. By default, - it will use the `home-manager` flake input. - ''; - }; - - homeManagerUsers = lib.mkOption { - type = lib.types.submodule { - options = { - users = lib.mkOption { - type = with lib.types; attrsOf (submodule homeManagerUserType); - default = { }; - description = '' - A set of home-manager users from {option}`setups.home-manager` to be - mapped within the NixOS system as a normal user with their - home-manager configuration. This would be the preferred method of - creating NixOS users if you have a more comprehensive home-manager - user that needed more setup to begin with. - ''; - }; - nixpkgsInstance = lib.mkOption { - type = lib.types.enum [ "global" "separate" "none" ]; - default = "global"; - description = '' - Indicates how to manage the nixpkgs instance (or instances) - of the holistic system. This will also dictate how to import - overlays from - {option}`setups.home-manager.configs..overlays`. - - * `global` enforces to use one nixpkgs instance for all - home-manager users and imports all of the overlays into the - nixpkgs instance of the NixOS system. - * `separate` enforces the NixOS system to use individual - nixpkgs instance for all home-manager users and imports the - overlays to the nixpkgs instance of the home-manager user. - * `none` leave the configuration alone and do not import - overlays at all where you have to set them yourself. This is - the best option if you want more control over each individual - NixOS and home-manager configuration. - - The default value is set to `global` which is the encouraged - practice with this module. - ''; - }; - }; - }; - default = { }; - example = lib.literalExpression '' - { - nixpkgsInstance = "global"; - users.foo-dogsquared = { - userConfig = { - extraGroups = [ - "adbusers" - "wheel" - "audio" - "docker" - "podman" - "networkmanager" - "wireshark" - ]; - hashedPassword = - "0000000000000000000000000000000000000000000000"; - isNormalUser = true; - createHome = true; - home = "/home/foo-dogsquared"; - description = "Gabriel Arazas"; - }; - additionalModules = [ - ({ config, lib, osConfig, ... }: { - programs.foo.enable = lib.mkIf osConfig.programs.bar.enable true; - }) - ]; - }; - } - ''; - description = '' - Import home-manager users from - {option}`setups.home-manager.configs` and map them as a normal - NixOS user. - ''; - }; - deploy = lib.mkOption { type = with lib.types; nullOr (submodule deployNodeType); default = null; @@ -313,16 +158,6 @@ let }; }; - diskoConfigs = lib.mkOption { - type = with lib.types; listOf str; - default = [ ]; - example = [ "external-hdd" ]; - description = '' - A list of declarative Disko configurations to be included alongside - the NixOS configuration. - ''; - }; - shouldBePartOfNixOSConfigurations = lib.mkOption { type = lib.types.bool; default = lib.isAttrs config.deploy || config.formats == null; @@ -334,131 +169,18 @@ let }; }; + config.nixpkgs.config = cfg.sharedNixpkgsConfig; + config.modules = [ # Bring in the required modules. - inputs.${config.homeManagerBranch}.nixosModules.home-manager - ../../../configs/nixos/${config.configName} - - # Mapping the declarative home-manager users (if it has one) into NixOS - # users. - (lib.mkIf (config.homeManagerUsers.users != { }) - ( - let - inherit (config.homeManagerUsers) nixpkgsInstance; - - setupConfig = config; - hasHomeManagerUsers = config.homeManagerUsers.users != { }; - isNixpkgs = state: hasHomeManagerUsers && nixpkgsInstance == state; - in - { config, lib, pkgs, ... }: { - config = lib.mkMerge [ - (lib.mkIf hasHomeManagerUsers { - users.users = - lib.mapAttrs - (name: hmUser: hmUser.userConfig) - setupConfig.homeManagerUsers.users; - - home-manager.users = - lib.mapAttrs - (name: hmUser: { - imports = - partsConfig.setups.home-manager.configs.${name}.modules - ++ hmUser.additionalModules; - }) - setupConfig.homeManagerUsers.users; - }) - - (lib.mkIf (isNixpkgs "global") { - home-manager.useGlobalPkgs = lib.mkForce true; - - # Disable all options that are going to be blocked once - # `home-manager.useGlobalPkgs` is used. - home-manager.users = - lib.mapAttrs - (name: _: { - nixpkgs.overlays = lib.mkForce null; - nixpkgs.config = lib.mkForce null; - }) - setupConfig.homeManagerUsers.users; - - # Then apply all of the user overlays into the nixpkgs instance - # of the NixOS system. - nixpkgs.overlays = - let - hmUsersOverlays = - lib.mapAttrsToList - (name: _: - partsConfig.setups.home-manager.configs.${name}.overlays) - setupConfig.homeManagerUsers.users; - - overlays = lib.lists.flatten hmUsersOverlays; - in - # Most of the overlays are going to be imported from a - # variable anyways. This should massively reduce the step - # needed for nixpkgs to do its thing. - # - # Though, it becomes unpredictable due to the way how the - # overlay list is constructed. However, this is much more - # preferable than letting a massive list with duplicated - # overlays from different home-manager users to be applied. - lib.lists.unique overlays; - }) - - (lib.mkIf (isNixpkgs "separate") { - home-manager.useGlobalPkgs = lib.mkForce false; - home-manager.users = - lib.mapAttrs - (name: _: { - nixpkgs.overlays = - partsConfig.setups.home-manager.configs.${name}.overlays; - }) - setupConfig.homeManagerUsers.users; - }) - ]; - } - )) - - # Next, we include the chosen NixVim configuration into NixOS. - (lib.mkIf (config.nixvim.instance != null) - ( - let - setupConfig = config; - in - { lib, ... }: { - imports = [ inputs.nixvim.nixosModules.nixvim ]; - - programs.nixvim = { ... }: { - enable = lib.mkDefault true; - imports = - partsConfig.setups.nixvim.configs.${config.nixvim.instance}.modules - ++ partsConfig.setups.nixvim.sharedModules - ++ setupConfig.nixvim.additionalModules; - }; - } - )) - - # Then we include the Disko configuration (if there's any). - (lib.mkIf (config.diskoConfigs != [ ]) ( - let - diskoConfigs = - builtins.map (name: import ../../../configs/disko/${name}) config.diskoConfigs; - in - { - imports = - [ inputs.disko.nixosModules.disko ] - ++ (lib.lists.flatten diskoConfigs); - }) - ) + "${partsConfig.setups.configDir}/nixos/${config.configName}" # Setting up the typical configuration. ( - let - setupConfig = config; - in { config, lib, ... }: { config = lib.mkMerge [ { - nixpkgs.overlays = setupConfig.overlays; + nixpkgs.overlays = setupConfig.nixpkgs.overlays; networking.hostName = lib.mkDefault setupConfig.hostname; } @@ -473,6 +195,20 @@ let in { options.setups.nixos = { + sharedNixpkgsConfig = options.setups.sharedNixpkgsConfig // { + description = '' + Shared configuration between all of the nixpkgs instance of the + declarative NixOS systems. + + ::: {.note} + This is implemented since the way how NixOS systems built here are made + with initializing a nixpkgs instance ourselves and NixOS doesn't allow + configuring the nixpkgs instances that are already defined outside of + its module environment. + ::: + ''; + }; + sharedModules = lib.mkOption { type = with lib.types; listOf deferredModule; default = [ ]; @@ -482,15 +218,12 @@ in }; configs = lib.mkOption { - type = with lib.types; attrsOf (submoduleWith { - specialArgs = { inherit (config) systems; }; - modules = [ - (import ./shared/nix-conf.nix { inherit inputs; }) - ./shared/config-options.nix - ./shared/nixvim-instance-options.nix - configType - ]; - }); + type = with lib.types; attrsOf (submodule [ + (import ./shared/nix-conf.nix { inherit inputs; }) + (import ./shared/config-options.nix { inherit (config) systems; }) + ./shared/nixpkgs-options.nix + configType + ]); default = { }; description = '' An attribute set of metadata for the declarative NixOS setups. This @@ -512,26 +245,29 @@ in modules = [ inputs.nur.nixosModules.nur ]; - overlays = [ - # Neovim nightly! - inputs.neovim-nightly-overlay.overlays.default + nixpkgs = { + branch = "nixos-unstable"; + overlays = [ + # Neovim nightly! + inputs.neovim-nightly-overlay.overlays.default - # Emacs unstable version! - inputs.emacs-overlay.overlays.default + # Emacs unstable version! + inputs.emacs-overlay.overlays.default - # Helix master! - inputs.helix-editor.overlays.default + # Helix master! + inputs.helix-editor.overlays.default - # Access to NUR. - inputs.nur.overlay - ]; + # Access to NUR. + inputs.nur.overlay + ]; + }; }; server = { systems = [ "x86_64-linux" "aarch64-linux" ]; domain = "work.example.com"; formats = [ "do" "linode" ]; - nixpkgsBranch = "nixos-unstable-small"; + nixpkgs.branch = "nixos-unstable-small"; deploy = { autoRollback = true; magicRollback = true; @@ -548,23 +284,14 @@ in }; config = lib.mkIf (cfg.configs != { }) { + setups.nixos.sharedNixpkgsConfig = config.setups.sharedNixpkgsConfig; + setups.nixos.sharedModules = [ # Import our own public NixOS modules. nixosModules # Import our private modules. ../../nixos/_private - - # Set the home-manager-related settings. - ({ lib, ... }: { - home-manager.sharedModules = partsConfig.setups.home-manager.sharedModules; - - # These are just the recommended options for home-manager that may be - # the default value in the future but this is how most of the NixOS - # setups are already done so... - home-manager.useUserPackages = lib.mkDefault true; - home-manager.useGlobalPkgs = lib.mkDefault true; - }) ]; flake = @@ -579,10 +306,19 @@ in lib.listToAttrs (builtins.map (system: + let + nixpkgs = inputs.${metadata.nixpkgs.branch}; + + # We won't apply the overlays here since it is set + # modularly. + pkgs = import nixpkgs { + inherit system; + inherit (metadata.nixpkgs) config; + }; + in lib.nameValuePair system (mkHost { - nixpkgsBranch = metadata.nixpkgsBranch; + inherit pkgs system; extraModules = cfg.sharedModules ++ metadata.modules; - inherit system; }) ) metadata.systems); @@ -612,9 +348,8 @@ in ( let deployConfig = cfg.configs.${name}.deploy; - deployConfig' = lib.attrsets.removeAttrs deployConfig [ "profiles" ]; in - deployConfig' + deployConfig // { profiles = cfg.configs.${name}.deploy.profiles { diff --git a/modules/flake-parts/setups/nixvim.nix b/modules/flake-parts/setups/nixvim.nix index 5b439bbb..65fe638f 100644 --- a/modules/flake-parts/setups/nixvim.nix +++ b/modules/flake-parts/setups/nixvim.nix @@ -1,23 +1,32 @@ +# Declarative NixVim configurations because everything under the Nix ecosystem +# must be so declarative so we're setting up declarative ways of declaring +# those accursed setups to be exported in this flake. { inputs , lib , config - -, defaultOverlays +, options , ... }: let + partsConfig = config; cfg = config.setups.nixvim; nixvimModules = ../../nixvim; - mkNixvimConfig = { system, pkgs, modules ? [ ] }: - inputs.nixvim.legacyPackages.${system}.makeNixvimWithModule { + mkNixvimConfig = { + system, + pkgs, + nixvimBranch ? "nixvim", + modules ? [ ], + specialArgs ? { }, + }: + inputs.${nixvimBranch}.legacyPackages.${system}.makeNixvimWithModule { inherit pkgs; module = { imports = modules; }; - extraSpecialArgs = { + extraSpecialArgs = specialArgs // { foodogsquaredModulesPath = builtins.toString nixvimModules; }; }; @@ -33,43 +42,124 @@ let ''; }; - configType = { name, lib, config, ... }: { + componentType = { lib, config, ... }: { + imports = [ + ./shared/nixpkgs-options.nix + (lib.mkAliasOptionModule [ "overlays" ] [ "nixpkgs" "overlays" ]) + ]; + options = { - nixpkgsBranches = lib.mkOption { - type = with lib.types; listOf str; + nixvimBranch = lib.mkOption { + type = lib.types.nonEmptyStr; + default = "nixvim"; + example = "nixvim-unstable"; description = '' - A list of nixpkgs branches for the NixVim configuration to be built - against. + The NixVim branch to be used for the NixVim configuration. + + It is recommend to match the NixVim branch with the nixpkgs branch. + For example, a NixVim configuration of `nixos-24.05` should be paired + with nixpkgs `nixos-24.05` branch. + + ::: {.note} + This refers to your flake inputs so in order to support multiple + NixVim branches, you need to import multiple NixVim branches as part + of the `inputs` flake attribute. + ::: ''; - example = [ - "nixos-unstable" - "nixos-stable" - ]; }; - neovimPackages = lib.mkOption { - type = with lib.types; functionTo (listOf package); - default = pkgs: with pkgs; [ neovim ]; - defaultText = "pkgs: with pkgs; [ neovim ]"; + neovimPackage = lib.mkOption { + type = with lib.types; functionTo package; + default = pkgs: pkgs.neovim; + defaultText = "pkgs: pkgs.neovim"; example = lib.literalExpression '' - pkgs: with pkgs; [ - (wrapNeovim neovim-unwrapped { }) - neovim-nightly - neovide - ] + pkgs: pkgs.neovim-nightly ''; description = '' - A list of Neovim packages from different branches to be built - against. Since this is to be used per-system, it should be a function - that returns a list of packages where the given statement is the - nixpkgs instance. + The package to be used for the NixVim configuration. Since this is + used per-system, it has to be a function returning a package from the + given nixpkgs instance. ''; }; }; + config = { + nixpkgs.config = cfg.sharedNixpkgsConfig; + }; + }; + + configType = { name, lib, config, ... }: { + options = { + components = lib.mkOption { + type = with lib.types; listOf (submodule componentType); + description = '' + A list of specific components for the NixVim configuration to be + built against. + ''; + example = [ + { nixpkgsBranch = "nixos-unstable"; nixvimBranch = "nixvim-unstable"; } + { nixpkgsBranch = "nixos-stable"; nixvimBranch = "nixvim-stable"; } + { nixpkgsBranch = "nixos-stable"; nixvimBranch = "nixvim-stable"; neovimPackage = pkgs: pkgs.neovim-nightly; } + ]; + }; + }; + config = { modules = [ - ../../../configs/nixvim/${config.configName} + "${partsConfig.setups.configDir}/nixvim/${config.configName}" + ]; + }; + }; + + nixvimIntegrationModule = { name, config, lib, ... }: { + options.nixvim = { + instance = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + example = "fiesta"; + description = '' + The name of the NixVim configuration from + {option}`setups.nixvim.configs.` to be included as part + of the wider-scoped environment. + ''; + }; + + branch = lib.mkOption { + type = lib.types.nonEmptyStr; + default = "nixvim"; + example = "nixvim-stable"; + description = '' + The branch of NixVim to be used for the module. + + ::: {.tip} + A rule of thumb for properly setting up NixVim with the wider-scoped + environment is it should match the nixpkgs version of it. For example, + a NixOS system of `nixos-23.11` nixpkgs branch should be paired with a NixVim + branch of `nixos-23.11`. + ::: + ''; + }; + + additionalModules = lib.mkOption { + type = with lib.types; listOf raw; + default = [ ]; + description = '' + A list of additional NixVim modules to be included. + ''; + }; + }; + + config = lib.mkIf (config.nixvim.instance != null) { + modules = [ + ({ lib, ... }: { + programs.nixvim = { ... }: { + enable = lib.mkDefault true; + imports = + partsConfig.setups.nixvim.configs.${config.nixvim.instance}.modules + ++ partsConfig.setups.nixvim.sharedModules + ++ config.nixvim.additionalModules; + }; + }) ]; }; }; @@ -77,13 +167,10 @@ in { options.setups.nixvim = { configs = lib.mkOption { - type = with lib.types; attrsOf (submoduleWith { - specialArgs = { inherit (config) systems; }; - modules = [ - ./shared/config-options.nix - configType - ]; - }); + type = with lib.types; attrsOf (submodule [ + (import ./shared/config-options.nix { inherit (config) systems; }) + configType + ]); default = { }; description = '' A set of NixVim configurations to be integrated into the declarative @@ -95,13 +182,44 @@ in sharedModules = modulesOption // { description = '' A list of NixVim modules to be shared across all of the NixVim - configurations. + configurations. This is also to be shared among wider-scoped + environments when NixVim-specific integrations has been enabled. ''; }; standaloneConfigModules = modulesOption' "standalone configuration"; + + sharedNixpkgsConfig = options.setups.sharedNixpkgsConfig // { + description = '' + nixpkgs configuration to be shared among the declared NixVim instances. + ''; + }; + }; + + options.setups.nixos.configs = lib.mkOption { + type = with lib.types; attrsOf (submodule [ + nixvimIntegrationModule + ({ config, lib, ... }: { + config.modules = [ + inputs.${config.nixvim.branch}.nixosModules.nixvim + ]; + }) + ]); + }; + + options.setups.home-manager.configs = lib.mkOption { + type = with lib.types; attrsOf (submodule [ + nixvimIntegrationModule + ({ config, lib, ... }: { + config.modules = [ + inputs.${config.nixvim.branch}.homeManagerModules.nixvim + ]; + }) + ]); }; config = lib.mkIf (cfg.configs != { }) { + setups.nixvim.sharedNixpkgsConfig = config.setups.sharedNixpkgsConfig; + setups.nixvim.sharedModules = [ nixvimModules @@ -120,34 +238,26 @@ in let generateNixvimConfigs = name: metadata: let - iterateThruBranches = nixpkgsBranch: + mkNixvimConfig' = component: let - pkgs = import inputs.${nixpkgsBranch} { + pkgs = import inputs.${component.nixpkgsBranch} { + inherit (component.nixpkgs) config overlays; inherit system; - overlays = defaultOverlays ++ [ - inputs.neovim-nightly-overlay.overlays.default - ]; - config.allowUnfree = true; }; - - neovimPackages = metadata.neovimPackages pkgs; - - mkNixvimConfig' = neovimPkg: - lib.nameValuePair - "${name}-${nixpkgsBranch}-${neovimPkg.name}" - (mkNixvimConfig { - inherit system pkgs; - modules = - cfg.sharedModules - ++ cfg.standaloneConfigModules - ++ metadata.modules - ++ [{ package = neovimPkg; }]; - }); + neovimPackage = component.neovimPackage pkgs; in - builtins.map mkNixvimConfig' neovimPackages; - - nixvimConfigs = lib.lists.flatten - (builtins.map iterateThruBranches metadata.nixpkgsBranches); + lib.nameValuePair + "${name}-${component.nixpkgsBranch}-${neovimPackage.pname}" + (mkNixvimConfig { + inherit system pkgs; + inherit (component) nixvimBranch; + modules = + cfg.sharedModules + ++ cfg.standaloneConfigModules + ++ metadata.modules + ++ [{ package = neovimPackage; }]; + }); + nixvimConfigs = builtins.map mkNixvimConfig' metadata.components; in lib.listToAttrs nixvimConfigs; in diff --git a/modules/flake-parts/setups/shared/config-options.nix b/modules/flake-parts/setups/shared/config-options.nix index 4346cec6..1c1bb9ea 100644 --- a/modules/flake-parts/setups/shared/config-options.nix +++ b/modules/flake-parts/setups/shared/config-options.nix @@ -1,4 +1,6 @@ -{ lib, name, systems, ... }: { +{ systems }: + +{ lib, name, ... }: { options = { systems = lib.mkOption { type = with lib.types; listOf str; @@ -6,7 +8,7 @@ defaultText = "config.systems"; example = [ "x86_64-linux" "aarch64-linux" ]; description = '' - A list of platforms that the NixOS configuration is supposed to be + A list of platforms that the environment config is supposed to be deployed on. ''; }; @@ -15,7 +17,7 @@ type = with lib.types; listOf raw; default = [ ]; description = '' - A list of NixOS modules specific for that host. + A list of modules specific for that environment. ''; }; diff --git a/modules/flake-parts/setups/shared/deploy-node-type.nix b/modules/flake-parts/setups/shared/deploy-node-type.nix index bedd5cac..c086626a 100644 --- a/modules/flake-parts/setups/shared/deploy-node-type.nix +++ b/modules/flake-parts/setups/shared/deploy-node-type.nix @@ -1,3 +1,6 @@ +# A deploy-rs submodule to be shared among other deploy-rs-related options in +# different environments. Take note this is supposed to be imported inside of a +# deploy-rs-related option, not in the top-level `configs` option. { lib, ... }: { options = { fastConnection = diff --git a/modules/flake-parts/setups/shared/home-manager-users.nix b/modules/flake-parts/setups/shared/home-manager-users.nix new file mode 100644 index 00000000..2d634015 --- /dev/null +++ b/modules/flake-parts/setups/shared/home-manager-users.nix @@ -0,0 +1,73 @@ +# Take note that the individual setup module would have to take care of +# integrating the users into their respective environment. +{ config, options, lib, ... }: + +let + homeManagerUserType = { name, config, lib, ... }: { + options = { + additionalModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + description = '' + A list of additional home-manager modules to be added with the + user. + ''; + }; + }; + }; +in +{ + # This option is for the wider-scoped environment to be easily compatible + # with the home-manager flake-parts module where it also shares the Nix + # configuration submodule. Without this option, it would not work (or we + # could just rename the options from the home-manager module). + imports = [ + (lib.mkAliasOptionModule [ "homeManagerBranch" ] [ "home-manager" "branch" ]) + ]; + + options.home-manager = { + branch = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + The name of the home-manager branch to be used. Take note this should + be set with care as home-manager typically recommends to be used with + the apprioriate nixpkgs branch. + ''; + default = "home-manager"; + example = "home-manager-stable"; + }; + + users = lib.mkOption { + type = with lib.types; attrsOf (submodule homeManagerUserType); + description = '' + A set of home-manager users from {option}`setups.home-manager.configs` to + be included with the wider-scoped environment. + ''; + default = { }; + example = { + foo-dogsquared = { + userConfig = { + uid = 1000; + extraGroups = [ + "adm" + "adbusers" + "wheel" + "audio" + "docker" + "podman" + "networkmanager" + "systemd-journal" + "wireshark" + ]; + }; + }; + + plover.userConfig = { + extraGroups = [ + "adm" + "wheel" + ]; + }; + }; + }; + }; +} diff --git a/modules/flake-parts/setups/shared/nix-conf.nix b/modules/flake-parts/setups/shared/nix-conf.nix index e2a4a8a5..7af0529a 100644 --- a/modules/flake-parts/setups/shared/nix-conf.nix +++ b/modules/flake-parts/setups/shared/nix-conf.nix @@ -4,9 +4,20 @@ let inputs' = inputs // { - nixpkgs = inputs.${config.nixpkgsBranch}; + nixpkgs = inputs.${config.nixpkgs.branch}; home-manager = inputs.${config.homeManagerBranch}; }; + + flakeInputName = name: + if name == "self" then "config" else name; + + nixChannels = + lib.mapAttrsToList + (name: source: "${flakeInputName name}=${source}") + inputs' + ++ [ + "/nix/var/nix/profiles/per-user/root/channels" + ]; in { config.modules = [( @@ -17,23 +28,13 @@ in nix.registry = lib.mapAttrs' (name: flake: - let - name' = if (name == "self") then "config" else name; - in - lib.nameValuePair name' { inherit flake; }) + lib.nameValuePair (flakeInputName name) { inherit flake; }) inputs'; - nix.settings.nix-path = - (lib.mapAttrsToList - (name: source: - let - name' = if (name == "self") then "config" else name; - in - "${name'}=${source}") - inputs' - ++ [ - "/nix/var/nix/profiles/per-user/root/channels" - ]); - } + nix.settings.nix-path = nixChannels; + + # It doesn't work on the traditional tools like nix-shell so ehhh... + nix.nixPath = nixChannels; + } )]; } diff --git a/modules/flake-parts/setups/shared/nixpkgs-options.nix b/modules/flake-parts/setups/shared/nixpkgs-options.nix new file mode 100644 index 00000000..b8dde580 --- /dev/null +++ b/modules/flake-parts/setups/shared/nixpkgs-options.nix @@ -0,0 +1,54 @@ +{ config, lib, options, ... }: + +{ + # A compatibility option while the newer iteration of configuring nixpkgs + # inside our internal flake-parts module is in progress. + imports = [ + (lib.mkAliasOptionModule [ "nixpkgsBranch" ] [ "nixpkgs" "branch" ]) + ]; + + options.nixpkgs = { + branch = lib.mkOption { + type = lib.types.nonEmptyStr; + default = "nixpkgs"; + description = '' + The nixpkgs branch to be used as the nixpkgs instance of the + environment. By default, it will use the `nixpkgs` flake input. + + ::: {.note} + This is based from your flake inputs and not somewhere else. If you + want to have support for multiple nixpkgs branch, simply add them as + a flake input. + ::: + ''; + example = "nixos-unstable-small"; + }; + + config = lib.mkOption { + type = with lib.types; attrsOf anything; + description = '' + The configuration to be passed to the nixpkgs instance of the module + environment. + ''; + default = { }; + example = { + allowUnfree = true; + }; + }; + + overlays = lib.mkOption { + type = with lib.types; listOf (functionTo raw); + default = [ ]; + example = lib.literalExpression '' + [ + inputs.neovim-nightly-overlay.overlays.default + inputs.emacs-overlay.overlays.default + ] + ''; + description = '' + A list of overlays to be applied for the nixpkgs instance of the + environment. + ''; + }; + }; +} diff --git a/modules/flake-parts/setups/shared/nixvim-instance-options.nix b/modules/flake-parts/setups/shared/nixvim-instance-options.nix deleted file mode 100644 index 4982f2a8..00000000 --- a/modules/flake-parts/setups/shared/nixvim-instance-options.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ lib, ... }: { - options.nixvim = { - instance = lib.mkOption { - type = with lib.types; nullOr str; - default = null; - example = "fiesta"; - description = '' - The name of the NixVim configuration from - {option}`setups.nixvim.configs.` to be included as part - of the NixOS system. - ''; - }; - - additionalModules = lib.mkOption { - type = with lib.types; listOf raw; - default = [ ]; - description = '' - A list of additional NixVim modules to be included. - ''; - }; - }; -} diff --git a/modules/flake-parts/setups/wrapper-manager.nix b/modules/flake-parts/setups/wrapper-manager.nix new file mode 100644 index 00000000..ef7a7bd7 --- /dev/null +++ b/modules/flake-parts/setups/wrapper-manager.nix @@ -0,0 +1,202 @@ +{ lib, config, options, inputs, ... }: + +let + partsConfig = config; + cfg = config.setups.wrapper-manager; + + mkWrapperManagerPackage = { + pkgs, + src, + modules ? [ ], + specialArgs ? { }, + }: + let + wrapperManagerEntrypoint = import src { }; + in + wrapperManagerEntrypoint.lib.build { + inherit pkgs modules specialArgs; + }; + + wrapperManagerIntegrationModule = { name, config, lib, ... }: { + options.wrapper-manager = { + src = lib.mkOption { + type = lib.types.path; + default = ../../../subprojects/wrapper-manager-fds; + description = '' + The path of the wrapper-manager-fds to be used to properly initialize + to the environment. + ''; + }; + + additionalModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + default = [ ]; + description = '' + Additional wrapper-manager modules to be included in the wider-scoped + environment. + ''; + }; + + packages = lib.mkOption { + type = with lib.types; attrsOf (submodule { + options.additionalModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + description = '' + Additional wrapper-manager modules to be included into the given + declarative wrapper-manager configuration. + ''; + default = [ ]; + }; + }); + default = { }; + description = '' + Include declared wrapper-manager packages into the wider environment. + ''; + }; + }; + + config = lib.mkIf (config.wrapper-manager.packages != { }) { + modules = [ + ({ lib, ... }: { + wrapper-manager.sharedModules = + cfg.sharedModules ++ config.wrapper-manager.additionalModules; + + wrapper-manager.packages = + lib.mapAttrs (name: wmPackage: { + imports = + partsConfig.setups.wrapper-manager.configs.${name}.modules + ++ wmPackage.additionalModules; + }) config.wrapper-manager.packages; + }) + ]; + }; + }; + + wrapperManagerConfigModule = { name, config, lib, ... }: { + options.wrapper-manager.src = lib.mkOption { + type = lib.types.path; + default = ../../../subprojects/wrapper-manager-fds; + description = '' + The path containing wrapper-manager-fds source code to be used to + properly initialize and create the wrapper-manager environment. + ''; + }; + + config = { + nixpkgs.config = cfg.sharedNixpkgsConfig; + + modules = [ + "${partsConfig.setups.configDir}/wrapper-manager/${config.configName}" + ]; + }; + }; +in +{ + options.setups.wrapper-manager = { + sharedNixpkgsConfig = options.setups.sharedNixpkgsConfig // { + description = '' + The nixpkgs configuration to be passed to all of the declarative + wrapper-manager configurations. + ''; + }; + + configs = lib.mkOption { + type = with lib.types; attrsOf (submodule [ + (import ./shared/config-options.nix { inherit (config) systems; }) + ./shared/nixpkgs-options.nix + wrapperManagerConfigModule + ]); + default = { }; + description = '' + Declarative wrapper-manager packages to be exported into the flake. + ''; + example = lib.literalExpression '' + { + music-setup = { + modules = [ + { config.build.isBinary = false; } + ]; + }; + } + ''; + }; + + sharedModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + default = [ ]; + description = '' + List of shared wrapper-manager modules in all of the declarative + wrapper-manager configurations. + ''; + }; + + standaloneModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + default = [ ]; + description = '' + List of wrapper-manager modules only available at standalone mode. + ''; + }; + }; + + # Integrations with the composable environments such as NixOS and home-manager. + options.setups.nixos.configs = lib.mkOption { + type = with lib.types; attrsOf (submodule [ + wrapperManagerIntegrationModule + ({ config, lib, ... }: { + config = lib.mkIf (config.wrapper-manager.packages != { }) { + modules = [ + (import config.wrapper-manager.src { }).nixosModules.default + ]; + }; + }) + ]); + }; + + options.setups.home-manager.configs = lib.mkOption { + type = with lib.types; attrsOf (submodule [ + wrapperManagerIntegrationModule + ({ config, lib, ... }: { + config = lib.mkIf (config.wrapper-manager.packages != { }) { + modules = [ + (import config.wrapper-manager.src { }).homeModules.default + ]; + }; + }) + ]); + }; + + config = lib.mkIf (cfg.configs != { }) { + setups.wrapper-manager.sharedNixpkgsConfig = config.setups.sharedNixpkgsConfig; + + setups.wrapper-manager.sharedModules = [ + ../../wrapper-manager + ../../wrapper-manager/_private + ]; + + perSystem = { system, config, lib, ... }: let + validWrapperManagerConfigs = + lib.filterAttrs (_: metadata: lib.elem system metadata.systems) cfg.configs; + in { + wrapperManagerPackages = + lib.mapAttrs + (name: metadata: + let + pkgs = import inputs.${metadata.nixpkgs.branch} { + inherit (metadata.nixpkgs) config; + inherit system; + }; + in + mkWrapperManagerPackage { + inherit pkgs; + inherit (metadata.wrapper-manager) src; + modules = + cfg.sharedModules + ++ cfg.standaloneModules + ++ metadata.modules; + } + ) + validWrapperManagerConfigs; + }; + }; +} diff --git a/modules/flake-parts/wrapper-manager-packages.nix b/modules/flake-parts/wrapper-manager-packages.nix new file mode 100644 index 00000000..153fee2c --- /dev/null +++ b/modules/flake-parts/wrapper-manager-packages.nix @@ -0,0 +1,48 @@ +# A flake-parts module containing definition for my custom wrapper-manager +# packages which should have its own flake output attribute at +# `wrapperManagerPackages` containing the derivations that can be run or build. +{ config, lib, flake-parts-lib, ... }: + +let + inherit (flake-parts-lib) mkSubmoduleOptions mkPerSystemOption; +in +{ + options = { + flake = mkSubmoduleOptions { + wrapperManagerPackages = lib.mkOption { + type = with lib.types; lazyAttrsOf (attrsOf package); + default = { }; + description = '' + An attribute set of per-system wrapper-manager configurations. + ''; + }; + }; + + perSystem = mkPerSystemOption { + options = { + wrapperManagerPackages = lib.mkOption { + type = with lib.types; attrsOf package; + default = { }; + description = '' + An attribute set of wrapper-manager configurations. + ''; + }; + }; + }; + }; + + config = { + flake.wrapperManagerPackages = + lib.mapAttrs + (k: v: v.wrapperManagerPackages) + (lib.filterAttrs + (k: v: v.wrapperManagerPackages != { }) + config.allSystems + ); + + perInput = system: flake: + lib.optionalAttrs (flake ? wrapperManagerPackages.${system}) { + wrapperManagerPackages = flake.wrapperManagerPackages.${system}; + }; + }; +} diff --git a/modules/home-manager/_private/default.nix b/modules/home-manager/_private/default.nix index ea8ac78f..14769755 100644 --- a/modules/home-manager/_private/default.nix +++ b/modules/home-manager/_private/default.nix @@ -1,7 +1,7 @@ { imports = [ ./extra-arguments.nix - ./state.nix + ./state ./suites/desktop.nix ./suites/dev.nix ./suites/editors.nix diff --git a/modules/home-manager/_private/extra-arguments.nix b/modules/home-manager/_private/extra-arguments.nix index 2085d87d..c9918dcc 100644 --- a/modules/home-manager/_private/extra-arguments.nix +++ b/modules/home-manager/_private/extra-arguments.nix @@ -1,6 +1,6 @@ # All of the extra module arguments to be passed as part of the home-manager # environment. -{ pkgs, lib, options, ... }: +{ pkgs, lib, options, ... }@attrs: let foodogsquaredLib = import ../../../lib { inherit pkgs; }; @@ -8,8 +8,10 @@ in { _module.args.foodogsquaredLib = foodogsquaredLib.extend (final: prev: { - home-manager = import ../../../lib/home-manager.nix { inherit pkgs lib; self = final; }; + home-manager = import ../../../lib/env-specific/home-manager.nix { inherit pkgs lib; self = final; }; } // lib.optionalAttrs (options?sops) { - sops-nix = import ../../../lib/sops.nix { inherit pkgs lib; self = final; }; + sops-nix = import ../../../lib/env-specific/sops.nix { inherit pkgs lib; self = final; }; + } // lib.optionalAttrs (attrs?nixosConfig) { + nixos = import ../../../lib/env-specific/nixos.nix { inherit pkgs lib; self = final; }; }); } diff --git a/modules/home-manager/_private/state.nix b/modules/home-manager/_private/state.nix deleted file mode 100644 index ba5d0a73..00000000 --- a/modules/home-manager/_private/state.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ lib, ... }: - -{ - options.state = lib.mkOption { - type = lib.types.submodule { - freeformType = with lib.types; attrsOf anything; - options = { - ignoreDirectories = lib.mkOption { - type = with lib.types; listOf str; - description = '' - A state variable holding a list of directory names to be excluded - in processes involving walking through directories (e.g., desktop - indexing). - ''; - default = [ ]; - example = [ - "node_modules" - ".direnv" - ]; - }; - }; - }; - description = '' - A set of values to be held in the home-manager configuration. Pretty much - used for anything that requires consistency or deduplicate the source of - truth for module values. - ''; - example = { - sampleValue = 10; - dev.ignoreDirectories = [ - ".git" - "node_modules" - ".direnv" - ]; - }; - }; -} diff --git a/modules/home-manager/_private/state/default.nix b/modules/home-manager/_private/state/default.nix new file mode 100644 index 00000000..2563921f --- /dev/null +++ b/modules/home-manager/_private/state/default.nix @@ -0,0 +1,29 @@ +{ lib, ... }: + +{ + imports = [ + ./ports.nix + ./paths.nix + ./packages.nix + ]; + + options.state = lib.mkOption { + type = lib.types.submodule { + freeformType = with lib.types; attrsOf anything; + default = { }; + }; + description = '' + A set of values to be held in the home-manager configuration. Pretty much + used for anything that requires consistency or deduplicate the source of + truth for module values. + ''; + example = { + sampleValue = 10; + paths.ignoreDirectories = [ + ".git" + "node_modules" + ".direnv" + ]; + }; + }; +} diff --git a/modules/home-manager/_private/state/packages.nix b/modules/home-manager/_private/state/packages.nix new file mode 100644 index 00000000..c0c86ca2 --- /dev/null +++ b/modules/home-manager/_private/state/packages.nix @@ -0,0 +1,29 @@ +{ lib, ... }: + +{ + options.state = + let + packagesSubmodule = { lib, ... }: { + options = { + packages = lib.mkOption { + type = with lib.types; attrsOf package; + default = { }; + description = '' + Source of truth containing a set of packages. Useful for options + where there are no specific options for a package or as a unified + source of truth for different module options requiring a package. + ''; + example = lib.literalExpression '' + { + diff = pkgs.vimdiff; + pager = pkgs.bat; + editor = pkgs.neovim; + } + ''; + }; + }; + }; + in lib.mkOption { + type = lib.types.submodule packagesSubmodule; + }; +} diff --git a/modules/home-manager/_private/state/paths.nix b/modules/home-manager/_private/state/paths.nix new file mode 100644 index 00000000..b52b33bc --- /dev/null +++ b/modules/home-manager/_private/state/paths.nix @@ -0,0 +1,27 @@ +{ lib, ... }: + +{ + options.state = + let + pathsSubmodule = { lib, ... }: { + options = { + paths = lib.mkOption { + type = with lib.types; attrsOf (either path (listOf str)); + default = { }; + description = '' + Set of paths to hold as a single source of truth for path-related + settings throughout the whole home environment. + ''; + example = lib.literalExpression '' + { + ignoreDirectories = [ "''${config.home.homeDirectory}/Nodes" ]; + ignorePaths = [ ".gitignore" "node_modules" "result" ]; + } + ''; + }; + }; + }; + in lib.mkOption { + type = lib.types.submodule pathsSubmodule; + }; +} diff --git a/modules/home-manager/_private/state/ports.nix b/modules/home-manager/_private/state/ports.nix new file mode 100644 index 00000000..f5ea0a0b --- /dev/null +++ b/modules/home-manager/_private/state/ports.nix @@ -0,0 +1,64 @@ +{ lib, ... }: + +let + supportedProtocols = [ "tcp" "udp" ]; +in +{ + options.state = + let + portRangeType = { + options = { + from = lib.mkOption { + type = lib.types.port; + description = '' + The start of the range of TCP/UDP ports to be taken over. + ''; + }; + + to = lib.mkOption { + type = lib.types.port; + description = '' + The end of the range of TCP/UDP ports to be taken over. + ''; + }; + }; + }; + + portValueModule = { lib, ... }: { + options = { + protocols = lib.mkOption { + type = with lib.types; listOf (enum supportedProtocols); + description = '' + Indicates the type of protocol of the service. + ''; + default = [ "tcp" "udp" ]; + example = [ "tcp" ]; + }; + + value = lib.mkOption { + type = with lib.types; either port (submodule portRangeType); + description = '' + The port number itself. + ''; + }; + }; + }; + + portsSubmodule = { lib, ... }: { + options = { + ports = lib.mkOption { + type = with lib.types; attrsOf (submodule portValueModule); + default = { }; + example = lib.literalExpression '' + { + gonic.value = 4629; + mopidy.value = 6034; + } + ''; + }; + }; + }; + in lib.mkOption { + type = lib.types.submodule portsSubmodule; + }; +} diff --git a/modules/home-manager/_private/suites/desktop.nix b/modules/home-manager/_private/suites/desktop.nix index cc21dfa3..9399d2d3 100644 --- a/modules/home-manager/_private/suites/desktop.nix +++ b/modules/home-manager/_private/suites/desktop.nix @@ -3,7 +3,6 @@ let cfg = config.suites.desktop; - nixosCfg = attrs.nixosConfig; in { options.suites.desktop = { @@ -14,7 +13,7 @@ in enable = lib.mkEnableOption "installations of audio-related apps"; pipewire.enable = lib.mkOption { type = lib.types.bool; - default = nixosCfg.services.pipewire.enable or false; + default = attrs.nixosConfig.services.pipewire.enable or false; description = '' Enable whether to install Pipewire-related applications. @@ -44,7 +43,7 @@ in ] ++ ( let - hasBlenderNixOSModule = nixosCfg.programs.blender.enable or false; + hasBlenderNixOSModule = attrs.nixosConfig.programs.blender.enable or false; in lib.optional (!hasBlenderNixOSModule) pkgs.blender ); @@ -54,15 +53,14 @@ in home.packages = with pkgs; [ audacity # EGADS!!! musescore # You won't find muses to score, only music: a common misconception. - #zrythm # The freer FL Studio (if you're sailing by the high seven seas). + zrythm # The freer FL Studio (if you're sailing by the high seven seas). supercollider # Not to be confused with the other Super Collider. sonic-pi # The only pie you'll get from this is worms which I heard is addicting. - ffmpeg-full # Ah yes, everyman's multimedia swiss army knife. ] ++ ( let - hasDesktopSuiteEnabled = nixosCfg.suites.desktop.enable or false; + hasDesktopSuiteEnabled = attrs.nixosConfig.suites.desktop.enable or false; in lib.optionals hasDesktopSuiteEnabled (with pkgs; [ yabridge # Building bridges to Windows and Linux audio tools. @@ -184,7 +182,6 @@ in home.packages = with pkgs; [ dino # Some modern chat client featuring a dinosaur mascot for what could be considered a dinosaur. foliate # The prettier PDF viewer (if you're OK with a mixed bag of GTK3+GTK4 apps). - thunderbird # Email and web feed checks. languagetool # You're personal assistant for proper grammar, vale # Elevate your fanfics to a frivolously higher caliber! ]; diff --git a/modules/home-manager/_private/suites/dev.nix b/modules/home-manager/_private/suites/dev.nix index accb73dc..8fb4006c 100644 --- a/modules/home-manager/_private/suites/dev.nix +++ b/modules/home-manager/_private/suites/dev.nix @@ -20,7 +20,7 @@ in { ({ # Contains a dev-adjacent list of directory names to be ignored usually # used in walking through directories. - state.ignoreDirectories = [ + state.paths.ignoreDirectories = [ ".git" ".direnv" ]; @@ -93,11 +93,7 @@ in { # Echolocation. Since you're using a home-manager configuration, you're # most likely using Nix anyways. - programs.nix-index.enable = - let - hasNixOSModuleEnabled = attrs ? nixosConfig && lib.attrByPath [ "programs" "nix-index" "enable" ] false attrs.nixosConfig; - in - !hasNixOSModuleEnabled; + programs.nix-index.enable = !attrs.nixosConfig.programs.nix-index.enable or false; }) # Level up your terminal-dwelling skills with these. @@ -112,7 +108,7 @@ in { changeDirWidgetCommand = "${fd} --type directory --unrestricted"; defaultCommand = "${fd} --type file --hidden"; defaultOptions = let - skipDirectories' = lib.concatStringsSep "," config.state.ignoreDirectories; + skipDirectories' = lib.concatStringsSep "," config.state.paths.ignoreDirectories; in [ "--walker-skip=${skipDirectories'}" ]; @@ -175,7 +171,7 @@ in { programs.eza = { enable = true; extraOptions = let - ignoreDirectories = lib.concatStringsSep "|" config.state.ignoreDirectories; + ignoreDirectories = lib.concatStringsSep "|" config.state.paths.ignoreDirectories; in [ "--group-directories-first" "--header" diff --git a/modules/home-manager/default.nix b/modules/home-manager/default.nix index 5e56d6f8..8de58c65 100644 --- a/modules/home-manager/default.nix +++ b/modules/home-manager/default.nix @@ -5,10 +5,14 @@ ./programs/pipewire.nix ./programs/pop-launcher.nix ./programs/zed-editor.nix + ./programs/borgmatic.nix ./services/archivebox.nix + ./services/borgmatic.nix ./services/bleachbit.nix ./services/distant.nix ./services/gallery-dl.nix + ./services/gonic.nix + ./services/ludusavi.nix ./services/matcha.nix ./services/plover.nix ./services/yt-dlp.nix diff --git a/modules/home-manager/files/mutable-files.nix b/modules/home-manager/files/mutable-files.nix index 9fb81e54..02296330 100644 --- a/modules/home-manager/files/mutable-files.nix +++ b/modules/home-manager/files/mutable-files.nix @@ -3,8 +3,12 @@ let cfg = config.home.mutableFile; + runtimeInputs = lib.makeBinPath (with pkgs; [ + coreutils archiver curl git gopass + ]); + # An attribute set to be used to get the fetching script. - fetchScript = path: value: + fetchScript = _: value: let url = lib.escapeShellArg value.url; path = lib.escapeShellArg value.path; @@ -39,6 +43,15 @@ let ''; }; + # The file submodule. Take note the values here are sanitized to only + # represent relative paths starting with the given base directory as the root + # (such as the home directory). + # + # Playing with absolute paths is basically like playing with fire, some use + # cases are nice for it, some are bad especially that this is only used for + # home-manager where it is expected to be limited to its associated home + # directory. But that's for the user to know how their user interact with the + # rest of the system. fileType = baseDir: { name, config, options, ... }: { options = { url = lib.mkOption { @@ -178,14 +191,12 @@ in '') cfg; - runtimeInputs = lib.makeBinPath (with pkgs; [ - archiver curl git gopass - ]); + shellScript = pkgs.writeShellScriptBin "fetch-mutable-files" '' + export PATH=${runtimeInputs}''${PATH:-:$PATH} + ${lib.concatStringsSep "\n" mutableFilesCmds} + ''; in - pkgs.writeShellScript "fetch-mutable-files" '' - export PATH=${runtimeInputs} - ${lib.concatStringsSep "\n" mutableFilesCmds} - ''; + lib.getExe shellScript; ExecStartPost = let @@ -193,13 +204,12 @@ in (path: value: value.postScript) cfg; - script = pkgs.writeShellApplication { - name = "fetch-mutable-files-post-script"; - runtimeInputs = with pkgs; [ archiver curl git gopass ]; - text = lib.concatStringsSep "\n" mutableFilesCmds; - }; + shellScript = pkgs.writeShellScriptBin "fetch-mutable-files-post-script" '' + export PATH=${runtimeInputs}''${PATH:-:$PATH} + ${lib.concatStringsSep "\n" mutableFilesCmds} + ''; in - "${script}/bin/fetch-mutable-files-post-script"; + lib.getExe shellScript; }; Install.WantedBy = [ "default.target" ]; diff --git a/modules/home-manager/profiles/nix-conf.nix b/modules/home-manager/profiles/nix-conf.nix index c4751fb0..15c6cd60 100644 --- a/modules/home-manager/profiles/nix-conf.nix +++ b/modules/home-manager/profiles/nix-conf.nix @@ -1,5 +1,4 @@ -{ lib, pkgs, ... }: { - +{ config, lib, pkgs, ... }: { # Set the package for generating the configuration. nix.package = lib.mkDefault pkgs.nixStable; @@ -21,11 +20,12 @@ # # Since we're using flakes to make this possible, we need it. Plus, the # UX of Nix CLI is becoming closer to Guix's which is a nice bonus. - experimental-features = [ "nix-command" "flakes" "repl-flake" ]; + experimental-features = + [ "nix-command" "flakes" ] + ++ lib.optionals (lib.versionOlder config.nix.package.version "2.22.0") [ "repl-flake" ]; auto-optimise-store = lib.mkDefault true; + + # We don't want to download every time we invoke Nix, seriously. Thanks. flake-registry = ""; }; - - # Stallman-senpai will be disappointed. - nixpkgs.config.allowUnfree = true; } diff --git a/modules/home-manager/programs/borgmatic.nix b/modules/home-manager/programs/borgmatic.nix new file mode 100644 index 00000000..8ebd5acc --- /dev/null +++ b/modules/home-manager/programs/borgmatic.nix @@ -0,0 +1,117 @@ +# A replacement module for the Borgmatic home-manager module. It is quite +# limited and also feels janky to use. +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.borgmatic; + + settingsFormat = pkgs.formats.yaml { }; + + borgmaticBackupsModule = { name, lib, ... }: { + options = { + settings = lib.mkOption { + type = settingsFormat.type; + default = { }; + example = lib.literalExpression '' + { + source_directories = [ + "''${config.xdg.configHome}" + "''${config.xdg.userDirs.extraConfig.XDG_PROJECTS_DIR}" + "''${config.home.homeDirectory}/.thunderbird" + "''${config.home.homeDirectory}/Zotero" + ]; + + repositories = [ + { + path = "ssh://k8pDxu32@k8pDxu32.repo.borgbase.com/./repo"; + label = "borgbase"; + } + + { + path = "/var/lib/backups/local.borg"; + label = "local"; + } + ]; + + keep_daily = 7; + keep_weekly = 4; + keep_monthly = 6; + + checks = [ + { name = "repository"; } + { name = "archives"; frequency = "2 weeks"; } + ]; + } + ''; + }; + + validateConfig = + lib.mkEnableOption "validation step for the resulting configuration" // { + default = true; + }; + }; + }; + + mkBorgmaticConfig = n: v: + lib.nameValuePair "borgmatic.d/${n}.yaml" { + source = let + settingsFile = settingsFormat.generate "borgmatic-config-${n}" v.settings; + + borgmaticValidateCmd = + if lib.versionOlder cfg.package.version "1.7.15" then + "borgmatic config validate --config ${settingsFile}" + else + "validate-borgmatic-config --config ${settingsFile}"; + in + if v.validateConfig then + pkgs.runCommand "generate-borgmatic-config-with-validation" { + buildInputs = [ cfg.package ]; + preferLocalBuild = true; + } '' + ${borgmaticValidateCmd} && install ${settingsFile} $out + '' + else + settingsFile; + }; + in +{ + disabledModules = [ "programs/borgmatic.nix" ]; + options.programs.borgmatic = { + enable = lib.mkEnableOption "configuring Borg backups with Borgmatic"; + + package = lib.mkPackageOption pkgs "borgmatic" { }; + + backups = lib.mkOption { + type = with lib.types; attrsOf (submodule borgmaticBackupsModule); + default = { }; + example = lib.literalExpression '' + { + personal = { + validateConfig = true; + settings = { + source_directories = [ + config.xdg.configHome + config.xdg.userDirs.documents + config.xdg.userDirs.photos + ]; + + repositories = lib.singleton { + path = "ssh://alskdjalskdjalsdkj"; + label = "remote-hetzner-box"; + }; + + keep_daily = 7; + keep_weekly = 6; + keep_monthly = 6; + } + }; + } + ''; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + xdg.configFile = lib.mapAttrs' mkBorgmaticConfig cfg.backups; + }; +} diff --git a/modules/home-manager/services/archivebox.nix b/modules/home-manager/services/archivebox.nix index 0fd3bbbe..d4c3de62 100644 --- a/modules/home-manager/services/archivebox.nix +++ b/modules/home-manager/services/archivebox.nix @@ -113,7 +113,7 @@ in Unit = { Description = "Archivebox archive group '${name}' for ${cfg.archivePath}"; - After = "network.target"; + After = [ "network-online.target" ]; Documentation = [ "https://docs.archivebox.io/" ]; }; @@ -142,7 +142,8 @@ in archivebox-server = { Unit = { Description = "Archivebox server for ${cfg.archivePath}"; - After = "network.target"; + After = [ "network-online.target" ]; + Wants = [ "network-online.target" ]; Documentation = [ "https://docs.archivebox.io/" ]; }; @@ -164,7 +165,8 @@ in lib.nameValuePair (jobUnitName name) { Unit = { Description = "Archivebox additions for ${cfg.archivePath}"; - After = "network.target"; + After = [ "network-online.target" ]; + Wants = [ "network-online.target" ]; Documentation = [ "https://docs.archivebox.io/" ]; }; diff --git a/modules/home-manager/services/borgmatic.nix b/modules/home-manager/services/borgmatic.nix new file mode 100644 index 00000000..1419875e --- /dev/null +++ b/modules/home-manager/services/borgmatic.nix @@ -0,0 +1,234 @@ +# A re-implementation of the Borgmatic service home-manager module. The +# reimplementation basically separates all of the configurations instead of a +# oneshot where it will execute Borgmatic with all present configurations +# (which is fine but too overwhelming for my taste). +# +# It has an added integration for individual Borgmatic configurations from +# `programs.borgmatic.backups` (also a reimplemented version from the upstream) +# to be added to the jobset and has more control over each service unit. +# +# As a design constraint, you should still be able to do what the upstream +# service module with a little bit of elbow grease. +{ config, lib, pkgs, ... }: + +let + cfg = config.services.borgmatic; + programCfg = config.programs.borgmatic; + settingsFormat = pkgs.formats.yaml { }; + + borgmaticProgramModule = { name, lib, ... }: { + options = { + initService = { + enable = lib.mkEnableOption "include this particular backup as part of Borgmatic jobset at {option}`services.borgmatic.jobs`"; + + startAt = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + Indicates how often the associated service occurs. Accepts value as + found from {manpage}`systemd.time(7)`. + ''; + default = "daily"; + example = "04:30"; + }; + }; + }; + }; + + borgmaticJobModule = { config, lib, name, ... }: let + settingsFile = settingsFormat.generate "borgmatic-job-config-${name}" config.settings; + in { + options = { + settings = lib.mkOption { + type = settingsFormat.type; + description = '' + Configuration settings associated with the job. If this is set, the + generated output is added as an additional argument (i.e., `--config + SETTINGSFILE`) in the service script. + ''; + default = { }; + example = lib.literalExpression '' + { + source_directories = [ + config.xdg.userDirs.document + config.xdg.userDirs.download + config.xdg.userDirs.music + config.xdg.userDirs.video + ]; + + keep_daily = 5; + keep_weekly = 10; + keep_monthly = 20; + + repositories = lib.singleton { + path = "ssh://asodajdoiasjdoij"; + label = "remote"; + }; + } + ''; + }; + + startAt = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + Indicates how often backup will occur. This is to be used as value + for `Timer.OnCalendar=` in the systemd unit. See + {manpage}`systemd.time(7)` for more details. + ''; + default = "daily"; + example = "04:30"; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + List of arguments to be passed to the Borgmatic backup service. + ''; + default = [ ]; + example = lib.literalExpression '' + [ + "--stats" + "--verbosity" "1" + "--syslog-verbosity" "1" + "--list" + ] + ''; + }; + }; + + config = { + extraArgs = lib.mkMerge [ + cfg.extraArgs + + (lib.optionals (config.settings != {}) ( + lib.mkBefore [ + "--config" settingsFile + ] + )) + ]; + }; + }; + + formatUnitName = name: "borgmatic-job-${name}"; + mkBorgmaticServiceUnit = n: v: + lib.nameValuePair (formatUnitName n) { + Unit = { + Description = "Borgmatic backup job '${n}'"; + Documentation = [ + "https://torsion.org/borgmatic/docs/reference/configuration" + ]; + ConditionACPower = true; + }; + + Service = { + # TODO: Just cargo-culted from the upstream home-manager module. Will + # need more info on this. + Nice = 19; + CPUSchedulingPolicy = "batch"; + IOSchedulingClass = "best-effort"; + IOSchedulingPriority = 7; + IOWeight = 100; + + Restart = "on-failure"; + LogRateLimitIntervalSec = 0; + + ExecStart = '' + ${lib.getExe' cfg.package "borgmatic"} ${lib.concatStringsSep " " v.extraArgs} + ''; + + PrivateTmp = true; + }; + }; + + mkBorgmaticTimerUnit = n: v: + lib.nameValuePair (formatUnitName n) { + Unit.Description = "Borgmatic backup job '${n}'"; + + Timer = { + OnCalendar = v.startAt; + Persistent = lib.mkDefault true; + RandomizedDelaySec = lib.mkDefault "10m"; + }; + + Install.WantedBy = [ "timers.target" ]; + }; + + mkBorgmaticServiceFromConfig = n: v: + lib.nameValuePair "borgmatic-config-${n}" { + inherit (v.initService) startAt; + extraArgs = [ + "--config" "${config.xdg.configHome}/borgmatic.d/${n}" + ]; + }; +in +{ + disabledModules = [ "services/borgmatic.nix" ]; + options.programs.borgmatic.backups = lib.mkOption { + type = with lib.types; attrsOf (submodule borgmaticProgramModule); + }; + + options.services.borgmatic = { + package = lib.mkPackageOption pkgs "borgmatic" { }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + Global list of additional arguments for all of the jobs. + ''; + default = [ ]; + example = [ + "--stats" + "--verbosity" "1" + ]; + }; + + jobs = lib.mkOption { + type = with lib.types; attrsOf (submodule borgmaticJobModule); + default = { }; + example = lib.literalExpression '' + { + personal = { + startAt = "05:30"; + settings = { + source_directories = [ + "''${config.xdg.configHome}" + "''${config.xdg.userDirs.extraConfig.XDG_PROJECTS_DIR}" + "''${config.home.homeDirectory}/.thunderbird" + "''${config.home.homeDirectory}/Zotero" + ]; + + repositories = [ + { + path = "ssh://k8pDxu32@k8pDxu32.repo.borgbase.com/./repo"; + label = "borgbase"; + } + + { + path = "/var/lib/backups/local.borg"; + label = "local"; + } + ]; + + keep_daily = 7; + keep_weekly = 4; + keep_monthly = 6; + }; + }; + } + ''; + }; + }; + + config = { + systemd.user.services = + lib.mapAttrs' mkBorgmaticServiceUnit cfg.jobs; + + systemd.user.timers = + lib.mapAttrs' mkBorgmaticTimerUnit cfg.jobs; + + services.borgmatic.jobs = + let + validService = lib.filterAttrs (n: v: v.initService.enable) programCfg.backups; + in + lib.mapAttrs' mkBorgmaticServiceFromConfig validService; + }; +} diff --git a/modules/home-manager/services/gonic.nix b/modules/home-manager/services/gonic.nix new file mode 100644 index 00000000..d135a3ad --- /dev/null +++ b/modules/home-manager/services/gonic.nix @@ -0,0 +1,54 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.gonic; + + settingsFormat = pkgs.formats.keyValue { + mkKeyValue = lib.generators.mkKeyValueDefault { } " "; + listsAsDuplicateKeys = true; + }; + settingsFile = settingsFormat.generate "gonic-settings-config" cfg.settings; +in +{ + options.services.gonic = { + enable = lib.mkEnableOption "Gonic, a Subsonic-compatible music server"; + + package = lib.mkPackageOption pkgs "gonic" { }; + + settings = lib.mkOption { + type = settingsFormat.type; + default = { }; + description = '' + Configuration to be included to the service. + ''; + example = lib.literalExpression '' + { + music-path = [ config.xdg.userDirs.music ]; + podcast-path = [ "''${config.xdg.userDirs.music}/Podcasts" ]; + } + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.gonic" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.gonic = { + Unit = { + Description = "Gonic media server"; + Documentation = [ "https://github.com/sentriz/gonic/wiki" ]; + After = [ "network-online.target" ]; + }; + + Service = { + ExecStart = "${lib.getExe' cfg.package "gonic"} -config-path ${settingsFile}"; + Restart = "on-failure"; + }; + + Install.WantedBy = [ "default.target" ]; + }; + }; +} diff --git a/modules/home-manager/services/ludusavi.nix b/modules/home-manager/services/ludusavi.nix new file mode 100644 index 00000000..8fc2d62f --- /dev/null +++ b/modules/home-manager/services/ludusavi.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.ludusavi; + + settingsFormat = pkgs.formats.yaml { }; + + configFile = + if cfg.configFile == null then + settingsFormat.generate "ludusavi-service-config" cfg.settings + else + cfg.configFile; +in +{ + options.services.ludusavi = { + enable = lib.mkEnableOption "Ludusavi game backup"; + + package = lib.mkPackageOption pkgs "ludusavi" { }; + + settings = lib.mkOption { + type = settingsFormat.type; + description = '' + The configuration for the backup service. If + {option}`services.ludusavi.configFile` contains a non-null value, this + option is effectively ignored. + ''; + default = { }; + example = lib.literalExpression '' + { + manifest.url = "https://raw.githubusercontent.com/mtkennerly/ludusavi-manifest/master/data/manifest.yaml"; + backup.path = "''${config.xdg.cacheHome}/ludusavi/backups"; + restore.path = "''${config.xdg.cacheHome}/ludusavi/backups"; + } + ''; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + Extra arguments to be passed to the game backup service. + ''; + default = [ "--force" ]; + example = [ + "--force" + "--compression" "zstd" + "--compression-level" "13" + ]; + }; + + startAt = lib.mkOption { + type = lib.types.str; + description = '' + How often the backup occurs. + + The value is used to `Calendar.OnCalendar` systemd timer option. For + more details about the value format, see {manpage}`systemd.time(7)`. + ''; + default = "daily"; + example = "weekly"; + }; + + configFile = lib.mkOption { + type = with lib.types; nullOr path; + description = '' + The path of the configuration file to be used for the game backup + service. If this is set to `null`, it will generate one from + {option}`services.ludusavi.settings`. + ''; + default = null; + example = lib.literalExpression "./config/ludusavi/config.yaml"; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.ludusavi" pkgs lib.platforms.linux) + ]; + + systemd.user.services.ludusavi = { + Unit = { + Description = "Periodic game backup"; + Documentation = [ "https://github.com/mtkennerly/ludusavi" ]; + }; + + Service = { + ExecStart = "${lib.getExe' cfg.package "ludusavi"} --config ${configFile} backup ${lib.concatStringsSep " " cfg.extraArgs}"; + Restart = "on-failure"; + }; + }; + + systemd.user.timers.ludusavi = { + Unit.Description = "Periodic game backup"; + Timer = { + Persistent = true; + OnCalendar = cfg.startAt; + }; + Install.WantedBy = [ "timers.target" ]; + }; + }; +} diff --git a/modules/home-manager/services/matcha.nix b/modules/home-manager/services/matcha.nix index 72bed472..d68843b0 100644 --- a/modules/home-manager/services/matcha.nix +++ b/modules/home-manager/services/matcha.nix @@ -59,10 +59,10 @@ in Unit = { Description = "Matcha periodic feed digest generator"; Documentation = [ "https://github.com/piqoni/matcha" ]; + After = [ "network-online.target" ]; + Wants = [ "network-online.target" ]; }; - Install.WantedBy = [ "default.target" ]; - Service = { ExecStart = "${cfg.package}/bin/matcha -c ${settingsFile}"; Restart = "on-failure"; @@ -73,7 +73,6 @@ in Unit = { Description = "Matcha periodic feed digest generator"; Documentation = [ "https://github.com/piqoni/matcha" ]; - After = [ "network.target" ]; }; Install.WantedBy = [ "timers.target" ]; Timer = { diff --git a/modules/nixos/_private/default.nix b/modules/nixos/_private/default.nix index fefc498a..1a6103ca 100644 --- a/modules/nixos/_private/default.nix +++ b/modules/nixos/_private/default.nix @@ -1,7 +1,8 @@ { imports = [ ./extra-arguments.nix - ./state.nix + ./shared-setups/server + ./state ./suites/archiving.nix ./suites/browsers.nix ./suites/desktop.nix diff --git a/modules/nixos/_private/extra-arguments.nix b/modules/nixos/_private/extra-arguments.nix index 41ed0ebe..da8cb8bb 100644 --- a/modules/nixos/_private/extra-arguments.nix +++ b/modules/nixos/_private/extra-arguments.nix @@ -8,8 +8,8 @@ in { _module.args.foodogsquaredLib = foodogsquaredLib.extend (final: prev: { - nixos = import ../../../lib/nixos.nix { inherit pkgs lib; self = final; }; + nixos = import ../../../lib/env-specific/nixos.nix { inherit pkgs lib; self = final; }; } // lib.optionalAttrs (options?sops) { - sops-nix = import ../../../lib/sops.nix { inherit pkgs lib; self = final; }; + sops-nix = import ../../../lib/env-specific/sops.nix { inherit pkgs lib; self = final; }; }); } diff --git a/modules/nixos/_private/shared-setups/server/crowdsec.nix b/modules/nixos/_private/shared-setups/server/crowdsec.nix new file mode 100644 index 00000000..a4236d57 --- /dev/null +++ b/modules/nixos/_private/shared-setups/server/crowdsec.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.shared-setups.server.crowdsec; +in +{ + options.shared-setups.server.crowdsec.enable = + lib.mkEnableOption "typical Crowdsec setup for public-facing servers"; + + config = lib.mkIf cfg.enable { + services.crowdsec = { + enable = true; + settings = { + common = { + daemonize = false; + log_media = "stdout"; + }; + }; + + notificationPlugins = { + http = { + settings = { + type = "http"; + log_level = "info"; + }; + }; + }; + + dataSources = { + ssh = lib.mkIf config.services.sshd.enable { + source = "journalctl"; + journalctl_filter = [ + "_SYSTEMD_UNIT=ssh.service" + ]; + labels.type = "syslog"; + }; + }; + }; + }; +} diff --git a/modules/nixos/_private/shared-setups/server/default.nix b/modules/nixos/_private/shared-setups/server/default.nix new file mode 100644 index 00000000..c1ae41c4 --- /dev/null +++ b/modules/nixos/_private/shared-setups/server/default.nix @@ -0,0 +1,8 @@ +{ + imports = [ + ./crowdsec.nix + ./fail2ban.nix + ./firewall.nix + ./nginx.nix + ]; +} diff --git a/modules/nixos/_private/shared-setups/server/fail2ban.nix b/modules/nixos/_private/shared-setups/server/fail2ban.nix new file mode 100644 index 00000000..e8bd21f2 --- /dev/null +++ b/modules/nixos/_private/shared-setups/server/fail2ban.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.shared-setups.server.fail2ban; +in +{ + options.shared-setups.server.fail2ban.enable = + lib.mkEnableOption "typical fail2ban configuration for public-facing servers"; + + config = lib.mkIf cfg.enable { + services.fail2ban = { + enable = true; + bantime-increment = { + enable = true; + factor = "4"; + maxtime = "24h"; + overalljails = true; + }; + extraPackages = with pkgs; [ ipset ]; + + # We're going to be unforgiving with this one since we only have key + # authentication and password authentication is disabled anyways. + jails.sshd.settings = { + enabled = true; + maxretry = 1; + }; + }; + }; +} diff --git a/modules/nixos/_private/shared-setups/server/firewall.nix b/modules/nixos/_private/shared-setups/server/firewall.nix new file mode 100644 index 00000000..3c1e6b28 --- /dev/null +++ b/modules/nixos/_private/shared-setups/server/firewall.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.shared-setups.server.firewall; +in +{ + options.shared-setups.server.firewall.enable = lib.mkEnableOption "typical firewall setup"; + + config = lib.mkIf cfg.enable { + networking = { + nftables.enable = true; + firewall = { + enable = true; + allowedTCPPorts = [ + 22 # Secure Shells. + ]; + }; + }; + }; +} diff --git a/modules/nixos/_private/shared-setups/server/nginx.nix b/modules/nixos/_private/shared-setups/server/nginx.nix new file mode 100644 index 00000000..309d0812 --- /dev/null +++ b/modules/nixos/_private/shared-setups/server/nginx.nix @@ -0,0 +1,86 @@ +# The reverse proxy of choice. Logs should be rotated weekly. +{ config, lib, pkgs, ... }: + +let + cfg = config.shared-setups.server.nginx; +in +{ + options.shared-setups.server.nginx.enable = + lib.mkEnableOption "typical Nginx configuration for public-facing servers"; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + # The main server where it will tie all of the services in one neat little + # place. Take note, the virtual hosts definition are all in their respective + # modules. + services.nginx = { + enable = true; + enableReload = true; + + package = pkgs.nginxMainline; + + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + + # Some more server-sided compressions. + recommendedBrotliSettings = true; + recommendedGzipSettings = true; + recommendedZstdSettings = true; + + proxyCachePath.apps = { + enable = true; + keysZoneName = "apps"; + }; + + appendConfig = '' + worker_processes auto; + ''; + + # We're avoiding any service to be the default server especially that it + # could be used for enter a service with unencrypted HTTP. So we're setting + # up one with an unresponsive server response. + appendHttpConfig = '' + # https://docs.nginx.com/nginx/admin-guide/content-cache/content-caching/ + proxy_cache_min_uses 5; + proxy_cache_valid 200 302 10m; + proxy_cache_valid 404 1m; + proxy_no_cache $http_pragma $http_authorization; + + server { + listen 80 default_server; + listen [::]:80 default_server; + return 444; + } + ''; + + # This is defined for other services. + upstreams."nginx" = { + extraConfig = '' + zone services 64k; + ''; + servers = { + "localhost:80" = { }; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ + 80 # HTTP servers. + 443 # HTTPS servers. + ]; + + # Generate a DH parameters for nginx-specific security configurations. + security.dhparams.params.nginx.bits = 4096; + } + + (lib.mkIf config.services.fail2ban.enable { + # Some fail2ban policies to apply for nginx. + services.fail2ban.jails = { + nginx-http-auth.settings = { enabled = true; }; + nginx-botsearch.settings = { enabled = true; }; + nginx-bad-request.settings = { enabled = true; }; + }; + }) + ]); +} diff --git a/modules/nixos/_private/state.nix b/modules/nixos/_private/state.nix deleted file mode 100644 index 48b5fb13..00000000 --- a/modules/nixos/_private/state.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ lib, ... }: - -{ - options.state = lib.mkOption { - type = lib.types.submodule { - freeFormType = with lib.types; attrsOf anything; - default = { }; - }; - description = '' - A set of values referring to the system state for use in other parts of - the NixOS system. Useful for consistent values and referring to a single - source of truth for different parts (e.g., services, program) of the - system. - ''; - example = { - services = { - postgresql.directory = "/var/lib/postgresql"; - backup.ignoreDirectories = [ - "node_modules" - ".direnv" - ]; - }; - }; - }; -} diff --git a/modules/nixos/_private/state/default.nix b/modules/nixos/_private/state/default.nix new file mode 100644 index 00000000..b1080dc7 --- /dev/null +++ b/modules/nixos/_private/state/default.nix @@ -0,0 +1,34 @@ +{ lib, ... }: + +{ + imports = [ + ./paths.nix + ./ports.nix + ]; + + # We can basically dump everything that is supposed to hold values for the + # entire system. This entry module should contain NOTHING ELSE! + options.state = lib.mkOption { + type = lib.types.submodule { + freeformType = with lib.types; attrsOf anything; + default = { }; + }; + description = '' + A set of values referring to the system state for use in other parts of + the NixOS system. Useful for consistent values and referring to a single + source of truth for different parts (e.g., services, program) of the + system. + ''; + example = lib.literalExpression '' + { + services = { + postgresql.directory = "/var/lib/postgresql"; + backup.ignoreDirectories = [ + "node_modules" + ".direnv" + ]; + }; + } + ''; + }; +} diff --git a/modules/nixos/_private/state/paths.nix b/modules/nixos/_private/state/paths.nix new file mode 100644 index 00000000..5e25c377 --- /dev/null +++ b/modules/nixos/_private/state/paths.nix @@ -0,0 +1,25 @@ +{ lib, ... }: + +{ + options.state = + let + directoriesSubmodule = { lib, ... }: { + options = { + paths = lib.mkOption { + type = with lib.types; attrsOf (either path (listOf str)); + description = '' + A set of directories to share its value to various parts of the + system. + ''; + default = { }; + example = { + ignoreDirectories = [ "/var/log" ]; + ignoreFiles = [ "node_modules" ".gitignore" ".bak" ]; + }; + }; + }; + }; + in lib.mkOption { + type = lib.types.submodule directoriesSubmodule; + }; +} diff --git a/modules/nixos/_private/state/ports.nix b/modules/nixos/_private/state/ports.nix new file mode 100644 index 00000000..092e1544 --- /dev/null +++ b/modules/nixos/_private/state/ports.nix @@ -0,0 +1,108 @@ +{ config, lib, ... }: + +let + cfg = config.state; + + supportedProtocols = [ "tcp" "udp" ]; + + portRangeType = { + options = { + from = lib.mkOption { + type = lib.types.port; + description = '' + The start of the range of TCP/UDP ports to be taken over. + ''; + }; + + to = lib.mkOption { + type = lib.types.port; + description = '' + The end of the range of TCP/UDP ports to be taken over. + ''; + }; + }; + }; + + portModule = { lib, ... }: { + options = { + protocols = lib.mkOption { + type = with lib.types; listOf (enum supportedProtocols); + description = '' + Indicates the type of protocol of the service. + ''; + default = [ "tcp" "udp" ]; + example = [ "tcp" ]; + }; + + value = lib.mkOption { + type = with lib.types; either port (submodule portRangeType); + description = '' + The port number itself. + ''; + }; + + openFirewall = lib.mkEnableOption "opening the ports to firewall"; + }; + }; +in +{ + options.state = + let + portsModule = { lib, ... }: { + options = { + ports = lib.mkOption { + type = with lib.types; attrsOf (submodule portModule); + description = '' + A set of ports indicating what goes where in the NixOS system. + ''; + example = lib.literalExpression '' + rec { + gonic = { + value = 5757; + protocols = [ "tcp" ]; + openFirewall = true; + }; + uxplay = { + value = 7864; + openFirewall = true; + }; + uxplayClients.value = { + from = uxplay.value + 1; + to = uxplay.value + 20; + }; + } + ''; + }; + }; + }; + in lib.mkOption { + type = lib.types.submodule portsModule; + }; + + config = lib.mkIf (cfg.ports != { }) { + networking.firewall = + let + allPortsToBeOpened = lib.filterAttrs (_: v: v.openFirewall) cfg.ports; + hasProtocol = protocol: v: lib.elem protocol v.protocols; + mkFirewallEntry = protocol: v: + let + inherit (v) value; + in + if lib.isAttrs value then { + ${if protocol == "tcp" + then "allowedTCPPortRanges" + else "allowedUDPPortRanges"} = [ value ]; + } else { + ${if protocol == "tcp" + then "allowedTCPPorts" + else "allowedUDPPorts"} = [ value ]; + }; + + mkFirewallEntryModule = _: v: + lib.optionalAttrs (hasProtocol "udp" v) (mkFirewallEntry "udp" v) + // lib.optionalAttrs (hasProtocol "tcp" v) (mkFirewallEntry "tcp" v); + in + lib.mkMerge + (lib.mapAttrsToList mkFirewallEntryModule allPortsToBeOpened); + }; +} diff --git a/modules/nixos/_private/suites/desktop.nix b/modules/nixos/_private/suites/desktop.nix index 2bfa77bf..4205b0ae 100644 --- a/modules/nixos/_private/suites/desktop.nix +++ b/modules/nixos/_private/suites/desktop.nix @@ -1,7 +1,7 @@ # This is where extra desktop goodies can be found. # As a note, this is not where you set the aesthetics of your graphical sessions. # That can be found in the `themes` module. -{ config, lib, pkgs, options, ... }: +{ config, lib, pkgs, ... }: let cfg = config.suites.desktop; in { @@ -86,7 +86,7 @@ in { pipewire ]; in - commonLibs ++ xorgLibs ++ options.programs.nix-ld.libraries.default; + commonLibs ++ xorgLibs; }; environment.systemPackages = with pkgs; [ diff --git a/modules/nixos/_private/suites/dev.nix b/modules/nixos/_private/suites/dev.nix index b206a47c..92474881 100644 --- a/modules/nixos/_private/suites/dev.nix +++ b/modules/nixos/_private/suites/dev.nix @@ -72,6 +72,7 @@ in { bandwhich # Sniffing your packets. cachix # Compile no more by using someone's binary cache! direnv # The power of local development environment. + difftastic # Cracked version of diff. lazygit # Git interface for the lazy. lazydocker # Git interface for the lazy. fd # Oh nice, a more reliable `find`. @@ -90,7 +91,7 @@ in { ++ (lib.optionals config.programs.git.enable (with pkgs; [ tea # Make some Tea... hut # ...in the Hut... - github-cli # ...in the GitHub CLI. + github-cli # ...in the Git Hub... git-filter-repo # History is written by the victors (and force-pushers which are surely not victors). ])); diff --git a/modules/nixos/_private/suites/filesystem.nix b/modules/nixos/_private/suites/filesystem.nix index 5efeb511..e628b141 100644 --- a/modules/nixos/_private/suites/filesystem.nix +++ b/modules/nixos/_private/suites/filesystem.nix @@ -29,11 +29,14 @@ in # Installing filesystem debugging utilities. environment.systemPackages = with pkgs; [ afuse + ntfs3g ]; }) (lib.mkIf cfg.setups.archive.enable { - fileSystems."/mnt/archives" = { + state.paths.archive = "/mnt/archives"; + + fileSystems."${config.state.paths.archive}" = { device = "/dev/disk/by-partlabel/disk-archive-root"; fsType = "btrfs"; noCheck = true; @@ -56,7 +59,9 @@ in }) (lib.mkIf cfg.setups.external-hdd.enable { - fileSystems."/mnt/external-storage" = { + state.paths.external-hdd = "/mnt/external-storage"; + + fileSystems."${config.state.paths.external-hdd}" = { device = "/dev/disk/by-partlabel/disk-live-installer-root"; fsType = "btrfs"; noCheck = true; diff --git a/modules/nixos/_private/suites/i18n.nix b/modules/nixos/_private/suites/i18n.nix index 8de4a2da..454ea27d 100644 --- a/modules/nixos/_private/suites/i18n.nix +++ b/modules/nixos/_private/suites/i18n.nix @@ -10,12 +10,12 @@ in options.suites.i18n = { enable = lib.mkEnableOption "main i18n config"; setup = lib.mkOption { - type = lib.types.enum [ "fcitx5" "ibus" ]; + type = with lib.types; nullOr (enum [ "fcitx5" "ibus" ]); description = '' The primary input method engine to be used and its related configuration and setup. ''; - default = "fcitx5"; + default = null; example = "ibus"; }; }; diff --git a/modules/nixos/_private/workflows/README.adoc b/modules/nixos/_private/workflows/README.adoc index 33cbd05e..9eb329af 100644 --- a/modules/nixos/_private/workflows/README.adoc +++ b/modules/nixos/_private/workflows/README.adoc @@ -13,14 +13,13 @@ This is where modules will define how you're going to interact with the computer The following list is the summary which can also serve as a guideline to developing a workflow module. -* All workflow modules should be under `workflows.workflows.` namespace with an `enable` option. +* All workflow modules should be enabled through `workflows.enable` option containing the names of the workflows to be used.= -* Due to the bigger scope and importance of this module, there is a limit where you can only enable one theme at a time. -You can disable this with `config.workflows.disableLimit` set to `true`. +* While there is no convention for naming workflow modules, they are mostly expected to be enabled with a reverse DNS-like scheme (e.g., `workflows.enable = [ "one.foodogsquared.MoseyBranch" ]`). +This is mainly to easily create custom desktop sessions where they are typically named this way. -* Custom themes should be defined in `config.workflows.workflows` attribute (e.g., `options.workflows.workflows.a-happy-gnome`, `options.workflows.workflows.simple-way`). -This makes up for a namespace entirely dedicated for setting themes. +* Custom themes should be configured in `workflows.workflows` namespace (e.g., `options.workflows.workflows.a-happy-gnome`, `options.workflows.workflows.simple-way`). +This is expected to contain options specific for that workflow module such as an extra list of applications to be installed, additional extensions, and hardware-specific options. -* Using link:../profiles[profiles] are heavily discouraged and it is better assumed to design and create workflows as if profiles are not imported. -This is because profiles are not exported in the flake output. -If it's something you have to use (e.g., setting up i18n configuration), you have to conditionally set a profile as seen from link:../profiles/README.adoc[../profiles/README.adoc]. +* No configuring display managers or localization. +This is expected more to be configured by the user themselves and it makes the workflow modules more composable. diff --git a/modules/nixos/_private/workflows/a-happy-gnome/default.nix b/modules/nixos/_private/workflows/a-happy-gnome/default.nix index 06794452..3ffe655e 100644 --- a/modules/nixos/_private/workflows/a-happy-gnome/default.nix +++ b/modules/nixos/_private/workflows/a-happy-gnome/default.nix @@ -3,6 +3,11 @@ let workflowName = "a-happy-gnome"; cfg = config.workflows.workflows.${workflowName}; + + requiredApps = with pkgs; [ + # The application menu. + junction + ]; in { options.workflows.enable = lib.mkOption { @@ -40,7 +45,6 @@ in just-perfection ]; ''; - internal = true; }; extraApps = lib.mkOption { @@ -58,7 +62,7 @@ in gnome-decoder # Go with them QR codes. gnome-frog # Graphical OCR with Tesseract that I always wanted. gnome-solanum # Cute little matodor timers. - gnome.dconf-editor # A saner version of Windows registry. + dconf-editor # A saner version of Windows registry. gnome.gnome-boxes # Virtual machines, son. gnome.polari # Your gateway to one of the most hidden and cobweb-ridden parts of the internet. ;) gradience # Make it rain! @@ -80,12 +84,51 @@ in example = lib.literalExpression '' with pkgs; [ gnome.polari ]; ''; - internal = true; + }; + + disableSearchProviders = lib.mkOption { + type = with lib.types; listOf ( + coercedTo str (lib.removeSuffix ".desktop") str + ); + description = '' + A list of the application filenames (without the `.desktop` part) where + its GNOME Shell search provider is to be disabled. + + By default, it disables some of the search providers from the default + list of applications in + {option}`workflows.workflows.a-happy-gnome.extraApps`. + ''; + default = [ + "org.gnome.seahorse.Application" + "org.gnome.Photos" + "org.gnome.Epiphany" + "app.drey.Dialect" + "com.belmoussaoui.Authenticator" + ]; + apply = builtins.map (x: "${x}.desktop"); + }; + + disableNotifications = lib.mkOption { + type = with lib.types; listOf str; + description = '' + A list of identifiers of the application's notification to be disabled + within GNOME Shell. + + By default, it just list a few from the default value of + {option}`workflows.workflows.a-happy-gnome.extraApps`. + ''; + default = [ + "re-sonny-tangram" + "org-gnome-polari" + "io-github-hexchat" + "org-gnome-evolution-alarm-notify" + "thunderbird" + ]; }; }; config = lib.mkIf (lib.elem workflowName config.workflows.enable) { - # Enable GNOME and GDM. + # Enable GNOME. services.xserver = { enable = true; desktopManager.gnome.enable = true; @@ -113,6 +156,9 @@ in # Bring all of the dconf keyfiles in there. programs.dconf = { enable = true; + + # In this case, we're using the default user dconf profile which is the + # fallback for every dconf-using components. Pretty handy. profiles.user.databases = lib.singleton { # Get them keyfiles. keyfiles = [ ./config/dconf ]; @@ -120,13 +166,7 @@ in settings = lib.mkMerge [ { "org/gnome/desktop/search-providers" = { - disabled = [ - "org.gnome.seahorse.Application.desktop" - "org.gnome.Photos.desktop" - "org.gnome.Epiphany.desktop" - "app.drey.Dialect.desktop" - "com.belmoussaoui.Authenticator.desktop" - ]; + disabled = cfg.disableSearchProviders; }; "org/gnome/shell" = { enabled-extensions = builtins.map (p: p.extensionUuid) cfg.shellExtensions; @@ -135,19 +175,14 @@ in # Disable all of the messenger's notification (only the annoying # ones). - (lib.listToAttrs - (builtins.map - (app: - lib.nameValuePair - "org/gnome/desktop/notifications/application/${app}" - { show-banners = false; }) - [ - "re-sonny-tangram" - "org-gnome-polari" - "io-github-hexchat" - "org-gnome-evolution-alarm-notify" - "thunderbird" - ])) + (lib.pipe cfg.disableNotifications [ + (builtins.map (app: + lib.nameValuePair + "org/gnome/desktop/notifications/application/${app}" + { show-banners = false; })) + + lib.listToAttrs + ]) ]; }; }; @@ -167,9 +202,6 @@ in }; }; - environment.systemPackages = with pkgs; [ - # The application menu. - junction - ] ++ cfg.shellExtensions ++ cfg.extraApps; + environment.systemPackages = requiredApps ++ cfg.shellExtensions ++ cfg.extraApps; }; } diff --git a/modules/nixos/_private/workflows/default.nix b/modules/nixos/_private/workflows/default.nix index e9d87236..6a11779f 100644 --- a/modules/nixos/_private/workflows/default.nix +++ b/modules/nixos/_private/workflows/default.nix @@ -9,7 +9,22 @@ default = [ ]; description = '' A list of workflows to be enabled. + + Each workflow basically represents a way to interact with your computer + such as a typical complete desktop environment or a minimalistic desktop + featuring a standalone window manager with a custom status bar. + + While there's no set convention as to what each workflow should be, + workflows usually contain a complete graphical session configured inside + of it. A couple of exceptions are, for example, a complete standalone + tmux configuration where it can be used inside of a TTY or something like + that. ''; + example = [ + "a-happy-gnome" + "knome" + "horizontal-hunger" + ]; }; imports = [ diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 2876743d..2365b765 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -7,9 +7,13 @@ ./programs/sessiond ./programs/wezterm.nix ./services/archivebox.nix + ./services/crowdsec.nix + ./services/ctrld.nix ./services/gallery-dl.nix + ./services/uxplay.nix ./services/wezterm-mux-server.nix ./services/vouch-proxy.nix ./services/yt-dlp.nix + ./xdg/mime-desktop-specific.nix ]; } diff --git a/modules/nixos/profiles/desktop/audio.nix b/modules/nixos/profiles/desktop/audio.nix index 76802346..024c057f 100644 --- a/modules/nixos/profiles/desktop/audio.nix +++ b/modules/nixos/profiles/desktop/audio.nix @@ -21,6 +21,9 @@ }; # This is based from https://jackaudio.org/faq/linux_rt_config.html. + # + # Anyways, this enables several audio-related software requiring realtime + # scheduling to work such as Sonic Pi. security.pam.loginLimits = [ { domain = "@audio"; diff --git a/modules/nixos/profiles/desktop/fonts.nix b/modules/nixos/profiles/desktop/fonts.nix index af88c16f..021464d1 100644 --- a/modules/nixos/profiles/desktop/fonts.nix +++ b/modules/nixos/profiles/desktop/fonts.nix @@ -23,7 +23,7 @@ monaspace jetbrains-mono - # Noto font family + # Noto font family with the MR. WORLDWIDE settings. noto-fonts noto-fonts-cjk noto-fonts-cjk-sans diff --git a/modules/nixos/profiles/generic.nix b/modules/nixos/profiles/generic.nix index 0eb11395..f5b7c4a6 100644 --- a/modules/nixos/profiles/generic.nix +++ b/modules/nixos/profiles/generic.nix @@ -17,6 +17,9 @@ programs.command-not-found.enable = false; programs.nix-index.enable = true; + # Improve the state of documentation (even if it's just a bit out-of-date). + documentation.man.generateCaches = true; + # BOOOOOOOOOOOOO! Somebody give me a tomato! services.xserver.excludePackages = with pkgs; [ xterm ]; diff --git a/modules/nixos/profiles/hardened.nix b/modules/nixos/profiles/hardened.nix index f24d9c0b..c3d934b6 100644 --- a/modules/nixos/profiles/hardened.nix +++ b/modules/nixos/profiles/hardened.nix @@ -10,7 +10,8 @@ # Don't replace it mid-way! DON'T TURN LEFT!!!! security.protectKernelImage = true; - # Hardened config equals hardened kernel. + # Hardened config equals hardened kernel equals hardened co--approval from the + # security-minded people. boot.kernelPackages = lib.mkOverride 500 pkgs.linuxKernel.packages.linux_6_6_hardened; # Disable system console entirely. We don't need it so get rid of it. diff --git a/modules/nixos/profiles/headless.nix b/modules/nixos/profiles/headless.nix index 76debf05..27e2b839 100644 --- a/modules/nixos/profiles/headless.nix +++ b/modules/nixos/profiles/headless.nix @@ -8,13 +8,16 @@ "${modulesPath}/profiles/headless.nix" ]; - # So does sounds... + # Sounds? We don't need in this void world of OURS! sound.enable = lib.mkDefault false; - # ...and Bluetooth because it's so insecure. + # Bluetooth is so 2000s, my wireless earbuds are scratching all to hell. hardware.bluetooth.enable = lib.mkDefault false; - # And other devices... + # You can draw from your imagination instead. hardware.opentabletdriver.enable = lib.mkDefault false; + + # Printers? In our godforsaken headless setups. (Ok there are servers that + # handle this but you know...) services.printing.enable = lib.mkDefault false; } diff --git a/modules/nixos/profiles/installer.nix b/modules/nixos/profiles/installer.nix index 5e7e8b7d..cbc27413 100644 --- a/modules/nixos/profiles/installer.nix +++ b/modules/nixos/profiles/installer.nix @@ -1,6 +1,7 @@ # A dedicated profile for installers with some niceties in it. This is also -# used for persistent live installers. -{ pkgs, modulesPath, ... }: +# used for persistent live installers so you'll have to exclude setting up shop +# and do that in the respective NixOS configuration instead. +{ pkgs, lib, modulesPath, ... }: { imports = [ @@ -18,4 +19,8 @@ neovim zellij ]; + + # Yeah, that's right, this is also a Guix System installer because SCREW YOU, + # NIXOS USERS! + services.guix.enable = lib.mkDefault true; } diff --git a/modules/nixos/profiles/nix-conf.nix b/modules/nixos/profiles/nix-conf.nix index c4751fb0..15c6cd60 100644 --- a/modules/nixos/profiles/nix-conf.nix +++ b/modules/nixos/profiles/nix-conf.nix @@ -1,5 +1,4 @@ -{ lib, pkgs, ... }: { - +{ config, lib, pkgs, ... }: { # Set the package for generating the configuration. nix.package = lib.mkDefault pkgs.nixStable; @@ -21,11 +20,12 @@ # # Since we're using flakes to make this possible, we need it. Plus, the # UX of Nix CLI is becoming closer to Guix's which is a nice bonus. - experimental-features = [ "nix-command" "flakes" "repl-flake" ]; + experimental-features = + [ "nix-command" "flakes" ] + ++ lib.optionals (lib.versionOlder config.nix.package.version "2.22.0") [ "repl-flake" ]; auto-optimise-store = lib.mkDefault true; + + # We don't want to download every time we invoke Nix, seriously. Thanks. flake-registry = ""; }; - - # Stallman-senpai will be disappointed. - nixpkgs.config.allowUnfree = true; } diff --git a/modules/nixos/programs/gnome-session/default.nix b/modules/nixos/programs/gnome-session/default.nix index 6656c100..9159f10f 100644 --- a/modules/nixos/programs/gnome-session/default.nix +++ b/modules/nixos/programs/gnome-session/default.nix @@ -8,25 +8,49 @@ let cfg = config.programs.gnome-session; + # The gnome-session config files uses one from GLib. See the following link + # at for details about the + # keyfile formatting and possibly the Desktop Entry specification at + # . + glibKeyfileFormat = { + type = with lib.types; + let + valueType = oneOf [ + bool + float + int + str + (listOf valueType) + ] // { + description = "GLib keyfile atom (bool, int, float, string, or a list of the previous atoms)"; + }; + in + attrsOf (attrsOf valueType); + + generate = name: value: + pkgs.callPackage ({ writeText }: + writeText name (lib.generators.toDconfINI value)); + }; + # The bulk of the work. Pretty much the main purpose of this module. sessionPackages = lib.mapAttrsToList (_: session: let - gnomeSession = '' - [GNOME Session] - Name=${session.fullName} session - RequiredComponents=${lib.concatStringsSep ";" session.requiredComponents}; - ''; + gnomeSession = glibKeyfileFormat.generate "session-${session.name}" session.settings; + # For now, we set this as a static template since there's not much + # things to configure especially for a desktop session anyways. displaySession = '' [Desktop Entry] - Name=@fullName@ + Name=${session.fullName} Comment=${session.description} Exec="@out@/libexec/${session.name}-session" Type=Application - DesktopNames=${lib.concatStringsSep ";" session.desktopNames}; + DesktopNames=${lib.concatStringsSep ";" session.desktopNames} ''; + # Similarly to the desktop session template, this is also set as a + # static template. sessionScript = '' #!${pkgs.runtimeShell} @@ -39,61 +63,24 @@ let ${lib.getExe' cfg.package "gnome-session"} ${lib.escapeShellArgs session.extraArgs} ''; - displayScripts = - let - hasMoreDisplays = protocol: lib.optionalString (lib.length session.display > 1) "fullName='${session.fullName} (${protocol})'"; - in - { - wayland = '' - ( - DISPLAY_SESSION_FILE="$out/share/wayland-sessions/${session.name}.desktop" - install -Dm0644 "$displaySessionPath" "$DISPLAY_SESSION_FILE" - ${hasMoreDisplays "Wayland"} substituteAllInPlace "$DISPLAY_SESSION_FILE" - ) - ''; - x11 = '' - ( - DISPLAY_SESSION_FILE="$out/share/xsessions/${session.name}.desktop" - install -Dm0644 "$displaySessionPath" "$DISPLAY_SESSION_FILE" - ${hasMoreDisplays "X11"} substituteAllInPlace "$DISPLAY_SESSION_FILE" - ) - ''; - }; - - installDesktopSessions = builtins.map - (display: - displayScripts.${display}) - session.display; - - installDesktops = + installDesktopFiles = lib.mapAttrsToList (name: component: let - scriptName = "${session.name}-${component.name}-script"; - - # There's already a lot of bad bad things in this world, we - # don't to add more of it here (only a fraction of it, though). - scriptPackage = pkgs.writeShellApplication { - name = scriptName; - text = component.script; - }; - - script = "${scriptPackage}/bin/${scriptName}"; - desktopConfig = lib.mergeAttrs component.desktopConfig { exec = script; }; - desktopPackage = pkgs.makeDesktopItem desktopConfig; + desktopPackage = pkgs.makeDesktopItem component.desktopConfig; in '' install -Dm0644 ${desktopPackage}/share/applications/*.desktop -t $out/share/applications '') session.components; in - pkgs.runCommandLocal "${session.name}-desktop-session-files" + pkgs.runCommand "${session.name}-desktop-session-files" { env = { inherit (session) fullName; }; inherit displaySession gnomeSession sessionScript; - passAsFile = [ "displaySession" "gnomeSession" "sessionScript" ]; + passAsFile = [ "displaySession" "sessionScript" ]; passthru.providedSessions = [ session.name ]; } '' @@ -102,12 +89,13 @@ let substituteAllInPlace "$SESSION_SCRIPT" GNOME_SESSION_FILE="$out/share/gnome-session/sessions/${session.name}.session" - install -Dm0644 "$gnomeSessionPath" "$GNOME_SESSION_FILE" - substituteAllInPlace "$GNOME_SESSION_FILE" + install -Dm0644 "$gnomeSession" "$GNOME_SESSION_FILE" - ${lib.concatStringsSep "\n" installDesktopSessions} + DISPLAY_SESSION_FILE="$out/share/wayland-sessions/${session.name}.desktop" + install -Dm0644 "$displaySessionPath" "$DISPLAY_SESSION_FILE" + substituteAllInPlace "$DISPLAY_SESSION_FILE" - ${lib.concatStringsSep "\n" installDesktops} + ${lib.concatStringsSep "\n" installDesktopFiles} '' ) cfg.sessions; @@ -119,20 +107,20 @@ let pathToUnit serviceToUnit targetToUnit timerToUnit socketToUnit; mkSystemdUnits = name: component: { - "${component.id}.service" = serviceToUnit component.serviceUnit; - "${component.id}.target" = targetToUnit component.targetUnit; - } // lib.optionalAttrs (component.socketUnit != null) { - "${component.id}.socket" = socketToUnit component.socketUnit; - } // lib.optionalAttrs (component.timerUnit != null) { - "${component.id}.timer" = timerToUnit component.timerUnit; - } // lib.optionalAttrs (component.pathUnit != null) { - "${component.id}.path" = pathToUnit component.pathUnit; + "${component.id}.service" = serviceToUnit component.systemd.serviceUnit; + "${component.id}.target" = targetToUnit component.systemd.targetUnit; + } // lib.optionalAttrs (component.systemd.socketUnit != null) { + "${component.id}.socket" = socketToUnit component.systemd.socketUnit; + } // lib.optionalAttrs (component.systemd.timerUnit != null) { + "${component.id}.timer" = timerToUnit component.systemd.timerUnit; + } // lib.optionalAttrs (component.systemd.pathUnit != null) { + "${component.id}.path" = pathToUnit component.systemd.pathUnit; }; componentsUnits = lib.concatMapAttrs mkSystemdUnits session.components; in componentsUnits // { - "gnome-session@${session.name}.target" = targetToUnit session.targetUnit; + "gnome-session@${session.name}.target" = targetToUnit session.systemd.targetUnit; } ) cfg.sessions; @@ -152,8 +140,9 @@ in sessions = lib.mkOption { type = with lib.types; attrsOf (submoduleWith { - specialArgs = { inherit utils; }; + specialArgs = { inherit utils glibKeyfileFormat pkgs; }; modules = [ ./submodules/session-type.nix ]; + shorthandOnlyDefinesConfig = true; }); description = '' A set of desktop sessions to be created with diff --git a/modules/nixos/programs/gnome-session/submodules/component-type.nix b/modules/nixos/programs/gnome-session/submodules/component-type.nix index 9af0b3b5..dd5dbbc5 100644 --- a/modules/nixos/programs/gnome-session/submodules/component-type.nix +++ b/modules/nixos/programs/gnome-session/submodules/component-type.nix @@ -1,10 +1,13 @@ -{ name, config, lib, utils, session, ... }: +{ name, config, pkgs, lib, utils, session, ... }: let - optionalSystemdUnitOption = type: systemdModuleAttribute: + optionalSystemdUnitOption = { + unitType, systemdModuleAttribute, otherType, + }: lib.mkOption { + type = lib.types.nullOr otherType; description = '' - An optional systemd ${type} configuration to be generated. This should + An optional systemd ${unitType} configuration to be generated. This should be configured if the session is managed by systemd. :::{.note} @@ -14,6 +17,7 @@ let `restartTriggers`. ::: ''; + visible = "shallow"; default = null; }; in @@ -29,14 +33,22 @@ in description = lib.mkOption { type = lib.types.nonEmptyStr; description = "One-sentence description of the component."; + default = name; example = "Desktop widgets"; }; script = lib.mkOption { type = lib.types.lines; description = '' - Shell script fragment of the component. Take note this will be - wrapped in a script for proper integration with `gnome-session`. + Shell script fragment of the component. + + The way it is handled is different per startup methods. + + * This will be wrapped in a script for proper integration with the + legacy non-systemd session management. + + * For systemd-managed sessions, it will be part of + {option}`programs.gnome-session.sessions..components..serviceUnit.script`. ''; }; @@ -64,104 +76,114 @@ in }; }; - # Most of the systemd config types are trying to eliminate as much of the - # NixOS systemd extensions as much as possible. For more details, see - # `config` attribute of the `sessionType`. - serviceUnit = lib.mkOption { - type = - let - inherit (utils.systemdUtils.lib) unitConfig serviceConfig; - inherit (utils.systemdUtils.unitOptions) commonUnitOptions serviceOptions; - in - lib.types.submodule [ - commonUnitOptions - serviceOptions - serviceConfig - unitConfig - ]; - description = '' - systemd service configuration to be generated. This should be - configured if the session is managed by systemd. + systemd = { + # Most of the systemd config types are trying to eliminate as much of the + # NixOS systemd extensions as much as possible. For more details, see + # `config` attribute of the `sessionType`. + serviceUnit = lib.mkOption { + type = + let + inherit (utils.systemdUtils.lib) unitConfig serviceConfig; + inherit (utils.systemdUtils.unitOptions) commonUnitOptions serviceOptions; + in + lib.types.submodule [ + commonUnitOptions + serviceOptions + serviceConfig + unitConfig + ]; + description = '' + systemd service configuration to be generated. This should be + configured if the session is managed by systemd. - :::{.note} - This has the same options as {option}`systemd.user.services.` - but without certain options from stage 2 counterparts such as - `reloadTriggers` and `restartTriggers`. + :::{.note} + This has the same options as {option}`systemd.user.services.` + but without certain options from stage 2 counterparts such as + `reloadTriggers` and `restartTriggers`. - By default, this module sets the service unit as part of the respective - target unit (i.e., `PartOf=$COMPONENTID.target`). + By default, this module sets the service unit as part of the respective + target unit (i.e., `PartOf=$COMPONENTID.target`). - On a typical case, you shouldn't mess with much of the dependency - ordering of the service unit. You should configure `targetUnit` for - that instead. - ::: - ''; - default = { }; - }; + On a typical case, you shouldn't mess with much of the dependency + ordering of the service unit. You should configure `targetUnit` for + that instead. + ::: + ''; + default = { }; + visible = "shallow"; + }; - targetUnit = lib.mkOption { - type = - let - inherit (utils.systemdUtils.lib) unitConfig; - inherit (utils.systemdUtils.unitOptions) commonUnitOptions; - in - lib.types.submodule [ - commonUnitOptions - unitConfig - ]; - description = '' - systemd target configuration to be generated. This should be - configured if the session is managed by systemd. + targetUnit = lib.mkOption { + type = + let + inherit (utils.systemdUtils.lib) unitConfig; + inherit (utils.systemdUtils.unitOptions) commonUnitOptions; + in + lib.types.submodule [ + commonUnitOptions + unitConfig + ]; + description = '' + systemd target configuration to be generated. This should be + configured if the session is managed by systemd. - :::{.note} - This has the same options as {option}`systemd.user.targets.` - but without certain options from stage 2 counterparts such as - `reloadTriggers` and `restartTriggers`. + :::{.note} + This has the same options as {option}`systemd.user.targets.` + but without certain options from stage 2 counterparts such as + `reloadTriggers` and `restartTriggers`. - This module doesn't set the typical dependency ordering relative to - gnome-session targets. This is on the user to manually set them. - ::: - ''; - default = { }; - }; + This module doesn't set the typical dependency ordering relative to + gnome-session targets. This is on the user to manually set them. + ::: + ''; + default = { }; + visible = "shallow"; + }; - timerUnit = optionalSystemdUnitOption "timer" "timers" // { - type = - let - inherit (utils.systemdUtils.unitOptions) timerOptions commonUnitOptions; - inherit (utils.systemdUtils.lib) unitConfig; - in - with lib.types; nullOr (submodule [ - commonUnitOptions - timerOptions - unitConfig - ]); - }; + timerUnit = optionalSystemdUnitOption { + unitType = "timer"; + systemdModuleAttribute = "timers"; + otherType = + let + inherit (utils.systemdUtils.unitOptions) timerOptions commonUnitOptions; + inherit (utils.systemdUtils.lib) unitConfig; + in + lib.types.submodule [ + commonUnitOptions + timerOptions + unitConfig + ]; + }; - socketUnit = optionalSystemdUnitOption "socket" "sockets" // { - type = - let - inherit (utils.systemdUtils.unitOptions) socketOptions commonUnitOptions; - inherit (utils.systemdUtils.lib) unitConfig; - in - with lib.types; nullOr (submodule [ - commonUnitOptions - socketOptions - unitConfig - ]); - }; + socketUnit = optionalSystemdUnitOption { + unitType = "socket"; + systemdModuleAttribute = "sockets"; + otherType = + let + inherit (utils.systemdUtils.unitOptions) socketOptions commonUnitOptions; + inherit (utils.systemdUtils.lib) unitConfig; + in + lib.types.submodule [ + commonUnitOptions + socketOptions + unitConfig + ]; + }; - pathUnit = optionalSystemdUnitOption "path" "paths" // { - type = - let - inherit (utils.systemdUtils.unitOptions) pathOptions commonUnitOptions; - inherit (utils.systemdUtils.lib) unitConfig; - in - with lib.types; nullOr (submodule [ - commonUnitOptions - pathOptions - unitConfig - ]); + pathUnit = optionalSystemdUnitOption { + unitType = "path"; + systemdModuleAttribute = "paths"; + otherType = + let + inherit (utils.systemdUtils.unitOptions) pathOptions commonUnitOptions; + inherit (utils.systemdUtils.lib) unitConfig; + in + lib.types.submodule [ + commonUnitOptions + pathOptions + unitConfig + ]; + }; }; id = lib.mkOption { @@ -182,6 +204,7 @@ in desktopConfig = { name = lib.mkForce config.id; desktopName = lib.mkDefault "${session.fullName} - ${config.description}"; + exec = lib.mkDefault (pkgs.writeShellScript "${session.name}-${config.name}-script" config.script); noDisplay = lib.mkForce true; onlyShowIn = session.desktopNames; @@ -213,7 +236,6 @@ in NixOS-module-generated gnome-session sessions so we're not bothering with those. - TODO: Is `Type=notify` a good default? * `Service.Type=` is obviously not included since not all desktop components are the same either. Some of them could be a D-Bus service, some of them are oneshots, etc. Though, it might be better to have this @@ -224,7 +246,7 @@ in systemd user unit, much of them are unnecessary and rarely needed (if ever like `Service.PrivateTmp=`?) so we didn't set such defaults here. */ - serviceUnit = { + systemd.serviceUnit = { script = lib.mkAfter config.script; description = lib.mkDefault config.description; @@ -271,7 +293,7 @@ in likely for a user to design their own desktop session with full control so it would be better for these options to be empty for less confusion. */ - targetUnit = { + systemd.targetUnit = { # This should be the dependency-related directive to be configured. The # rest is for the user to judge. wants = [ "${config.id}.service" ]; diff --git a/modules/nixos/programs/gnome-session/submodules/session-type.nix b/modules/nixos/programs/gnome-session/submodules/session-type.nix index fa4c5e46..93a85e24 100644 --- a/modules/nixos/programs/gnome-session/submodules/session-type.nix +++ b/modules/nixos/programs/gnome-session/submodules/session-type.nix @@ -1,4 +1,4 @@ -{ name, config, lib, utils, ... }: +{ name, config, pkgs, lib, utils, glibKeyfileFormat, ... }: let # For an updated list, see `menu/menu-spec.xml` from @@ -78,16 +78,6 @@ in example = [ "GNOME" "Garden" ]; }; - display = lib.mkOption { - type = with lib.types; listOf (enum [ "wayland" "x11" ]); - description = '' - A list of display server protocols supported by the desktop - environment. - ''; - default = [ "wayland" ]; - example = [ "wayland" "x11" ]; - }; - description = lib.mkOption { type = lib.types.nonEmptyStr; description = '' @@ -101,13 +91,14 @@ in components = lib.mkOption { type = with lib.types; attrsOf (submoduleWith { specialArgs = { - inherit utils; + inherit utils pkgs; session = { inherit (config) fullName desktopNames description; inherit name; }; }; modules = [ ./component-type.nix ]; + shorthandOnlyDefinesConfig = true; }); description = '' The individual components to be launched with the desktop session. @@ -132,7 +123,7 @@ in extraArgs = lib.mkOption { type = with lib.types; listOf str; description = '' - A list of arguments from {program}`gnome-session` to be added for the session + A list of arguments from {command}`gnome-session` to be added for the session script. ::: {.note} @@ -146,6 +137,28 @@ in ]; }; + settings = lib.mkOption { + type = glibKeyfileFormat.type; + description = '' + Settings to be included to the gnome-session keyfile of the session. + + Generally, you won't need to set this since the module will set the + common settings such as the `RequiredComponents=` key. + ''; + default = { }; + example = lib.literalExpression '' + { + "GNOME Session" = { + # A helper script to check if the session is runnable. + IsRunnableHelper = "''${lib.getExe' pkgs.niri "niri"} --validate config"; + + # A fallback session in case it failed. + FallbackSession = "gnome"; + }; + } + ''; + }; + requiredComponents = lib.mkOption { type = with lib.types; listOf str; description = '' @@ -162,6 +175,7 @@ in customized version of GNOME. ::: ''; + default = lib.mapAttrsToList (_: component: component.id) config.components; example = [ "org.gnome.Shell" "org.gnome.SettingsDaemon.A11ySettings" @@ -170,39 +184,42 @@ in ]; }; - targetUnit = lib.mkOption { - type = - let - inherit (utils.systemdUtils.lib) unitConfig; - inherit (utils.systemdUtils.unitOptions) commonUnitOptions; - in - lib.types.submodule [ - commonUnitOptions - unitConfig - ]; - description = '' - systemd target configuration to be generated for - `gnome-session@.target`. This should be configured if the - session is managed by systemd and you want to control the session - further (which is recommended since this module don't know what - components are more important, etc.). + systemd = { + targetUnit = lib.mkOption { + type = + let + inherit (utils.systemdUtils.lib) unitConfig; + inherit (utils.systemdUtils.unitOptions) commonUnitOptions; + in + lib.types.submodule [ + commonUnitOptions + unitConfig + ]; + description = '' + systemd target configuration to be generated for + `gnome-session@.target`. This should be configured if the + session is managed by systemd and you want to control the session + further (which is recommended since this module don't know what + components are more important, etc.). - By default, the session target will have all of its components from - {option}`.requiredComponents` under `Wants=` directive. It - also assumes all of them have a target unit at - `''${requiredComponent}.target`. + By default, the session target will have all of its components from + {option}`.requiredComponents` under `Wants=` directive. It + also assumes all of them have a target unit at + `''${requiredComponent}.target`. - :::{.note} - This has the same options as {option}`systemd.user.targets.` - but without certain options from stage 2 counterparts such as - `reloadTriggers` and `restartTriggers`. - ::: - ''; - defaultText = '' - { - wants = ... # All of the required components as a target unit. - } - ''; + :::{.note} + This has the same options as {option}`systemd.user.targets.` + but without certain options from stage 2 counterparts such as + `reloadTriggers` and `restartTriggers`. + ::: + ''; + visible = "shallow"; + defaultText = '' + { + wants = ... # All of the required components as a target unit. + } + ''; + }; }; }; @@ -210,13 +227,14 @@ in # Append the session argument. extraArgs = [ "--session=${name}" ]; - # By default. set the required components from the given desktop - # components. - requiredComponents = lib.mapAttrsToList (_: component: component.id) config.components; - - targetUnit = { + systemd.targetUnit = { overrideStrategy = lib.mkForce "asDropin"; wants = lib.mkDefault (builtins.map (c: "${c}.target") config.requiredComponents); }; + + settings."GNOME Session" = { + Name = lib.mkDefault "${config.fullName} session"; + RequiredComponents = config.requiredComponents; + }; }; } diff --git a/modules/nixos/programs/sessiond/submodules/component-type.nix b/modules/nixos/programs/sessiond/submodules/component-type.nix index b4285281..297de0f7 100644 --- a/modules/nixos/programs/sessiond/submodules/component-type.nix +++ b/modules/nixos/programs/sessiond/submodules/component-type.nix @@ -13,6 +13,7 @@ let `restartTriggers`. ::: ''; + visible = "shallow"; default = null; }; in @@ -61,6 +62,7 @@ in service unit. You should configure `targetUnit` for that instead. ::: ''; + visible = "shallow"; }; targetUnit = lib.mkOption { @@ -84,6 +86,7 @@ in `reloadTriggers` and `restartTriggers`. ::: ''; + visible = "shallow"; }; timerUnit = optionalSystemdUnitOption "timer" "timers" // { diff --git a/modules/nixos/programs/sessiond/submodules/session-type.nix b/modules/nixos/programs/sessiond/submodules/session-type.nix index 9406c73e..beb1c000 100644 --- a/modules/nixos/programs/sessiond/submodules/session-type.nix +++ b/modules/nixos/programs/sessiond/submodules/session-type.nix @@ -159,6 +159,8 @@ in `reloadTriggers` and `restartTriggers`. ::: ''; + visible = "shallow"; + default = { }; defaultText = '' { wants = ... # All of the required components as a target unit. @@ -178,6 +180,8 @@ in serviceConfig unitConfig ]; + default = { }; + visible = "shallow"; description = '' systemd service configuration to be generated for the sessiond session itself. @@ -200,9 +204,10 @@ in extraArgs = lib.mkOption { type = with lib.types; listOf str; description = '' - A list of arguments from {program}`sessiond` to be added for the session + A list of arguments from {command}`sessiond` to be added for the session script. ''; + default = [ ]; example = lib.literalExpression '' [ "--hooksd=''${./config/sessiond/hooks.d}" diff --git a/modules/nixos/services/archivebox.nix b/modules/nixos/services/archivebox.nix index 11424f8d..6b64b1c5 100644 --- a/modules/nixos/services/archivebox.nix +++ b/modules/nixos/services/archivebox.nix @@ -46,7 +46,8 @@ let (jobUnitName name) { description = "Archivebox download group '${name}'"; - after = [ "network.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; documentation = [ "https://docs.archivebox.io/" ]; preStart = '' mkdir -p ${lib.escapeShellArg cfg.archivePath} @@ -151,6 +152,9 @@ in curl yt-dlp ] ++ lib.optional config.programs.git.enable config.programs.git.package; + defaultText = '' + Chromium, NodeJS, wget, yt-dlp, and git if enabled. + ''; example = lib.literalExpression '' with pkgs; [ curl @@ -186,14 +190,15 @@ in (lib.mkIf cfg.webserver.enable { systemd.services.archivebox-server = { description = "Archivebox web server"; - after = [ "network.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; documentation = [ "https://docs.archivebox.io/" ]; wantedBy = [ "graphical-session.target" ]; serviceConfig = { User = "archivebox"; Group = "archivebox"; - ExecStart = "${pkgs.archivebox}/bin/archivebox server localhost:${ + ExecStart = "${lib.getExe' cfg.package "archivebox"} server localhost:${ toString cfg.webserver.port }"; diff --git a/modules/nixos/services/crowdsec.nix b/modules/nixos/services/crowdsec.nix new file mode 100644 index 00000000..bcb22bde --- /dev/null +++ b/modules/nixos/services/crowdsec.nix @@ -0,0 +1,269 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.crowdsec; + + settingsFormat = pkgs.formats.yaml { }; + + settingsSubmodule = { lib, ... }: { + freeformType = settingsFormat.type; + options.config_paths = { + notification_dir = lib.mkOption { + type = lib.types.path; + description = '' + Directory where configuration files of notification plugins are kept. + ''; + default = pluginsConfigDrv; + defaultText = '' + All of the compiled configuration files from + {option}`services.crowdsec.plugins..settings`. + ''; + example = "./config/crowdsec/plugins"; + }; + + plugin_dir = lib.mkOption { + type = lib.types.path; + description = '' + Directory where plugin executables are kept. + ''; + default = pluginsDir; + defaultText = '' + All of the compiled plugins from + {options}`services.crowdsec.notificationPlugins..package`. + ''; + }; + }; + + options.crowdsec_service = { + acqusition_dir = lib.mkOption { + type = lib.types.path; + description = '' + Directory containing acqusition configurations. + ''; + default = acqusitionsDir; + defaultText = '' + All of the compiled configuration from + {options}`services.crowdsec.acqusitions..settings`. + ''; + example = "./config/crowdsec/acqusitions"; + }; + }; + }; + + pluginsDir = pkgs.symlinkJoin { + name = "crowdsec-system-notification-plugins"; + paths = + let + plugins = lib.filterAttrs (n: v: v.package != null) cfg.notificationPlugins; + in + lib.mapAttrsToList (n: v: "${v.package}/share/crowdsec") plugins; + }; + + pluginsConfigDrv = let + pluginsConfigs = + lib.mapAttrsToList + (n: v: settingsFormat.generate "crowdsec-system-plugin-config-${n}" v.settings) + cfg.notificationPlugins; + in pkgs.symlinkJoin { + name = "crowdsec-system-notification-plugins-configs"; + paths = pluginsConfigs; + }; + + acqusitionsDir = let + acqusitionConfigs = + lib.mapAttrsToList + (n: v: settingsFormat.generate "crowdsec-system-acqusition-config-${n}" v.settings) + cfg.dataSources; + in pkgs.symlinkJoin { + name = "crowdsec-system-acqusitions-configs"; + paths = acqusitionConfigs; + }; + + crowdsecPluginsModule = { name, config, ... }: { + options = { + settings = lib.mkOption { + type = settingsFormat.type; + description = '' + Configuration settings associated with the plugin. + + ::: {.caution} + This setting is effectively ignored if + {option}`services.crowdsec.settings.config_paths.notification_dir` is + set. + ::: + ''; + default = { }; + example = { + type = "http"; + log_level = "info"; + }; + }; + + package = lib.mkOption { + type = with lib.types; nullOr package; + description = '' + Derivation containing a Crowdsec plugin at `$out/share/crowdsec`. + ''; + default = null; + example = lib.literalExpression "pkgs.crowdsec-slack-notification"; + }; + }; + }; + + acqusitionsSubmodule = { name, config, ... }: { + options.settings = lib.mkOption { + type = settingsFormat.type; + description = '' + Configuration associated with each data source. + ''; + default = { }; + example = { + source = "journalctl"; + journalctl_filter = [ + "_SYSTEMD_UNIT=ssh.service" + ]; + }; + }; + }; + + configFile = settingsFormat.generate "crowdsec-config" cfg.settings; +in +{ + options.services.crowdsec = { + enable = lib.mkEnableOption "[Crowdsec](https://crowdsec.net), a monitoring service using crowdsourced data"; + + package = lib.mkPackageOption pkgs "crowdsec" { }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + Extra arguments to be passed to the Crowdsec service. + ''; + default = [ ]; + example = [ "-warning" ]; + }; + + settings = lib.mkOption { + type = lib.types.submodule settingsSubmodule; + description = '' + Configuration settings to be used with the service. + ''; + default = { }; + example = lib.literalExpression '' + { + common = { + daemonize = false; + log_media = "stdout"; + } + } + ''; + }; + + notificationPlugins = lib.mkOption { + type = with lib.types; attrsOf (submodule crowdsecPluginsModule); + description = '' + Set of Crowdsec notification plugins and their configuration (if + given). + ''; + default = { }; + example = lib.literalExpression '' + { + http = { + settings = { + type = "http"; + log_level = "info"; + }; + }; + + slack = { + package = pkgs.crowdsec-slack-notification; + settings = { + type = ""; + log_level = "info"; + }; + }; + } + ''; + }; + + dataSources = lib.mkOption { + type = with lib.types; attrsOf (submodule acqusitionsSubmodule); + description = '' + Set of data sources where logs are to be analyzed from. + + ::: {.caution} + This is to be included as part of the default acqusition configuration + directory. + + If {option}`services.crowdsec.settings.crowdsec_agent.acqusition_dir` + is set by the user, this option is effectively ignored. + ::: + ''; + default = { }; + example = { + ssh = { + source = "journalctl"; + journalctl_filter = [ + "_SYSTEMD_UNIT=ssh.service" + ]; + labels.type = "syslog"; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.crowdsec = { + description = "Crowdsec monitoring server"; + script = '' + ${lib.getExe' cfg.package "crowdsec"} -c ${configFile} ${lib.escapeShellArgs cfg.extraArgs} + ''; + after = [ + "syslog.target" + "network-online.target" + "remote-fs.target" + "nss-lookup.target" + ]; + wants = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ReadWritePaths = + lib.optionals (cfg.settings.common.log_media or "" == "file") [ + cfg.settings.common.log_folder + ]; + + Type = "notify"; + Restart = "always"; + RestartSec = "60"; + + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + PrivateMounts = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + RemoveIPC = true; + StandardOutput = "journal"; + StandardError = "journal"; + SystemCallFilter = "@system-service"; + SystemCallErrorNumber = "EPERM"; + + RestrictAddressFamilies = [ + "AF_LOCAL" + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictSUIDGUID = true; + MemoryDenyWriteExecute = true; + }; + }; + }; +} diff --git a/modules/nixos/services/ctrld.nix b/modules/nixos/services/ctrld.nix new file mode 100644 index 00000000..5df489ab --- /dev/null +++ b/modules/nixos/services/ctrld.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.ctrld; + + settingsFormat = pkgs.formats.toml { }; + settingsFile = settingsFile.generate "ctrld-proxy-settings" cfg.settings; +in +{ + options.services.ctrld = { + enable = lib.mkEnableOption "ctrld, a DNS forwarding proxy"; + package = lib.mkPackageOption pkgs "ctrld" { }; + + settings = lib.mkOption { + type = settingsFormat.type; + description = '' + Settings to be used for the ctrld server. + ''; + default = { }; + example = lib.literalExpression '' + { + service = { + log_level = "info"; + log_path = ""; + cache_enable = true; + cache_size = 4096; + cache_ttl_override = 60; + cache_serve_stale = true; + }; + + "upstream.0" = { + bootstrap_ip = "76.76.2.11"; + endpoint = "https://freedns.controld.com/p1"; + name = "Control D - Anti-Malware"; + timeout = 5000; + type = "doh"; + ip_stack = "both"; + }; + + "network.0" = { + cidrs = ["0.0.0.0/0"]; + name = "Everyone"; + }; + } + ''; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.ctrld = { + description = "Forwarding DNS proxy"; + script = '' + ${lib.getExe' cfg.package "ctrld"} run --config ${settingsFile} + ''; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + wantedBy = [ "default.target" ]; + + serviceConfig = { + User = "ctrld"; + Group = "ctrld"; + DynamicUser = true; + + Restart = "on-failure"; + LockPersonality = true; + NoNewPrivileges = true; + + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; + + # TODO: ProtectProc=? + PrivateDevices = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "full"; + RestrictAddressFamilies = [ + "AF_LOCAL" + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + SystemCallArchitectures = [ "native" ]; + SystemCallFilter = [ "@system-service" ]; + }; + }; + }; +} diff --git a/modules/nixos/services/gallery-dl.nix b/modules/nixos/services/gallery-dl.nix index a500f725..a2128713 100644 --- a/modules/nixos/services/gallery-dl.nix +++ b/modules/nixos/services/gallery-dl.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, options, ... }: let cfg = config.services.gallery-dl; @@ -9,7 +9,7 @@ let settingsFormatFile = settingsFormat.generate "gallery-dl-service-config" cfg.settings; - jobType = { name, config, options, ... }: { + jobType = { name, config, ... }: { options = { urls = lib.mkOption { type = with lib.types; listOf str; @@ -37,6 +37,10 @@ let example = "*-*-3/4"; }; + downloadPath = options.services.gallery-dl.downloadPath // { + default = cfg.downloadPath; + }; + extraArgs = lib.mkOption { type = with lib.types; listOf str; description = '' @@ -52,19 +56,19 @@ let ''; }; - settings = lib.mkOption { - type = settingsFormat.type; + settings = options.services.gallery-dl.settings // { description = '' - Job-specific settings to be overridden to the service-wide settings. + Job-specific settings to be overridden to the service-wide settings + (if there's any). ''; default = { }; - example = lib.literalExpression '' - { - extractor.directory = [ "{category}" "{user|artist|uploader}" ]; - } - ''; }; }; + + config = { + extraArgs = cfg.extraArgs; + settings = cfg.settings; + }; }; in { @@ -79,13 +83,13 @@ in defaultText = lib.literalExpression "pkgs.gallery-dl"; }; - archivePath = lib.mkOption { + downloadPath = lib.mkOption { type = lib.types.str; description = '' - The location of the archive to be downloaded. Take note it is assumed - to be created at the time of running the service. Should be an absolute - path. + The default download path of the entire jobset (which can easily be + overriden). ''; + default = "/var/gallery-dl"; example = "/var/archives/gallery-dl-service"; }; @@ -100,14 +104,16 @@ in example = lib.literalExpression '' { cache.file = "~/.gallery-dl-cache.sqlite3"; + extractor.directory = [ "{category}" "{user|artist|uploader}" ]; } ''; }; extraArgs = lib.mkOption { type = with lib.types; listOf str; - description = - "List of arguments to be passed to {command}`gallery-dl`."; + description = '' + Global list of arguments to be passed to each gallery-dl download jobs. + ''; default = [ ]; example = lib.literalExpression '' [ @@ -153,7 +159,7 @@ in enable = true; path = with pkgs; [ brotli ffmpeg cfg.package ]; preStart = '' - mkdir -p ${lib.escapeShellArg cfg.archivePath} + mkdir -p ${lib.escapeShellArg value.downloadPath} ''; # Order matters here. We're letting service-level arguments and @@ -172,13 +178,10 @@ in value.settings; in '' - gallery-dl ${lib.escapeShellArgs cfg.extraArgs} ${ - lib.optionalString (cfg.settings != null) - "--config ${settingsFormatFile}" - } ${lib.escapeShellArgs value.extraArgs} ${ + gallery-dl ${lib.escapeShellArgs value.extraArgs} ${ lib.optionalString (value.settings != null) "--config ${jobLevelSettingsFile}" - } --destination ${lib.escapeShellArg cfg.archivePath} ${ + } --destination ${lib.escapeShellArg value.downloadPath} ${ lib.escapeShellArgs value.urls } ''; diff --git a/modules/nixos/services/uxplay.nix b/modules/nixos/services/uxplay.nix new file mode 100644 index 00000000..ad7ca43d --- /dev/null +++ b/modules/nixos/services/uxplay.nix @@ -0,0 +1,79 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.uxplay; +in +{ + options.services.uxplay = { + enable = lib.mkEnableOption "uxplay, an Airplay mirroring server"; + + package = lib.mkPackageOption pkgs "uxplay" { }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + Extra arguments to passed onto the service executable. + ''; + default = [ ]; + example = [ "-p" "4747" ]; + }; + }; + + config = lib.mkIf cfg.enable { + # UXPlay requires a DNS-SD server so we'll enable Avahi. + services.avahi.enable = lib.mkDefault true; + services.avahi.publish.enable = lib.mkDefault true; + services.avahi.publish.userServices = lib.mkDefault true; + + # We also have enabled mDNS since we're already using Avahi anyways. + services.avahi.nssmdns4 = lib.mkDefault true; + services.avahi.nssmdns6 = lib.mkDefault true; + + systemd.services.uxplay = { + description = "Airplay mirroring server"; + after = [ "network.target" ]; + documentation = [ "man:uxplay(1)" ]; + wantedBy = [ "multi-user.target" ]; + script = "${lib.getExe' cfg.package "uxplay"} ${lib.escapeShellArgs cfg.extraArgs}"; + serviceConfig = { + DynamicUser = true; + User = "uxplay"; + Group = "uxplay"; + RuntimeDirectory = "uxplay"; + + Restart = "on-failure"; + LockPersonality = true; + NoNewPrivileges = true; + MemoryDenyWriteExecute = true; + + CapabilityBoundSet = lib.mkForce [ ]; + PrivateTmp = true; + PrivateUsers = true; + PrivateDevices = true; + ProtectControlGroups = true; + ProtectClock = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + + RestrictRealtime = true; + RestrictAddressFamilies = [ + "AF_LOCAL" + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + + SystemCallFilter = [ "@system-service" "~@privileged" ]; + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + }; + unitConfig = { + StartLimitBurst = 5; + StartLimitIntervalSec = 10; + }; + }; + }; +} diff --git a/modules/nixos/services/wezterm-mux-server.nix b/modules/nixos/services/wezterm-mux-server.nix index b14d77dc..bf93696f 100644 --- a/modules/nixos/services/wezterm-mux-server.nix +++ b/modules/nixos/services/wezterm-mux-server.nix @@ -31,7 +31,8 @@ in config = lib.mkIf cfg.enable { systemd.services.wezterm-mux-server = { description = "Wezterm mux server"; - after = [ "network.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; path = [ cfg.package ]; wantedBy = [ "multi-user.target" ]; diff --git a/modules/nixos/services/yt-dlp.nix b/modules/nixos/services/yt-dlp.nix index 788f045f..63aee604 100644 --- a/modules/nixos/services/yt-dlp.nix +++ b/modules/nixos/services/yt-dlp.nix @@ -1,13 +1,35 @@ -{ config, lib, pkgs, ... }: +{ config, lib, options, pkgs, ... }: let cfg = config.services.yt-dlp; - serviceLevelArgs = lib.escapeShellArgs cfg.extraArgs; - jobUnitName = name: "yt-dlp-archive-service-${name}"; - jobType = { name, config, options, ... }: { + metadataType = { lib, ... }: { + options = { + path = lib.mkOption { + type = with lib.types; nullOr path; + description = '' + Associated path of the metadata to be downloaded. This will be passed to + the appropriate `--paths` option of yt-dlp. + ''; + default = null; + example = "/var/yt-dlp/thumbnails"; + }; + + output = lib.mkOption { + type = with lib.types; nullOr str; + description = '' + Associated output name for the metadata. This is passed to the + appropriate `--output` option of yt-dlp. + ''; + default = null; + example = "%(title)s.%(ext)s"; + }; + }; + }; + + jobType = { name, config, ... }: { options = { urls = lib.mkOption { type = with lib.types; listOf str; @@ -35,18 +57,30 @@ let example = "*-*-3/4"; }; - extraArgs = lib.mkOption { - type = with lib.types; listOf str; - description = - "Job-specific extra arguments to be passed to the {command}`yt-dlp`."; - default = [ ]; - example = lib.literalExpression '' - [ - "--date" "today" - ] + extraArgs = options.services.yt-dlp.extraArgs; + + downloadPath = options.services.yt-dlp.downloadPath // { + default = cfg.downloadPath; + description = "Job-specific download path of the service."; + }; + + metadata = options.services.yt-dlp.metadata // { + default = cfg.metadata; + description = '' + Per-job set of metadata with their associated options. ''; }; }; + + config.extraArgs = + let + mkPathArg = n: v: + lib.optionals (v.output != null) [ "--output" "${n}:${v.output}" ] + ++ lib.optionals (v.path != null) [ "--paths" "${n}:${v.path}" ]; + in + cfg.extraArgs + ++ (lib.lists.flatten (lib.mapAttrsToList mkPathArg config.metadata)) + ++ [ "--paths" config.downloadPath ]; }; in { @@ -63,25 +97,39 @@ in "pkgs.yt-dlp.override { phantomjsSupport = true; }"; }; - archivePath = lib.mkOption { - type = lib.types.str; + downloadPath = lib.mkOption { + type = lib.types.path; + description = "Download path of the service to be given per job (unless overridden)."; + default = "/var/yt-dlp"; + example = "/srv/Videos"; + }; + + metadata = lib.mkOption { + type = with lib.types; attrsOf (submodule metadataType); description = '' - The location of the archive to be downloaded. Must be an absolute path. + Global set of metadata with their appropriate options to be set. ''; - example = "/var/archives/yt-dlp-service"; + default = { }; + example = { + thumbnail = { + path = "/var/yt-dlp/thumbnails"; + output = "%(uploader,artist,creator,Unknown)s/%(title)s.%(ext)s"; + }; + infojson.path = "/var/yt-dlp/infojson"; + }; }; extraArgs = lib.mkOption { type = with lib.types; listOf str; description = - "List of arguments to be passed to {command}`yt-dlp`."; - default = [ "--download-archive videos" ]; + "Global list of arguments to be passed to each yt-dlp job."; + default = [ ]; example = lib.literalExpression '' [ "--verbose" - "--download-archive" "''${cfg.archivePath}/download-list" "--concurrent-fragments" "2" "--retries" "20" + "--download-archive" "videos" ] ''; }; @@ -114,43 +162,56 @@ in }; }; - # There's no need to go to the working directory since yt-dlp has the - # `--paths` flag. config = lib.mkIf cfg.enable { systemd.services = lib.mapAttrs' - (name: value: - let - jobLevelArgs = lib.escapeShellArgs value.extraArgs; - in + (name: job: lib.nameValuePair (jobUnitName name) { + inherit (job) startAt; wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; description = "yt-dlp archive job for group '${name}'"; documentation = [ "man:yt-dlp(1)" ]; enable = true; - path = [ cfg.package pkgs.coreutils ]; - preStart = '' - mkdir -p ${lib.escapeShellArg cfg.archivePath} - ''; script = '' - yt-dlp ${serviceLevelArgs} ${jobLevelArgs} \ - ${lib.escapeShellArgs value.urls} --paths ${lib.escapeShellArg cfg.archivePath} + ${lib.getExe' cfg.package "yt-dlp"} \ + ${lib.escapeShellArgs job.extraArgs} \ + ${lib.escapeShellArgs job.urls} ''; - startAt = value.startAt; serviceConfig = { + ReadWritePaths = + [ job.downloadPath ] + ++ lib.lists.flatten (lib.mapAttrsToList (n: v: lib.optionals (v.path != null) v.path) job.metadata); + LockPersonality = true; NoNewPrivileges = true; + PrivateDevices = true; PrivateTmp = true; PrivateUsers = true; - PrivateDevices = true; - ProtectControlGroups = true; + PrivateMounts = true; ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; + ProtectSystem = "full"; + RemoveIPC = true; StandardOutput = "journal"; StandardError = "journal"; SystemCallFilter = "@system-service"; SystemCallErrorNumber = "EPERM"; + + CapabilityBoundingSet = lib.mkDefault [ ]; + AmbientCapabilities = lib.mkDefault [ ]; + RestrictAddressFamilies = [ + "AF_LOCAL" + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictSUIDGUID = true; + MemoryDenyWriteExecute = true; }; }) cfg.jobs; diff --git a/modules/nixos/xdg/mime-desktop-specific.nix b/modules/nixos/xdg/mime-desktop-specific.nix new file mode 100644 index 00000000..013a40a8 --- /dev/null +++ b/modules/nixos/xdg/mime-desktop-specific.nix @@ -0,0 +1,42 @@ +{ config, lib, options, ... }: + +let + cfg = config.xdg.mime; + + mkMimeSource = name: value: + lib.nameValuePair + "xdg/${name}-mimeapps.list" + (lib.mkIf (value.defaultApplications != { }) { + text = lib.generators.toINI { } { + "Default Applications" = value.defaultApplications; + }; + }); + + xdgMimeAssociations = { name, lib, ... }: { + options.defaultApplications = options.xdg.mime.defaultApplications; + }; +in +{ + options.xdg.mime.desktops = lib.mkOption { + type = with lib.types; attrsOf (submodule xdgMimeAssociations); + description = '' + Additional desktop-specific associations. + + ::: {.note} + This can only specify default applications for a specific MIME type and + cannot be used to remove or add associations. + ::: + ''; + default = { }; + example = { + gnome.defaultApplications = { + "application/pdf" = "firefox.desktop"; + }; + }; + }; + + config = lib.mkIf (cfg.desktops != { }) { + environment.etc = + lib.mapAttrs' mkMimeSource cfg.desktops; + }; +} diff --git a/modules/nixvim/_private/extra-arguments.nix b/modules/nixvim/_private/extra-arguments.nix index bfc64aa3..cb0908ab 100644 --- a/modules/nixvim/_private/extra-arguments.nix +++ b/modules/nixvim/_private/extra-arguments.nix @@ -7,6 +7,6 @@ in { _module.args.foodogsquaredLib = foodogsquaredLib.extend (final: prev: { - nixvim = import ../../../lib/nixvim.nix { inherit pkgs lib; self = final; }; + nixvim = import ../../../lib/env-specific/nixvim.nix { inherit pkgs lib; self = final; }; }); } diff --git a/modules/nixvim/default.nix b/modules/nixvim/default.nix index ba914da3..37f778d0 100644 --- a/modules/nixvim/default.nix +++ b/modules/nixvim/default.nix @@ -2,9 +2,9 @@ imports = [ ./keyunmaps.nix ./plugins/dressing-nvim.nix - ./plugins/firenvim.nix ./plugins/lush-nvim.nix ./plugins/legendary-nvim.nix ./plugins/nvim-config-local.nix + ./plugins/nvim-remote-containers.nix ]; } diff --git a/modules/nixvim/plugins/dressing-nvim.nix b/modules/nixvim/plugins/dressing-nvim.nix index bd86dc5b..66c159c5 100644 --- a/modules/nixvim/plugins/dressing-nvim.nix +++ b/modules/nixvim/plugins/dressing-nvim.nix @@ -7,7 +7,7 @@ in options.plugins.dressing-nvim = { enable = lib.mkEnableOption "dressing.nvim configuration"; - package = helpers.mkPackageOption "dressing.nvim" pkgs.vimPlugins.dressing-nvim; + package = helpers.mkPluginPackageOption "dressing.nvim" pkgs.vimPlugins.dressing-nvim; settings = lib.mkOption { type = with lib.types; attrsOf anything; diff --git a/modules/nixvim/plugins/firenvim.nix b/modules/nixvim/plugins/firenvim.nix deleted file mode 100644 index 81420d51..00000000 --- a/modules/nixvim/plugins/firenvim.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ config, lib, pkgs, helpers, ... }: - -let - cfg = config.plugins.firenvim; -in -{ - options.plugins.firenvim = { - enable = lib.mkEnableOption "Firenvim"; - package = helpers.mkPackageOption "firenvim" pkgs.vimPlugins.firenvim; - settings = lib.mkOption { - type = with lib.types; attrsOf anything; - default = { }; - description = '' - Extra configuration options for Firenvim. - ''; - example = { - globalSettings = { alt = "all"; }; - localSettings = { - "\".*\"" = { - cmdline = "nvim"; - content = "text"; - priority = 0; - selector = "textarea"; - takeover = "always"; - }; - }; - }; - }; - }; - - config = lib.mkIf cfg.enable { - extraPlugins = [ cfg.package ]; - - globals.firenvim_config = cfg.settings; - }; -} diff --git a/modules/nixvim/plugins/legendary-nvim.nix b/modules/nixvim/plugins/legendary-nvim.nix index 53efdb7c..cad05d9f 100644 --- a/modules/nixvim/plugins/legendary-nvim.nix +++ b/modules/nixvim/plugins/legendary-nvim.nix @@ -9,7 +9,7 @@ in options.plugins.legendary-nvim = { enable = lib.mkEnableOption "legendary.nvim"; - package = helpers.mkPackageOption "legendary.nvim" pkgs.vimPlugins.legendary-nvim; + package = helpers.mkPluginPackageOption "legendary.nvim" pkgs.vimPlugins.legendary-nvim; additionalSetup = mkEnableOption' "dependencies for additional features like frecency sorting"; diff --git a/modules/nixvim/plugins/lush-nvim.nix b/modules/nixvim/plugins/lush-nvim.nix index 4f221fd8..c2373d4a 100644 --- a/modules/nixvim/plugins/lush-nvim.nix +++ b/modules/nixvim/plugins/lush-nvim.nix @@ -37,31 +37,33 @@ let in # This is based from rktjmp/lush-template. We'll improve on things from # here whenever necessary. - lib.nameValuePair "colors/${name}.lua" '' - ${cfg.extraConfigLua} - ${theme.extraConfigLua} + lib.nameValuePair "colors/${name}.lua" { + text = '' + ${cfg.extraConfigLua} + ${theme.extraConfigLua} - vim.g.colors_name = '${name}' - vim.o.termguicolors = true + vim.g.colors_name = '${name}' + vim.o.termguicolors = true - -- This needs to be parsed twice: once to generate the Lush spec - -- and the other to actually apply the spec. - -- - -- @diagnostic disable: undefined-global - local spec = lush(function(injected_functions) - local sym = injected_functions.sym - return { ${lib.concatStringsSep "," highlightList} } - end) + -- This needs to be parsed twice: once to generate the Lush spec + -- and the other to actually apply the spec. + -- + -- @diagnostic disable: undefined-global + local spec = lush(function(injected_functions) + local sym = injected_functions.sym + return { ${lib.concatStringsSep "," highlightList} } + end) - -- We then apply the theme. - lush(spec) - ''; + -- We then apply the theme. + lush(spec) + ''; + }; in { options.colorschemes.lush = { enable = lib.mkEnableOption "theming with lush.nvim"; - package = helpers.mkPackageOption "lush.nvim" pkgs.vimPlugins.lush-nvim; + package = helpers.mkPluginPackageOption "lush.nvim" pkgs.vimPlugins.lush-nvim; extraConfigLua = lib.mkOption { type = lib.types.lines; diff --git a/modules/nixvim/plugins/nvim-config-local.nix b/modules/nixvim/plugins/nvim-config-local.nix index d46e6d92..9c5403b8 100644 --- a/modules/nixvim/plugins/nvim-config-local.nix +++ b/modules/nixvim/plugins/nvim-config-local.nix @@ -4,40 +4,34 @@ let cfg = config.plugins.nvim-config-local; in { - options.plugins.nvim-config-local = - helpers.neovim-plugin.extraOptionsOptions // { - enable = lib.mkEnableOption "nvim-config-local"; + options.plugins.nvim-config-local = { + enable = lib.mkEnableOption "nvim-config-local"; - package = helpers.mkPackageOption "nvim-config-local" pkgs.vimPlugins.nvim-config-local; + package = helpers.mkPluginPackageOption "nvim-config-local" pkgs.vimPlugins.nvim-config-local; - configFiles = lib.mkOption { - type = with lib.types; listOf str; - default = [ ".nvim.lua" ".nvimrc" ".exrc" ]; - example = [ "config/nvim.lua" ]; - description = '' - A list of patterns to load (includes Lua configurations). - ''; + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = with lib.types; attrsOf anything; + options = { + config_files = lib.mkOption { + type = with lib.types; listOf str; + default = [ ".nvim.lua" ".nvimrc" ".exrc" ]; + example = [ "config/nvim.lua" ]; + description = '' + A list of patterns to load (includes Lua configurations). + ''; + }; + }; }; - - autocommandsCreate = helpers.defaultNullOpts.mkBool true "Create autocommands for sourcing local files."; - commandsCreate = helpers.defaultNullOpts.mkBool true "Create user commands for nvim-config-local."; - lookupParents = helpers.defaultNullOpts.mkBool false "Enable lookup in parent directories when sourcing local configs."; }; + }; config = - let - setupOptions = { - config_files = cfg.configFiles; - autocommands_create = cfg.autocommandsCreate; - commands_create = cfg.commandsCreate; - lookup_parents = cfg.lookupParents; - } // cfg.extraOptions; - in lib.mkIf cfg.enable { extraPlugins = [ cfg.package ]; extraConfigLua = '' - require("config-local").setup(${helpers.toLuaConfig setupOptions}) + require("config-local").setup(${helpers.toLuaConfig cfg.settings}) ''; }; } diff --git a/modules/nixvim/plugins/nvim-remote-containers.nix b/modules/nixvim/plugins/nvim-remote-containers.nix new file mode 100644 index 00000000..f28dcd6f --- /dev/null +++ b/modules/nixvim/plugins/nvim-remote-containers.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, helpers,... }: + +let + cfg = config.plugins.nvim-remote-containers; +in +{ + options.plugins.nvim-remote-containers = { + enable = lib.mkEnableOption "nvim-remote-containers"; + + package = helpers.mkPluginPackageOption "nvim-remote-containers" pkgs.vimPlugins.nvim-remote-containers; + }; + + config = lib.mkIf cfg.enable { + plugins.treesitter.enable = lib.mkDefault true; + extraPlugins = [ cfg.package ]; + }; +} diff --git a/modules/wrapper-manager/_private/default.nix b/modules/wrapper-manager/_private/default.nix new file mode 100644 index 00000000..af907387 --- /dev/null +++ b/modules/wrapper-manager/_private/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./extra-arguments.nix + ]; +} diff --git a/modules/wrapper-manager/_private/extra-arguments.nix b/modules/wrapper-manager/_private/extra-arguments.nix new file mode 100644 index 00000000..eceaf0b9 --- /dev/null +++ b/modules/wrapper-manager/_private/extra-arguments.nix @@ -0,0 +1,12 @@ +{ pkgs, lib, ... }: + +let + foodogsquaredLib = import ../../../lib { inherit pkgs; }; +in +{ + _module.args.foodogsquaredLib = + foodogsquaredLib.extend (final: prev: { + wrapper-manager = + import ../../../lib/env-specific/wrapper-manager.nix { inherit pkgs lib; self = final; }; + }); +} diff --git a/modules/wrapper-manager/dconf.nix b/modules/wrapper-manager/dconf.nix new file mode 100644 index 00000000..fe6aaaea --- /dev/null +++ b/modules/wrapper-manager/dconf.nix @@ -0,0 +1,155 @@ +# This is a terrible idea (at least from the app developer's perspective) +# because what we're doing is a massive hack. We're essentially instilling a +# forced isolated environment for the settings backend to look into. This will +# go downhill very badly once the dconf-enabled wrapper has mismatched +# configuration with the wider environment. Once that occurred, this is a +# problem neither the app developer nor the system maintainers are to blame but +# the user. So yeah, it is terrible to put this into wrapper-manager-fds +# upstream and it may be here for the rest of time. +# +# In other words, dconf is just not built for this case. +{ config, lib, pkgs, ... }: + +let + cfg = config.dconf; + + settingsFormat = { + type = with lib.types; + let + valueType = (oneOf [ + bool + float + int + str + (listOf valueType) + ]) // { + description = "dconf value"; + }; + in + attrsOf (attrsOf valueType); + + generate = name: value: + pkgs.writeTextDir "/dconf/${name}" (lib.generators.toDconfINI value); + }; + + dconfModuleFactory = { isGlobal ? false }: { + enable = lib.mkEnableOption "configuration with dconf" // lib.optionalAttrs (!isGlobal) { + default = cfg.enable; + }; + + package = lib.mkPackageOption pkgs "dconf" { } // lib.optionalAttrs (!isGlobal) { + default = cfg.package; + }; + + settings = lib.mkOption { + type = settingsFormat.type; + default = { }; + description = if isGlobal then '' + Global settings to be applied per dconf-enabled wrapper. + '' else '' + The settings of the dconf database that the wrapper uses. + ''; + example = lib.literalExpression '' + { + "org/gnome/nautilus/list-view".use-tree-view = true; + "org/gnome/nautilus/preferences".show-create-link = true; + "org/gtk/settings/file-chooser" = { + sort-directories-first = true; + show-hidden = true; + }; + } + ''; + }; + + keyfiles = lib.mkOption { + type = with lib.types; listOf path; + description = if isGlobal then '' + Global list of keyfiles to be included to each dconf-enabled wrapper. + '' else '' + Additional list of keyfiles to be included as part of the dconf + database. + ''; + default = if isGlobal then [ ] else [ "user-db" ]; + example = lib.literalExpression '' + [ + ./config/dconf/90-extra-settings.conf + ] + ''; + }; + + profile = lib.mkOption { + type = with lib.types; listOf str; + description = if isGlobal then '' + Global list of dconf database that will be used for each dconf-enabled + wrappers. + '' else '' + A list of dconf databases that will be used for the main dconf + profile of the dconf-configured wrapper. + ''; + default = [ "user-db:user" ]; + defaultText = '' + "user-db:user" as the writeable database alongside the generated + database file from our settings. + ''; + }; + }; +in +{ + options.dconf = dconfModuleFactory { isGlobal = true; }; + + options.wrappers = + let + dconfSubmodule = { config, lib, name, ... }: let + submoduleCfg = config.dconf; + + dconfProfileFile = + pkgs.writeText + "dconf-profile" + (lib.concatMapStrings (db: "${db}\n") submoduleCfg.profile); + + dconfSettings = + settingsFormat.generate "wrapper-manager-dconf-${config.executableName}-settings" submoduleCfg.settings; + + keyfilesDir = pkgs.symlinkJoin { + name = "wrapper-manager-dconf-${config.executableName}"; + paths = submoduleCfg.keyfiles ++ [ "${dconfSettings}/dconf" ]; + }; + + dconfSettingsDatabase = + pkgs.runCommand "wrapper-manager-dconf-${config.executableName}-database" { + nativeBuildInputs = [ submoduleCfg.package ]; + } '' + dconf compile ${builtins.placeholder "out"} "${keyfilesDir}" + ''; + in { + options.dconf = dconfModuleFactory { isGlobal = false; } // { + databaseDrv = lib.mkOption { + type = lib.types.package; + description = '' + Derivation containing the compiled dconf database. Useful for + integrating with your own module. + ''; + readOnly = true; + }; + }; + + config = lib.mkIf submoduleCfg.enable { + env.DCONF_PROFILE.value = dconfProfileFile; + + dconf = { + profile = lib.mkMerge [ + cfg.profile + + (lib.mkAfter [ (builtins.toString submoduleCfg.databaseDrv) ]) + ]; + keyfiles = cfg.keyfiles; + settings = cfg.settings; + databaseDrv = dconfSettingsDatabase; + }; + }; + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule dconfSubmodule); + }; +} diff --git a/modules/wrapper-manager/default.nix b/modules/wrapper-manager/default.nix new file mode 100644 index 00000000..1f722aa9 --- /dev/null +++ b/modules/wrapper-manager/default.nix @@ -0,0 +1,11 @@ +{ + imports = [ + ./programs/blender.nix + ./programs/zellij.nix + ./programs/neovim.nix + ./programs/jujutsu.nix + ./nixgl.nix + ./dconf.nix + ./sandboxing + ]; +} diff --git a/modules/wrapper-manager/nixgl.nix b/modules/wrapper-manager/nixgl.nix new file mode 100644 index 00000000..afab8a0e --- /dev/null +++ b/modules/wrapper-manager/nixgl.nix @@ -0,0 +1,127 @@ +{ config, lib, options, pkgs, ... }: + +let + cfg = config.nixgl; + + nixgl = variant: src: + let + nixgl = import src { inherit pkgs; }; + in + lib.getAttrFromPath variant nixgl; +in +{ + options.nixgl = { + enableAll = lib.mkEnableOption "wrapping all wrappers with NixGL"; + + src = lib.mkOption { + type = lib.types.pathInStore; + description = '' + The source code of NixGL to be used for all NixGL-enabled wrappers + (unless overridden with their own). + ''; + default = builtins.fetchGit { + url = "https://github.com/nix-community/nixGL.git"; + ref = "main"; + }; + defaultText = '' + The current revision of NixGL. + + ::: {.note} + It is recommended to fetch with your own NixGL source (either from + flakes, builtin fetchers, or however you manage your Nix dependencies). + ::: + ''; + }; + + variant = lib.mkOption { + type = with lib.types; listOf nonEmptyStr; + description = '' + The variant to be used for NixGL listed as a attrpath. The default + wrapper to be used is `auto.nixGLDefault`. + ''; + default = [ "auto" "nixGLDefault" ]; + example = [ "nixGLIntel" ]; + }; + + executable = lib.mkOption { + type = lib.types.nonEmptyStr; + default = lib.getExe (nixgl cfg.variant cfg.src); + description = '' + The path of the NixGL executable. By default, it will get + `meta.mainProgram` of the variant from the `src` instead. + ''; + example = lib.literalExpression '' + let + src = builtins.fetchGit { + url = "https://github.com/nix-community/nixGL.git"; + ref = "main"; + rev = "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a"; + }; + nixgl = import src { inherit pkgs; }; + in + lib.getExe' nixgl.auto.nixGLDefault "nixGL" + ''; + }; + }; + + options.wrappers = + let + nixglWrapperModule = { config, lib, name, ... }: let + submoduleCfg = config.nixgl; + in { + options.nixgl = { + enable = lib.mkEnableOption "wrapping NixGL for this wrapper" // { + default = cfg.enableAll; + }; + + src = options.nixgl.src // { + default = cfg.src; + }; + + executable = options.nixgl.executable // { + default = lib.getExe (nixgl config.nixgl.variant config.nixgl.src); + }; + + variant = options.nixgl.variant // { + default = cfg.variant; + }; + + wraparound = { + arg0 = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + The executable to be wrapped around. + ''; + example = lib.literalExpression '' + lib.getExe' pkgs.wezterm "wezterm" + ''; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + description = '' + List of arguments associated to the wraparound. + ''; + example = lib.literalExpression '' + [ + "--config-file" ./config/wezterm/config.lua + ] + ''; + }; + }; + }; + + config = lib.mkIf config.nixgl.enable { + arg0 = + if submoduleCfg.executable == null + then lib.getExe (nixgl config.nixgl.variant config.nixgl.src) + else submoduleCfg.executable; + prependArgs = lib.mkBefore ([ submoduleCfg.wraparound.arg0 ] ++ submoduleCfg.wraparound.extraArgs); + }; + }; + in + lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule nixglWrapperModule); + }; +} diff --git a/modules/wrapper-manager/programs/blender.nix b/modules/wrapper-manager/programs/blender.nix new file mode 100644 index 00000000..cc1cd6ef --- /dev/null +++ b/modules/wrapper-manager/programs/blender.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.blender; + + blenderVersion = lib.versions.majorMinor cfg.package.version; + addons = + pkgs.runCommand "blender-system-resources" + { + passAsFile = [ "paths" ]; + paths = cfg.addons ++ [ cfg.package ]; + nativeBuildInputs = with pkgs; [ outils ]; + } '' + mkdir -p $out + for i in $(cat $pathsPath); do + resourcesPath="$i/share/blender" + if [ -d $i/share/blender/${blenderVersion} ]; then + resourcesPath="$i/share/blender/${blenderVersion}"; + fi + lndir -silent $resourcesPath $out + done + ''; +in +{ + options.programs.blender = { + enable = lib.mkEnableOption "Blender, a 3D computer graphics tool"; + + package = lib.mkPackageOption pkgs "blender" { + example = lib.literalExpression '' + pkgs.blender-with-packages { + name = "sample-studio-wrapped"; + packages = with pkgs.python3Packages; [ pandas ]; + } + ''; + }; + + addons = lib.mkOption { + type = with lib.types; listOf package; + description = lib.mdDoc '' + List of packages providing Blender system resources at + {file}`/share/blender` or at {file}`/share/blender/$MAJORMINORVERSION`. + ''; + default = [ ]; + defaultText = "[]"; + example = lib.literalExpression '' + with pkgs; [ + blender-addons-machin3tools + blender-addons-glslTexture + ] + ''; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + basePackages = [ cfg.package ]; + + wrappers.blender = { + arg0 = lib.getExe' cfg.package "blender"; + }; + } + + (lib.mkIf (builtins.length cfg.addons > 0) { + wrappers.blender.env.BLENDER_SYSTEM_RESOURCES.value = addons; + }) + ]); +} diff --git a/modules/wrapper-manager/programs/jujutsu.nix b/modules/wrapper-manager/programs/jujutsu.nix new file mode 100644 index 00000000..1bc8eb4b --- /dev/null +++ b/modules/wrapper-manager/programs/jujutsu.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.jujutsu; + + settingsFormat = pkgs.formats.toml { }; +in +{ + options.programs.jujutsu = { + enable = lib.mkEnableOption "Jujutsu, a Git-compatible DVCS"; + + package = lib.mkPackageOption pkgs "jujutsu" { }; + + executableName = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + The name of the executable Jujutsu wrapper. + ''; + default = "jj"; + example = "jj-custom"; + }; + + settings = lib.mkOption { + type = settingsFormat.type; + description = '' + Nix-configured settings to be used by the wrapper. This option is + ignored if {option}`programs.jujutsu.configFile` is not `null`. + ''; + default = { }; + example = lib.literalExpression '' + { + user.name = "Your Name"; + user.email = "youremail@example.com"; + ui.color = "never"; + ui.diff.tool = "vimdiff"; + merge-tools.vimdiff.diff-invocation-mode = "file-by-file"; + } + ''; + }; + + configFile = lib.mkOption { + type = with lib.types; nullOr path; + description = '' + The configuration file to be used for the Jujutsu wrapper. If the value + is `null`, it will generate one from + {option}`programs.jujutsu.settings`. + ''; + default = null; + example = lib.literalExpression "./config/jujutsu.toml"; + }; + }; + + config = lib.mkIf cfg.enable { + basePackages = [ cfg.package ]; + wrappers.jujutsu = lib.mkMerge [ + { + inherit (cfg) executableName; + arg0 = lib.getExe' cfg.package "jj"; + } + + (lib.mkIf (cfg.configFile != null) { + env.JJ_CONFIG.value = cfg.configFile; + }) + + (lib.mkIf (cfg.settings != { } && cfg.configFile == null) { + env.JJ_CONFIG.value = + settingsFormat.generate "wrapper-manager-jujutsu-config" cfg.settings; + }) + ]; + }; +} diff --git a/modules/wrapper-manager/programs/neovim.nix b/modules/wrapper-manager/programs/neovim.nix new file mode 100644 index 00000000..7c379bf1 --- /dev/null +++ b/modules/wrapper-manager/programs/neovim.nix @@ -0,0 +1,112 @@ +# Basically a poor man's version of NixVim or those configuration options from +# either NixOS or home-manager, really. +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.neovim; + + neovimConfigPluginType = { name, lib, ... }: { + freeformType = with lib.types; attrsOf anything; + options = { + plugin = lib.mkOption { + type = lib.types.package; + description = '' + Package containing the Neovim module. + ''; + }; + + pluginConfig = lib.mkOption { + type = lib.types.lines; + description = '' + Plugin configuration in VimL. + ''; + default = ""; + }; + + optional = lib.mkEnableOption "inclusion of this configuration"; + }; + }; + + neovimConfig = pkgs.neovimUtils.makeNeovimConfig { + inherit (cfg) plugins extraPython3Packages extraLuaPackages; + wrapRc = true; + withRuby = cfg.providers.ruby.enable; + withNodeJs = cfg.providers.nodejs.enable; + withPython = cfg.providers.python.enable; + }; + + finalNeovimPackage = pkgs.wrapNeovimUnstable cfg.package neovimConfig; +in +{ + options.programs.neovim = { + enable = lib.mkEnableOption "Neovim, a terminal text editor"; + + package = lib.mkPackageOption pkgs "neovim-unwrapped" { }; + + executableName = lib.mkOption { + type = lib.types.str; + description = '' + The name of the executable name. Pretty useful for creating multiple + Neovim packages. + ''; + default = "nvim"; + example = "nvim-foodogsquared"; + }; + + plugins = lib.mkOption { + type = with lib.types; listOf (submodule neovimConfigPluginType); + description = '' + List of Neovim plugins to be included within the wrapper. + ''; + default = [ ]; + example = lib.literalExpression '' + [ + { plugin = pkgs.vimPlugins.vim-nickel; } + ] + ''; + }; + + extraPython3Packages = lib.mkOption { + type = with lib.types; functionTo (listOf package); + description = '' + A function containing an extra list of Python packages to be included + in the Neovim installation. + ''; + default = _: [ ]; + example = lib.literalExpression '' + p: with p; [ + numpy + ] + ''; + }; + + extraLuaPackages = lib.mkOption { + type = with lib.types; functionTo (listOf package); + description = '' + A function containing an extra list of Lua packages to be included + within the Neovim installation. + ''; + default = _: [ ]; + example = lib.literalExpression '' + p: with p; [ + lz-n + ] + ''; + }; + + providers = { + python.enable = lib.mkEnableOption "Python provider with Neovim"; + nodejs.enable = lib.mkEnableOption "NodeJS provider with Neovim"; + ruby.enable = lib.mkEnableOption "Ruby provider with Neovim"; + }; + }; + + config = lib.mkIf cfg.enable { + basePackages = finalNeovimPackage; + + wrappers.nvim = { + executableName = cfg.executableName; + arg0 = lib.getExe' finalNeovimPackage "nvim"; + }; + }; +} diff --git a/modules/wrapper-manager/programs/zellij.nix b/modules/wrapper-manager/programs/zellij.nix new file mode 100644 index 00000000..b273f22e --- /dev/null +++ b/modules/wrapper-manager/programs/zellij.nix @@ -0,0 +1,32 @@ +{ lib, pkgs, config, ... }: + +let + cfg = config.programs.zellij; +in +{ + options.programs.zellij = { + enable = lib.mkEnableOption "Zellij, a terminal multiplexer"; + + package = lib.mkPackageOption pkgs "zellij" { }; + + configFile = lib.mkOption { + type = lib.types.path; + description = '' + The configuration file of the Zellij wrapper to be used. This module + will use the environment variable `ZELLIJ_CONFIG_FILE` which would + still allow overriding of the user's own if they choose to. + ''; + example = lib.literalExpression '' + ./config/zellij/config.kdl + ''; + }; + }; + + config = lib.mkIf cfg.enable { + basePackages = [ cfg.package ]; + wrappers.zellij = { + arg0 = lib.getExe' cfg.package "zellij"; + env.ZELLIJ_CONFIG_FILE.value = cfg.configFile; + }; + }; +} diff --git a/modules/wrapper-manager/sandboxing/boxxy.nix b/modules/wrapper-manager/sandboxing/boxxy.nix new file mode 100644 index 00000000..337ae69a --- /dev/null +++ b/modules/wrapper-manager/sandboxing/boxxy.nix @@ -0,0 +1,121 @@ +{ lib, pkgs, config, ... }: + +let + cfg = config.sandboxing.boxxy; + + boxxyRuleModule = { name, lib, ... }: { + options = { + source = lib.mkOption { + type = lib.types.str; + description = '' + The path of the file to be remounted. + ''; + example = "~/.tmux.conf"; + }; + + destination = lib.mkOption { + type = lib.types.str; + default = name; + description = '' + The path where the source will be remounted to. + ''; + example = "~/.config/tmux/tmux.conf"; + }; + + mode = lib.mkOption { + type = with lib.types; nullOr (enum [ "file" "dir" ]); + description = '' + Mode indicating the behavior for remounting. + ''; + default = null; + example = "dir"; + }; + }; + }; + + boxxyModuleFactory = { isGlobal ? false }: { + package = lib.mkPackageOption pkgs "boxxy" { } // lib.optionalAttrs (!isGlobal) { + default = cfg.package; + }; + + # TODO: Perhaps, consider creating a PR to upstream repo to pass a config file? + # Boxxy doesn't have a way to pass a custom configuration file so we're + # settling with this. Besides, Boxxy-launched programs can inherit the + # environment anyways so a custom config file is not needed for now. + rules = lib.mkOption { + type = with lib.types; attrsOf (submodule boxxyRuleModule); + default = { }; + description = if isGlobal then '' + Global set of rules to be applied per-wrapper. + '' else '' + Set of rules to be applied to the wrapper. + ''; + example = lib.literalExpression '' + { + "~/.config/tmux/tmux.conf".source = "~/.tmux.conf"; + "~/.config/bash/bashrc".source = "~/.bashrc"; + "~/.config/vscode" = { + source = "~/.vscode"; + mode = "dir"; + }; + } + ''; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = if isGlobal then '' + Global list of arguments to be appended to each Boxxy-enabled wrappers. + '' else '' + List of arguments to the {command}`boxxy` executable. + ''; + default = [ ]; + example = [ "--immutable" "--daemon" ]; + }; + }; +in +{ + options.sandboxing.boxxy = boxxyModuleFactory { isGlobal = true; }; + + options.wrappers = + let + boxxySandboxModule = { name, lib, config, pkgs, ... }: + let + submoduleCfg = config.sandboxing.boxxy; + in + { + options.sandboxing.variant = lib.mkOption { + type = with lib.types; nullOr (enum [ "boxxy" ]); + }; + + options.sandboxing.boxxy = boxxyModuleFactory { isGlobal = false; }; + + config = lib.mkIf (config.sandboxing.variant == "boxxy") { + sandboxing.boxxy.rules = cfg.rules; + + sandboxing.boxxy.extraArgs = + cfg.extraArgs + ++ (lib.mapAttrsToList + (_: metadata: + let + inherit (metadata) source destination mode; + ruleArg = + if mode != null + then "${source}:${destination}:${mode}" + else "${source}:${destination}"; + in + "--rule ${ruleArg}") + submoduleCfg.rules); + + arg0 = lib.getExe' submoduleCfg.package "boxxy"; + prependArgs = lib.mkBefore + (submoduleCfg.extraArgs + ++ [ "--" config.sandboxing.wraparound.arg0 ] + ++ config.sandboxing.wraparound.extraArgs); + }; + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule boxxySandboxModule); + }; +} diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/dbus-filter.nix b/modules/wrapper-manager/sandboxing/bubblewrap/dbus-filter.nix new file mode 100644 index 00000000..8ca74e60 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/dbus-filter.nix @@ -0,0 +1,188 @@ +# The D-Bus integration for Bubblewrap-wrapped wrappers. As noted from the +# Bubblewrap's README, it encourages to use something like xdg-dbus-proxy to +# limit reach to overarching services such as systemd's so we're doing it here. +{ config, lib, options, pkgs, ... }: + +let + cfg = config.sandboxing.bubblewrap; + + dbusFilterType = { lib, ... }: + let + ruleBasedPoliciesType = with lib.types; listOf str; + in + { + options = { + level = lib.mkOption { + type = with lib.types; nullOr (enum [ "see" "talk" "own" ]); + description = '' + Basic policy action level for a given name. + ''; + default = null; + example = "see"; + }; + + call = lib.mkOption { + type = ruleBasedPoliciesType; + description = '' + A list of rules to be specified for calls on the given name. + ''; + default = [ ]; + example = [ "*@com.example.*" ]; + }; + + broadcast = lib.mkOption { + type = ruleBasedPoliciesType; + description = '' + A list of rules to be specified for broadcasts on the given name; + ''; + default = [ ]; + example = [ ]; + }; + }; + }; + + bubblewrapModuleFactory = { isGlobal ? false }: { + dbus = { + enable = lib.mkEnableOption "D-Bus integration" // { + default = if isGlobal then false else cfg.dbus.enable; + }; + + filter = { + package = lib.mkPackageOption pkgs "xdg-dbus-proxy" { } // lib.optionalAttrs isGlobal { + default = cfg.filter.package; + }; + }; + }; + }; +in +{ + options.sandboxing.bubblewrap = + lib.recursiveUpdate + (bubblewrapModuleFactory { isGlobal = true; }) + { + dbus.filter.policies = lib.mkOption { + type = with lib.types; attrsOf (submodule dbusFilterType); + description = '' + A global set of D-Bus addresses with their policies set with + {command}`xdg-dbus-proxy` for each D-Bus address specified on the + Bubblewrap-enabled wrappers. See {manpage}`xdg-dbus-proxy(1)` for + more details. + ''; + default = { }; + example = { + "org.systemd.Systemd".level = "talk"; + "org.example.*".level = "own"; + "org.foo.Bar" = { + call = [ "*" ]; + broadcast = [ ]; + }; + }; + }; + }; + + options.wrappers = + let + addressesModule = { config, lib, name, ... }: { + options = { + path = lib.mkOption { + type = lib.types.str; + default = "$XDG_RUNTIME_DIR/wrapper-manager-fds/$(echo $RANDOM | base64)"; + description = '' + Path of the unix socket domain. A value of `null` means + the launcher takes care of it. + ''; + }; + + policies = lib.mkOption { + type = lib.types.submodule dbusFilterType; + description = '' + Policies to be set to that address. + ''; + default = { }; + example = { + level = "see"; + }; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + List of proxy-specific arguments to be passed to + {command}`xdg-dbus-proxy`. + ''; + default = [ ]; + }; + }; + + config.policies = cfg.dbus.filter.policies; + config.extraArgs = + let + inherit (config) policies; + in + lib.optionals (policies.level != null) [ "--${policies.level}=${name}" ] + ++ builtins.map (rule: "--call=${name}=${rule}") policies.call + ++ builtins.map (rule: "--broadcast=${name}=${rule}") policies.broadcast; + }; + + bubblewrapModule = { config, lib, pkgs, name, ... }: + let + submoduleCfg = config.sandboxing.bubblewrap; + in + { + options.sandboxing.bubblewrap = + lib.recursiveUpdate + (bubblewrapModuleFactory { isGlobal = false; }) + { + dbus.filter = { + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + List of arguments to be passed to {command}`xdg-dbus-proxy`. + ''; + default = [ ]; + }; + + bwrapArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + List of arguments to be passed to the Bubblewrap + environment of the D-Bus proxy. + ''; + default = [ ]; + }; + + addresses = lib.mkOption { + type = with lib.types; attrsOf (submodule addressesModule); + description = '' + A set of addresses to be applied with the filter through + {command}`xdg-dbus-proxy`. + ''; + default = { }; + example = { + "org.example.Bar".policies.level = "talk"; + "org.freedesktop.systemd1".policies.level = "talk"; + "org.gtk.vfs.*".policies.level = "talk"; + "org.gtk.vfs".policies.level = "talk"; + }; + }; + }; + }; + + config = lib.mkIf (config.sandboxing.variant == "bubblewrap") { + sandboxing.bubblewrap.dbus.filter.extraArgs = + let + makeDbusProxyArgs = address: metadata: + [ address (builtins.toString metadata.path) ] ++ metadata.extraArgs; + in + lib.lists.flatten (lib.mapAttrsToList makeDbusProxyArgs submoduleCfg.dbus.filter.addresses); + + sandboxing.bubblewrap.sharedNixPaths = [ + submoduleCfg.dbus.filter.package + ]; + }; + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule bubblewrapModule); + }; +} diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/default.nix b/modules/wrapper-manager/sandboxing/bubblewrap/default.nix new file mode 100644 index 00000000..82aaf26d --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/default.nix @@ -0,0 +1,135 @@ +# Bubblewrap integration within wrapper-manager. Several parts were inspired +# from the source code's given examples (at `demo` directory) as well as a few +# Nix projects integrating with it such as `nix-bubblewrap` +# (https://git.sr.ht/~fgaz/nix-bubblewrap) and NixPak +# (https://github.com/nixpak/nixpak). +# +# Similar to most of them, this is basically a builder for the right arguments +# to be passed to `bwrap`. +# +# Also similar to those projects, we also have a launcher (at `launcher` +# subdirectory) specializing in Bubblewrap-wrapped programs. The reasoning is +# it allows us to easily take care of things that are hard to do inside of Nix +# such as handling hardware configuration and the experience to have to do all +# of that in nixpkgs runtime shell (Bash) is a pain to develop. +# +# As already mentioned from the Bubblewrap README, we'll have to be careful for +# handling D-Bus so we'll use xdg-dbus-proxy for that. +{ config, lib, pkgs, ... }: + +let + cfg = config.sandboxing.bubblewrap; + + bubblewrapModuleFactory = { isGlobal ? false }: { + package = lib.mkPackageOption pkgs "bubblewrap" { } // lib.optionalAttrs isGlobal { + default = cfg.package; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + description = + if isGlobal + then '' + Global list of extra arguments to be given to all Bubblewrap-enabled + wrappers. + '' + else '' + List of extra arguments to be given to the Bubblewrap executable. + ''; + }; + + enableNetwork = lib.mkEnableOption "sharing of the host network" // { + default = if isGlobal then true else cfg.enableNetwork; + }; + + enableBundledCertificates = lib.mkEnableOption "bundling additional certificates from nixpkgs" // { + default = if isGlobal then true else cfg.enableBundledCertificates; + }; + + enableIsolation = lib.mkEnableOption "unsharing most of the system" // { + default = if isGlobal then true else cfg.enableIsolation; + }; + + enableEnsureChildDiesWithParent = lib.mkEnableOption "ensuring child processes die with parent" // { + default = if isGlobal then true else cfg.enableEnsureChildDiesWithParent; + }; + }; +in +{ + imports = [ + ./launcher.nix + ./dbus-filter.nix + ./filesystem.nix + ]; + + options.sandboxing.bubblewrap = bubblewrapModuleFactory { isGlobal = true; }; + + options.wrappers = + let + bubblewrapModule = { name, config, lib, ... }: + let + submoduleCfg = config.sandboxing.bubblewrap; + env' = lib.filterAttrs (n: _: !(lib.strings.hasPrefix "WRAPPER_MANAGER_BWRAP_LAUNCHER" n)) config.env; + in + { + options.sandboxing.variant = lib.mkOption { + type = with lib.types; nullOr (enum [ "bubblewrap" ]); + }; + + options.sandboxing.bubblewrap = bubblewrapModuleFactory { isGlobal = false; }; + + config = lib.mkIf (config.sandboxing.variant == "bubblewrap") (lib.mkMerge [ + { + # Ordering of the arguments here matter(?). + sandboxing.bubblewrap.extraArgs = + cfg.extraArgs + ++ lib.mapAttrsToList + (var: metadata: + if metadata.action == "unset" then + "--unsetenv ${var}" + else if lib.elem metadata.action [ "prefix" "suffix" ] then + "--setenv ${var} ${lib.concatStringsSep metadata.separator metadata.value}" + else + "--setenv ${var} ${metadata.value}") + env'; + } + + (lib.mkIf submoduleCfg.enableNetwork { + # In case isolation is also enabled, we'll have this still + # enabled at least. + sandboxing.bubblewrap.extraArgs = lib.mkAfter [ "--share-net" ]; + + # The most common network-related files found on most + # distributions. This should be enough in most cases. If not, + # we'll probably let the launcher handle this. + sandboxing.bubblewrap.binds.ro = [ + "/etc/ssh" + "/etc/ssl" + "/etc/hosts" + "/etc/resolv.conf" + ]; + }) + + (lib.mkIf submoduleCfg.enableBundledCertificates { + sandboxing.bubblewrap.sharedNixPaths = [ pkgs.cacert ]; + }) + + (lib.mkIf config.locale.enable { + sandboxing.bubblewrap.sharedNixPaths = [ config.locale.package ]; + }) + + (lib.mkIf submoduleCfg.enableIsolation { + sandboxing.bubblewrap.extraArgs = lib.mkBefore [ "--unshare-all" ]; + }) + + (lib.mkIf submoduleCfg.enableEnsureChildDiesWithParent { + sandboxing.bubblewrap.extraArgs = lib.mkBefore [ "--die-with-parent" ]; + }) + ]); + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule bubblewrapModule); + }; +} diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/filesystem.nix b/modules/wrapper-manager/sandboxing/bubblewrap/filesystem.nix new file mode 100644 index 00000000..190a37ab --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/filesystem.nix @@ -0,0 +1,265 @@ +# Essentially a poor man's version of NixOS filesystem module except that is +# made for Bubblewrap environment. Everything here should only make use of +# Bubblewrap's filesystem options from the command-line application. +{ config, lib, pkgs, ... }: + +let + cfg = config.sandboxing.bubblewrap; + + fileOperationsWithPerms = [ + "file" "dir" "remount-ro" + "bind-data" "ro-bind-data" + ]; + fileOperationsWithoutPerms = [ + "symlink" + "bind" "bind-try" + "dev-bind" "dev-bind-try" + "ro-bind" "ro-bind-try" + ]; + + bubblewrapModuleFactory = { isGlobal ? false }: let + filesystemSubmodule = { config, lib, name, ... }: { + options = { + source = lib.mkOption { + type = lib.types.str; + description = '' + The source of the path to be copied from. + ''; + example = lib.literalExpression "./files/example.file"; + }; + + destination = lib.mkOption { + type = lib.types.str; + description = '' + The source of the path to be copied from. + ''; + default = name; + example = lib.literalExpression "./files/example.file"; + }; + + permissions = lib.mkOption { + type = with lib.types; nullOr (strMatching "[0-7]{0,4}"); + description = '' + The permissions of the node in octal. If the value is `null`, it + will be handled by Bubblewrap executable. For more details for each + operation, see {manpage}`bwrap(1)`. + ''; + default = null; + example = "0755"; + }; + + operation = lib.mkOption { + type = lib.types.enum (fileOperationsWithPerms ++ fileOperationsWithoutPerms); + description = '' + Specify what filesystem-related operations to be done for the given + filesystem object. Only certain operations accept permissions given + from {option}`sandboxing.bubblewrap.filesystem..permissions`. + ''; + default = "ro-bind-try"; + example = "bind"; + }; + + lock = lib.mkEnableOption "locking the file"; + }; + }; + + bindsType = with lib.types; listOf (oneOf [ str package ]); + in { + enableSharedNixStore = lib.mkEnableOption null // { + default = if isGlobal then true else cfg.enableSharedNixStore; + description = '' + Whether to share the entire Nix store directory. + ''; + }; + + sharedNixPaths = lib.mkOption { + type = with lib.types; listOf package; + default = [ ]; + description = if isGlobal then '' + A global list of store paths (including its dependencies) to be shared + per-Bubblewrap-enabled-wrappers. + '' else '' + A list of store paths to be mounted (as read-only bind-mounts). Note + that this also includes the listed store objects' dependencies. + ''; + example = lib.literalExpression '' + with pkgs; [ + gtk3 + ] + ''; + }; + + binds = { + ro = lib.mkOption { + type = bindsType; + default = [ ]; + description = + if isGlobal + then '' + Global list of read-only mounts to be given to all + Bubblewrap-enabled wrappers. + '' + else '' + List of read-only mounts to the Bubblewrap environment. + ''; + example = [ + "/etc/resolv.conf" + "/etc/ssh" + ]; + }; + + rw = lib.mkOption { + type = bindsType; + default = [ ]; + description = + if isGlobal + then '' + Global list of read-write mounts to be given to all + Bubblewrap-enabled wrappers. + '' + else '' + List of read-write mounts to the Bubblewrap environment. + ''; + }; + + dev = lib.mkOption { + type = bindsType; + default = [ ]; + description = + if isGlobal + then '' + Global list of devices to be mounted to all Bubblewrap-enabled + wrappers. + '' + else '' + List of devices to be mounted inside of the Bubblewrap environment. + ''; + }; + }; + + filesystem = lib.mkOption { + type = with lib.types; attrsOf (submodule filesystemSubmodule); + description = + if isGlobal then '' + Set of filesystem configurations to be copied to per-wrapper. + '' else '' + Set of wrapper-specific filesystem configurations in the Bubblewrap + environment. + ''; + default = { }; + example = lib.literalExpression '' + { + "/etc/hello" = { + source = ./files/hello; + permissions = "0700"; + operation = "file"; + }; + + "/etc/xdg" = { + permissions = "0700"; + operation = "dir"; + }; + + "/srv/data" = { + source = "/srv/data"; + operation = "symlink"; + }; + + "/srv/logs".operation = "dir"; + } + ''; + }; + }; + + # TODO: There has to be a better way to get this info without relying on + # pkgs.closureInfo builder, right? + getClosurePaths = rootPaths: + let + sharedNixPathsClosureInfo = pkgs.closureInfo { inherit rootPaths; }; + closurePaths = lib.readFile "${sharedNixPathsClosureInfo}/store-paths"; + in + lib.lists.filter (p: p != "") (lib.splitString "\n" closurePaths); +in +{ + options.sandboxing.bubblewrap = bubblewrapModuleFactory { isGlobal = true; }; + + options.wrappers = + let + bubblewrapModule = { config, lib, name, ... }: let + submoduleCfg = config.sandboxing.bubblewrap; + in { + options.sandboxing.bubblewrap = bubblewrapModuleFactory { isGlobal = false; }; + + config = lib.mkIf (config.sandboxing.variant == "bubblewrap") (lib.mkMerge [ + { + sandboxing.bubblewrap.binds = cfg.binds; + sandboxing.bubblewrap.sharedNixPaths = cfg.sharedNixPaths; + sandboxing.bubblewrap.filesystem = cfg.filesystem; + } + + { + sandboxing.bubblewrap.filesystem = + let + renameNixStorePaths = path: + if lib.isDerivation path then path.pname else path; + makeFilesystemMapping = operation: bind: + lib.nameValuePair (renameNixStorePaths bind) { + inherit operation; + source = builtins.toString bind; + destination = builtins.toString bind; + }; + filesystemMappings = + lib.lists.map (makeFilesystemMapping "ro-bind-try") submoduleCfg.binds.ro + ++ lib.lists.map (makeFilesystemMapping "bind-try") submoduleCfg.binds.rw + ++ lib.lists.map (makeFilesystemMapping "dev-bind-try") submoduleCfg.binds.dev; + in + builtins.listToAttrs filesystemMappings; + + sandboxing.bubblewrap.extraArgs = + let + makeFilesystemArgs = _: metadata: + let + src = metadata.source; + dst = metadata.destination; + hasPermissions = metadata.permissions != null; + isValidOperationWithPerms = lib.elem metadata.operation fileOperationsWithPerms; + in + # Take note of the ordering here such as `--perms` requiring + # to be before the file operation flags. + lib.optionals (hasPermissions && isValidOperationWithPerms) [ "--perms ${metadata.permissions}" ] + ++ ( + if lib.elem metadata.operation [ "dir" "remount-ro" ] + then [ "--${metadata.operation} ${dst}" ] + else [ "--${metadata.operation} ${src} ${dst}" ] + ) + ++ lib.optionals metadata.lock [ "--lock-file ${dst}" ]; + in + lib.lists.flatten (lib.mapAttrsToList makeFilesystemArgs submoduleCfg.filesystem); + } + + (lib.mkIf submoduleCfg.enableSharedNixStore { + sandboxing.bubblewrap.binds.ro = [ builtins.storeDir ] ++ lib.optionals (builtins.storeDir != "/nix/store") [ "/nix/store" ]; + }) + + (lib.mkIf (submoduleCfg.sharedNixPaths != [ ]) { + sandboxing.bubblewrap.extraArgs = + let + closurePaths = getClosurePaths submoduleCfg.sharedNixPaths; + in + builtins.map (p: "--ro-bind ${p} ${p}") closurePaths; + }) + + (lib.mkIf submoduleCfg.dbus.enable { + sandboxing.bubblewrap.dbus.filter.bwrapArgs = + let + closurePaths = getClosurePaths submoduleCfg.sharedNixPaths; + in + builtins.map (p: "--ro-bind ${p} ${p}") closurePaths; + }) + ]); + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule bubblewrapModule); + }; +} diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/launcher.nix b/modules/wrapper-manager/sandboxing/bubblewrap/launcher.nix new file mode 100644 index 00000000..cd1270c9 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/launcher.nix @@ -0,0 +1,87 @@ +# Module revolving around the specialized launcher. It is managed as a separate +# project in the launcher subdirectory. Just look into the source code as you +# would spelunk any other project. So far, the subproject itself doesn't have a +# good state of testing (which is just used as a program for this very purpose) +# so just use wrapper-manager's testing infra instead. +{ config, lib, options, pkgs, ... }: + +let + cfg = config.sandboxing.bubblewrap.launcher; + + bubblewrapModuleFactory = { isGlobal ? false }: { + package = lib.mkOption { + type = lib.types.package; + description = '' + Package containing the specialized Bubblewrap launcher used for this + module. + ''; + default = if isGlobal then pkgs.callPackage ./launcher/package.nix { } else cfg.package; + }; + + integrations = let + mkLauncherEnableOption = service: serviceName: lib.mkEnableOption "launcher integration for ${serviceName}" // { + default = if isGlobal then true else cfg.integrations.${service}.enable; + }; + in { + pipewire.enable = mkLauncherEnableOption "pipewire" "Pipewire"; + pulseaudio.enable = mkLauncherEnableOption "pulseaudio" "PulseAudio"; + wayland.enable = mkLauncherEnableOption "wayland" "Wayland desktop sessions"; + x11.enable = mkLauncherEnableOption "x11" "X11-based desktop sessions"; + }; + }; +in +{ + options.sandboxing.bubblewrap.launcher = bubblewrapModuleFactory { isGlobal = true; }; + + options.wrappers = + let + bubblewrapLauncherSubmodule = { config, lib, name, ... }: let + submoduleCfg = config.sandboxing.bubblewrap.launcher; + envSuffix = word: "WRAPPER_MANAGER_BWRAP_LAUNCHER_${word}"; + in { + options.sandboxing.bubblewrap.launcher = bubblewrapModuleFactory { isGlobal = false; }; + + config = lib.mkIf (config.sandboxing.variant == "bubblewrap") (lib.mkMerge [ + { + arg0 = lib.getExe' submoduleCfg.package "wrapper-manager-bubblewrap-launcher"; + prependArgs = lib.mkBefore + (config.sandboxing.bubblewrap.extraArgs + ++ [ "--" config.sandboxing.wraparound.arg0 ] + ++ config.sandboxing.wraparound.extraArgs); + env = { + "${envSuffix "BWRAP"}".value = lib.getExe' config.sandboxing.bubblewrap.package "bwrap"; + # We're just unsetting autoconfigure since we're configuring this + # through the module system anyways and would allow the user to + # have some more control over what can be enabled. + "${envSuffix "AUTOCONFIGURE"}".value = "0"; + }; + } + + (lib.mkIf config.sandboxing.bubblewrap.dbus.enable { + env.${envSuffix "DBUS_PROXY"}.value = lib.getExe' config.sandboxing.bubblewrap.dbus.filter.package "xdg-dbus-proxy"; + env.${envSuffix "DBUS_PROXY_ARGS"}.value = lib.concatStringsSep " " config.sandboxing.bubblewrap.dbus.filter.extraArgs; + env.${envSuffix "DBUS_PROXY_BWRAP_ARGS"}.value = lib.concatStringsSep " " config.sandboxing.bubblewrap.dbus.filter.bwrapArgs; + }) + + (lib.mkIf submoduleCfg.integrations.pulseaudio.enable { + env.${envSuffix "PULSEAUDIO"}.value = "1"; + }) + + (lib.mkIf submoduleCfg.integrations.pipewire.enable { + env.${envSuffix "PIPEWIRE"}.value = "1"; + }) + + (lib.mkIf submoduleCfg.integrations.x11.enable { + env.${envSuffix "X11"}.value = "1"; + }) + + (lib.mkIf submoduleCfg.integrations.wayland.enable { + env.${envSuffix "WAYLAND"}.value = "1"; + }) + ]); + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule bubblewrapLauncherSubmodule); + }; +} diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/launcher/CHANGELOG.adoc b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/CHANGELOG.adoc new file mode 100644 index 00000000..046a4a07 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/CHANGELOG.adoc @@ -0,0 +1,15 @@ += Changelog +:toc: + +All changes in this project will be documented for the users. +The structure is loosely based on https://keepachangelog.com/en/1.1.0/[Keep a changelog format]. + + +[#0-1-0] +== 0.1.0 (Unreleased) + +=== Added + +* Add conditional flags for Wayland, Pipewire, Pulseaudio, and X11-enabled setups. +* Init xdg-dbus-proxy support. +* Init Linux foot:[Pretty much the only OS to be supported.] support. diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/launcher/LICENSE b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/LICENSE new file mode 100644 index 00000000..ce20b53f --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2024 Gabriel Arazas + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/launcher/app.sh b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/app.sh new file mode 100644 index 00000000..fd40ab61 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/app.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash + +# A specialized launcher intended to handle a bunch of things in runtime such +# as adding flags when in certain systems and running xdg-dbus-proxy if +# required. Take note, we don't enforce any security model whatsoever, it's +# just a launcher that adds `bwrap` arguments in runtime for certain +# situations. +# +# Take note, we have the following design constraints for this launcher: +# +# * Using only the nixpkgs runtime shell and a few common dependencies found on +# Unix-adjacent systems. +# * No additional command-line options which means no flags and command-line +# parsing. This is essentially just a Bubblewrap wrapper. +# * If we ever let the user configure things, it should be done with +# environment variables with `WRAPPER_MANAGER_BWRAP_LAUNCHER` prefix. It's very +# long but who cares. +# * Ideally, there should be no options to clear the environment in this +# launcher. Let the user do it themselves if they want. + +declare -a additional_flags +: "${XDG_RUNTIME_DIR:="/run/user/$(id -u)"}" \ + "${WRAPPER_MANAGER_BWRAP_LAUNCHER_BWRAP:="bwrap"}" \ + "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY:="xdg-dbus-proxy"}" \ + "${WRAPPER_MANAGER_BWRAP_LAUNCHER_AUTOCONFIGURE:="1"}" + +is_autoconfigured_or() { + local service="$1" + [ "${WRAPPER_MANAGER_BWRAP_LAUNCHER_AUTOCONFIGURE}" = "1" ] || [ "${service}" = "1" ] +} + +# Bubblewrap is aggressively Linux-exclusive so we can add some things in here +# that are surely common within most Linux distros but just in case... +case "$(uname)" in + Linux*) + additional_flags+=(--proc /proc) + additional_flags+=(--dev /dev) + additional_flags+=(--dev-bind /dev/dri /dev/dri) + additional_flags+=(--tmpfs /tmp) + additional_flags+=(--ro-bind '/sys/dev/char' '/sys/dev/char') + additional_flags+=(--ro-bind '/sys/devices/pci0000:00' '/sys/devices/pci0000:00') + + # Check if we're in a NixOS system. + if [[ -f /etc/NIXOS ]]; then + additional_flags+=(--ro-bind /run/opengl-driver /run/opengl-driver) + + if [[ -d /run/opengl-driver-32 ]]; then + additional_flags+=(--ro-bind /run/opengl-driver-32 /run/opengl-driver-32) + fi + fi + + for sysfs_dir in /sys/{block,bus,class,dev,devices}; do + if [[ -r "$sysfs_dir" ]] && [[ -x "$sysfs_dir" ]]; then + additional_flags+=(--ro-bind "${sysfs_dir}" "${sysfs_dir}") + fi + done + ;; +esac + +# TODO: Much of the flags added here are so far just cargo-culted lmao. +# Investigate it pls for the love of God. + +# Bind Wayland if it's detected to be running on one. +if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_WAYLAND}" && [ -S "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" ]; then + additional_flags+=(--ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}") +fi + +# Bind Pipewire if it's detected. +if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_PIPEWIRE}" && [ -S "${XDG_RUNTIME_DIR}/pipewire-0" ]; then + additional_flags+=(--ro-bind "${XDG_RUNTIME_DIR}/pipewire-0" "${XDG_RUNTIME_DIR}/pipewire-0") +fi + +# Bind PulseAudio if it's detected and configured. +if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_PULSEAUDIO}" && [ -e "${XDG_RUNTIME_DIR}/pulse/pid" ]; then + additional_flags+=(--ro-bind "${XDG_RUNTIME_DIR}/pulse" "${XDG_RUNTIME_DIR}/pulse") +fi + +# Bind X11 thingies if it's configured and detected. +if is_autoconfigured_or "${WRAPPER_MANAGER_BWRAP_LAUNCHER_X11}" && [ "${XAUTHORITY}" ]; then + additional_flags+=(--ro-bind "${XAUTHORITY}" "${XAUTHORITY}") + additional_flags+=(--ro-bind '/tmp/.X11-unix' '/tmp/.X11-unix') +fi + +# TODO: Create a Flatpak workaround trick to enable sandboxing with XDG Portals. + +# Fork the D-Bus proxy in case it is needed. We only need to know if its needed +# if the *DBUS_PROXY_ARGS envvar is set. +if [ -n "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY_ARGS}" ] && [ -n "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY}" ]; then + ( + # We need the proxy-specific bwrap arguments to split since they are + # passed as a string. + # shellcheck disable=2068 + ${WRAPPER_MANAGER_BWRAP_LAUNCHER_BWRAP} \ + ${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY_BWRAP_ARGS[@]} \ + -- "${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY}" \ + ${WRAPPER_MANAGER_BWRAP_LAUNCHER_DBUS_PROXY_ARGS[@]} + ) & +fi +exec ${WRAPPER_MANAGER_BWRAP_LAUNCHER_BWRAP} "${additional_flags[@]}" "$@" diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/launcher/meson.build b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/meson.build new file mode 100644 index 00000000..0dc17e87 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/meson.build @@ -0,0 +1,13 @@ +project('wrapper-manager-bubblewrap-launcher', + version: '0.1.0', + license: 'MIT', + meson_version: '>=0.54.0', +) + +configure_file( + input: 'app.sh', + output: meson.project_name(), + install_dir: get_option('bindir'), + install_mode: 'rwxr-xr-x', + copy: true, +) diff --git a/modules/wrapper-manager/sandboxing/bubblewrap/launcher/package.nix b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/package.nix new file mode 100644 index 00000000..b180e658 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/bubblewrap/launcher/package.nix @@ -0,0 +1,21 @@ +{ + stdenv, + lib, + meson, + ninja +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "wrapper-manager-bubblewrap-launcher"; + version = "0.1.0"; + + src = lib.cleanSource ./.; + + nativeBuildInputs = [ meson ninja ]; + + meta = { + description = "wrapper-manager specialized launcher for Bubblewrap environments"; + license = lib.licenses.mit; + mainProgram = finalAttrs.pname; + }; +}) diff --git a/modules/wrapper-manager/sandboxing/default.nix b/modules/wrapper-manager/sandboxing/default.nix new file mode 100644 index 00000000..bed896b7 --- /dev/null +++ b/modules/wrapper-manager/sandboxing/default.nix @@ -0,0 +1,33 @@ +{ lib, ... }: + +{ + imports = [ + ./boxxy.nix + ./bubblewrap + ]; + + options.wrappers = + let + sandboxingType = { name, lib, config, options, ... }: { + options.sandboxing = { + variant = lib.mkOption { + type = with lib.types; nullOr (enum []); + description = '' + The sandboxing framework to be applied to the wrapper. A value of + `null` will essentially disable it. + ''; + default = null; + example = "bubblewrap"; + }; + + wraparound = { + arg0 = options.arg0; + extraArgs = options.appendArgs; + }; + }; + }; + in + lib.mkOption { + type = with lib.types; attrsOf (submodule sandboxingType); + }; +} diff --git a/overlays/default.nix b/overlays/default.nix index 883d1688..71bdd539 100644 --- a/overlays/default.nix +++ b/overlays/default.nix @@ -7,4 +7,5 @@ ffmpeg-foodogsquared = import ./ffmpeg-foodogsquared; firefox-foodogsquared = import ./firefox-foodogsquared; blender-foodogsquared = import ./blender-foodogsquared; + thunderbird-foodogsquared = import ./thunderbird-foodogsquared; } diff --git a/overlays/firefox-foodogsquared/default.nix b/overlays/firefox-foodogsquared/default.nix index 4e487518..813d6e0b 100644 --- a/overlays/firefox-foodogsquared/default.nix +++ b/overlays/firefox-foodogsquared/default.nix @@ -66,7 +66,11 @@ final: prev: install_url = mozillaAddon "wayback-machine_new"; default_area = "navbar"; }; - "zotero@chnm.gmu.edu".install_url = "https://download.zotero.org/connector/firefox/release/Zotero_Connector-5.0.114.xpi"; + "zotero@chnm.gmu.edu".install_url = "https://www.zotero.org/download/connector/dl?browser=firefox"; + "info@oahelper.org" = { + install_url = mozillaAddon "open-access-helper"; + default_area = "navbar"; + }; }; applyInstallationMode = name: value: diff --git a/overlays/thunderbird-foodogsquared/default.nix b/overlays/thunderbird-foodogsquared/default.nix new file mode 100644 index 00000000..640473d5 --- /dev/null +++ b/overlays/thunderbird-foodogsquared/default.nix @@ -0,0 +1,37 @@ +# My custom installation of Thunderbird where it's customized to be as +# standalone as possible. +final: prev: + +{ + thunderbird-foodogsquared = with prev; wrapThunderbird thunderbird-unwrapped { + extraPolicies = { + AppsAutoUpdate = false; + DisableAppUpdate = false; + + ExtensionSettings = let + thunderbirdAddon = name: + "https://addons.thunderbird.net/thunderbird/downloads/latest/${name}/latest.xpi"; + + extensions = { + "uBlock0@raymondhill.net" = { + installation_mode = "force_installed"; + installation_url = thunderbirdAddon "ublock-origin"; + }; + + "{e6696d02-466a-11e3-a162-04e36188709b}".installation_url = thunderbirdAddon "eds-calendar-integration"; + "quickfolders@curious.be".installation_url = thunderbirdAddon "quickfolders-tabbed-folders"; + }; + + applyInstallationMode = name: value: + lib.nameValuePair name (value // + (lib.optionalAttrs + (! (lib.hasAttrByPath [ "installation_mode" ] value)) + { installation_mode = "normal_installed"; })); + in + lib.mapAttrs' applyInstallationMode extensions; + + OfferToSaveLoginsDefault = false; + PasswordManagerEnabled = false; + }; + }; +} diff --git a/pkgs/README.adoc b/pkgs/README.adoc index d19355fe..3820d128 100644 --- a/pkgs/README.adoc +++ b/pkgs/README.adoc @@ -1,7 +1,7 @@ = Packages :toc: -My custom packages live here. +My custom packages and nixpkgs extensions live here. It is setup similar to link:https://github.com/NixOS/nixpkgs/[nixpkgs] and link:https://github.com/foo-dogsquared/nur[my previous NUR]. Thus, the conventions are similar to the package definitions in the mentioned repositories. diff --git a/pkgs/ctrld/default.nix b/pkgs/ctrld/default.nix new file mode 100644 index 00000000..793a1df0 --- /dev/null +++ b/pkgs/ctrld/default.nix @@ -0,0 +1,30 @@ +{ + lib, + fetchFromGitHub, + buildGoModule, +}: + +buildGoModule rec { + pname = "ctrld"; + version = "1.3.7"; + + src = fetchFromGitHub { + owner = "Control-D-Inc"; + repo = "ctrld"; + rev = "v${version}"; + hash = "sha256-3rAGH3GfCQR+Ii5KazsgQzydeWlPeHpiEvHNHQXjNVQ="; + }; + + vendorHash = "sha256-UN0gOFxMS0iWvg6Iv+aeYoduffJ9Zanz1htRh3ANjkY="; + + # It takes a long time so uhhh... + doCheck = false; + + meta = with lib; { + homepage = "https://github.com/Control-D-Inc/ctrld"; + description = "Multi-protocol DNS proxy"; + license = licenses.mit; + mainProgram = "ctrld"; + platforms = platforms.all; + }; +} diff --git a/pkgs/default.nix b/pkgs/default.nix index 82fd77d7..6be92c1b 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,36 +1,52 @@ { pkgs ? import { } }: -with pkgs; -lib.makeScope newScope (self: { +let + inherit (pkgs) lib callPackage python3Packages qt5; +in +lib.makeScope pkgs.newScope (self: { + # My custom nixpkgs extensions. + foodogsquaredLib = import ../lib { inherit pkgs; }; + inherit (self.foodogsquaredLib.builders) + makeXDGMimeAssociationList makeXDGPortalConfiguration makeXDGDesktopEntry + buildHugoSite; + inherit (self.foodogsquaredLib.fetchers) + fetchInternetArchive; + + # My custom packages. awesome-cli = callPackage ./awesome-cli { }; base16-builder-go = callPackage ./base16-builder-go { }; blender-blendergis = python3Packages.callPackage ./blender-blendergis { }; blender-machin3tools = python3Packages.callPackage ./blender-machin3tools { }; clidle = callPackage ./clidle.nix { }; - domterm = libsForQt5.callPackage ./domterm { }; + ctrld = callPackage ./ctrld { }; + domterm = qt5.callPackage ./domterm { }; fastn = callPackage ./fastn { }; + flatsync = callPackage ./flatsync { }; freerct = callPackage ./freerct.nix { }; distant = callPackage ./distant.nix { }; gnome-search-provider-recoll = callPackage ./gnome-search-provider-recoll.nix { }; hush-shell = callPackage ./hush-shell.nix { }; + lazyjj = callPackage ./lazyjj { }; lwp = callPackage ./lwp { }; moac = callPackage ./moac.nix { }; mopidy-beets = callPackage ./mopidy-beets.nix { }; mopidy-funkwhale = callPackage ./mopidy-funkwhale.nix { }; mopidy-internetarchive = callPackage ./mopidy-internetarchive.nix { }; + mopidy-listenbrainz = callPackage ./mopidy-listenbrainz { }; nautilus-annotations = callPackage ./nautilus-annotations { }; pop-launcher-plugin-brightness = callPackage ./pop-launcher-plugin-brightness { }; pop-launcher-plugin-duckduckgo-bangs = callPackage ./pop-launcher-plugin-duckduckgo-bangs.nix { }; pop-launcher-plugin-jetbrains = callPackage ./pop-launcher-plugin-jetbrains { }; - swh = callPackage ./software-heritage { python3Packages = python310Packages; }; + pigeon-mail = callPackage ./pigeon-mail { }; + swh = callPackage ./software-heritage { python3Packages = pkgs.python310Packages; }; speki = callPackage ./speki { }; tic-80 = callPackage ./tic-80 { }; smile = callPackage ./smile { }; sessiond = callPackage ./sessiond { }; uwsm = callPackage ./uwsm { }; - vgc = qt6Packages.callPackage ./vgc { }; + vgc = qt5.callPackage ./vgc { }; watc = callPackage ./watc { }; willow = callPackage ./willow { }; wzmach = callPackage ./wzmach { }; diff --git a/pkgs/fastn/Cargo.lock b/pkgs/fastn/Cargo.lock index af56beba..8d6c016a 100644 --- a/pkgs/fastn/Cargo.lock +++ b/pkgs/fastn/Cargo.lock @@ -9,12 +9,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2bc21ffc9b77e9c31e733bb7e937c11dcf6157bb74f80bf94734110aa9b9ebc" [[package]] -name = "actix-codec" -version = "0.5.1" +name = "accept-language" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" +checksum = "8f27d075294830fcab6f66e320dab524bc6d048f4a151698e153205559113772" + +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "bytes", "futures-core", "futures-sink", @@ -27,17 +33,17 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.3.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74" +checksum = "3ae682f693a9cd7b058f2b0b5d9a6d7728a8555779bedbbc35dd88528611d020" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", - "ahash 0.8.3", - "base64 0.21.2", - "bitflags 1.3.2", + "ahash", + "base64 0.22.1", + "bitflags 2.6.0", "brotli", "bytes", "bytestring", @@ -46,7 +52,7 @@ dependencies = [ "flate2", "futures-core", "h2", - "http", + "http 0.2.12", "httparse", "httpdate", "itoa", @@ -61,37 +67,39 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "zstd 0.12.3+zstd.1.5.2", + "zstd", ] [[package]] name = "actix-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 1.0.109", + "syn 2.0.70", ] [[package]] name = "actix-router" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", - "http", + "cfg-if", + "http 0.2.12", "regex", + "regex-lite", "serde", "tracing", ] [[package]] name = "actix-rt" -version = "2.8.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ "futures-core", "tokio", @@ -99,18 +107,17 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327" +checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" dependencies = [ "actix-rt", "actix-service", "actix-utils", "futures-core", "futures-util", - "mio 0.8.8", - "num_cpus", - "socket2 0.4.9", + "mio", + "socket2", "tokio", "tracing", ] @@ -138,9 +145,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.3.1" +version = "4.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3cb42f9566ab176e1ef0b8b3a896529062b4efc6be0123046095914c4c1c96" +checksum = "1988c02af8d2b718c05bc4aeb6a66395b7cdf32858c2c71131e5637a8c05a9ff" dependencies = [ "actix-codec", "actix-http", @@ -151,7 +158,7 @@ dependencies = [ "actix-service", "actix-utils", "actix-web-codegen", - "ahash 0.7.6", + "ahash", "bytes", "bytestring", "cfg-if", @@ -160,7 +167,6 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "http", "itoa", "language-tags", "log", @@ -168,34 +174,44 @@ dependencies = [ "once_cell", "pin-project-lite", "regex", + "regex-lite", "serde", "serde_json", "serde_urlencoded", "smallvec", - "socket2 0.4.9", + "socket2", "time", "url", ] [[package]] name = "actix-web-codegen" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2262160a7ae29e3415554a3f1fc04c764b1540c116aa524683208078b7a75bc9" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.70", ] [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli", + "gimli 0.28.1", +] + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli 0.29.0", ] [[package]] @@ -218,9 +234,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher 0.4.4", @@ -229,41 +245,22 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -283,12 +280,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "allocator-api2" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" - [[package]] name = "android-tzdata" version = "0.1.1" @@ -310,56 +301,56 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -370,15 +361,18 @@ checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] -name = "anymap" -version = "1.0.0-beta.2" +name = "arbitrary" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "arrayvec" @@ -386,56 +380,52 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - [[package]] name = "async-lock" -version = "2.7.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-recursion" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "async-trait" -version = "0.1.70" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79fa67157abdfd688a259b6648808757db9347af834624f27ec646da976aee5d" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ - "addr2line", + "addr2line 0.22.0", "cc", "cfg-if", "libc", @@ -446,30 +436,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.2" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" - -[[package]] -name = "base64-simd" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" -dependencies = [ - "simd-abstraction", -] - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -503,21 +478,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -556,9 +519,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "brotli" -version = "3.3.4" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -567,9 +530,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.4" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -577,9 +540,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "serde", @@ -587,58 +550,27 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bumpslab" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5816c875b50b9866d759fa24d46159dccab0d7942c0ccbfd700b4f45dd961e" -dependencies = [ - "bumpalo", -] - -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytestring" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" dependencies = [ "bytes", ] @@ -666,23 +598,19 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" [[package]] name = "cc" -version = "1.0.79" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "eaff6f8ce506b9773fa786672d63fc7a191ffea1be33f72bbd4aeacefca9ffc8" dependencies = [ "jobserver", + "libc", + "once_cell", ] [[package]] @@ -693,24 +621,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", - "winapi 0.3.9", -] - -[[package]] -name = "ci_info" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f638c70e8c5753795cc9a8c07c44da91554a09e4cf11a7326e8161b0a3c45e" -dependencies = [ - "envmnt", + "wasm-bindgen", + "windows-targets 0.52.6", ] [[package]] @@ -734,18 +655,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.11" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.3.11" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -755,85 +676,89 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "clift" +version = "0.1.6" +dependencies = [ + "clap", + "ignore", + "reqwest", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "tokio", +] + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", - "lazy_static 1.4.0", + "lazy_static 1.5.0", "windows-sys 0.48.0", ] [[package]] name = "comrak" -version = "0.14.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf1e432b302dc6236dd0db580d182ce520bb24af82d6462e2d7a5e0a31c50d" -dependencies = [ - "entities", - "lazy_static 1.4.0", - "memchr", - "pest", - "pest_derive", - "regex", - "shell-words", - "typed-arena 1.7.0", - "unicode_categories", - "xdg", -] - -[[package]] -name = "comrak" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "482aa5695bca086022be453c700a40c02893f1ba7098a2c88351de55341ae894" +checksum = "5a972c8ec1be8065f7b597b5f7f5b3be535db780280644aebdcd1966decf58dc" dependencies = [ + "derive_builder", "entities", "memchr", "once_cell", "regex", "slug", - "typed-arena 2.0.2", + "typed-arena", "unicode_categories", ] [[package]] -name = "const-str" -version = "0.3.2" +name = "concurrent-queue" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21077772762a1002bb421c3af42ac1725fa56066bfc53d9a55bb79905df2aaf3" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "const-str-proc-macro", + "crossbeam-utils", ] [[package]] -name = "const-str-proc-macro" -version = "0.3.2" +name = "console" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1e0fdd2e5d3041e530e1b21158aeeef8b5d0e306bc5c1e3d6cf0930d10e25a" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "encode_unicode", + "lazy_static 1.5.0", + "libc", + "unicode-width", + "windows-sys 0.52.0", ] [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "convert_case" @@ -841,6 +766,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cookie" version = "0.16.2" @@ -854,155 +788,204 @@ dependencies = [ [[package]] name = "copy_dir" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4281031634644843bd2f5aa9c48cf98fc48d6b083bd90bb11becf10deaf8b0" +checksum = "543d1dd138ef086e2ff05e3a48cf9da045da2033d16f8538fd76b86cd49b2ca3" dependencies = [ - "walkdir 0.1.8", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", + "walkdir", ] [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpp_demangle" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +dependencies = [ + "cfg-if", +] [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] -name = "crc-any" -version = "2.4.3" +name = "cranelift-bforest" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774646b687f63643eb0f4bf13dc263cb581c8c9e57973b6ddf78bda3994d88df" +checksum = "0b6b33d7e757a887989eb18b35712b2a67d96171ec3149d1bfb657b29b7b367c" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9acf15cb22be42d07c3b57d7856329cb228b7315d385346149df2566ad5e4aa" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli 0.28.1", + "hashbrown 0.14.5", + "log", + "regalloc2", + "rustc-hash", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e934d301392b73b3f8b0540391fb82465a0f179a3cee7c726482ac4727efcc97" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb2a2566b3d54b854dfb288b3b187f6d3d17d6f762c92898207eba302931da" + +[[package]] +name = "cranelift-control" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0100f33b704cdacd01ad66ff41f8c5030d57cbff078e2a4e49ab1822591299fa" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8cfdc315e5d18997093e040a8d234bea1ac1e118a716d3e30f40d449e78207b" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "cranelift-frontend" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f74b84f16af2e982b0c0c72233503d9d55cbfe3865dbe807ca28dc6642a28b5" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adf306d3dde705fb94bd48082f01d38c4ededc74293a4c007805f610bf08bc6e" + +[[package]] +name = "cranelift-native" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea0ebdef7aff4a79bcbc8b6495f31315f16b3bf311152f472eaa8d679352581" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d549108a1942065cdbac3bb96c2952afa0e1b9a3beff4b08c4308ac72257576d" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools 0.12.1", + "log", + "smallvec", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-any" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62ec9ff5f7965e4d7280bd5482acd20aadb50d632cf6c1d74493856b011fa73" dependencies = [ "debug-helper", ] [[package]] -name = "crc32fast" -version = "1.3.2" +name = "crc-catalog" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] -name = "crossbeam-channel" -version = "0.5.8" +name = "crc32fast" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", - "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossterm" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" -dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio 0.7.14", - "parking_lot 0.11.2", - "signal-hook", - "signal-hook-mio", - "winapi 0.3.9", -] - -[[package]] -name = "crossterm" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" -dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio 0.8.8", - "parking_lot 0.12.1", - "signal-hook", - "signal-hook-mio", - "winapi 0.3.9", -] - -[[package]] -name = "crossterm" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" -dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio 0.8.8", - "parking_lot 0.12.1", - "signal-hook", - "signal-hook-mio", - "winapi 0.3.9", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi 0.3.9", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -1023,156 +1006,58 @@ dependencies = [ "lazy_static 0.1.16", ] -[[package]] -name = "cssparser" -version = "0.29.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "matches", - "phf 0.10.1", - "proc-macro2", - "quote", - "smallvec", - "syn 1.0.109", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn 2.0.23", -] - -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "darling" -version = "0.14.4" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - -[[package]] -name = "darling" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" -dependencies = [ - "darling_core 0.20.1", - "darling_macro 0.20.1", + "darling_core", + "darling_macro", ] [[package]] name = "darling_core" -version = "0.14.4" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "darling_macro" -version = "0.14.4" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.14.4", + "darling_core", "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" -dependencies = [ - "darling_core 0.20.1", - "quote", - "syn 2.0.23", -] - -[[package]] -name = "dashmap" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" -dependencies = [ - "cfg-if", - "hashbrown 0.12.3", - "lock_api", - "once_cell", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "data-encoding" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" - -[[package]] -name = "data-url" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193" -dependencies = [ - "matches", + "syn 2.0.70", ] [[package]] name = "deadpool" -version = "0.9.5" -source = "git+https://github.com/amitu/deadpool?rev=dbf5a46#dbf5a460d5e9dcc1db44c4a2c23e26d92462a337" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" dependencies = [ "async-trait", "deadpool-runtime", "num_cpus", - "retain_mut", "tokio", ] [[package]] name = "deadpool-postgres" -version = "0.10.5" -source = "git+https://github.com/amitu/deadpool?rev=dbf5a46#dbf5a460d5e9dcc1db44c4a2c23e26d92462a337" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda39fa1cfff190d8924d447ad04fd22772c250438ca5ce1dfb3c80621c05aaa" dependencies = [ "deadpool", "tokio", @@ -1182,8 +1067,9 @@ dependencies = [ [[package]] name = "deadpool-runtime" -version = "0.1.2" -source = "git+https://github.com/amitu/deadpool?rev=dbf5a46#dbf5a460d5e9dcc1db44c4a2c23e26d92462a337" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" dependencies = [ "tokio", ] @@ -1195,16 +1081,82 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" [[package]] -name = "derive_more" -version = "0.99.17" +name = "debugid" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "convert_case", + "uuid", +] + +[[package]] +name = "deflate64" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83ace6c86376be0b6cdcf3fb41882e81d94b31587573d1cfa9d01cd06bba210d" + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core", + "syn 2.0.70", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.70", ] [[package]] @@ -1220,9 +1172,9 @@ dependencies = [ [[package]] name = "deunicode" -version = "0.4.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" [[package]] name = "diff" @@ -1232,11 +1184,11 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "diffy" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e616e59155c92257e84970156f506287853355f58cd4a6eb167385722c32b790" +checksum = "5d3041965b7a63e70447ec818a46b1e5297f7fcae3058356d226c02750c4e6cb" dependencies = [ - "nu-ansi-term", + "nu-ansi-term 0.50.0", ] [[package]] @@ -1260,114 +1212,87 @@ dependencies = [ ] [[package]] -name = "dioxus-core" -version = "0.3.2" -source = "git+https://github.com/DioxusLabs/dioxus?rev=fb52673433cc57a70c86185ffa7da5fa3a2394da#fb52673433cc57a70c86185ffa7da5fa3a2394da" +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" dependencies = [ - "bumpalo", - "bumpslab", - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "log", - "longest-increasing-subsequence", - "rustc-hash", - "serde", - "slab", - "smallbox", + "cfg-if", + "dirs-sys-next", ] [[package]] -name = "dioxus-html" -version = "0.3.1" -source = "git+https://github.com/DioxusLabs/dioxus?rev=fb52673433cc57a70c86185ffa7da5fa3a2394da#fb52673433cc57a70c86185ffa7da5fa3a2394da" +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "async-trait", - "dioxus-core", - "enumset", - "euclid", - "keyboard-types", - "serde", - "serde-value", - "serde_repr", + "dirs-sys", ] [[package]] -name = "dioxus-native-core" -version = "0.2.0" -source = "git+https://github.com/DioxusLabs/dioxus?rev=fb52673433cc57a70c86185ffa7da5fa3a2394da#fb52673433cc57a70c86185ffa7da5fa3a2394da" +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ - "anymap", - "crossbeam-deque", - "dashmap", - "hashbrown 0.13.2", - "keyboard-types", - "lightningcss", - "parking_lot 0.12.1", - "rayon", - "rustc-hash", - "shipyard", - "slab", - "smallvec", - "taffy 0.2.2", + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", ] [[package]] -name = "dioxus-native-core-macro" -version = "0.3.0" -source = "git+https://github.com/DioxusLabs/dioxus?rev=fb52673433cc57a70c86185ffa7da5fa3a2394da#fb52673433cc57a70c86185ffa7da5fa3a2394da" +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "quote", - "syn 1.0.109", + "libc", + "redox_users", + "winapi", ] [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] -name = "dtoa" -version = "1.0.8" +name = "dotenvy" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519b83cd10f5f6e969625a409f735182bea5558cd8b64c655806ceaae36f1999" - -[[package]] -name = "dtoa-short" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" -dependencies = [ - "dtoa", -] - -[[package]] -name = "edit" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c562aa71f7bc691fde4c6bf5f93ae5a5298b617c2eb44c76c87832299a17fbb4" -dependencies = [ - "tempfile", - "which", -] +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "either" -version = "1.8.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1399,91 +1324,64 @@ dependencies = [ ] [[package]] -name = "enumset" -version = "1.1.2" +name = "env_filter" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" dependencies = [ - "enumset_derive", -] - -[[package]] -name = "enumset_derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" -dependencies = [ - "darling 0.20.1", - "proc-macro2", - "quote", - "syn 2.0.23", + "log", + "regex", ] [[package]] name = "env_logger" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ + "anstream", + "anstyle", + "env_filter", "humantime", - "is-terminal", "log", - "regex", - "termcolor", -] - -[[package]] -name = "envmnt" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d328fc287c61314c4a61af7cfdcbd7e678e39778488c7cb13ec133ce0f4059" -dependencies = [ - "fsio", - "indexmap 1.9.3", ] [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "euclid" -version = "0.22.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" -dependencies = [ - "num-traits", - "serde", + "windows-sys 0.52.0", ] [[package]] name = "event-listener" -version = "2.5.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] [[package]] name = "fallible-iterator" @@ -1491,6 +1389,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "fallible-streaming-iterator" version = "0.1.9" @@ -1499,9 +1403,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fancy-regex" -version = "0.7.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" dependencies = [ "bit-set", "regex", @@ -1509,35 +1413,24 @@ dependencies = [ [[package]] name = "fastn" -version = "0.3.0" -dependencies = [ - "clap", - "colored", - "fastn-cloud", - "fastn-core", - "thiserror", - "tokio", - "tracing", - "tracing-forest", - "tracing-subscriber", -] - -[[package]] -name = "fastn-cloud" -version = "0.1.0" +version = "0.4.75" dependencies = [ + "actix-web", "camino", + "clap", + "clift", + "deadpool-postgres", + "dotenvy", "fastn-core", + "fastn-ds", + "fastn-observer", + "fastn-update", "futures", - "home", - "mime_guess", "reqwest", + "scc", "serde", - "serde_json", - "tejar", "thiserror", "tokio", - "walkdir 2.3.3", ] [[package]] @@ -1548,65 +1441,113 @@ dependencies = [ "antidote", "async-lock", "async-recursion", + "async-trait", + "bytes", "camino", + "chrono", "clap", "colored", + "deadpool", "deadpool-postgres", "diffy", - "edit", + "dirs", "env_logger", + "fastn-ds", + "fastn-expr", + "fastn-js", + "fastn-observer", "fastn-package", + "fastn-utils", "fbt-lib", - "fluent", - "ftd 0.3.0", + "ft-sys-shared", + "ftd", + "ftd-ast", + "ftd-p1", "futures", + "futures-core", + "futures-util", + "http 1.1.0", "hyper", "ignore", - "indoc 2.0.2", - "intl-memoizer", - "itertools", - "magic-crypt", + "indoc", + "itertools 0.13.0", "mime_guess", - "native-tls", - "notify", - "oauth2", "once_cell", - "postgres-native-tls", "postgres-types", "pretty_assertions", + "rand", "realm-lang", "regex", "reqwest", "rusqlite", - "rusty-hook", + "scc", "serde", "serde_json", - "sha2 0.10.7", - "slug", + "sha2 0.10.8", "thiserror", "tokio", "tokio-postgres", "tracing", - "tracing-forest", "tracing-subscriber", "url", "zip", ] +[[package]] +name = "fastn-ds" +version = "0.1.0" +dependencies = [ + "actix-http", + "actix-web", + "async-lock", + "async-trait", + "bytes", + "camino", + "chrono", + "deadpool", + "deadpool-postgres", + "dirs", + "fastn-utils", + "ft-sys-shared", + "futures-util", + "http 1.1.0", + "ignore", + "libsqlite3-sys", + "magic-crypt", + "once_cell", + "rand", + "reqwest", + "rusqlite", + "scc", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-postgres", + "tracing", + "url", + "wasmtime", +] + +[[package]] +name = "fastn-expr" +version = "0.1.0" +dependencies = [ + "thiserror", +] + [[package]] name = "fastn-grammar" version = "0.1.0" dependencies = [ - "ron", "serde", - "serde_json", ] [[package]] name = "fastn-issues" version = "0.1.0" dependencies = [ - "ftd 0.3.0", + "ftd", "rusqlite", "thiserror", ] @@ -1616,12 +1557,36 @@ name = "fastn-js" version = "0.1.0" dependencies = [ "fastn-grammar", - "indoc 2.0.2", - "itertools", + "indoc", + "itertools 0.13.0", + "prettify-js", "pretty", - "pretty_assertions", "quick-js", "rquickjs", + "thiserror", +] + +[[package]] +name = "fastn-lang" +version = "0.1.0" +dependencies = [ + "accept-language 3.1.0", + "enum-iterator", + "enum-iterator-derive", + "serde", + "thiserror", +] + +[[package]] +name = "fastn-observer" +version = "0.1.0" +source = "git+https://github.com/fastn-stack/fastn-observer?rev=5f64c7b#5f64c7b28b447ce76e24e9428a9c113fa11118fb" +dependencies = [ + "ansi_term", + "smallvec", + "tokio", + "tracing", + "tracing-subscriber", ] [[package]] @@ -1629,9 +1594,9 @@ name = "fastn-package" version = "0.1.0" dependencies = [ "async-trait", - "camino", "fastn-issues", - "ftd 0.3.0", + "ftd", + "ftd-ast", "futures", "rusqlite", "serde", @@ -1639,93 +1604,62 @@ dependencies = [ ] [[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +name = "fastn-update" +version = "0.1.0" dependencies = [ - "instant", + "bytes", + "colored", + "fastn-core", + "fastn-ds", + "indicatif", + "serde_json", + "sha2 0.10.8", + "snafu", + "thiserror", + "tracing", + "zip", +] + +[[package]] +name = "fastn-utils" +version = "0.1.0" +dependencies = [ + "ft-sys-shared", + "rusqlite", + "serde_json", + "thiserror", + "wasmtime", +] + +[[package]] +name = "fbt" +version = "0.1.18" +dependencies = [ + "fbt-lib", ] [[package]] name = "fbt-lib" version = "0.1.18" -source = "git+https://github.com/FifthTry/fbt?rev=ea0ee98#ea0ee9832ab515c8acf7f0a1f4d89f2d4e6671eb" dependencies = [ "colored", "diffy", - "ftd 0.2.0", + "ftd", "rand", - "sha2 0.10.7", - "walkdir 2.3.3", -] - -[[package]] -name = "filetime" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", + "sha2 0.10.8", + "walkdir", ] [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", ] -[[package]] -name = "fluent" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7" -dependencies = [ - "fluent-bundle", - "unic-langid", -] - -[[package]] -name = "fluent-bundle" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd" -dependencies = [ - "fluent-langneg", - "fluent-syntax", - "intl-memoizer", - "intl_pluralrules", - "rustc-hash", - "self_cell", - "smallvec", - "unic-langid", -] - -[[package]] -name = "fluent-langneg" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" -dependencies = [ - "unic-langid", -] - -[[package]] -name = "fluent-syntax" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78" -dependencies = [ - "thiserror", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1733,25 +1667,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +name = "foo" +version = "0.1.0" dependencies = [ - "foreign-types-shared", + "tokio", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1766,28 +1692,16 @@ dependencies = [ ] [[package]] -name = "fsio" -version = "0.1.3" +name = "ft-sys-shared" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd087255f739f4f1aeea69f11b72f8080e9c2e7645cd06955dad4a178a49e3" - -[[package]] -name = "ftd" -version = "0.2.0" -source = "git+https://github.com/FifthTry/ftd?rev=b698bd6#b698bd6acf4b6dfc1557976ef63f378c473e8432" +checksum = "a5b532b534b1d9ac90e67a134ff546747fc1754b52891603f100a565acd9a889" dependencies = [ - "comrak 0.14.0", - "css-color-parser", - "format_num", - "include_dir", - "indoc 1.0.9", - "itertools", - "once_cell", - "regex", + "bytes", + "chrono", + "http 1.1.0", + "rusqlite", "serde", - "serde_json", - "slug", - "syntect", "thiserror", ] @@ -1795,52 +1709,69 @@ dependencies = [ name = "ftd" version = "0.3.0" dependencies = [ - "comrak 0.18.0", - "crossterm 0.26.1", + "comrak", "css-color-parser", "diffy", - "dioxus-html", - "dioxus-native-core", - "dioxus-native-core-macro", "fastn-grammar", "fastn-js", "format_num", - "futures", + "ftd-ast", + "ftd-p1", "include_dir", - "indexmap 2.0.0", - "indoc 2.0.2", - "itertools", + "indexmap", + "indoc", + "itertools 0.13.0", "once_cell", - "prettify-js", "pretty_assertions", - "rand", - "rand_pcg", "regex", - "rink", - "ron", - "rustc-hash", - "rusty-hook", "serde", "serde_json", "slug", "syntect", - "taffy 0.3.12", "thiserror", - "tokio", "tracing", ] [[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +name = "ftd-ast" +version = "0.1.0" +dependencies = [ + "colored", + "ftd-p1", + "itertools 0.13.0", + "pretty_assertions", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "ftd-p1" +version = "0.1.0" +dependencies = [ + "diffy", + "indoc", + "itertools 0.13.0", + "pretty_assertions", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "ftd-tc" +version = "0.1.0" +dependencies = [ + "ftd-ast", + "ftd-p1", + "thiserror", +] [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1853,9 +1784,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1863,15 +1794,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1880,38 +1811,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1934,6 +1865,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "fxprof-processed-profile" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" +dependencies = [ + "bitflags 2.6.0", + "debugid", + "fxhash", + "serde", + "serde_json", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1944,123 +1888,111 @@ dependencies = [ "version_check", ] -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "globset" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ - "aho-corasick 0.7.20", - "bstr", - "fnv", - "log", - "regex", + "fallible-iterator 0.3.0", + "indexmap", + "stable_deref_trait", ] [[package]] -name = "grid" -version = "0.9.0" +name = "gimli" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0634107a3a005070dd73e27e74ecb691a94e9e5ba7829f434db7fbf73a6b5c47" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ - "no-std-compat", + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", ] [[package]] name = "h2" -version = "0.3.20" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 1.9.3", + "http 0.2.12", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - [[package]] name = "hashbrown" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", + "ahash", ] [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.3", - "allocator-api2", + "ahash", + "serde", ] [[package]] name = "hashlink" -version = "0.8.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.5", ] [[package]] -name = "hermit-abi" -version = "0.3.2" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hex" -version = "0.4.3" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hmac" @@ -2072,19 +2004,21 @@ dependencies = [ ] [[package]] -name = "home" -version = "0.5.5" +name = "http" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "windows-sys 0.48.0", + "bytes", + "fnv", + "itoa", ] [[package]] name = "http" -version = "0.2.9" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -2093,26 +2027,38 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -2122,67 +2068,74 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", - "h2", - "http", + "http 1.1.0", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", - "http", + "http 1.1.0", "hyper", + "hyper-util", "rustls", + "rustls-pki-types", "tokio", "tokio-rustls", + "tower-service", + "webpki-roots", ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-util" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", "hyper", - "native-tls", + "pin-project-lite", + "socket2", "tokio", - "tokio-native-tls", + "tower", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -2194,6 +2147,12 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + [[package]] name = "ident_case" version = "1.0.1" @@ -2202,9 +2161,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2212,35 +2171,34 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static 1.4.0", "log", "memchr", - "regex", + "regex-automata", "same-file", - "thread_local", - "walkdir 2.3.3", + "walkdir", "winapi-util", ] [[package]] name = "include_dir" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" dependencies = [ "include_dir_macros", ] [[package]] name = "include_dir_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ "proc-macro2", "quote", @@ -2248,56 +2206,33 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.5", "serde", ] [[package]] -name = "indoc" -version = "1.0.9" +name = "indicatif" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" - -[[package]] -name = "indoc" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761cde40c27e2a9877f8c928fd248b7eec9dd48623dd514b256858ca593fbba7" - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", ] [[package]] -name = "inotify-sys" -version = "0.1.5" +name = "indoc" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "inout" @@ -2310,134 +2245,87 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] -[[package]] -name = "intl-memoizer" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" -dependencies = [ - "type-map", - "unic-langid", -] - -[[package]] -name = "intl_pluralrules" -version = "7.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" -dependencies = [ - "unic-langid", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] -name = "is-terminal" -version = "0.4.8" +name = "is_terminal_polyfill" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ - "hermit-abi", - "rustix 0.38.3", - "windows-sys 0.48.0", + "either", ] [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "keyboard-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7668b7cff6a51fe61cdde64cd27c8a220786f399501b57ebe36f7d8112fd68" -dependencies = [ - "bitflags 1.3.2", - "serde", - "unicode-segmentation", -] - -[[package]] -name = "kqueue" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - [[package]] name = "language-tags" version = "0.3.2" @@ -2452,15 +2340,27 @@ checksum = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libquickjs-sys" @@ -2473,48 +2373,26 @@ dependencies = [ ] [[package]] -name = "libsqlite3-sys" -version = "0.26.0" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" dependencies = [ "cc", "pkg-config", "vcpkg", ] -[[package]] -name = "lightningcss" -version = "1.0.0-alpha.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cc864b2dc5f078725908d7be7b35ce934e156ff52db40643ba6cb55f813c14" -dependencies = [ - "ahash 0.7.6", - "bitflags 2.3.3", - "const-str", - "cssparser", - "dashmap", - "data-encoding", - "itertools", - "lazy_static 1.4.0", - "parcel_selectors", - "parcel_sourcemap", - "paste", - "pathdiff", - "rayon", - "serde", - "smallvec", -] - -[[package]] -name = "line-wrap" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -2523,64 +2401,76 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "local-channel" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" dependencies = [ "futures-core", "futures-sink", - "futures-util", "local-waker", ] [[package]] name = "local-waker" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", ] [[package]] -name = "log" -version = "0.4.19" +name = "lockfree-object-pool" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lzma-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] [[package]] name = "magic-crypt" -version = "3.1.12" +version = "3.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0196bd5c76f5f51d7d6563545f86262fef4c82d75466ba6f6d359c40a523318d" +checksum = "6c42f95f9d296f2dcb50665f507ed5a68a171453142663ce44d77a4eb217b053" dependencies = [ "aes 0.7.5", - "base64 0.13.1", + "base64 0.21.7", "block-modes", "crc-any", "des", @@ -2590,12 +2480,6 @@ dependencies = [ "tiger", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "md-5" version = "0.9.1" @@ -2609,24 +2493,34 @@ dependencies = [ [[package]] name = "md-5" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ + "cfg-if", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix", +] [[package]] name = "memoffset" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] @@ -2639,9 +2533,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -2649,31 +2543,18 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.7.14" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi 0.3.9", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2681,70 +2562,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static 1.4.0", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nias" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab250442c86f1850815b5d268639dff018c0627022bc1940eb2d642ca1ce12f0" - -[[package]] -name = "no-std-compat" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" - -[[package]] -name = "notify" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51" -dependencies = [ - "bitflags 1.3.2", - "filetime", - "inotify", - "kqueue", - "libc", - "mio 0.8.8", - "walkdir 2.3.3", - "windows-sys 0.45.0", -] - -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2752,14 +2569,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "num-traits" -version = "0.2.15" +name = "nu-ansi-term" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -2775,113 +2607,40 @@ dependencies = [ ] [[package]] -name = "oauth2" -version = "4.4.1" +name = "number_prefix" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a6e2a2b13a56ebeabba9142f911745be6456163fd6c3d361274ebcd891a80c" -dependencies = [ - "base64 0.13.1", - "chrono", - "getrandom", - "http", - "rand", - "reqwest", - "serde", - "serde_json", - "serde_path_to_error", - "sha2 0.10.7", - "thiserror", - "url", -] +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.31.1" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ + "crc32fast", + "hashbrown 0.14.5", + "indexmap", "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] -name = "openssl" -version = "0.10.55" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.23", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "outref" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "overload" @@ -2890,178 +2649,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] -name = "parcel_selectors" -version = "0.26.0" +name = "parking" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e808c7a75aedcc522bd24187de6903adab3265d690a61f8b8181edaa988377" -dependencies = [ - "bitflags 2.3.3", - "cssparser", - "fxhash", - "log", - "phf 0.10.1", - "phf_codegen", - "precomputed-hash", - "smallvec", -] - -[[package]] -name = "parcel_sourcemap" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "485b74d7218068b2b7c0e3ff12fbc61ae11d57cb5d8224f525bd304c6be05bbb" -dependencies = [ - "base64-simd", - "data-url", - "rkyv", - "serde", - "serde_json", - "vlq", -] +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.48.1", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" - -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", "hmac", - "password-hash", - "sha2 0.10.7", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "pest" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.23", -] - -[[package]] -name = "pest_meta" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" -dependencies = [ - "once_cell", - "pest", - "sha2 0.10.7", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros", - "phf_shared 0.10.0", - "proc-macro-hack", -] +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -3069,50 +2705,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" -dependencies = [ - "phf_generator", - "phf_shared 0.10.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", + "phf_shared", ] [[package]] @@ -3125,10 +2718,30 @@ dependencies = [ ] [[package]] -name = "pin-project-lite" -version = "0.2.10" +name = "pin-project" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -3138,80 +2751,84 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.4.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.2", - "indexmap 1.9.3", - "line-wrap", + "base64 0.22.1", + "indexmap", "quick-xml", "serde", "time", ] [[package]] -name = "postgres-native-tls" -version = "0.5.0" +name = "portable-atomic" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d442770e2b1e244bb5eb03b31c79b65bb2568f413b899eaba850fa945a65954" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" dependencies = [ - "futures", - "native-tls", - "tokio", - "tokio-native-tls", - "tokio-postgres", + "cobs", + "embedded-io", + "serde", ] [[package]] name = "postgres-protocol" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b7fa9f396f51dffd61546fd8573ee20592287996568e6175ceb0f8699ad75d" +checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "byteorder", "bytes", - "fallible-iterator", + "fallible-iterator 0.2.0", "hmac", - "md-5 0.10.5", + "md-5 0.10.6", "memchr", "rand", - "sha2 0.10.7", + "sha2 0.10.8", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f028f05971fe20f512bcc679e2c10227e57809a3af86a7606304435bc8896cd6" +checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" dependencies = [ "bytes", - "fallible-iterator", + "fallible-iterator 0.2.0", "postgres-protocol", "serde", "serde_json", + "uuid", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - [[package]] name = "prettify-js" version = "0.1.0" @@ -3226,24 +2843,22 @@ dependencies = [ [[package]] name = "pretty" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563c9d701c3a31dfffaaf9ce23507ba09cbe0b9125ba176d15e629b0235e9acc" +checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" dependencies = [ - "arrayvec 0.5.2", - "typed-arena 2.0.2", - "unicode-segmentation", + "arrayvec", + "typed-arena", + "unicode-width", ] [[package]] name = "pretty_assertions" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "ctor", "diff", - "output_vt100", "yansi", ] @@ -3254,7 +2869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -3281,39 +2896,22 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] -name = "ptr_meta" -version = "0.1.4" +name = "psm" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "cc", ] [[package]] @@ -3328,27 +2926,68 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.28.2" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] [[package]] -name = "quote" -version = "1.0.29" +name = "quinn" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" dependencies = [ - "proc-macro2", + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", ] [[package]] -name = "radium" -version = "0.7.0" +name = "quinn-proto" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] [[package]] name = "rand" @@ -3380,20 +3019,11 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_pcg" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" -dependencies = [ - "rand_core", -] - [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3401,14 +3031,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -3417,7 +3045,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a276abf828a904b7cfe15798441f9c99d57004a7c2e11d24bab2de0cd587a9" dependencies = [ - "accept-language", + "accept-language 2.0.0", "enum-iterator", "enum-iterator-derive", "serde", @@ -3426,104 +3054,119 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", ] [[package]] name = "regex" -version = "1.9.0" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89089e897c013b3deb627116ae56a6955a72b8bed395c9526af31c9fe528b484" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.7.3", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.3.0" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa250384981ea14565685dea16a9ccc4d1c541a13f82b9c168572264d1df8c56" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", - "regex-syntax 0.7.3", + "regex-syntax", ] [[package]] -name = "regex-syntax" -version = "0.6.29" +name = "regex-lite" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relative-path" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" - -[[package]] -name = "rend" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" -dependencies = [ - "bytecheck", -] +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64 0.21.2", + "base64 0.22.1", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2", - "http", + "http 1.1.0", "http-body", + "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "tokio", - "tokio-native-tls", "tokio-rustls", "tower-service", "url", @@ -3544,93 +3187,26 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "retain_mut" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" - [[package]] name = "ring" -version = "0.16.20" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi 0.3.9", -] - -[[package]] -name = "rink" -version = "0.2.2" -source = "git+https://github.com/DioxusLabs/dioxus?rev=fb52673433cc57a70c86185ffa7da5fa3a2394da#fb52673433cc57a70c86185ffa7da5fa3a2394da" -dependencies = [ - "anyhow", - "anymap", - "crossterm 0.23.2", - "dioxus-html", - "dioxus-native-core", - "dioxus-native-core-macro", - "futures", - "futures-channel", - "once_cell", - "rustc-hash", - "shipyard", - "smallvec", - "taffy 0.2.2", - "tokio", - "tui", -] - -[[package]] -name = "rkyv" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" -dependencies = [ - "bitvec", - "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ron" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff" -dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", - "serde", + "windows-sys 0.52.0", ] [[package]] name = "rquickjs" -version = "0.1.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc022cc82b5de6f38b2f4ddb8ed9c49cdbd7ce112e650b181598e102157257de" +checksum = "9cbd33e0b668aea0ab238b9164523aca929096f9f40834700d71d91dd4888882" dependencies = [ "rquickjs-core", "rquickjs-macro", @@ -3638,9 +3214,9 @@ dependencies = [ [[package]] name = "rquickjs-core" -version = "0.1.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa1ecc1c84b31da87e5b26ce2b5218d36ffeb5c322141c78b79fa86a6ee3b9" +checksum = "2e9129d69b7b8f7ee8ad1da5b12c7f4a8a8acd45f2e6dd9cb2ee1bc5a1f2fa3d" dependencies = [ "relative-path", "rquickjs-sys", @@ -3648,39 +3224,39 @@ dependencies = [ [[package]] name = "rquickjs-macro" -version = "0.1.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a59ea6b93ccb811b02fefef0eec225d7fed0366b929ebf849afb22013c2953a0" +checksum = "c7d2ecaf7c9eda262e02a91e9541989a9dd18984d17d0d97f99f33b464318057" dependencies = [ - "darling 0.14.4", + "convert_case 0.6.0", "fnv", "ident_case", - "indexmap 1.9.3", + "indexmap", "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", "rquickjs-core", - "syn 1.0.109", + "syn 2.0.70", ] [[package]] name = "rquickjs-sys" -version = "0.1.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24311952af42d8252e399cf48e7d470cb413b1a11a1a5b7fab648cd2edec76c5" +checksum = "bf6f2288d8e7fbb5130f62cf720451641e99d55f6fde9db86aa2914ecb553fd2" dependencies = [ "cc", ] [[package]] name = "rusqlite" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" +checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" dependencies = [ - "bitflags 2.3.3", - "fallible-iterator", + "bitflags 2.6.0", + "fallible-iterator 0.3.0", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", @@ -3689,9 +3265,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3710,85 +3286,63 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" -dependencies = [ - "bitflags 2.3.3", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.3", - "windows-sys 0.48.0", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.2" +version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ - "log", + "once_cell", "ring", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.2", + "base64 0.22.1", + "rustls-pki-types", ] [[package]] -name = "rustls-webpki" -version = "0.100.1" +name = "rustls-pki-types" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] -[[package]] -name = "rusty-hook" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96cee9be61be7e1cbadd851e58ed7449c29c620f00b23df937cb9cbc04ac21a3" -dependencies = [ - "ci_info", - "getopts", - "nias", - "toml", -] - [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3800,106 +3354,57 @@ dependencies = [ ] [[package]] -name = "schannel" -version = "0.1.22" +name = "scc" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "af947d0ca10a2f3e00c7ec1b515b7c83e5cb3fa62d4c11a64301d9eec54440e9" dependencies = [ - "windows-sys 0.48.0", + "sdd", ] [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "sct" -version = "0.7.0" +name = "sdd" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - -[[package]] -name = "security-framework" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "self_cell" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" +checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.166" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.166" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "serde_json" -version = "1.0.100" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -3907,26 +3412,14 @@ dependencies = [ ] [[package]] -name = "serde_path_to_error" -version = "0.1.13" +name = "serde_spanned" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ - "itoa", "serde", ] -[[package]] -name = "serde_repr" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.23", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3941,9 +3434,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -3965,9 +3458,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -3976,179 +3469,139 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "lazy_static 1.4.0", -] - -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - -[[package]] -name = "shipyard" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3511ae730f2e1c3d62a9025e2f9b2acbf130968057f1b3caab6d74a54a5e0e56" -dependencies = [ - "hashbrown 0.12.3", - "lock_api", - "shipyard_proc", -] - -[[package]] -name = "shipyard_proc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb847f4b9582e468198b5cfb5731b65cc67fe5e535acc9cbf3c11703d15f08c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "signal-hook" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio 0.7.14", - "mio 0.8.8", - "signal-hook", + "lazy_static 1.5.0", ] [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] -name = "simd-abstraction" -version = "0.7.1" +name = "simd-adler32" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" -dependencies = [ - "outref", -] - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] -name = "slotmap" -version = "1.0.6" +name = "slice-group-by" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check", -] +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slug" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" dependencies = [ "deunicode", + "wasm-bindgen", ] -[[package]] -name = "smallbox" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4679d6eef28b85020158619fc09769de89e90886c5de7157587d87cb72648faa" - [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] -name = "socket2" -version = "0.4.9" +name = "snafu" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "2b835cb902660db3415a672d862905e791e54d306c6e8189168c7f3d9ae1c79d" dependencies = [ - "libc", - "winapi 0.3.9", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d1e02fca405f6280643174a50c942219f0bbf4dbf7d480f1dd864d6f211ae5" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.70", ] [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stringprep" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -4163,9 +3616,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.23" +version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ "proc-macro2", "quote", @@ -4173,121 +3626,71 @@ dependencies = [ ] [[package]] -name = "syntect" -version = "5.0.0" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "syntect" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" dependencies = [ "bincode", "bitflags 1.3.2", "fancy-regex", "flate2", "fnv", - "lazy_static 1.4.0", "once_cell", "plist", - "regex-syntax 0.6.29", + "regex-syntax", "serde", "serde_derive", "serde_json", "thiserror", - "walkdir 2.3.3", + "walkdir", "yaml-rust", ] [[package]] -name = "taffy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13e87d38366d3cadcf282165b6ba51d5422ed846459997f55a347fe98242f61" +name = "t" +version = "0.1.0" dependencies = [ - "arrayvec 0.7.4", - "num-traits", - "slotmap", + "rusqlite", ] [[package]] -name = "taffy" -version = "0.3.12" +name = "target-lexicon" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3540ec65df399929a04a485feb50144475735920cc47eaf8eba09c70b1df4055" -dependencies = [ - "arrayvec 0.7.4", - "grid", - "num-traits", - "slotmap", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tejar" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69348a5c80d5e535c653709742976b1f627474ac8446a27d9d2eaa84d7e10022" -dependencies = [ - "camino", - "hex", - "mime_guess", - "rand", - "sha2 0.10.7", - "thiserror", - "tokio", - "walkdir 2.3.3", -] - -[[package]] -name = "tempfile" -version = "3.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" -dependencies = [ - "autocfg", - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix 0.37.23", - "windows-sys 0.48.0", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" [[package]] name = "thiserror" -version = "1.0.41" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c16a64ba9387ef3fdae4f9c1a7f07a0997fce91985c0336f1ddc1822b3b37802" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.41" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d14928354b01c4d6a4f0e549069adef399a284e7995c7ccca94e8a07a5346c59" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -4306,11 +3709,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -4318,33 +3724,25 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef" -dependencies = [ - "displaydoc", -] - [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4357,119 +3755,150 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", - "mio 0.8.8", + "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.4.9", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", + "syn 2.0.70", ] [[package]] name = "tokio-postgres" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e89f6234aa8fd43779746012fcf53603cdb91fdd8399aa0de868c2d56b6dde1" +checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8" dependencies = [ "async-trait", "byteorder", "bytes", - "fallible-iterator", + "fallible-iterator 0.2.0", "futures-channel", "futures-util", "log", - "parking_lot 0.12.1", + "parking_lot", "percent-encoding", - "phf 0.11.2", + "phf", "pin-project-lite", "postgres-protocol", "postgres-types", - "socket2 0.5.3", + "rand", + "socket2", "tokio", "tokio-util", + "whoami", ] [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml" -version = "0.5.11" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.15", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] [[package]] -name = "toml_datetime" -version = "0.6.3" +name = "toml_edit" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ - "indexmap 2.0.0", + "indexmap", + "serde", + "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.13", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4478,11 +3907,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -4491,58 +3919,43 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-forest" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" -dependencies = [ - "ansi_term", - "serde", - "smallvec", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static 1.4.0", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "nu-ansi-term", + "nu-ansi-term 0.46.0", "sharded-slab", "smallvec", "thread_local", @@ -4552,37 +3965,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tui" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ed0a32c88b039b73f1b6c5acbd0554bfa5b6be94467375fd947c4de3a02271" -dependencies = [ - "bitflags 1.3.2", - "cassowary", - "crossterm 0.22.1", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "type-map" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" -dependencies = [ - "rustc-hash", -] - -[[package]] -name = "typed-arena" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typed-arena" @@ -4592,75 +3977,57 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - -[[package]] -name = "unic-langid" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f" -dependencies = [ - "unic-langid-impl", -] - -[[package]] -name = "unic-langid-impl" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff" -dependencies = [ - "tinystr", -] +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] -name = "unicode-segmentation" -version = "1.10.1" +name = "unicode-properties" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -4676,33 +4043,32 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.4.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] name = "valuable" @@ -4722,27 +4088,11 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "vlq" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65dd7eed29412da847b0f78bcec0ac98588165988a8cfe41d4ea1d429f8ccfff" - [[package]] name = "walkdir" -version = "0.1.8" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" -dependencies = [ - "kernel32-sys", - "winapi 0.2.8", -] - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4764,10 +4114,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.87" +name = "wasite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4775,24 +4131,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -4802,9 +4158,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4812,69 +4168,370 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.70", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "wasm-encoder" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4a05336882dae732ce6bd48b7e11fe597293cb72c13da4f35d7d5f8d53b2a7" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.212.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501940df4418b8929eb6d52f1aade1fdd15a5b86c92453cb696e3c906bd3fc33" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasmparser" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07035cc9a9b41e62d3bb3a3815a66ab87c993c06fe1cf6b2a3f2a18499d937db" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "hashbrown 0.14.5", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wasmprinter" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceca8ae6eaa8c7c87b33c25c53bdf299f8c2a764aee1179402ff7652ef3a6859" +dependencies = [ + "anyhow", + "wasmparser", +] + +[[package]] +name = "wasmtime" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786d8b5e7a4d54917c5ebe555b9667337e5f93383f49bddaaeec2eba68093b45" +dependencies = [ + "addr2line 0.21.0", + "anyhow", + "async-trait", + "bumpalo", + "cc", + "cfg-if", + "encoding_rs", + "fxprof-processed-profile", + "gimli 0.28.1", + "hashbrown 0.14.5", + "indexmap", + "ittapi", + "libc", + "libm", + "log", + "mach2", + "memfd", + "memoffset", + "object", + "once_cell", + "paste", + "postcard", + "psm", + "rayon", + "rustix", + "semver", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "sptr", + "target-lexicon", + "wasm-encoder 0.209.1", + "wasmparser", + "wasmtime-asm-macros", + "wasmtime-cache", + "wasmtime-component-macro", + "wasmtime-component-util", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-slab", + "wasmtime-versioned-export-macros", + "wasmtime-winch", + "wat", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d697d99c341d4a9ffb72f3af7a02124d233eeb59aee010f36d88e97cca553d5e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-cache" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916610f9ae9a6c22deb25bba2e6247ba9f00b093d30620875203b91328a1adfa" +dependencies = [ + "anyhow", + "base64 0.21.7", + "directories-next", + "log", + "postcard", + "rustix", + "serde", + "serde_derive", + "sha2 0.10.8", + "toml", + "windows-sys 0.52.0", + "zstd", +] + +[[package]] +name = "wasmtime-component-macro" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29b462b068e73b5b27fae092a27f47e5937cabf6b26be2779c978698a52feca" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.70", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d2912c53d9054984b380dfbd7579f9c3681b2a73b903a56bd71a1c4f175f1e" + +[[package]] +name = "wasmtime-cranelift" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3975deafea000457ba84355c7c0fce0372937204f77026510b7b454f28a3a65" +dependencies = [ + "anyhow", + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli 0.28.1", + "log", + "object", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-environ", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-environ" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f444e900e848b884d8a8a2949b6f5b92af642a3e663ff8fbe78731143a55be61" +dependencies = [ + "anyhow", + "cpp_demangle", + "cranelift-entity", + "gimli 0.28.1", + "indexmap", + "log", + "object", + "postcard", + "rustc-demangle", + "serde", + "serde_derive", + "target-lexicon", + "wasm-encoder 0.209.1", + "wasmparser", + "wasmprinter", + "wasmtime-component-util", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-fiber" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ded58eb2d1bf0dcd2182d0ccd7055c4b10b50d711514f1d73f61515d0fa829d" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "rustix", + "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bc54198c6720f098210a85efb3ba8c078d1de4d373cdb6778850a66ae088d11" +dependencies = [ + "object", + "once_cell", + "rustix", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5afe2f0499542f9a4bcfa1b55bfdda803b6ade4e7c93c6b99e0f39dba44b0a91" +dependencies = [ + "anyhow", + "cfg-if", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-slab" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a7de1f2bec5bbb35d532e61c85c049dc84ae671df60492f90b954ecf21169e7" + +[[package]] +name = "wasmtime-types" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "412463e9000e14cf6856be48628d2213c20c153e29ffc22b036980c892ea6964" +dependencies = [ + "cranelift-entity", + "serde", + "serde_derive", + "smallvec", + "wasmparser", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5a9bc4f44ceeb168e9e8e3be4e0b4beb9095b468479663a9e24c667e36826f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "wasmtime-winch" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4db238a0241df2d15f79ad17b3a37a27f2ea6cb885894d81b42ae107544466" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli 0.28.1", + "object", + "target-lexicon", + "wasmparser", + "wasmtime-cranelift", + "wasmtime-environ", + "winch-codegen", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc077306b38288262e5ba01d4b21532a6987416cdc0aedf04bb06c22a68fdc" +dependencies = [ + "anyhow", + "heck 0.4.1", + "indexmap", + "wit-parser", +] + +[[package]] +name = "wast" +version = "212.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4606a05fb0aae5d11dd7d8280a640d88a63ee019360ba9be552da3d294b8d1f5" +dependencies = [ + "bumpalo", + "leb128", + "memchr", + "unicode-width", + "wasm-encoder 0.212.0", +] + +[[package]] +name = "wat" +version = "1.212.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c74ca7f93f11a5d6eed8499f2a8daaad6e225cab0151bc25a091fff3b987532f" +dependencies = [ + "wast", +] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" -version = "0.22.6" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ - "webpki", + "rustls-pki-types", ] [[package]] -name = "which" -version = "4.4.0" +name = "whoami" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "either", - "libc", - "once_cell", + "redox_syscall 0.4.1", + "wasite", + "web-sys", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -4885,12 +4542,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4899,11 +4550,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi 0.3.9", + "windows-sys 0.52.0", ] [[package]] @@ -4913,21 +4564,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "winch-codegen" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "85c6915884e731b2db0d8cf08cb64474cb69221a161675fd3c135f91febc3daa" dependencies = [ - "windows-targets 0.48.1", + "anyhow", + "cranelift-codegen", + "gimli 0.28.1", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser", + "wasmtime-cranelift", + "wasmtime-environ", ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.52.6", ] [[package]] @@ -4936,157 +4595,183 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.10.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "winapi 0.3.9", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] -name = "wyz" -version = "0.5.1" +name = "wit-parser" +version = "0.209.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "3e79b9e3c0b6bb589dec46317e645851e0db2734c44e2be5e251b03ff4a51269" dependencies = [ - "tap", -] - -[[package]] -name = "xdg" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688597db5a750e9cad4511cb94729a078e274308099a0382b5b8203bbc767fee" -dependencies = [ - "home", + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", ] [[package]] @@ -5105,70 +4790,112 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] -name = "zip" -version = "0.6.6" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "aes 0.8.3", - "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "zip" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775a2b471036342aa69bc5a602bc889cb0a06cda00477d0c69566757d5553d39" +dependencies = [ + "aes 0.8.4", + "arbitrary", "bzip2", "constant_time_eq", "crc32fast", "crossbeam-utils", + "deflate64", + "displaydoc", "flate2", "hmac", + "indexmap", + "lzma-rs", + "memchr", "pbkdf2", + "rand", "sha1", + "thiserror", "time", - "zstd 0.11.2+zstd.1.5.2", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", ] [[package]] name = "zstd" -version = "0.11.2+zstd.1.5.2" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.12.3+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" -dependencies = [ - "zstd-safe 6.0.5+zstd.1.5.4", + "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-safe" -version = "6.0.5+zstd.1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56d9e60b4b1758206c238a10165fbcae3ca37b01744e394c463463f6529d23b" -dependencies = [ - "libc", "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.12+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/pkgs/fastn/default.nix b/pkgs/fastn/default.nix index 84b22822..544fbf05 100644 --- a/pkgs/fastn/default.nix +++ b/pkgs/fastn/default.nix @@ -1,33 +1,31 @@ { lib , rustPlatform , fetchFromGitHub +, cmake , pkg-config , openssl }: rustPlatform.buildRustPackage rec { pname = "fastn"; - version = "0.3.9"; + version = "0.4.75"; src = fetchFromGitHub { owner = "fastn-stack"; repo = pname; rev = version; - hash = "sha256-KhJc6cM1KnJSoaD3a0uRwlObGsu8p66gn4XAtFTHlVg="; + hash = "sha256-8/0fOpZhboBJWN2sNrVD54uW3J3UPxGW9wil0UfdfuM="; }; cargoLock = { lockFile = ./Cargo.lock; outputHashes = { - "deadpool-0.9.5" = "sha256-4M2+nVVG/w0gnHkxTWVnfvy5HegW9A+nlWAkMltapeI="; - "dioxus-core-0.3.2" = "sha256-jOVkqWPcGa/GGeZiQji7JbD2YF+qrXC9AZGozZg47+c="; - "fbt-lib-0.1.18" = "sha256-xzhApWSVsVelii0R8vfB60kj0gA87MRTEplmX+UT96A="; - "ftd-0.2.0" = "sha256-iHWR5KMgmo1QfLPc8ZKS4NvshXEg/OJw7c7fy3bs8v0="; + "fastn-observer-0.1.0" = "sha256-D7ch6zB1xw54vGbpcQ3hf+zG11Le/Fy01W3kHhc8bOg="; }; }; OPENSSL_NO_VENDOR = "1"; - nativeBuildInputs = [ pkg-config ]; + nativeBuildInputs = [ cmake pkg-config ]; buildInputs = [ openssl ]; checkFlags = [ @@ -39,5 +37,6 @@ rustPlatform.buildRustPackage rec { description = "An integrated development environment for FTD"; license = licenses.bsd3; maintainers = with maintainers; [ foo-dogsquared ]; + mainProgram = "fastn"; }; } diff --git a/pkgs/firefox-addons/default.nix b/pkgs/firefox-addons/default.nix index 7c5a5650..b84f8081 100644 --- a/pkgs/firefox-addons/default.nix +++ b/pkgs/firefox-addons/default.nix @@ -1,5 +1,24 @@ { buildFirefoxXpiAddon, fetchurl, lib, stdenv }: { + "extended-color-management" = buildFirefoxXpiAddon { + pname = "extended-color-management"; + version = "1.1.1"; + addonId = "{816dd215-0e91-4621-9d89-3bac78798e6f}"; + url = "https://addons.mozilla.org/firefox/downloads/file/3966904/extended_color_management-1.1.1.xpi"; + sha256 = "8b09d9fb312635c428571bd74beacf67e426089ebc812c7f39e9c3b4dad05a0b"; + meta = with lib; + { + description = "Ever wish that Firefox didn't use color management when viewing images or video? Turn it off easily with this add-on."; + license = licenses.mpl20; + mozPermissions = [ + "browserSettings" + "notifications" + "storage" + "" + ]; + platforms = platforms.all; + }; + }; "get-rss-feed-url" = buildFirefoxXpiAddon { pname = "get-rss-feed-url"; version = "2.2"; @@ -44,6 +63,51 @@ platforms = platforms.all; }; }; + "microsoft-container" = buildFirefoxXpiAddon { + pname = "microsoft-container"; + version = "1.0.4"; + addonId = "@contain-microsoft"; + url = "https://addons.mozilla.org/firefox/downloads/file/3711415/microsoft_container-1.0.4.xpi"; + sha256 = "8780c9edcfa77a9f3eaa7da228a351400c42a884fec732cafc316e07f55018d3"; + meta = with lib; + { + homepage = "https://github.com/kouassi-goli/contain-microsoft"; + description = "This add-on is an unofficial fork of Mozilla's Facebook Container designed for Microsoft. \n Microsoft Container isolates your Microsoft activity from the rest of your web activity and prevent Microsoft from tracking you outside of the its website."; + license = licenses.mpl20; + mozPermissions = [ + "" + "contextualIdentities" + "cookies" + "management" + "tabs" + "webRequestBlocking" + "webRequest" + ]; + platforms = platforms.all; + }; + }; + "open-access-helper" = buildFirefoxXpiAddon { + pname = "open-access-helper"; + version = "2024.1"; + addonId = "info@oahelper.org"; + url = "https://addons.mozilla.org/firefox/downloads/file/4334632/open_access_helper-2024.1.xpi"; + sha256 = "9f0a4fd3f45fd5c863815971062c1b1d1207de20ffa79a0dbfdadaa86cab996c"; + meta = with lib; + { + homepage = "https://www.oahelper.org"; + description = "Effortless legal access to full text scholarly articles: \nOpen Access Helper will help you identify legal open access copies of academic articles, using unpaywall.org and core.ac.uk"; + mozPermissions = [ + "tabs" + "storage" + "contextMenus" + "http://*/*" + "https://*/*" + "*://*/*" + "https://www.oahelper.org/backend/institutes/" + ]; + platforms = platforms.all; + }; + }; "regretsreporter" = buildFirefoxXpiAddon { pname = "regretsreporter"; version = "2.1.2"; diff --git a/pkgs/firefox-addons/firefox-addons.json b/pkgs/firefox-addons/firefox-addons.json index 022c446f..6ce3b1c2 100644 --- a/pkgs/firefox-addons/firefox-addons.json +++ b/pkgs/firefox-addons/firefox-addons.json @@ -2,32 +2,34 @@ { "slug": "updateswh" }, - { "slug": "zhongwen" }, - { "slug": "get-rss-feed-url" }, - { "slug": "regretsreporter" }, - + { + "slug": "extended-color-management" + }, { "slug": "simple-translate" }, - { "slug": "tineye-reverse-image-search" }, - { "slug": "google-container" }, - + { + "slug": "microsoft-container" + }, { "slug": "sourcegraph-for-firefox" + }, + { + "slug": "open-access-helper" } ] diff --git a/pkgs/flatsync/default.nix b/pkgs/flatsync/default.nix new file mode 100644 index 00000000..000d76b4 --- /dev/null +++ b/pkgs/flatsync/default.nix @@ -0,0 +1,71 @@ +{ stdenv +, lib +, fetchFromGitLab +, rustPlatform +, cargo +, rustc +, meson +, ninja +, pkg-config +, glib +, gobject-introspection +, libadwaita +, wrapGAppsHook4 +, openssl +, appstream-glib +, desktop-file-utils +, blueprint-compiler +, flatpak +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "flatsync"; + version = "unstable-2024-08-16"; + + src = fetchFromGitLab { + domain = "gitlab.gnome.org"; + owner = "Cogitri"; + repo = "flatsync"; + rev = "4ae868217b00d8c7fc9450cdf41eda8d8303508f"; + hash = "sha256-ATFJv9XtNuIYrz7gbVt1yFM10wNAbOa/cUeDVjSGrGY="; + }; + + strictDeps = true; + cargoDeps = rustPlatform.fetchCargoTarball { + name = "${finalAttrs.pname}-${finalAttrs.version}-deps"; + inherit (finalAttrs) src; + hash = "sha256-qC/kj0eCrSjFmyDwrqtameYRTajnY8HoQaOxME4zWJI="; + }; + + nativeBuildInputs = [ + appstream-glib + blueprint-compiler + cargo + desktop-file-utils + gobject-introspection + meson + ninja + pkg-config + rustPlatform.cargoSetupHook + rustPlatform.bindgenHook + rustc + wrapGAppsHook4 + ]; + + buildInputs = [ + glib + flatpak + libadwaita + openssl + ]; + + meta = with lib; { + homepage = "https://gitlab.gnome.org/Cogitri/flatsync"; + # It has no license yet so technically it's unfree. + license = licenses.unfree; + description = "Synchronize your Flatpaks across multiple machines"; + platforms = platforms.linux; + maintainers = with maintainers; [ foo-dogsquared ]; + mainProgram = "flatsync"; + }; +}) diff --git a/pkgs/gnome-search-provider-recoll.nix b/pkgs/gnome-search-provider-recoll.nix index 1832de6e..a6248f77 100644 --- a/pkgs/gnome-search-provider-recoll.nix +++ b/pkgs/gnome-search-provider-recoll.nix @@ -6,7 +6,7 @@ , python3Packages , glib , gobject-introspection -, wrapGAppsHook +, wrapGAppsHook3 , gnome }: @@ -23,7 +23,7 @@ python3Packages.buildPythonPackage rec { format = "other"; strictDeps = false; dontWrapGApps = true; - nativeBuildInputs = [ wrapGAppsHook autoreconfHook gobject-introspection ]; + nativeBuildInputs = [ wrapGAppsHook3 autoreconfHook gobject-introspection ]; propagatedBuildInputs = [ recoll ] ++ (with python3Packages; [ pydbus pygobject3 ]); buildInputs = [ glib ]; diff --git a/pkgs/lazyjj/default.nix b/pkgs/lazyjj/default.nix new file mode 100644 index 00000000..77618dd3 --- /dev/null +++ b/pkgs/lazyjj/default.nix @@ -0,0 +1,38 @@ +{ + lib, + rustPlatform, + fetchFromGitHub, + jujutsu, +}: + +let + version = "0.3.1"; +in +rustPlatform.buildRustPackage { + inherit version; + pname = "lazyjj"; + + src = fetchFromGitHub { + owner = "Cretezy"; + repo = "lazyjj"; + rev = "v${version}"; + hash = "sha256-VlGmOdF/XsrZ/9vQ14UuK96LIK8NIkPZk4G4mbS8brg="; + }; + + cargoHash = "sha256-TAq9FufGsNVsmqCE41REltYRSSLihWJwTMoj0bTxdFc="; + + # I have no clue how to properly make these tests pass so NO for now. + doCheck = false; + preCheck = '' + export HOME=$TMPDIR + ''; + checkInputs = [ jujutsu ]; + + meta = with lib; { + homepage = "https://github.com/Cretezy/lazyjj"; + description = "lazygit-inspired user interface for Jujutsu VCS"; + license = licenses.apsl20; + maintainers = with maintainers; [ foo-dogsquared ]; + mainProgram = "lazyjj"; + }; +} diff --git a/pkgs/mopidy-listenbrainz/default.nix b/pkgs/mopidy-listenbrainz/default.nix new file mode 100644 index 00000000..db9a718d --- /dev/null +++ b/pkgs/mopidy-listenbrainz/default.nix @@ -0,0 +1,25 @@ +{ lib, fetchFromGitHub, python3, mopidy }: + +python3.pkgs.buildPythonApplication rec { + pname = "mopidy-listenbrainz"; + version = "0.3.0"; + format = "pyproject"; + + src = fetchFromGitHub { + owner = "suaviloquence"; + repo = "mopidy-listenbrainz"; + rev = "v${version}"; + hash = "sha256-kYZgG2KQMTxMR8tdwwCKkfexDcxcndXG9LSdlnoN/CY="; + }; + + propagatedBuildInputs = with python3.pkgs; + [ pykka musicbrainzngs ] ++ [ mopidy ]; + + meta = with lib; { + description = + "Mopidy extension for getting recommendations with Listenbrainz"; + homepage = "https://github.com/suaviloquence/mopidy-listenbrainz"; + license = licenses.apsl20; + platforms = mopidy.meta.platforms; + }; +} diff --git a/pkgs/nautilus-annotations/default.nix b/pkgs/nautilus-annotations/default.nix index 0566d746..37cdc1ee 100644 --- a/pkgs/nautilus-annotations/default.nix +++ b/pkgs/nautilus-annotations/default.nix @@ -6,7 +6,7 @@ , gtksourceview5 , libadwaita , autoreconfHook -, wrapGAppsHook +, wrapGAppsHook4 , pkg-config }: @@ -27,7 +27,7 @@ stdenv.mkDerivation rec { glib gnome.nautilus pkg-config - wrapGAppsHook + wrapGAppsHook4 ]; buildInputs = [ diff --git a/pkgs/pigeon-mail/default.nix b/pkgs/pigeon-mail/default.nix new file mode 100644 index 00000000..cfec0702 --- /dev/null +++ b/pkgs/pigeon-mail/default.nix @@ -0,0 +1,39 @@ +{ lib +, fetchFromGitHub +, rustPlatform +, pkg-config +, openssl +}: + +rustPlatform.buildRustPackage rec { + pname = "pigeon-mail"; + version = "0.4.2"; + + src = fetchFromGitHub { + owner = "quambene"; + repo = "pigeon-rs"; + rev = "v${version}"; + hash = "sha256-qtyPSOG6QFbOM4i9XDXMz1Cmn9a5J8lLhnRkBIWz8Ic="; + }; + + cargoHash = "sha256-MRSO89qg08GyyIuzEpSO4qQTZS876U3SeGJ6eCO+3BA="; + + env = { + OPENSSL_NO_VENDOR = "1"; + }; + + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ openssl ]; + + # It requires Postgres environment to test so that's a no-go for now. + doCheck = false; + + meta = with lib; { + homepage = "https://github.com/quambene/pigeon-rs"; + description = "Email automation on the command line"; + license = licenses.asl20; + maintainers = with maintainers; [ foo-dogsquared ]; + mainProgram = "pigeon"; + platform = platforms.unix; + }; +} diff --git a/pkgs/smile/default.nix b/pkgs/smile/default.nix index c3278a22..7ad5dc4f 100644 --- a/pkgs/smile/default.nix +++ b/pkgs/smile/default.nix @@ -8,7 +8,7 @@ , gettext , glib , gtk4 -, libwnck3 +, libwnck , wrapGAppsHook4 , pkg-config , python3Packages @@ -60,7 +60,7 @@ python3Packages.buildPythonApplication rec { ]; buildInputs = [ - libwnck3 + libwnck gtk4 ]; diff --git a/pkgs/vgc/default.nix b/pkgs/vgc/default.nix index f38568d8..50b1e7ca 100644 --- a/pkgs/vgc/default.nix +++ b/pkgs/vgc/default.nix @@ -11,17 +11,15 @@ , git }: -# TODO: Get rid of the build date or at least set the build date to zero to be -# reproducible. stdenv.mkDerivation rec { pname = "vgc"; - version = "unstable-2023-02-05"; + version = "unstable-2024-08-16"; src = fetchFromGitHub { owner = "vgc"; repo = "vgc"; - rev = "8e8d958ab9f7fa6f741346d60f17af44d7abb592"; - sha256 = "sha256-84dckIOrHmxVX7U7VM1Le6tEqG1cJYaAfBcbKqJ6Ros="; + rev = "f9814daf5b7d411feeca0a1d994b344243402989"; + sha256 = "sha256-86Ze8+aKMn0EU+RjcyUuDCCaEleh48gzyU9ZuYxpSdM="; fetchSubmodules = true; }; @@ -45,5 +43,6 @@ stdenv.mkDerivation rec { description = "Upcoming suite of vector-drawing applications that makes use of Vector Graphics Complex (VGC)"; license = licenses.asl20; + maintainers = with maintainers; [ foo-dogsquared ]; }; } diff --git a/pkgs/willow/default.nix b/pkgs/willow/default.nix index 0bd43dd6..0c69b51a 100644 --- a/pkgs/willow/default.nix +++ b/pkgs/willow/default.nix @@ -5,16 +5,16 @@ buildGoModule { pname = "willow"; - version = "unstable-2024-05-17"; + version = "unstable-2024-08-15"; src = fetchFromGitHub { owner = "Amolith"; repo = "willow"; - rev = "5219377958faf103e16f16c29b2eb82f33a4f1c4"; - hash = "sha256-MGz+X8Az2Cqzp5SB7L/RU18m15WOIS8vnAjCJwcTQ/s="; + rev = "af7202f230e42808b705bb9d4ddd04cfa28b401b"; + hash = "sha256-ewXYkx2P2LO6Stg4P4WuVeDLgy2Zh/NYGkMl43DJ+Es="; }; - vendorHash = "sha256-DCqD9GTszw7KJ+BlEX4T1Mra/D7uAFcWsMXg73V8a7k="; + vendorHash = "sha256-KLDoAd/YbQGW1v8bxffJS1PC8fJyEwWT5vT7g0a7rsg="; meta = with lib; { homepage = "https://github.com/Amolith/willow"; diff --git a/shell.nix b/shell.nix index f76747bf..dd5ddea6 100644 --- a/shell.nix +++ b/shell.nix @@ -13,9 +13,12 @@ pkgs.mkShell { asciidoctor disko deploy-rs + npins + nixos-anywhere home-manager git sops + nix-update bind opentofu @@ -33,6 +36,6 @@ pkgs.mkShell { treefmt # The universal formatter (if you configured it). stylua # ...for Lua. black # ...for Python. - nixpkgs-fmt # ...for Nix. + nixfmt # ...for Nix. ] ++ extraPackages; } diff --git a/shells/README.adoc b/shells/README.adoc index 85782eb8..3c9d534c 100644 --- a/shells/README.adoc +++ b/shells/README.adoc @@ -3,6 +3,7 @@ My development shells for usual type of projects to quickly spawn one when spelunking other peoples' projects. This can be easily spawned from the `devShells` attribute from the flake output (i.e., `nix develop $FLAKE#$DEVENV`). +But if you are using a non-flake setup and the channels are set correctly, it should still be usable with `nix-shell -A $SHELL_NAME`. CAUTION: This is not supposed to be a list of development environment encompassing all type of projects but rather it is just for quickly spawning one for spelunking. diff --git a/subprojects/bahaghari/LICENSE b/subprojects/bahaghari/LICENSE index ce20b53f..ef817257 100644 --- a/subprojects/bahaghari/LICENSE +++ b/subprojects/bahaghari/LICENSE @@ -1,5 +1,9 @@ Copyright (c) 2024 Gabriel Arazas +Program uses the following files/implementations from other authors; +see their respective license headers for more details: +lib/math.nix, specifically the sin, cos, tan, and arctan functions: Copyright (c) 2023 Yuhui Xu + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/subprojects/bahaghari/README.adoc b/subprojects/bahaghari/README.adoc index ad5879f7..082e5341 100644 --- a/subprojects/bahaghari/README.adoc +++ b/subprojects/bahaghari/README.adoc @@ -5,7 +5,7 @@ :fn-specialization-comment: footnote:[Which I can see is useful for separating rices and booting into them separately for whatever reason (again, your system, your rules but my guess is because you're a control freak).] -Bahaghari (Tagalog word for "rainbow" or a "king's loincloth" if you prefer) is a specialized set of Nix modules for generating and applying themes. +Bahaghari footnote:[Tagalog word for "rainbow" or a "king's loincloth" if you prefer.] is a specialized set of Nix modules for generating and applying themes. Mainly useful for making your ricing process with NixOS and home-manager environments easier. This module set should allow for some flexibility for your use case. @@ -19,32 +19,13 @@ At its current state, Bahaghari is considered unstable and might have breaking c To get started using Bahaghari, you have to set some things up first. The way how Bahaghari expects you to use it is by choosing one (or more if you want) of the module sets which you can view more details at <>. -For now, let's assume that you are using Tinted Theming module set in your NixOS configuration which you can set it up with the following code. +For now, let's assume that you are using Tinted Theming module set (which is basically the most developed out of all of them) in your NixOS configuration which you can set it up with the following code. // TODO: Change all of the URLs once this moves into its own repo. First, you'll have to install Bahaghari as part of your Nix project or whatever. There are multiple ways to do this. -* We'll first start with the increasingly popular method of including Nix dependencies with https://zero-to-nix.com/concepts/flakes[Nix flakes], a built-in way of pinning them dependencies. -+ -[source, nix] ----- -{ - inputs.bahaghari.url = "github:foo-dogsquared/nixos-config?dir=subprojects/bahaghari"; - - # ... - - outputs = { nixpkgs, ... }@inputs: { - nixosConfigurations = nixpkgs.lib.nixosSystem { - modules = [ - inputs.bahaghari.nixosModules.bahaghari - ]; - }; - }; -} ----- - -* You can also import the dependencies with a pinning tool (that is not flakes) like https://github.com/nmattia/niv[niv]. +* You can import the dependencies with a pinning tool (that is not flakes) like https://github.com/nmattia/niv[niv] or https://github.com/andir/npins[npins]. + [source, shell] ---- @@ -65,7 +46,26 @@ in } ---- -* Lastly, you can import it through https://zero-to-nix.com/concepts/channels[channels]. +* You could install it with https://zero-to-nix.com/concepts/flakes[Nix flakes], an experimental feature featuring a built-in way of pinning them dependencies. ++ +[source, nix] +---- +{ + inputs.bahaghari.url = "github:foo-dogsquared/nixos-config?dir=subprojects/bahaghari"; + + # ... + + outputs = { nixpkgs, ... }@inputs: { + nixosConfigurations = nixpkgs.lib.nixosSystem { + modules = [ + inputs.bahaghari.nixosModules.bahaghari + ]; + }; + }; +} +---- + +* Last but not least, you can import it through https://zero-to-nix.com/concepts/channels[channels]. + [source, shell] ---- @@ -90,7 +90,7 @@ in Importing the module will also import Bahaghari's library set (`bahaghariLib`), making it available as `bahaghariLib` module argument. -If for whatever reason you need Bahaghari library outside of using it with Bahaghari, you can also import it yourself. +If for whatever reason you need Bahaghari library outside of using it with Bahaghari (for example, you want to use the math subset), you can also import it yourself. Here's one way to set it to be available in the module of your environment. [source, nix] @@ -108,8 +108,6 @@ in ---- - - [#module-sets] == Module sets @@ -117,17 +115,39 @@ As a whole, Bahaghari is more like a set of sets, a metaset, if you will. Specifically, it is composed of module sets of which has different ways to use them. Here is the exhaustive list of them and its details. - [#tinted-theming] === Tinted Theming -Bahaghari has a module set for interacting with Tinted Theming standard schemes and templates. +Bahaghari has a module set for interacting with https://github.com/tinted-theming/[Tinted Theming] standard schemes and templates. This module is designed to closely follow Tinted Theming's standard while offering some convenience with the library set. For example, you can use `importYAML` from Bahaghari's standard library set to easily import standard Base16 schemes into Nix-representable data which you can press onto your Nix configuration. +However, Bahaghari has a dedicated set of library functions in `bahaghariLib.tinted-theming` to make interacting with this module set a bit easier. +For example, instead of using `importYAML`, you can use `tinted-theming.importScheme` instead which the function will also take care of modernizing legacy Base16 schemes if it detected as one. + +[source, nix] +---- +{ config, lib, bahaghariLib, ... }: + +{ + bahaghari.tinted-theming.schemes = { + # Instead of using `importYAML`... + bark-on-a-tree = bahaghariLib.importYAML ./legacy-base16-scheme.yml; + + # ...you can use `tinted-theming.importScheme` instead. + albino-bark-on-a-tree = bahaghariLib.tinted-theming.importScheme ./legacy-base16-scheme.yml; + + # This should work both on legacy and modern Tinted Theming schemes. + ice-ice-baby = bahaghariLib.tinted-theming.importScheme ./modern-base16-scheme.yml; + }; +} +---- + + // TODO: GNOME HIG module set // TODO: Material You module set +// TODO: Panapton module set [#templated-configuration-sub-modules] === Templated configuration sub-modules @@ -141,10 +161,13 @@ To make use of this, you'll have to import Bahaghari module set's [#comparison-with-other-modules] == Comparison with other modules +Bahaghari is not the first nor the last Nix project to ever deal with setting up a foundation for generating them rainbowy rices. +Here's some (unbiased ;p) insights comparing Bahaghari and some of the more established projects in this space. + [#nix-colors] === nix-colors -Bahaghari initially started as a derivative to nix-colors as a single Nix module entirely dedicated for Tinted Theming standard. +Bahaghari initially started as a derivative to nix-colors as a single Nix module entirely dedicated for Tinted Theming standard "proper". It was created to address its limitation of allowing only one colorscheme at a time which limits a lot of possible applications. Most notably, the feature I'm looking for is generating multiple colorscheme templates for different applications which is nice for hybrid deployments of home-manager-plus-mutable-configurations (AKA traditional dotfiles) and for mixed installations of NixOS and home-manager (or whatever else that can be combined). @@ -166,16 +189,13 @@ Here's one way to implement it. } ---- - - - [#stylix] === Stylix While Bahaghari can be used similarly to Stylix, it isn't completely 1-to-1 to Stylix as the latter focuses on the holistic side of customization including for fonts and wallpaper. On the other hand, Bahaghari completely focuses on colorscheme generation. footnote:[While Bahaghari as a project can also focus beyond colorschemes similar to Stylix, it isn't a part of the vision for now.] -Bahaghari also took some cues from Stylix specifically from its Stylix targets which became the pre-templated configurations submodules for each of the design system module set (e.g., Tinted Theming). +Still, if you're looking for a streamlined way of generating a theme configuration, Stylix is still the tool for the job. @@ -195,12 +215,29 @@ This is used both by the flake- and non-flake-based setups for consistency (and * link:./lib/[./lib/] is where the Bahaghari library set lives. It takes a lot of cues from nixpkgs how the library is maintained with individual files separated by purpose and the module sets (most of the time). +* link:./utils/[./utils/] is another part of Bahaghari library. +You can see more details in <>. + * link:./modules/[./modules/] is where the Bahaghari module sets reside. All of them are then separated by... module sets and are organized by the aforementioned `default.nix`. * link:./tests/[./tests/] is where the test suites reside. We'll cover how to interact with the test suite right after this section. +An interesting thing to note: being a project where it exposes a Nix module and a library set, we actually don't use flakes for pinning our supported branches of nixpkgs and/or NixOS as much as we don't want to be fully locked into that feature and will also limit support for non-flake usage especially if a potential contributor doesn't use flakes. +Instead, we use a different pinning tool with https://github.com/andir/npins[npins]. +Please see its homepage for more information on using it. + + +[#library-development] +=== Library development + +A large part of Bahaghari is its library. +There's actually two top-level directories that you have to keep in mind: `lib` and `utils`. +Bahaghari separates its function set as either part of the library subset or utilities subset patterned after the NixOS environment of adding `utils` module argument. +The main difference between these two is the utilities subset depends on the environment configuration (for example, using `config.bahaghari.tinted-theming.schemes`) while those in library subset does not. +We just separate these for easier maintenance. + [#testing] === Testing diff --git a/subprojects/bahaghari/default.nix b/subprojects/bahaghari/default.nix index 1b273f88..01f31181 100644 --- a/subprojects/bahaghari/default.nix +++ b/subprojects/bahaghari/default.nix @@ -1,3 +1,7 @@ +# The user entrypoint for Bahaghari. Basically, the most important piece to +# maintain. Just keep in mind we shouldn't have anything requiring from the +# npins sources in here. +# # This is just kept for future compatiblity in case we require pkgs or something. {}: diff --git a/subprojects/bahaghari/flake.nix b/subprojects/bahaghari/flake.nix index 6c38dd49..ed63966e 100644 --- a/subprojects/bahaghari/flake.nix +++ b/subprojects/bahaghari/flake.nix @@ -1,16 +1,54 @@ +# It has a design constraint of requiring no flake inputs as we're already +# using npins. { description = "Specialized set of Nix modules for generating and applying themes."; - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - }; - - outputs = inputs@{ self, nixpkgs, ... }: - let systems = inputs.flake-utils.lib.defaultSystems; - in inputs.flake-utils.lib.eachSystem systems - (system: { + outputs = { ... }: + let + sources = import ./npins; + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + eachSystem = + systems: f: + let + # Merge together the outputs for all systems. + op = + attrs: system: + let + ret = f system; + op = + attrs: key: + attrs + // { + ${key} = (attrs.${key} or { }) // { + ${system} = ret.${key}; + }; + }; + in + builtins.foldl' op attrs (builtins.attrNames ret); + in + builtins.foldl' op { } ( + systems + # add the current system if --impure is used + ++ ( + if builtins ? currentSystem then + if builtins.elem builtins.currentSystem systems then [ ] else [ builtins.currentSystem ] + else + [ ] + ) + ); + in eachSystem systems + (system: let + tests = branch: import ./tests { inherit branch system; }; + in { devShells.default = - import ./shell.nix { pkgs = import nixpkgs { inherit system; }; }; + import ./shell.nix { pkgs = import sources.nixos-stable { inherit system; }; }; + + checks = { + bahaghariLibStable = (tests "stable").libTestPkg; + bahaghariLibUnstable = (tests "unstable").libTestPkg; + }; }) // import ./default.nix { }; } diff --git a/subprojects/bahaghari/lib/colors/README.adoc b/subprojects/bahaghari/lib/colors/README.adoc new file mode 100644 index 00000000..c016237c --- /dev/null +++ b/subprojects/bahaghari/lib/colors/README.adoc @@ -0,0 +1,8 @@ += Bahaghari library: Colors subset +:toc: + +The colors subset of the Bahaghari library. +It's not on the level of https://www.colour-science.org/[Color Science for Python] or https://crates.io/crates/palette[palette library for Rust] where it gives you a complete toolkit for manipulating a lot of aspects of colors. +Rather, this is only in relation to generating them colors to be pressed onto a template like program configurations from Nix modules and even some light templating for some. +Its API should only limit on that aspect. +No way in hell we're trying to reimplment that in Nix, lol. diff --git a/subprojects/bahaghari/lib/colors/hsl.nix b/subprojects/bahaghari/lib/colors/hsl.nix new file mode 100644 index 00000000..e1d900c8 --- /dev/null +++ b/subprojects/bahaghari/lib/colors/hsl.nix @@ -0,0 +1,135 @@ +# Similar to RGB, we're also going to base our implementation from looking +# after the W3 CSS Color Module Level 4 specification simply because it is the +# most common one. +{ pkgs, lib, self }: + +let inherit (self.colors) rgb; +in rec { + valueHueMin = 0.0; + valueHueMax = 360.0; + valueParamMin = 0.0; + valueParamMax = 100.0; + + /* Generates an HSL colorspace object to be generated with its method for + convenience. + + Type: HSL :: Attrs -> Attrs + + Example: + HSL { h = 242.0; s = 25; l = 50; } + => { + # The individual hue, saturation, and luminance levels. + + # And several methods. + methods = { + toRgb = ; + lighten = ; + }; + } + */ + HSL = { h, s, l, ... }@color: + assert lib.assertMsg (isHsl color) + "bahaghariLib.colors.hsl.HSL: given color does not have valid HSL value"; + { + inherit h s l; + } // lib.optionalAttrs (color ? a) { inherit (color) a; }; + + /* Returns a boolean if the object is a valid HSL Nix object. + + Type: isHsl :: Attrs -> Bool + + Example: + isHsl { h = 43; s = 89; l = 79; } + => true + + # The hue value is over 360 so it isn't valid. + isHsl { h = 467; s = 78; l = 50; } + => false + + # The lightness is over 100 so not valid either. + isHsl { h = 360; s = 86; l = 120; } + => false + */ + isHsl = { h, s, l, ... }@color: + let + isValidHue = self.math.isWithinRange valueHueMin valueHueMax; + isValidPercentage = self.math.isWithinRange valueParamMin valueParamMax; + in + isValidHue h && isValidPercentage s && isValidPercentage l; + + /* Converts an HSL object to RGB instance. + + Formula is directly taken from the following resource: + https://www.rapidtables.com/convert/color/hsl-to-rgb.html + + Type: toRgb :: Attrs -> Attrs + + Example: + toRgb { h = 234; s = 65; l = 73; } + => { r = 43; g = 52; b = 56 } + */ + toRgb = { h, s, l, ... }@color: + let + inherit (self.colors.rgb) RGB valueMax; + inherit (self.math) abs sub remainder round; + + l' = l / valueParamMax; + s' = s / valueParamMax; + + # This may as well turn into Scheme code. + C = (1 - (abs ((2 * l') - 1))) * s'; + X = C * (1 - (abs (sub (remainder (h / 60.0) 2) 1))); + m = l' - (C / 2); + + isHueWithin = min: max: + (h >= min) && (h < max); + rgb' = + if (isHueWithin 0 60) then + { r = C; g = X; b = 0; } + else if (isHueWithin 60 120) then + { r = X; g = C; b = 0; } + else if (isHueWithin 120 180) then + { r = 0; g = C; b = X; } + else if (isHueWithin 180 240) then + { r = 0; g = X; b = C; } + else if (isHueWithin 240 300) then + { r = X; g = 0; b = C; } + else if (isHueWithin 300 360) then + { r = C; g = 0; b = X; } + else throw "WHAT IN THE HELL"; + + scaleValue = x: round ((x + m) * valueMax); + in + RGB { + r = scaleValue rgb'.r; + g = scaleValue rgb'.g; + b = scaleValue rgb'.b; + }; + + /* Converts an HSL object into an RGB hex string. + + Type: toHex :: Attrs -> String + + Example: + toHex { h = 34; s = 76; l = 100; } + => "FFFFFF" + */ + toHex = color: rgb.toHex (toRgb color); + + /* Converts an HSL object into an RGBA hex string. + + Type: toHex :: Attrs -> String + + Example: + toHex { h = 34; s = 76; l = 100; } + => "FFFFFF" + */ + toHex' = color: rgb.toHex' (toRgb color); + + lighten = { h, s, l, ... }: + percentage: + HSL { + inherit h s; + l = l + percentage; + }; +} diff --git a/subprojects/bahaghari/lib/colors/rgb.nix b/subprojects/bahaghari/lib/colors/rgb.nix new file mode 100644 index 00000000..df50f06b --- /dev/null +++ b/subprojects/bahaghari/lib/colors/rgb.nix @@ -0,0 +1,192 @@ +# The most antiquated colorspace like ever. For this implementation, we will be +# looking after the RGB specification (especially the hexadecimal notation) as +# specified from W3 CSS Color Module Level 4 +# (https://www.w3.org/TR/css-color-4) since it is the most common one. +{ pkgs, lib, self }: + +rec { + # A bunch of metadata for this implementation. Might be useful if you want to + # create functions from this subset. + valueMin = 0.0; + valueMax = 255.0; + + /* Generates an RGB colorspace object. The point is to provide some + typechecking if the values passed are correct. + + Type: RGB :: Attrs -> Attrs + + Example: + RGB { r = 242.0; g = 12; b = 23; } + => { + # The individual red, green, and blue components. + } + */ + RGB = { r, g, b, ... }@color: + assert lib.assertMsg (isRgb color) + "bahaghariLib.colors.rgb.RGB: Given object has invalid values (only 0-255 are allowed)"; + lib.optionalAttrs (color ? a) { inherit (color) a; } // { + inherit r g b; + }; + + /* Returns a boolean to check if it's a valid RGB Nix object or not. + + Type: isRgb :: Attrs -> Bool + + Example: + isRgb { r = 34; g = 43; b = 555; } + # `b` is more than 255.0 so it's a false + => false + + isRgb { r = 123; g = null; b = 43; } + # `g` is not a number so it's'a false again + => false + + isRgb { r = 123; g = 123; b = 123; } + => true + */ + isRgb = { r, g, b, ... }@color: + let + isWithinRGBRange = v: self.math.isWithinRange valueMin valueMax v; + isValidRGB = v: self.isNumber v && isWithinRGBRange v; + colors = [ r g b ] ++ lib.optionals (color ? a) [ color.a ]; + in lib.lists.all (v: isValidRGB v) colors; + + /* Converts the color to a 6-digit hex string. Unfortunately, it cannot + handle floats very well so we'll have to round these up. + + Type: toHex :: RGB -> String + + Example: + toHex { r = 231; g = 12; b = 21; } + => "E70C15" + */ + toHex = { r, g, b, ... }: + let + components = builtins.map (c: + let c' = self.math.round c; + in self.hex.pad 2 (self.hex.fromDec c')) [ r g b ]; + in lib.concatStringsSep "" components; + + /* Converts the color to a 8-digit hex string (RGBA). If no `a` component, it + will be assumed to be at maximum value. Unfortunately, it cannot handle + floats very well so we'll have to round these up. + + Type: toHex :: RGB -> String + + Example: + toHex' { r = 231; g = 12; b = 21; } + => "E70C15FF" + + toHex' { r = 231; g = 12; b = 21; a = 0; } + => "E70C1500" + */ + toHex' = { r, g, b, a ? valueMax, ... }: + let + components = builtins.map (c: + let c' = self.math.round c; + in self.hex.pad 2 (self.hex.fromDec c')) [ r g b a ]; + in lib.concatStringsSep "" components; + + /* Converts a valid hex string into an RGB object. + + Type: fromHex :: String -> RGB + + Example: + fromHex "FFFFFF" + => { r = 255; g = 255; b = 255; } + + fromHex "FFF" + => { r = 255; g = 255; b = 255; } + + fromHex "FFFF" + => { r = 255; g = 255; b = 255; a = 255; } + + fromHex "FFFFFFFF" + => { r = 255; g = 255; b = 255; a = 255; } + */ + fromHex = hex: + let + hex' = hexMatch hex; + r = lib.lists.elemAt hex' 0; + g = lib.lists.elemAt hex' 1; + b = lib.lists.elemAt hex' 2; + a = + if lib.lists.length hex' == 4 then + lib.lists.elemAt hex' 3 + else + null; + in RGB { + inherit r g b; + ${self.optionalNull (a != null) "a"} = a; + }; + + /* Given a percentage, uniformly lighten the given RGB color. + + Type: lighten :: RGB -> Number -> RGB + + Example: + let + color = RGB { r = 12; g = 46; b = 213; }; + in + lighten color 50 + */ + lighten = { r, g, b, ... }: + percentage: + let grow' = c: self.math.grow' valueMin valueMax percentage; + in RGB { + r = grow' r; + g = grow' g; + b = grow' b; + }; + + /* Given an RGB color in hexadecimal notation, returns a list of integers + representing each of the components in order. Certain forms of hex strings + will also return a fourth component representing the alpha channel (RGBA). + + Type: hexMatch :: String -> List + + Example: + hexMatch "FFF" + => [ 255 255 255 ] + + hexMatch "FFFF" + => [ 255 255 255 255 ] + + hexMatch "0A0B0C0D" + => [ 10 11 12 13 ] + */ + hexMatch = hex: + let + length = lib.stringLength hex; + generateRegex = r: n: + lib.strings.replicate r "([[:xdigit:]]{${builtins.toString n}})"; + nonAlphaGenMatch = generateRegex 3; + withAlphaGenMatch = generateRegex 4; + + regex = + if (length == 6) then + nonAlphaGenMatch 2 + else if (length == 3) then + nonAlphaGenMatch 1 + else if (length == 8) then + withAlphaGenMatch 2 + else if (length == 4) then + withAlphaGenMatch 1 + else + throw "Not a valid hex code"; + + scale = self.trivial.scale { + inMin = 0; + inMax = 15; + outMin = valueMin; + outMax = valueMax; + }; + + match = lib.strings.match regex hex; + output = builtins.map (x: self.hex.toDec x) match; + in + if (length == 3 || length == 4) then + builtins.map (x: scale x) output + else + output; +} diff --git a/subprojects/bahaghari/lib/default.nix b/subprojects/bahaghari/lib/default.nix index b2a80a75..afa85dcf 100644 --- a/subprojects/bahaghari/lib/default.nix +++ b/subprojects/bahaghari/lib/default.nix @@ -30,6 +30,13 @@ pkgs.lib.makeExtensible hex = callLibs ./hex.nix; math = callLibs ./math.nix; + # We won't export any of the attributes here as a top-level attribute for + # some unbeknownst and probably irrational reason. + colors = { + rgb = callLibs ./colors/rgb.nix; + hsl = callLibs ./colors/hsl.nix; + }; + # Dedicated module sets are not supposed to have any of its functions as a # top-level attribute. It's to make things a bit easier to organize and # maintain. Plus, if there's any functions that are easily applicable @@ -38,8 +45,10 @@ pkgs.lib.makeExtensible tinted-theming = callLibs ./tinted-theming.nix; inherit (self.trivial) importYAML toYAML toBaseDigitsWithGlyphs - generateGlyphSet generateConversionTable generateBaseDigitType clamp; + generateGlyphSet generateConversionTable generateBaseDigitType clamp + isNumber scale optionalNull toFloat; inherit (self.hex) isHexString; - inherit (self.math) abs pow percentage; + inherit (self.math) abs pow percentage factorial floor ceil round round' + summate product sqrt remainder mod radiansToDegrees degreesToRadians; }) diff --git a/subprojects/bahaghari/lib/hex.nix b/subprojects/bahaghari/lib/hex.nix index 29edffc8..56876e72 100644 --- a/subprojects/bahaghari/lib/hex.nix +++ b/subprojects/bahaghari/lib/hex.nix @@ -27,10 +27,37 @@ let baseSet = self.generateBaseDigitType glyphList; in rec { - /* Returns a convenient glyph set for creating your own conversion or - hex-related functions. + inherit (baseSet) glyphSet conversionTable; + + /* Converts a hexadecimal digit string into its decimal equivalent. + + Type: toDec :: String -> Number + + Example: + toDec "FF" + => 255 + + toDec "ff" + => 255 */ - inherit (baseSet) glyphSet conversionTable fromDec toDec; + toDec = digit: + let + digit' = lib.toUpper digit; + in + baseSet.toDec digit'; + + /* Converts a decimal digit into its hexadecimal notation. + + Type: fromDec :: Number -> String + + Example: + fromDec 255 + => "FF" + + fromDec 293454837 + => "117DC3F5" + */ + fromDec = decimal: lib.toUpper (baseSet.fromDec decimal); /* A variant of `lib.lists.range` function just with hexadecimal digits. diff --git a/subprojects/bahaghari/lib/math.nix b/subprojects/bahaghari/lib/math.nix index d5f82fba..7f543d6b 100644 --- a/subprojects/bahaghari/lib/math.nix +++ b/subprojects/bahaghari/lib/math.nix @@ -4,6 +4,48 @@ { pkgs, lib, self }: rec { + # We have the rounding functions here anyways so we may as well include the + # rest of the decimal place changing functions here for consistency. + inherit (builtins) floor ceil; + + constants = { + pi = 3.141592653589793238462643383279502884197; + e = 2.7182818284590452353602874713527; + ln10 = 2.302585092994046; + ln2 = 0.6931471805599453; + + # The precision target for our functions that need them. + epsilon = pow 0.1 13; + }; + + # TODO: We may need to export these functions as a separate Nix library. + /* Given a number, check if it's an even number. + + Type: isEven :: Int -> Int + + Example: + isEven 10 + => true + + isEven 13 + => false + */ + isEven = x: + (builtins.bitAnd x 1) == 0; + + /* Given a number, check if it's an odd number. + + Type: isOdd :: Int -> Int + + Example: + isOdd 10 + => true + + isOdd 13 + => false + */ + isOdd = x: !(isEven x); + /* Returns the absolute value of the given number. Type: abs :: Int -> Int @@ -30,17 +72,86 @@ rec { => 1296 */ pow = base: exponent: - # I'll just make this as a tail recursive function instead. + # Just to be a contrarian, I'll just make this as a tail recursive function + # instead lol. let absValue = abs exponent; - iter = product: counter: max-count: - if counter > max-count + iter = product: counter: maxCount: + if counter > maxCount then product - else iter (product * base) (counter + 1) max-count; + else iter (product * base) (counter + 1) maxCount; value = iter 1 1 absValue; in if exponent < 0 then (1 / value) else value; + /* Given a number as x, return e^x. + + Type: exp :: Number -> Number + + Example: + exp 0 + => 1 + + exp 1 + => 2.7182818284590452353602874713527 + + exp -1 + => 0.36787944117144233 + */ + exp = x: + pow constants.e x; + + /* Given a number, find its square root. This method is implemented using + Newton's method. + + Type: sqrt :: Number -> Number + + Example: + sqrt 4 + => 2 + + sqrt 169 + => 13 + + sqrt 12 + => 3.464101615 + */ + sqrt = number: + assert lib.assertMsg (number >= 0) + "bahaghariLib.math.sqrt: Only positive numbers are allowed"; + let + # Changing this value can change the result drastically. A value of + # 10^-13 for tolerance seems to be the most balanced so far since we are + # dealing with floats and should be enough for most cases. + tolerance = constants.epsilon; + + iter = value: + let + root = 0.5 * (value + (number / value)); + in + if (abs (root - value) > tolerance) then + iter root + else + value; + in + iter number; + + /* Implements the factorial function with the given value. + + Type: factorial :: Number -> Number + + Example: + factorial 3 + => 6 + + factorial 10 + => 3628800 + */ + factorial = x: + assert lib.assertMsg (x >= 0) + "bahaghariLib.math.factorial: Given value is not a positive integer"; + product (lib.range 1 x); + /* Returns a boolean whether the given number is within the given (inclusive) range. Type: isWithinRange :: Number -> Number -> Number -> Bool @@ -55,6 +166,20 @@ rec { isWithinRange = min: max: number: (lib.max number min) <= (lib.min number max); + /* Returns a boolean whether the given number is within the given (exclusive) range. + + Type: isWithinRange :: Number -> Number -> Number -> Bool + + Example: + isWithinRange 30 50 6 + => false + + isWithinRange 0 100 75 + => true + */ + isWithinRange' = min: max: number: + (lib.max number min) < (lib.min number max); + /* Given a number, make it grow by given amount of percentage. A value of 100 should make the number doubled. @@ -83,10 +208,7 @@ rec { => 1 */ grow' = min: max: value: number: - let - res = grow number value; - in - lib.min max (lib.max res min); + self.trivial.clamp min max (grow number value); /* Given a number, return its value by the given percentage. @@ -110,7 +232,7 @@ rec { then 0 else number / (100.0 / value); - /* Given a number, round up (or down) its number to the nearest integer. + /* Given a number, round up (or down) its number to the nearest ones place. Type: round :: Number -> Number @@ -124,10 +246,184 @@ rec { round 2.7 => 3 */ - round = number: + round = round' 0; + + /* Given a tens place (10 ^ n) and a number, round the nearest integer to its + given place. + + Type: round' :: Number -> Number -> Number + + Example: + # Round the number to the nearest ones. + round' 0 5.65 + => 6 + + # Round the number to the nearest tens. + round' 1 5.65 + => 10 + + # Round the number to the nearest hundreds. + round' 2 5.65 + => 0 + + # Round the number to the nearest tenth. + round' (-1) 5.65 + => 5.7 + */ + round' = tens: number: let - number' = builtins.floor number; - difference = number - number'; + nearest = pow 10.0 tens; + difference = number / nearest; in - if difference >= 0.5 then (number' + 1) else number'; + floor (difference + 0.5) * nearest; + + /* Given a base and a modulus, returns the value of a modulo operation. + + Type: mod :: Number -> Number -> Number + + Example: + mod 5 4 + => 1 + + mod 1245 4.5 + => 3 + + mod 19 (-12) + => -5 + */ + mod = base: modulus: + remainder ((remainder base modulus) + modulus) modulus; + + /* Similar to the nixpkgs' `trivial.mod` but retain the decimal values. This + is just an approximation from ECMAScript's implementation of the remainder + operator. + + Type: remainder :: Number -> Number -> Number + + Example: + remainder 4.25 2 + => 0.25 + + remainder 1.5 2 + => 1.5 + + remainder 65 5 + => 0 + + remainder (-54) 4 + => -2 + + remainder (-54) (-4) + => -2 + */ + remainder = dividend: divisor: + let + quotient = dividend / divisor; + in + dividend - ((floor quotient) * divisor); + + /* Adds all of the given items on the list starting from a sum of zero. + + Type: summate :: List[Number] -> Number + + Example: + summate [ 1 2 3 4 ] + => 10 + */ + summate = builtins.foldl' builtins.add 0; + + /* Multiply all of the given items on the list starting from a product of 1. + + Type: product :: List[Number] -> Number + + Example: + product [ 1 2 3 4 ] + => 24 + */ + product = builtins.foldl' builtins.mul 1; + + # The following trigonometric functions is pretty much sourced from the following link. + # https://lantian.pub/en/article/modify-computer/nix-trigonometric-math-library-from-zero.lantian/ + + /* Given a number in radians, return the value applied with a sine function. + + Type: sin :: Number -> Number + + Example: + sin 10 + => -0.5440211108893698 + + sin (constants.pi / 2) + => 1 + */ + sin = x: let + x' = mod (toFloat x) (2 * constants.pi); + step = i: (pow (-1) (i - 1)) * product (lib.genList (j: x' / (j + 1)) (i * 2 - 1)); + iter = value: counter: let + value' = step counter; + in + if (abs value') < constants.epsilon + then value + else iter (value' + value) (counter + 1); + in + if x < 0 + then -(sin (-x)) + else iter 0 1; + + /* Given a number in radians, apply the cosine function. + + Type: cos :: Number -> Number + + Example: + cos 10 + => -0.8390715290764524 + + cos 0 + => 1 + */ + cos = x: sin (0.5 * constants.pi - x); + + /* Given a number in radians, apply the tan trigonometric function. + + Type: tan :: Number -> Number + + Example: + tan 0 + => 0 + + tan 10 + => 0.6483608274590866 + */ + tan = x: (sin x) / (cos x); + + /* Given a number in radians, convert it to degrees. + + Type: radiansToDegrees :: Number -> Number + + Example: + radiansToDegrees bahaghariLib.math.constants.pi + => 180 + + radiansToDegrees 180 + => 10313.240312355 + */ + radiansToDegrees = x: + x * 180.0 / constants.pi; + + /* Given a number in degrees unit, convert it to radians. + + Type: degreesToRadians :: Number -> Number + + Example: + degreesToRadians 180 + => 3.141592653589793238462643383279502884197 + + degreesToRadians 360 + => 6.283185307 + + degreesToRadians 95 + => 1.658062789 + */ + degreesToRadians = x: + x * constants.pi / 180.0; } diff --git a/subprojects/bahaghari/lib/tinted-theming.nix b/subprojects/bahaghari/lib/tinted-theming.nix index 39e29dcd..df00e07e 100644 --- a/subprojects/bahaghari/lib/tinted-theming.nix +++ b/subprojects/bahaghari/lib/tinted-theming.nix @@ -44,7 +44,7 @@ rec { scheme = self.importYAML yamlpath; in assert lib.assertMsg (isValidScheme scheme || isLegacyScheme scheme) - "bahaghariLib.tinted-theming.importScheme: given data is not a valid Tinted Theming scheme"; + "bahaghariLib.tinted-theming.importScheme: Given data is not a valid Tinted Theming scheme"; if isLegacyScheme scheme then modernizeLegacyScheme scheme else scheme; diff --git a/subprojects/bahaghari/lib/trivial.nix b/subprojects/bahaghari/lib/trivial.nix index 9c559361..1791d87b 100644 --- a/subprojects/bahaghari/lib/trivial.nix +++ b/subprojects/bahaghari/lib/trivial.nix @@ -160,4 +160,71 @@ rec { */ clamp = min: max: value: lib.min max (lib.max min value); + + /* Given a value, check if it's a number type. + + Type: isNumber :: Number -> bool + + Example: + isNumber 3.0 + => true + + isNumber 653 + => true + + isNumber true + => false + */ + isNumber = v: + lib.isInt v || lib.isFloat v; + + /* Given a Nix number, force it to be a floating value. + + Type: toFloat :: Number -> Float + + Example: + toFloat 5 + => 5.0 + + toFloat 59.0 + => 59.0 + */ + toFloat = x: + 1.0 * x; + + /* Given an initial range of integers, scale the given number with its own + set of range. + + Type: scale :: Attrs -> Number -> Number + + Example: + scale { inMin = 0; inMax = 15; outMin = 0; outMax = 255; } 4 + => 68 + + scale { inMin = 0; inMax = 15; outMin = 0; outMax = 255; } (-4) + => -68 + + scale { inMin = 0; inMax = 15; outMin = 0; outMax = 255; } 15 + => 255 + */ + scale = { inMin, inMax, outMin, outMax }: v: + ((v - inMin) * (outMax - outMin)) / ((inMax - inMin) + outMin); + + /* Returns a null value if the condition fails. Otherwise, returns the given + value `as`. + + Type: optionalNull :: Bool -> Any -> Any + + Example: + optionalNull true "HELLO" + => "HELLO" + + optionalNull (null != null) "HELLO" + => null + */ + optionalNull = cond: as: + if cond then + as + else + null; } diff --git a/subprojects/bahaghari/lib/utils/default.nix b/subprojects/bahaghari/lib/utils/default.nix deleted file mode 100644 index 4584d2a6..00000000 --- a/subprojects/bahaghari/lib/utils/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ config, lib, pkgs, bahaghariLib }: - -let - callLib = path: import path { inherit config lib pkgs bahaghariLib; }; -in -{ - tinted-theming = callLib ./tinted-theming.nix; -} diff --git a/subprojects/bahaghari/modules/extra-arguments.nix b/subprojects/bahaghari/modules/extra-arguments.nix index 4fc1aa75..e0459b69 100644 --- a/subprojects/bahaghari/modules/extra-arguments.nix +++ b/subprojects/bahaghari/modules/extra-arguments.nix @@ -8,6 +8,6 @@ in # largely based from the `utils` module argument found in NixOS systems. _module.args = { inherit bahaghariLib; - bahaghariUtils = import ../lib/utils { inherit config pkgs lib bahaghariLib; }; + bahaghariUtils = import ../utils { inherit config pkgs lib bahaghariLib; }; }; } diff --git a/subprojects/bahaghari/npins/default.nix b/subprojects/bahaghari/npins/default.nix new file mode 100644 index 00000000..5e7d086e --- /dev/null +++ b/subprojects/bahaghari/npins/default.nix @@ -0,0 +1,80 @@ +# Generated by npins. Do not modify; will be overwritten regularly +let + data = builtins.fromJSON (builtins.readFile ./sources.json); + version = data.version; + + mkSource = + spec: + assert spec ? type; + let + path = + if spec.type == "Git" then + mkGitSource spec + else if spec.type == "GitRelease" then + mkGitSource spec + else if spec.type == "PyPi" then + mkPyPiSource spec + else if spec.type == "Channel" then + mkChannelSource spec + else + builtins.throw "Unknown source type ${spec.type}"; + in + spec // { outPath = path; }; + + mkGitSource = + { + repository, + revision, + url ? null, + hash, + branch ? null, + ... + }: + assert repository ? type; + # At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository + # In the latter case, there we will always be an url to the tarball + if url != null then + (builtins.fetchTarball { + inherit url; + sha256 = hash; # FIXME: check nix version & use SRI hashes + }) + else + assert repository.type == "Git"; + let + urlToName = + url: rev: + let + matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url; + + short = builtins.substring 0 7 rev; + + appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else ""; + in + "${if matched == null then "source" else builtins.head matched}${appendShort}"; + name = urlToName repository.url revision; + in + builtins.fetchGit { + url = repository.url; + rev = revision; + inherit name; + # hash = hash; + }; + + mkPyPiSource = + { url, hash, ... }: + builtins.fetchurl { + inherit url; + sha256 = hash; + }; + + mkChannelSource = + { url, hash, ... }: + builtins.fetchTarball { + inherit url; + sha256 = hash; + }; +in +if version == 3 then + builtins.mapAttrs (_: mkSource) data.pins +else + throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`" diff --git a/subprojects/bahaghari/npins/sources.json b/subprojects/bahaghari/npins/sources.json new file mode 100644 index 00000000..d26ca022 --- /dev/null +++ b/subprojects/bahaghari/npins/sources.json @@ -0,0 +1,29 @@ +{ + "pins": { + "nixos-stable": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "NixOS", + "repo": "nixpkgs" + }, + "branch": "nixos-24.05", + "revision": "b3b2b28c1daa04fe2ae47c21bb76fd226eac4ca1", + "url": "https://github.com/NixOS/nixpkgs/archive/b3b2b28c1daa04fe2ae47c21bb76fd226eac4ca1.tar.gz", + "hash": "06jxcg73ymibvfg3czmq856f84bkhxhqgwa51mf87xprjz74zxks" + }, + "nixos-unstable": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "NixOS", + "repo": "nixpkgs" + }, + "branch": "nixos-unstable", + "revision": "57610d2f8f0937f39dbd72251e9614b1561942d8", + "url": "https://github.com/NixOS/nixpkgs/archive/57610d2f8f0937f39dbd72251e9614b1561942d8.tar.gz", + "hash": "0k8az8vmfdk1n8xlza252sqk0hm1hfc7g67adin6jxqaab2s34n9" + } + }, + "version": 3 +} diff --git a/subprojects/bahaghari/shell.nix b/subprojects/bahaghari/shell.nix index b3b8623b..c025b6cd 100644 --- a/subprojects/bahaghari/shell.nix +++ b/subprojects/bahaghari/shell.nix @@ -1,7 +1,19 @@ -{ pkgs ? import { } }: +let + sources = import ./npins; +in +{ pkgs ? import sources.nixos-stable { } }: with pkgs; mkShell { - inputsFrom = [ nix ]; + inputsFrom = [ + nix + ]; + + packages = [ + npins + + treefmt + nixfmt-rfc-style + ]; } diff --git a/subprojects/bahaghari/tests/default.nix b/subprojects/bahaghari/tests/default.nix index a151c1a9..5643ea1d 100644 --- a/subprojects/bahaghari/tests/default.nix +++ b/subprojects/bahaghari/tests/default.nix @@ -1,8 +1,27 @@ -# This is the unit cases for our Nix project. -{ pkgs ? import { } }: - +# This is the unit cases for our Nix project. It should only require a nixpkgs +# instance and we'll have to make it easy to test between the unstable and +# stable version of home-manager and NixOS. +{ branch ? "stable", system ? builtins.currentSystem }: +let + sources = import ../npins; + pkgs = import sources."nixos-${branch}" { inherit system; }; + bahaghariLib = import ./lib { inherit pkgs; }; +in { - lib = import ./lib { inherit pkgs; }; + lib = bahaghariLib; + libTestPkg = + pkgs.runCommand "bahaghari-lib-test" + { + testData = builtins.toJSON bahaghariLib; + passAsFile = [ "testData" ]; + nativeBuildInputs = with pkgs; [ + yajsv + jq + ]; + } + '' + yajsv -s "${./lib/tests.schema.json}" "$testDataPath" && touch $out || jq . "$testDataPath" + ''; #modules = import ./modules { inherit pkgs; }; } diff --git a/subprojects/bahaghari/tests/lib/default.nix b/subprojects/bahaghari/tests/lib/default.nix index d0a5bc24..f0cff478 100644 --- a/subprojects/bahaghari/tests/lib/default.nix +++ b/subprojects/bahaghari/tests/lib/default.nix @@ -12,4 +12,6 @@ in math = callLib ./math.nix; trivial = callLib ./trivial; tinted-theming = callLib ./tinted-theming; + rgb = callLib ./rgb.nix; + hsl = callLib ./hsl.nix; } diff --git a/subprojects/bahaghari/tests/lib/hex.nix b/subprojects/bahaghari/tests/lib/hex.nix index e78558cb..bd558ded 100644 --- a/subprojects/bahaghari/tests/lib/hex.nix +++ b/subprojects/bahaghari/tests/lib/hex.nix @@ -26,11 +26,41 @@ lib.runTests { expected = 13756969779; }; + testHexToDec3 = { + expr = self.hex.toDec "0FF"; + expected = 255; + }; + + testHexToDec4 = { + expr = self.hex.toDec "0000FF"; + expected = 255; + }; + + testHexToDec5 = { + expr = self.hex.toDec "0A05"; + expected = 2565; + }; + + testHexToDecLowercase = { + expr = self.hex.toDec "0A0FfbA"; + expected = 10551226; + }; + + testHexToDecLowercase2 = { + expr = self.hex.toDec "0af"; + expected = 175; + }; + testCreateHexRange = { expr = self.hex.range 10 17; expected = [ "A" "B" "C" "D" "E" "F" "10" "11" ]; }; + testCreateHexRange2 = { + expr = self.hex.range 64 76; + expected = [ "40" "41" "42" "43" "44" "45" "46" "47" "48" "49" "4A" "4B" "4C" ]; + }; + testCreateHexWithHigherStart = { expr = self.hex.range 49 17; expected = [ ]; @@ -60,4 +90,9 @@ lib.runTests { expr = self.hex.pad (-5) "A42C"; expected = "A42C"; }; + + testHexPadWithMixedLetterCase = { + expr = self.hex.pad 8 "AfB9"; + expected = "0000AfB9"; + }; } diff --git a/subprojects/bahaghari/tests/lib/hsl.nix b/subprojects/bahaghari/tests/lib/hsl.nix new file mode 100644 index 00000000..da25e399 --- /dev/null +++ b/subprojects/bahaghari/tests/lib/hsl.nix @@ -0,0 +1,59 @@ +{ pkgs, lib, self }: + +let + inherit (self.colors.rgb) RGB; + inherit (self.colors.hsl) HSL; + + hslSample = HSL { + h = 254; + s = 100; + l = 45; + }; +in lib.runTests { + testsBasicHsl = { + expr = HSL { + h = 245; + s = 16; + l = 60; + }; + expected = { + h = 245; + s = 16; + l = 60; + }; + }; + + testsBasicHsl2 = { + expr = HSL { + h = 350; + s = 16; + l = 60; + a = 100; + }; + expected = { + h = 350; + s = 16; + l = 60; + a = 100; + }; + }; + + testsToRgb = { + expr = self.colors.hsl.toRgb hslSample; + expected = RGB { + r = 54; + g = 0; + b = 230; + }; + }; + + testsToHex = { + expr = self.colors.hsl.toHex hslSample; + expected = "3600E6"; + }; + + testsToHex' = { + expr = self.colors.hsl.toHex' hslSample; + expected = "3600E6FF"; + }; +} diff --git a/subprojects/bahaghari/tests/lib/math.nix b/subprojects/bahaghari/tests/lib/math.nix index f25ab4fd..1704067b 100644 --- a/subprojects/bahaghari/tests/lib/math.nix +++ b/subprojects/bahaghari/tests/lib/math.nix @@ -1,6 +1,37 @@ +# Being a math library implementation, we should be careful of making tests +# here to be consistent with the other math libraries. All of the answers here +# should be sourced from another tool such as a calculator. +# +# For future references, the initial maintainer (foodogsquared) basically used +# GNOME Calculator which uses libmath. { pkgs, lib, self }: +let + # The typical rounding procedure for our results. 10 decimal places should be + # enough to test accuracy at least for a basic math subset like this. + round' = self.math.round' (-10); +in lib.runTests { + testMathIsOdd = { + expr = self.math.isOdd 45; + expected = true; + }; + + testMathIsOdd2 = { + expr = self.math.isOdd 10; + expected = false; + }; + + testMathIsEven = { + expr = self.math.isEven 45; + expected = false; + }; + + testMathIsEven2 = { + expr = self.math.isEven 10; + expected = true; + }; + testMathPowPositive = { expr = self.math.pow 2 8; expected = 256; @@ -16,6 +47,11 @@ lib.runTests { expected = 1; }; + testsMathPowWithFloat = { + expr = self.math.pow 2 7.0; + expected = 128.0; + }; + testMathAbsoluteValue = { expr = self.math.abs 5493; expected = 5493; @@ -76,6 +112,26 @@ lib.runTests { expected = 0; }; + testMathFloor = { + expr = self.math.floor 3.467; + expected = 3; + }; + + testMathFloor2 = { + expr = self.math.floor 3.796; + expected = 3; + }; + + testMathCeil = { + expr = self.math.ceil 3.469; + expected = 4; + }; + + testMathCeil2 = { + expr = self.math.ceil 3.796; + expected = 4; + }; + testMathRoundDown = { expr = self.math.round 2.3; expected = 2; @@ -86,6 +142,31 @@ lib.runTests { expected = 3; }; + testMathRoundOnes = { + expr = self.math.round' 0 5.65; + expected = 6; + }; + + testMathRoundTens = { + expr = self.math.round' 1 5.65; + expected = 10; + }; + + testMathRoundHundreds = { + expr = self.math.round' 2 5.65; + expected = 0; + }; + + testMathRoundTenth = { + expr = self.math.round' (-1) 5.65; + expected = 5.7; + }; + + testMathRoundHundredth = { + expr = self.math.round' (-2) 5.655; + expected = 5.66; + }; + testMathWithinRange = { expr = self.math.isWithinRange (-100) 100 50; expected = true; @@ -95,4 +176,299 @@ lib.runTests { expr = self.math.isWithinRange 5 10 (-5); expected = false; }; + + testMathWithinRangeExclusive = { + expr = self.math.isWithinRange' 5 10 (-5); + expected = false; + }; + + testMathWithinRangeExclusive2 = { + expr = self.math.isWithinRange' 5 10 10; + expected = false; + }; + + testMathWithinRangeExclusive3 = { + expr = self.math.isWithinRange' (-100) 100 750; + expected = false; + }; + + testMathFactorial = { + expr = self.math.factorial 3; + expected = 6; + }; + + testMathFactorial2 = { + expr = self.math.factorial 10; + expected = 3628800; + }; + + testMathFactorialZero = { + expr = self.math.factorial 0; + expected = 1; + }; + + testMathSummate = { + expr = self.math.summate [ 1 2 3 4 ]; + expected = 10; + }; + + testMathSummate2 = { + expr = self.math.summate [ 1 2 3 4.5 5.6 6.7 ]; + expected = 22.8; + }; + + testMathProduct = { + expr = self.math.product [ 1 2 3 4 ]; + expected = 24; + }; + + testMathProduct2 = { + expr = self.math.product [ 1.5 2 3 4.6 ]; + expected = 41.4; + }; + + testMathSqrt = { + expr = round' (self.math.sqrt 4); + expected = 2; + }; + + testMathSqrt2 = { + expr = self.math.sqrt 169; + expected = 13; + }; + + testMathSqrt3 = { + expr = round' (self.math.sqrt 12); + expected = 3.4641016151; + }; + + testMathSqrt4 = { + expr = round' (self.math.sqrt 2); + expected = 1.4142135624; + }; + + testMathMod = { + expr = self.math.mod 5 4; + expected = 1; + }; + + testMathMod2 = { + expr = self.math.mod 1245 4.5; + expected = 3; + }; + + testMathModPositiveOperands = { + expr = self.math.mod 19 12; + expected = 7; + }; + + testMathModNegativeDividend = { + expr = self.math.mod (-19) 12; + expected = 5; + }; + + testMathModNegativeDivisor = { + expr = self.math.mod 19 (-12); + expected = -5; + }; + + testMathModNegativeOperands = { + expr = self.math.mod (-19) (-12); + expected = -7; + }; + + testMathRemainder = { + expr = self.math.remainder 65.5 3; + expected = 2.5; + }; + + testMathRemainder2 = { + expr = self.math.remainder 1.5 3; + expected = 1.5; + }; + + testMathRemainder3 = { + expr = self.math.remainder 4.25 2; + expected = 0.25; + }; + + testMathRemainder4 = { + expr = self.math.remainder 6 6; + expected = 0; + }; + + testMathRemainder5 = { + expr = self.math.remainder 6.5 6; + expected = 0.5; + }; + + testMathRemainder6 = { + expr = self.math.remainder 7856.5 20; + expected = 16.5; + }; + + # Computers and their quirky floating-values implementations... + testMathRemainder7 = { + expr = self.math.remainder 7568639.2 45633; + expected = 39194.200000000186; + }; + + testMathRemainder8 = { + expr = self.math.remainder 567.5 3.5; + expected = 0.5; + }; + + testMathRemainderPositiveOperands = { + expr = self.math.remainder 54.5 20.5; + expected = 13.5; + }; + + testMathRemainderNegativeDividend = { + expr = self.math.remainder (-54.5) 20.5; + expected = 7; + }; + + testMathRemainderNegativeDivisor = { + expr = self.math.remainder 54.5 (-20.5); + expected = -7; + }; + + testMathRemainderNegativeOperands = { + expr = self.math.remainder (-54.5) (-20.5); + expected = -13.5; + }; + + testMathExp = { + expr = self.math.exp 1; + expected = 2.7182818284590452353602874713527; + }; + + testMathExp2 = { + expr = self.math.exp (-1); + expected = 0.36787944117144233; + }; + + testMathExp3 = { + expr = round' (self.math.exp 2); + expected = 7.3890560989; + }; + + testDegreesToRadians = { + expr = self.math.degreesToRadians 180; + expected = self.math.constants.pi; + }; + + testDegreesToRadians2 = { + expr = self.math.degreesToRadians 360; + expected = self.math.constants.pi * 2; + }; + + testDegreesToRadians3 = { + expr = self.math.round' (-5) (self.math.degreesToRadians 95); + expected = 1.65806; + }; + + testRadiansToDegrees = { + expr = self.math.radiansToDegrees self.math.constants.pi; + expected = 180; + }; + + testRadiansToDegrees2 = { + expr = self.math.round' (-3) (self.math.radiansToDegrees 180); + expected = 10313.24; + }; + + testRadiansToDegrees3 = { + expr = self.math.round' (-3) (self.math.radiansToDegrees 4.5); + expected = 257.831; + }; + + # At this point, most of the things are just adjusting to the quirks of those + # accursed floating-values. + testMathSine = { + expr = round' (self.math.sin 10); + expected = round' (-0.5440211108893698); + }; + + testMathSine2 = { + expr = self.math.sin 0; + expected = 0; + }; + + testMathSine3 = let + round' = self.math.round' (-5); + in { + expr = round' (self.math.sin (self.math.constants.pi / 2)); + expected = round' 1; + }; + + testMathSine4 = { + expr = round' (self.math.sin 360); + expected = round' 0.9589157234143065; + }; + + testMathSine5 = { + expr = round' (self.math.sin 152); + expected = round' 0.933320523748862; + }; + + testMathSine6 = { + expr = round' (self.math.sin (-152)); + expected = round' (-0.933320523748862); + }; + + testMathCosine = { + expr = round' (self.math.cos 10); + expected = round' (-0.8390715290764524); + }; + + testMathCosine2 = { + expr = round' (self.math.cos 0); + expected = 1; + }; + + testMathCosine3 = { + expr = round' (self.math.cos self.math.constants.pi); + expected = -1; + }; + + testMathCosine4 = { + expr = round' (self.math.cos (self.math.constants.pi * 2)); + expected = 1; + }; + + testMathCosine5 = { + expr = round' (self.math.cos 1); + expected = round' 0.5403023058681398; + }; + + testMathCosine6 = { + expr = round' (self.math.cos 152); + expected = round' 0.35904428689111606; + }; + + testMathTangent = { + expr = round' (self.math.tan 10); + expected = round' 0.6483608274590866; + }; + + testMathTangent2 = { + expr = round' (self.math.tan 0); + expected = 0; + }; + + testMathTangent3 = { + expr = round' (self.math.tan (self.math.constants.pi / 4)); + expected = round' (0.99999999999999999); + }; + + testMathTangent4 = { + expr = round' (self.math.tan 152); + expected = round' 2.5994579438382797; + }; + + testMathTangent5 = { + expr = round' (self.math.tan (-152)); + expected = round' (-2.5994579438382797); + }; } diff --git a/subprojects/bahaghari/tests/lib/rgb.nix b/subprojects/bahaghari/tests/lib/rgb.nix new file mode 100644 index 00000000..b1c2f3ab --- /dev/null +++ b/subprojects/bahaghari/tests/lib/rgb.nix @@ -0,0 +1,147 @@ +{ pkgs, lib, self }: + +let + # A modified version that simply removes the functor to focus more on the + # actual results. Also, it will mess up the result comparison since comparing + # functions is reference-based so it will always fail. + normalizeData = colors: + lib.attrsets.removeAttrs colors [ "__functor" "methods" ]; + + rgbSample = self.colors.rgb.RGB { + r = 255; + g = 255; + b = 255; + }; + + # A modified version of RGB that normalizes data out-of-the-boxly. + RGB = colors: normalizeData (self.colors.rgb.RGB colors); +in lib.runTests { + testsBasicRgb = { + expr = RGB { + r = 34; + g = 2; + b = 0; + }; + expected = { + r = 34; + g = 2; + b = 0; + }; + }; + + testsBasicRgb2 = { + expr = RGB { + r = 23; + g = 65; + b = 241; + a = 255; + }; + expected = { + r = 23; + g = 65; + b = 241; + a = 255; + }; + }; + + testsFromHex = { + expr = normalizeData (self.colors.rgb.fromHex "FFFFFF"); + expected = normalizeData (self.colors.rgb.RGB { + r = 255; + g = 255; + b = 255; + }); + }; + + testsFromHex2 = { + expr = normalizeData (self.colors.rgb.fromHex "FFF"); + expected = normalizeData (self.colors.rgb.RGB { + r = 255; + g = 255; + b = 255; + }); + }; + + testsFromHex3 = { + expr = normalizeData (self.colors.rgb.fromHex "FFFF"); + expected = normalizeData (self.colors.rgb.RGB { + r = 255; + g = 255; + b = 255; + a = 255; + }); + }; + + testsFromHex4 = { + expr = normalizeData (self.colors.rgb.fromHex "FFFFFFFF"); + expected = normalizeData (self.colors.rgb.RGB { + r = 255; + g = 255; + b = 255; + a = 255; + }); + }; + + testsToHex = { + expr = self.colors.rgb.toHex rgbSample; + expected = "FFFFFF"; + }; + + testsToHex2 = { + expr = self.colors.rgb.toHex (RGB { + r = 23; + g = 58; + b = 105; + }); + expected = "173A69"; + }; + + testsToHex3 = { + expr = self.colors.rgb.toHex (RGB { + r = 23; + g = 58; + b = 105; + a = 21; + }); + expected = "173A69"; + }; + + testsToHexVariant = { + expr = self.colors.rgb.toHex' (RGB { + r = 255; + g = 56; + b = 105; + }); + expected = "FF3869FF"; + }; + + testsToHexVariant2 = { + expr = self.colors.rgb.toHex' (RGB { + r = 255; + g = 56; + b = 105; + a = 34; + }); + expected = "FF386922"; + }; + + testsHexMatch = { + expr = self.colors.rgb.hexMatch "FFF"; + expected = [ 255 255 255 ]; + }; + + testsHexMatch2 = { + expr = self.colors.rgb.hexMatch "FFFF"; + expected = [ 255 255 255 255 ]; + }; + + testsHexMatch3 = { + expr = self.colors.rgb.hexMatch "0A0B0C0D"; + expected = [ 10 11 12 13 ]; + }; + + testsHexMatch4 = { + expr = self.colors.rgb.hexMatch "0A0B0C"; + expected = [ 10 11 12 ]; + }; +} diff --git a/subprojects/bahaghari/tests/lib/tests.schema.json b/subprojects/bahaghari/tests/lib/tests.schema.json new file mode 100644 index 00000000..e1c660f5 --- /dev/null +++ b/subprojects/bahaghari/tests/lib/tests.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "nix-lib-bahaghari Nix test object", + "type": "object", + "patternProperties": { + "^\\w+$": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 0, + "maxItems": 0 + }, + "required": true + } +} diff --git a/subprojects/bahaghari/tests/lib/trivial/default.nix b/subprojects/bahaghari/tests/lib/trivial/default.nix index 9d311271..8d9bec5c 100644 --- a/subprojects/bahaghari/tests/lib/trivial/default.nix +++ b/subprojects/bahaghari/tests/lib/trivial/default.nix @@ -1,6 +1,10 @@ { pkgs, lib, self }: let + # The typical rounding procedure for our results. 10 decimal places should be + # enough to test accuracy at least for a basic math subset like this. + round' = self.math.round' (-6); + customOctalGlyphs = { "0" = "A"; "1" = "B"; @@ -225,4 +229,74 @@ lib.runTests { expr = self.trivial.clamp 1 10 453; expected = 10; }; + + testNumberScale = { + expr = self.trivial.scale { inMin = 0; inMax = 15; outMin = 0; outMax = 255; } 15; + expected = 255; + }; + + testNumberScale2 = { + expr = self.trivial.scale { inMin = 0; inMax = 15; outMin = 0; outMax = 255; } 4; + expected = 68; + }; + + testNumberScale3 = { + expr = self.trivial.scale { inMin = 0; inMax = 15; outMin = 0; outMax = 255; } (-4); + expected = (-68); + }; + + testNumberScaleFloat = { + expr = self.trivial.scale { inMin = 0; inMax = 255; outMin = 0.0; outMax = 1.0; } 255; + expected = 1.0; + }; + + testNumberScaleFloat2 = { + expr = self.trivial.scale { inMin = 0; inMax = 255; outMin = 0.0; outMax = 1.0; } 127.5; + expected = 0.5; + }; + + testNumberScaleFloat3 = { + expr = round' (self.trivial.scale { inMin = 0; inMax = 255; outMin = 0.0; outMax = 1.0; } 53); + expected = round' 0.207843; + }; + + testIsNumber1 = { + expr = self.trivial.isNumber 3; + expected = true; + }; + + testIsNumber2 = { + expr = self.trivial.isNumber 4.09; + expected = true; + }; + + testIsNumber3 = { + expr = self.trivial.isNumber "HELLO"; + expected = false; + }; + + testIsNumber4 = { + expr = self.trivial.isNumber true; + expected = false; + }; + + testOptionalNull = { + expr = self.trivial.optionalNull true "HELLO"; + expected = "HELLO"; + }; + + testOptionalNull2 = { + expr = self.trivial.optionalNull false "HELLO"; + expected = null; + }; + + testToFloat = { + expr = self.trivial.toFloat 46; + expected = 46.0; + }; + + testToFloat2 = { + expr = self.trivial.toFloat 26.5; + expected = 26.5; + }; } diff --git a/subprojects/bahaghari/treefmt.toml b/subprojects/bahaghari/treefmt.toml new file mode 100644 index 00000000..9afb623c --- /dev/null +++ b/subprojects/bahaghari/treefmt.toml @@ -0,0 +1,3 @@ +[formatter.nix] +command = "nixfmt" +includes = [ "*.nix" ] diff --git a/subprojects/bahaghari/utils/README.adoc b/subprojects/bahaghari/utils/README.adoc new file mode 100644 index 00000000..5b42361a --- /dev/null +++ b/subprojects/bahaghari/utils/README.adoc @@ -0,0 +1,8 @@ += Utilities +:toc: + +Bahaghari separates its function set as either part of the library subset or utilities subset patterned after the NixOS environment of adding `utils` module argument. +The main difference between these two is the utilities subset depends on the environment configuration (for example, using `config.bahaghari.tinted-theming.schemes`) while those in library subset does not. +We just separate these for easier maintenance. + +Just like the library subset, these are expected to be included as a module argument modularly so there should be no functions that generates Nix modules or anything that requires `bahagariUtils` to be fully evaluated (such as putting it in `imports` top-level module attribute). diff --git a/subprojects/bahaghari/utils/default.nix b/subprojects/bahaghari/utils/default.nix new file mode 100644 index 00000000..7b9b7ab0 --- /dev/null +++ b/subprojects/bahaghari/utils/default.nix @@ -0,0 +1,8 @@ +{ config, lib, pkgs, bahaghariLib }@args: + +let + callLib = path: import path args; +in +{ + tinted-theming = callLib ./tinted-theming.nix; +} diff --git a/subprojects/bahaghari/lib/utils/tinted-theming.nix b/subprojects/bahaghari/utils/tinted-theming.nix similarity index 100% rename from subprojects/bahaghari/lib/utils/tinted-theming.nix rename to subprojects/bahaghari/utils/tinted-theming.nix diff --git a/subprojects/wrapper-manager-fds/.gitignore b/subprojects/wrapper-manager-fds/.gitignore new file mode 100644 index 00000000..e132401e --- /dev/null +++ b/subprojects/wrapper-manager-fds/.gitignore @@ -0,0 +1,6 @@ +# The typical output name for Nix builds. +result* + +### direnv ### +.direnv +.envrc diff --git a/subprojects/wrapper-manager-fds/LICENSE b/subprojects/wrapper-manager-fds/LICENSE new file mode 100644 index 00000000..f665d889 --- /dev/null +++ b/subprojects/wrapper-manager-fds/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2024 Gabriel Arazas + +Program uses the following files/implementations from other authors; +see their respective license headers for more details: +flake.nix, specifically the eachSystem which is taken directly from flake-utils: Copyright (c) 2020 zimbatm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/subprojects/wrapper-manager-fds/Makefile b/subprojects/wrapper-manager-fds/Makefile new file mode 100644 index 00000000..eddb26dd --- /dev/null +++ b/subprojects/wrapper-manager-fds/Makefile @@ -0,0 +1,18 @@ +.PHONY: docs-serve +docs-serve: + hugo -s docs/website serve + +.PHONY: docs-build +docs-build: + hugo -s docs/website + +# Ideally, this should be done only in the remote CI environment with a certain +# update cadence/rhythm. +.PHONY: update +update: + npins update + +# Ideally this should be done before committing. +.PHONY: format +format: + treefmt diff --git a/subprojects/wrapper-manager-fds/README.adoc b/subprojects/wrapper-manager-fds/README.adoc new file mode 120000 index 00000000..0b90a039 --- /dev/null +++ b/subprojects/wrapper-manager-fds/README.adoc @@ -0,0 +1 @@ +docs/website/content/en/project-overview.adoc \ No newline at end of file diff --git a/subprojects/wrapper-manager-fds/default.nix b/subprojects/wrapper-manager-fds/default.nix new file mode 100644 index 00000000..55a4a4cc --- /dev/null +++ b/subprojects/wrapper-manager-fds/default.nix @@ -0,0 +1,35 @@ +# The user entrypoint which makes it especially important to be maintained. +# +# Anyways, we just keep this attribute set for forward compatability in case it +# became required for users to pass something like the nixpkgs instance. +{ }: + +{ + # Self-explanatory attributes, yeah? These are just integration modules for + # the select environments... + # ...such as for NixOS, ... + nixosModules = rec { + default = wrapper-manager; + wrapper-manager = ./modules/env/nixos; + }; + + # ...and for home-manager. + homeModules = rec { + default = wrapper-manager; + wrapper-manager = ./modules/env/home-manager; + }; + + # The main library interface that can be used for immediate consumption. + lib = import ./lib/env.nix; + + # This is intended to be imported by the user in case they want to initialize + # their own wrapper-manager library for whatever reason. + wrapperManagerLib = ./lib; + + # The overlay that can be included in the nixpkgs instance which includes + # only the wrapper-manager library set for now (and pretty much in the + # distant future). + overlays.default = final: prev: { + wrapperManagerLib = import ./lib { pkgs = final; }; + }; +} diff --git a/subprojects/wrapper-manager-fds/docs/.gitignore b/subprojects/wrapper-manager-fds/docs/.gitignore new file mode 100644 index 00000000..b83ab0b6 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/.gitignore @@ -0,0 +1,58 @@ +### Ruby ### +*.gem +*.rbc +/.config +/coverage/ +/InstalledFiles +/pkg/ +/spec/reports/ +/spec/examples.txt +/test/tmp/ +/test/version_tmp/ +/tmp/ + +# Used by dotenv library to load environment variables. +# .env + +# Ignore Byebug command history file. +.byebug_history + +## Specific to RubyMotion: +.dat* +.repl_history +build/ +*.bridgesupport +build-iPhoneOS/ +build-iPhoneSimulator/ + +## Specific to RubyMotion (use of CocoaPods): +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# vendor/Pods/ + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ + +## Environment normalization: +/.bundle/ +/vendor/bundle +/lib/bundler/man/ + +# for a library or gem, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# Gemfile.lock +# .ruby-version +# .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc + +# Used by RuboCop. Remote config files pulled in from inherit_from directive. +# .rubocop-https?--* + diff --git a/subprojects/wrapper-manager-fds/docs/Gemfile b/subprojects/wrapper-manager-fds/docs/Gemfile new file mode 100644 index 00000000..57481b81 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/Gemfile @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' +gem 'asciidoctor' +gem 'asciidoctor-diagram' +gem 'asciidoctor-foodogsquared-extensions' +gem 'concurrent-ruby' +gem 'open-uri-cached' +gem 'rouge' +gem 'slim' +gem 'tilt' + +group :development do + gem 'rake' + gem 'ruby-lsp', require: false +end + +group :lint do + gem 'rubocop', require: false +end diff --git a/subprojects/wrapper-manager-fds/docs/Gemfile.lock b/subprojects/wrapper-manager-fds/docs/Gemfile.lock new file mode 100644 index 00000000..7f412d78 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/Gemfile.lock @@ -0,0 +1,84 @@ +GEM + remote: https://rubygems.org/ + specs: + asciidoctor (2.0.23) + asciidoctor-diagram (2.3.1) + asciidoctor (>= 1.5.7, < 3.x) + asciidoctor-diagram-ditaamini (~> 1.0) + asciidoctor-diagram-plantuml (~> 1.2021) + rexml + asciidoctor-diagram-batik (1.17) + asciidoctor-diagram-ditaamini (1.0.3) + asciidoctor-diagram-plantuml (1.2024.5) + asciidoctor-diagram-batik (~> 1.17) + asciidoctor-foodogsquared-extensions (1.2.1) + asciidoctor (~> 2.0) + rugged (~> 1.0) + ast (2.4.2) + concurrent-ruby (1.3.3) + json (2.7.2) + language_server-protocol (3.17.0.3) + logger (1.6.0) + open-uri-cached (1.0.0) + parallel (1.25.1) + parser (3.3.4.0) + ast (~> 2.4.1) + racc + prism (0.30.0) + racc (1.8.0) + rainbow (3.1.1) + rake (13.2.1) + rbs (3.5.2) + logger + regexp_parser (2.9.2) + rexml (3.3.1) + strscan + rouge (4.3.0) + rubocop (1.65.0) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.4, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.31.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.31.3) + parser (>= 3.3.1.0) + ruby-lsp (0.17.7) + language_server-protocol (~> 3.17.0) + prism (>= 0.29.0, < 0.31) + rbs (>= 3, < 4) + sorbet-runtime (>= 0.5.10782) + ruby-progressbar (1.13.0) + rugged (1.7.2) + slim (5.2.1) + temple (~> 0.10.0) + tilt (>= 2.1.0) + sorbet-runtime (0.5.11481) + strscan (3.1.0) + temple (0.10.3) + tilt (2.4.0) + unicode-display_width (2.5.0) + +PLATFORMS + ruby + x86_64-linux + +DEPENDENCIES + asciidoctor + asciidoctor-diagram + asciidoctor-foodogsquared-extensions + concurrent-ruby + open-uri-cached + rake + rouge + rubocop + ruby-lsp + slim + tilt + +BUNDLED WITH + 2.5.11 diff --git a/subprojects/wrapper-manager-fds/docs/LICENSE b/subprojects/wrapper-manager-fds/docs/LICENSE new file mode 100644 index 00000000..3aba2ccd --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/LICENSE @@ -0,0 +1,450 @@ + GNU Free Documentation License + Version 1.3, 3 November 2008 + + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. See +https://www.gnu.org/licenses/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/subprojects/wrapper-manager-fds/docs/README.adoc b/subprojects/wrapper-manager-fds/docs/README.adoc new file mode 100644 index 00000000..8e2c2e20 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/README.adoc @@ -0,0 +1,11 @@ += Documentation +:toc: + +This is where the documentation is created, namely both the website and the manual page. + +* The website is powered by Hugo and it is pretty much what makes most of the files here. +It requires Hugo and whatever Hugo module feature requires so it isn't possible to build it offline. +For now, we rely on the remote CI having network access for it (which is pretty much the standard for the most part so no worries there). + +* The manual page is powered by some under-documented tool in the Nix ecosystem (as is tradition) called https://github.com/NixOS/nixpkgs/tree/de19b7eaffd1ec24c50a6a257f3674a841ab1221/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs[nixos-render-docs]. +The adjacent tools in the Nix-module-options-doc-generation ecosystem are also what makes the (autogenerated) Nix module options pages found in the website. diff --git a/subprojects/wrapper-manager-fds/docs/default.nix b/subprojects/wrapper-manager-fds/docs/default.nix new file mode 100644 index 00000000..13266f5f --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/default.nix @@ -0,0 +1,192 @@ +let + sources = import ../npins; +in +{ + pkgs ? import sources.nixos-unstable { }, + extraModules ? [ ], +}: + +let + inherit (pkgs) nixosOptionsDoc lib; + + src = builtins.toString ../.; + + # Pretty much inspired from home-manager's documentation build process. + evalDoc = + args@{ + modules, + includeModuleSystemOptions ? false, + ... + }: + let + options = + (pkgs.lib.evalModules { + modules = modules ++ [ + { + _module.check = false; + _module.args.pkgs = pkgs; + } + ]; + class = "wrapperManager"; + }).options; + + # Based from nixpkgs' and home-manager's code. + gitHubDeclaration = user: repo: subpath: + { + url = "https://github.com/${user}/${repo}/blob/master/${subpath}"; + name = "<${repo}/${subpath}>"; + }; + + in + nixosOptionsDoc ( + { + options = + if includeModuleSystemOptions then options else builtins.removeAttrs options [ "_module" ]; + transformOptions = opt: + opt // { + declarations = map (decl: + if lib.hasPrefix src (toString decl) then + gitHubDeclaration "foo-dogsquared" "wrapper-manager-fds" + (lib.removePrefix "/" (lib.removePrefix src (toString decl))) + else if decl == "lib/modules.nix" then + gitHubDeclaration "NixOS" "nixpkgs" decl + else + decl) opt.declarations; + }; + } + // builtins.removeAttrs args [ + "modules" + "includeModuleSystemOptions" + ] + ); + releaseConfig = lib.importJSON ../release.json; + + wrapperManagerLib = (import ../. { }).lib; + wmOptionsDoc = evalDoc { + modules = [ ../modules/wrapper-manager ] ++ extraModules; + includeModuleSystemOptions = true; + }; + wmNixosDoc = evalDoc { modules = [ ../modules/env/nixos ]; }; + wmHmDoc = evalDoc { modules = [ ../modules/env/home-manager ]; }; + + gems = pkgs.bundlerEnv { + name = "wrapper-manager-fds-gem-env"; + ruby = pkgs.ruby_3_1; + gemdir = ./.; + }; +in +{ + # I forgot about the fact Hugo also uses Go modules for its Hugo modules + # feature. For now, this is considered broken up until that is working and I + # know squat about Go build system. Also, Hugo has several features such as + # embedding metadata from VCS which doesn't play well with Nix that is + # requiring a clean source. + # + # For now, we're just relying on nix-shell to build it for us. + website = + let + buildHugoSite = pkgs.callPackage ./hugo-build-module.nix { }; + + # Now this is some dogfooding. + asciidoctorWrapped = wrapperManagerLib.build { + inherit pkgs; + modules = [ + ( + { + config, + lib, + pkgs, + ... + }: + { + wrappers.asciidoctor = { + arg0 = lib.getExe' gems "asciidoctor"; + appendArgs = [ + "-T" + "${sources.website}/templates" + ]; + }; + } + ) + ]; + }; + in + buildHugoSite { + pname = "wrapper-manager-docs"; + version = "2024-07-13"; + + src = lib.fileset.toSource { + root = ./website; + fileset = lib.fileset.unions [ + ./website/assets + ./website/config + ./website/content + ./website/layouts + ./website/go.mod + ./website/go.sum + ]; + }; + + vendorHash = "sha256-W0PJdS9C8Qz9jU5zRmfwBshsCK8BJFIYBFVstpfZEUI="; + + buildInputs = with pkgs; [ + asciidoctorWrapped + git + gems + gems.wrappedRuby + ]; + + preBuild = '' + install -Dm0644 ${wmOptionsDoc.optionsAsciiDoc} ./content/en/wrapper-manager-env-options.adoc + install -Dm0644 ${wmNixosDoc.optionsAsciiDoc} ./content/en/wrapper-manager-nixos-module.adoc + install -Dm0644 ${wmHmDoc.optionsAsciiDoc} ./content/en/wrapper-manager-home-manager-module.adoc + ''; + + meta = with lib; { + description = "wrapper-manager-fds documentation"; + homepage = "https://github.com/foo-dogsquared/wrapper-manager-fds"; + license = with licenses; [ + mit + fdl13Only + ]; + platforms = platforms.all; + }; + }; + + inherit wmOptionsDoc wmHmDoc wmNixosDoc; + + inherit releaseConfig; + outputs = { + manpage = + pkgs.runCommand "wrapper-manager-reference-manpage" + { + nativeBuildInputs = with pkgs; [ + nixos-render-docs + gems + gems.wrappedRuby + ]; + } + '' + mkdir -p $out/share/man/man5 + asciidoctor --attribute is-wider-scoped --backend manpage \ + ${./manpages/header.adoc} --out-file header.5 + nixos-render-docs options manpage --revision ${releaseConfig.version} \ + --header ./header.5 --footer ${./manpages/footer.5} \ + ${wmOptionsDoc.optionsJSON}/share/doc/nixos/options.json \ + $out/share/man/man5/wrapper-manager.nix.5 + ''; + + html = + pkgs.runCommand "wrapper-manager-reference-html" + { + nativeBuildInputs = [ + gems + gems.wrappedRuby + ]; + } + '' + mkdir -p $out/share/wrapper-manager + asciidoctor --backend html ${wmOptionsDoc.optionsAsciiDoc} --attribute toc --out-file $out/share/wrapper-manager/options-reference.html + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/docs/gemset.nix b/subprojects/wrapper-manager-fds/docs/gemset.nix new file mode 100644 index 00000000..11fe6e82 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/gemset.nix @@ -0,0 +1,424 @@ +{ + asciidoctor = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1wyxgwmnz9bw377r3lba26b090hbsq9qnbw8575a1prpy83qh82j"; + type = "gem"; + }; + version = "2.0.23"; + }; + asciidoctor-diagram = { + dependencies = [ + "asciidoctor" + "asciidoctor-diagram-ditaamini" + "asciidoctor-diagram-plantuml" + "rexml" + ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1214scxm36k409gfy3wilfqx3akrm52r530zmra6cmmf6d22c5q4"; + type = "gem"; + }; + version = "2.3.1"; + }; + asciidoctor-diagram-batik = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0220xqxmkmimxmhsqhlbr0hslijvnhzdds3s6h6fxbxqrrmm0jrl"; + type = "gem"; + }; + version = "1.17"; + }; + asciidoctor-diagram-ditaamini = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "13h65bfbq7hc7z3kqn0m28w9c6ap7fikpjcvsdga6jg01slb4c56"; + type = "gem"; + }; + version = "1.0.3"; + }; + asciidoctor-diagram-plantuml = { + dependencies = [ "asciidoctor-diagram-batik" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1ppl5nsq40x11731ciahi89k5yvszlm12pml1pqaj0lwbi7ww6x0"; + type = "gem"; + }; + version = "1.2024.5"; + }; + asciidoctor-foodogsquared-extensions = { + dependencies = [ + "asciidoctor" + "rugged" + ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fm6shyysj51wi4s7nnb643j2mphp68fh44gmr83x8n613hg9a4l"; + type = "gem"; + }; + version = "1.2.1"; + }; + ast = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04nc8x27hlzlrr5c2gn7mar4vdr0apw5xg22wp6m8dx3wqr04a0y"; + type = "gem"; + }; + version = "2.4.2"; + }; + concurrent-ruby = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0skwdasxq7mnlcccn6aqabl7n9r3jd7k19ryzlzzip64cn4x572g"; + type = "gem"; + }; + version = "1.3.3"; + }; + json = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0b4qsi8gay7ncmigr0pnbxyb17y3h8kavdyhsh7nrlqwr35vb60q"; + type = "gem"; + }; + version = "2.7.2"; + }; + language_server-protocol = { + groups = [ + "default" + "development" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0gvb1j8xsqxms9mww01rmdl78zkd72zgxaap56bhv8j45z05hp1x"; + type = "gem"; + }; + version = "3.17.0.3"; + }; + logger = { + groups = [ + "default" + "development" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0gpg8gzi0xwymw4aaq2iafcbx31i3xzkg3fb30mdxn1d4qhc3dqa"; + type = "gem"; + }; + version = "1.6.0"; + }; + open-uri-cached = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "03v0if3jlvbclnd6jgjk94fbhf0h2fq1wxr0mbx7018sxzm0biwr"; + type = "gem"; + }; + version = "1.0.0"; + }; + parallel = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "145bn5q7ysnjj02jdf1x4nc1f0xxrv7ihgz9yr1j7sinmawqkq0j"; + type = "gem"; + }; + version = "1.25.1"; + }; + parser = { + dependencies = [ + "ast" + "racc" + ]; + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "10ly2wind06nylyqa5724ld2l0l46d3ag4fm04ifjgw7qdlpf94d"; + type = "gem"; + }; + version = "3.3.4.0"; + }; + prism = { + groups = [ + "default" + "development" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05j9bcxdz6wfnrjn32zvdwj1qsbp88mwx3rv7g256gziya6avc2r"; + type = "gem"; + }; + version = "0.30.0"; + }; + racc = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "021s7maw0c4d9a6s07vbmllrzqsj2sgmrwimlh8ffkvwqdjrld09"; + type = "gem"; + }; + version = "1.8.0"; + }; + rainbow = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0smwg4mii0fm38pyb5fddbmrdpifwv22zv3d3px2xx497am93503"; + type = "gem"; + }; + version = "3.1.1"; + }; + rake = { + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "17850wcwkgi30p7yqh60960ypn7yibacjjha0av78zaxwvd3ijs6"; + type = "gem"; + }; + version = "13.2.1"; + }; + rbs = { + dependencies = [ "logger" ]; + groups = [ + "default" + "development" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1fzk0a3d68fglnkwpaz07npi929y1kh2hh1j63y04943vvshyjmc"; + type = "gem"; + }; + version = "3.5.2"; + }; + regexp_parser = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0ik40vcv7mqigsfpqpca36hpmnx0536xa825ai5qlkv3mmkyf9ss"; + type = "gem"; + }; + version = "2.9.2"; + }; + rexml = { + dependencies = [ "strscan" ]; + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "09f3sw7f846fpcpwdm362ylqldwqxpym6z0qpld4av7zisrrzbrl"; + type = "gem"; + }; + version = "3.3.1"; + }; + rouge = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "072qvvrcqj0yfr3b0j932mlhvn41i38bq37z7z07i3ikagndkqwy"; + type = "gem"; + }; + version = "4.3.0"; + }; + rubocop = { + dependencies = [ + "json" + "language_server-protocol" + "parallel" + "parser" + "rainbow" + "regexp_parser" + "rexml" + "rubocop-ast" + "ruby-progressbar" + "unicode-display_width" + ]; + groups = [ "lint" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "18g462bccr0rvszc7kirr89laggdf6254p7pqsckk3izg901chv2"; + type = "gem"; + }; + version = "1.65.0"; + }; + rubocop-ast = { + dependencies = [ "parser" ]; + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "063qgvqbyv354icl2sgx758z22wzq38hd9skc3n96sbpv0cdc1qv"; + type = "gem"; + }; + version = "1.31.3"; + }; + ruby-lsp = { + dependencies = [ + "language_server-protocol" + "prism" + "rbs" + "sorbet-runtime" + ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1kvyk0cald1cw6fqxy5w68la1gnc1nv2mqx8myijjsbcf9npjbp8"; + type = "gem"; + }; + version = "0.17.7"; + }; + ruby-progressbar = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0cwvyb7j47m7wihpfaq7rc47zwwx9k4v7iqd9s1xch5nm53rrz40"; + type = "gem"; + }; + version = "1.13.0"; + }; + rugged = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1sccng15h8h3mcjxfgvxy85lfpswbj0nhmzwwsqdffbzqgsb2jch"; + type = "gem"; + }; + version = "1.7.2"; + }; + slim = { + dependencies = [ + "temple" + "tilt" + ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1rqk7jn66wgx50b18ndhbppjq55rbcwgqg1rbhnhxwiggvzisdbj"; + type = "gem"; + }; + version = "5.2.1"; + }; + sorbet-runtime = { + groups = [ + "default" + "development" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "122702d5cmrbaydcqfjksh1d78g0mq69h77zd4yljwjrc50jz70b"; + type = "gem"; + }; + version = "0.5.11481"; + }; + strscan = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0mamrl7pxacbc79ny5hzmakc9grbjysm3yy6119ppgsg44fsif01"; + type = "gem"; + }; + version = "3.1.0"; + }; + temple = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fwia5hvc1xz9w7vprzjnsym3v9j5l9ggdvy70jixbvpcpz4acfz"; + type = "gem"; + }; + version = "0.10.3"; + }; + tilt = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0kds7wkxmb038cwp6ravnwn8k65ixc68wpm8j5jx5bhx8ndg4x6z"; + type = "gem"; + }; + version = "2.4.0"; + }; + unicode-display_width = { + groups = [ + "default" + "lint" + ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1d0azx233nags5jx3fqyr23qa2rhgzbhv8pxp46dgbg1mpf82xky"; + type = "gem"; + }; + version = "2.5.0"; + }; +} diff --git a/subprojects/wrapper-manager-fds/docs/hugo-build-module.nix b/subprojects/wrapper-manager-fds/docs/hugo-build-module.nix new file mode 100644 index 00000000..7332eb9c --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/hugo-build-module.nix @@ -0,0 +1,320 @@ +# Copyright (c) 2003-2024 Eelco Dolstra and the Nixpkgs/NixOS contributors +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +{ + hugo, + go, + cacert, + git, + lib, + stdenv, +}: + +{ + name ? "${args'.pname}-${args'.version}", + nativeBuildInputs ? [ ], + passthru ? { }, + + # A function to override the goModules derivation + overrideModAttrs ? (_oldAttrs: { }), + + # path to go.mod and go.sum directory + modRoot ? "./", + + # vendorHash is the SRI hash of the vendored dependencies + # + # if vendorHash is null, then we won't fetch any dependencies and + # rely on the vendor folder within the source. + vendorHash ? throw ( + if args' ? vendorSha256 then + "buildGoModule: Expect vendorHash instead of vendorSha256" + else + "buildGoModule: vendorHash is missing" + ), + # Whether to delete the vendor folder supplied with the source. + deleteVendor ? false, + # Whether to fetch (go mod download) and proxy the vendor directory. + # This is useful if your code depends on c code and go mod tidy does not + # include the needed sources to build or if any dependency has case-insensitive + # conflicts which will produce platform dependant `vendorHash` checksums. + proxyVendor ? false, + + # We want parallel builds by default + enableParallelBuilding ? true, + + # Do not enable this without good reason + # IE: programs coupled with the compiler + allowGoReference ? false, + + CGO_ENABLED ? go.CGO_ENABLED, + + meta ? { }, + + ldflags ? [ ], + + GOFLAGS ? [ ], + + ... +}@args': + +let + args = removeAttrs args' [ + "overrideModAttrs" + "vendorSha256" + "vendorHash" + ]; + + GO111MODULE = "on"; + GOTOOLCHAIN = "local"; + + hugoModules = + if (vendorHash == null) then + "" + else + (stdenv.mkDerivation { + name = "${name}-hugo-modules"; + + nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ + hugo + go + git + cacert + ]; + + inherit (args) src; + inherit (go) GOOS GOARCH; + inherit GO111MODULE GOTOOLCHAIN; + + # The following inheritence behavior is not trivial to expect, and some may + # argue it's not ideal. Changing it may break vendor hashes in Nixpkgs and + # out in the wild. In anycase, it's documented in: + # doc/languages-frameworks/go.section.md + prePatch = args.prePatch or ""; + patches = args.patches or [ ]; + patchFlags = args.patchFlags or [ ]; + postPatch = args.postPatch or ""; + preBuild = args.preBuild or ""; + postBuild = args.modPostBuild or ""; + sourceRoot = args.sourceRoot or ""; + setSourceRoot = args.setSourceRoot or ""; + env = args.env or { }; + + impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ + "GIT_PROXY_COMMAND" + "SOCKS_SERVER" + "GOPROXY" + ]; + + configurePhase = + args.modConfigurePhase or '' + runHook preConfigure + export GOCACHE=$TMPDIR/go-cache + export GOPATH="$TMPDIR/go" + cd "${modRoot}" + runHook postConfigure + ''; + + buildPhase = + args.modBuildPhase or ( + '' + runHook preBuild + '' + + lib.optionalString deleteVendor '' + if [ ! -d _vendor ]; then + echo "_vendor folder does not exist, 'deleteVendor' is not needed" + exit 10 + else + rm -rf _vendor + fi + '' + + '' + if [ -d _vendor ]; then + echo "_vendor folder exists, please set 'vendorHash = null;' in your expression" + exit 10 + fi + + ${ + if proxyVendor then + '' + mkdir -p "''${GOPATH}/pkg/mod/cache/download" + hugo mod vendor + '' + else + '' + if (( "''${NIX_DEBUG:-0}" >= 1 )); then + hugoModVendorFlags+=(-v) + fi + hugo mod vendor "''${hugoModVendorFlags[@]}" + '' + } + + mkdir -p _vendor + + runHook postBuild + '' + ); + + installPhase = + args.modInstallPhase or '' + runHook preInstall + + ${ + if proxyVendor then + '' + rm -rf "''${GOPATH}/pkg/mod/cache/download/sumdb" + cp -r --reflink=auto "''${GOPATH}/pkg/mod/cache/download" $out + '' + else + '' + cp -r --reflink=auto _vendor $out + '' + } + + if ! [ "$(ls -A $out)" ]; then + echo "_vendor folder is empty, please set 'vendorHash = null;' in your expression" + exit 10 + fi + + runHook postInstall + ''; + + dontFixup = true; + + outputHashMode = "recursive"; + outputHash = vendorHash; + # Handle empty vendorHash; avoid + # error: empty hash requires explicit hash algorithm + outputHashAlgo = if vendorHash == "" then "sha256" else null; + }).overrideAttrs + overrideModAttrs; + + package = stdenv.mkDerivation ( + args + // { + nativeBuildInputs = [ + hugo + git + go + ] ++ nativeBuildInputs; + + inherit (go) GOOS GOARCH; + + GOFLAGS = + GOFLAGS + ++ + lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) + "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS" + (lib.optional (!proxyVendor) "-mod=vendor") + ++ + lib.warnIf (builtins.elem "-trimpath" GOFLAGS) + "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true" + (lib.optional (!allowGoReference) "-trimpath"); + inherit + CGO_ENABLED + enableParallelBuilding + GO111MODULE + GOTOOLCHAIN + ; + + # If not set to an explicit value, set the buildid empty for reproducibility. + ldflags = ldflags ++ lib.optional (!lib.any (lib.hasPrefix "-buildid=") ldflags) "-buildid="; + + configurePhase = + args.configurePhase or ( + '' + runHook preConfigure + + export GOCACHE=$TMPDIR/go-cache + export GOPATH="$TMPDIR/go" + export GOPROXY=off + export GOSUMDB=off + cd "$modRoot" + '' + + lib.optionalString (vendorHash != null) '' + ${ + if proxyVendor then + '' + export GOPROXY=file://${hugoModules} + '' + else + '' + rm -rf _vendor + cp -r --reflink=auto ${hugoModules} _vendor + '' + } + '' + + '' + + # currently pie is only enabled by default in pkgsMusl + # this will respect the `hardening{Disable,Enable}` flags if set + if [[ $NIX_HARDENING_ENABLE =~ "pie" ]]; then + export GOFLAGS="-buildmode=pie $GOFLAGS" + fi + + runHook postConfigure + '' + ); + + buildPhase = + args.buildPhase or '' + runHook preBuild + hugo "''${buildFlags[@]}" --destination public + runHook postBuild + ''; + + doCheck = args.doCheck or true; + checkPhase = + args.checkPhase or '' + runHook preCheck + + runHook postCheck + ''; + + installPhase = + args.installPhase or '' + runHook preInstall + + mkdir -p $out + cp -r public/* $out + + runHook postInstall + ''; + + strictDeps = true; + + disallowedReferences = lib.optional (!allowGoReference) go; + + passthru = passthru // { + inherit + go + hugo + hugoModules + vendorHash + ; + }; + + meta = { + # Add default meta information + platforms = go.meta.platforms or lib.platforms.all; + } // meta; + } + ); +in +package diff --git a/subprojects/wrapper-manager-fds/docs/manpages/footer.5 b/subprojects/wrapper-manager-fds/docs/manpages/footer.5 new file mode 100644 index 00000000..fe3169d5 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/manpages/footer.5 @@ -0,0 +1,3 @@ +.SH "AUTHORS" +.PP +foodogsquared diff --git a/subprojects/wrapper-manager-fds/docs/manpages/header.adoc b/subprojects/wrapper-manager-fds/docs/manpages/header.adoc new file mode 100644 index 00000000..f6fa3bc8 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/manpages/header.adoc @@ -0,0 +1,30 @@ += wrapper-manager-configuration(5) +:doctype: manpage +:mantitle: WRAPPER-MANAGER-CONFIGURATION.NIX(5) +:manmanual: wrapper-manager configuration +:mansource: wrapper-manager configuration +:man-linkstyle: pass:[blue R < >] + + +== Name + +wrapper-manager-configuration.nix - wrapper-manager configuration specification + +ifdef::is-wider-scoped[] +== Additional notes + +If you've included env-specific integration wrapper-manager modules (e.g., NixOS, home-manager), there are additional things that are included. + +* The wider-scoped environment configuration is included as a module argument in each wrapper-manager package (i.e., `wrapper-manager.packages`). +This is mainly useful to create a dynamic wrapper-manager package with different parameters when in NixOS, home-manager, or as standalone package. ++ +-- +* For NixOS integration, the NixOS configuration is available as `nixosConfig`. +* For home-manager integration, `hmConfig` stores the home-manager configuration. +-- + +* Additional wrapper-manager documentation can be deployed with the wider environment. +So far, there should be a manpage or an HTML document that can be enabled with `wrapper-manager.documentation.{manpage,html}.enable`. +endif::[] + +== Options diff --git a/subprojects/wrapper-manager-fds/docs/website/.gitignore b/subprojects/wrapper-manager-fds/docs/website/.gitignore new file mode 100644 index 00000000..fb0be8db --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/.gitignore @@ -0,0 +1,17 @@ +# All of the generated assets. +/content/**/wrapper-manager-*.adoc + +### Hugo ### +# Generated files by hugo +/public/ +/resources/_gen/ +/assets/jsconfig.json +hugo_stats.json + +# Executable may be added to repository +hugo.exe +hugo.darwin +hugo.linux + +# Temporary lock file while building +/.hugo_build.lock diff --git a/subprojects/wrapper-manager-fds/docs/website/assets/js/site.js b/subprojects/wrapper-manager-fds/docs/website/assets/js/site.js new file mode 100644 index 00000000..52edafe8 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/assets/js/site.js @@ -0,0 +1,49 @@ +(function() { + // Set up shop for QoL code listing features. + var codeListings = document.querySelectorAll("main .listingblock > .content, main .literalblock > .content"); + + for (elem of codeListings) { + var parent = elem.parentElement; + + var fullscreenButton = document.createElement("button"); + fullscreenButton.classList.add("listingblock__fullscreen-btn"); + fullscreenButton.ariaLabel = "{{ T "fullscreenButtonAriaLabel" }}"; + fullscreenButton.title = "{{ T "fullscreenButtonLabel" }}"; + fullscreenButton.ariaDescription = "{{ T "fullscreenButtonDescription" }}"; + fullscreenButton.innerHTML = `{{- partial "components/heroicon.html" (dict "id" "arrows-pointing-out") | safeHTML }}`; + + fullscreenButton.addEventListener("click", (event) => { + const { target } = event; + const parent = target.closest(".listingblock") || target.closest(".literalblock"); + if (!document.fullscreenElement) { + parent.requestFullscreen(); + } else if (document.exitFullscreen) { + document.exitFullscreen(); + } + }); + + var copyButton = document.createElement("button"); + copyButton.classList.add("listingblock__copy-btn"); + copyButton.ariaLabel = "{{ T "copyButtonAriaLabel" }}"; + copyButton.title = "{{ T "copyButtonLabel" }}"; + copyButton.ariaDescription = "{{ T "copyButtonDescription" }}"; + copyButton.innerHTML = `{{- partial "components/heroicon.html" (dict "id" "clipboard") }}`; + + copyButton.addEventListener("click", (event) => { + const { target } = event; + const parent = target.closest(".listingblock"); + const codeListing = parent.querySelector(".content"); + navigator.clipboard.writeText(codeListing.textContent.trim()); + }); + + var buttonRow = document.createElement("div"); + buttonRow.classList.add("listingblock__btn-row"); + + if (parent.classList.contains("listingblock")) { + buttonRow.appendChild(copyButton); + } + + buttonRow.appendChild(fullscreenButton); + parent.appendChild(buttonRow); + } +})() diff --git a/subprojects/wrapper-manager-fds/docs/website/config/_default/config.toml b/subprojects/wrapper-manager-fds/docs/website/config/_default/config.toml new file mode 100644 index 00000000..784dab7c --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/config/_default/config.toml @@ -0,0 +1,24 @@ +baseURL = 'https://foo-dogsquared.github.io/wrapper-manager-fds' +defaultContentLanguage = 'en' +title = "wrapper-manager-fds" +timeZone = "UTC" + +[params] +toc = true + +[security.exec] +allow = [ + "^go$", + "^asciidoctor$", +] +osEnv = [ + '^LAST_COMMIT_DATE$', + '^PATH$', + '^GOPATH$', + '^GOPROXY$', + '^HTTP_PROXY$', + '^HTTPS_PROXY$', +] + +[security.funcs] +getenv = [ "^LAST_COMMIT_DATE$" ] diff --git a/subprojects/wrapper-manager-fds/docs/website/config/_default/languages.toml b/subprojects/wrapper-manager-fds/docs/website/config/_default/languages.toml new file mode 100644 index 00000000..efec485e --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/config/_default/languages.toml @@ -0,0 +1,4 @@ +[en] +languageName = "English" +languageCode = "en" +contentDir = "content/en" diff --git a/subprojects/wrapper-manager-fds/docs/website/config/_default/markup.toml b/subprojects/wrapper-manager-fds/docs/website/config/_default/markup.toml new file mode 100644 index 00000000..b5621578 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/config/_default/markup.toml @@ -0,0 +1,27 @@ +[asciidocExt] +extensions = [ + "asciidoctor-diagram", + "asciidoctor-foodogsquared-extensions", +] +trace = true +workingFolderCurrent = true + +[asciidocExt.attributes] +toc = true +sectanchors = true +"figure-caption!" = true +source-highlighter = "rouge" +allow-uri-read = true +experimental = true +linkcss = true +cache-uri = true +reproducible = true +stem = "latexmath" +env-hugo = true + +avatarsdir = "/wrapper-manager-fds/icons/avatars" +avatarstype = "svg" + +icons = "image" +iconsdir = "/wrapper-manager-fds/icons/asciidoctor" +icontype = "svg" diff --git a/subprojects/wrapper-manager-fds/docs/website/config/_default/menu.toml b/subprojects/wrapper-manager-fds/docs/website/config/_default/menu.toml new file mode 100644 index 00000000..543c849b --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/config/_default/menu.toml @@ -0,0 +1,20 @@ +[[main]] +identifier = "nix-module-options" +name = "Module options" +url = "wrapper-manager-env-options/" +weight = 1 + +[[main]] +identifier = "source-code" +name = "Source code" +url = "https://github.com/foo-dogsquared/wrapper-manager-fds" + +[[main]] +identifier = "wrapper-manager-nixos" +name = "NixOS module" +url = "wrapper-manager-nixos-module/" + +[[main]] +identifier = "wrapper-manager-home-manager" +name = "home-manager module" +url = "wrapper-manager-home-manager-module/" diff --git a/subprojects/wrapper-manager-fds/docs/website/config/_default/module.toml b/subprojects/wrapper-manager-fds/docs/website/config/_default/module.toml new file mode 100644 index 00000000..dc9b7ae2 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/config/_default/module.toml @@ -0,0 +1,36 @@ +[[imports]] +path = "github.com/foo-dogsquared/website" + +[[imports.mounts]] +source = "assets/scss/" +target = "assets/scss/" + +[[imports.mounts]] +source = "assets/css/" +target = "assets/css/" + +[[imports.mounts]] +source = "layouts/partials" +target = "layouts/partials" +excludeFiles = [ "footer.html" ] + +[[imports.mounts]] +source = "layouts/_default" +target = "layouts/_default" +includeFiles = [ "baseof.html" ] + +[[imports.mounts]] +source = "assets/svg/avatars/" +target = "static/icons/avatars/" + +[[imports.mounts]] +source = "assets/svg/avatars/" +target = "assets/svg/avatars/" + +[[imports.mounts]] +source = "i18n/" +target = "i18n/" + +[[imports.mounts]] +source = "data/more-contentful/themes/" +target = "data/more-contentful/themes/" diff --git a/subprojects/wrapper-manager-fds/docs/website/content/en/project-overview.adoc b/subprojects/wrapper-manager-fds/docs/website/content/en/project-overview.adoc new file mode 100644 index 00000000..b4195a4f --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/content/en/project-overview.adoc @@ -0,0 +1,556 @@ +--- +title: Project overview +--- += nix-wrapper-manager-fds +:toc: + +:current-version: 0.1.0 +:github-repo: nix-module-wrapper-manager-fds +:github-full: foo-dogsquared/{github-repo} +:remote-git-repo: https://github.com/{github-full} +:docs-site: https://foo-dogsquared.github.io/{github-repo} + + +wrapper-manager-fds is foodogsquared's reimagining of https://github.com/viperML/wrapper-manager/[wrapper-manager]. + +[CAUTION] +==== +wrapper-manager-fds is considered unstable and the author is still freely experimenting with various aspects of the project including the module options, library set API, and ease of use for third-partyuse. +Expect constant breakages here and put on a hard hat before exploring this part of the town. +==== + +As a recap, the aim of wrapper-manager is to pave a way of configuring Nix environments through wrappers. +There has been https://discourse.nixos.org/t/declarative-wrappers/1775[interest on] https://github.com/NixOS/rfcs/pull/75[this feature] footnote:[I mean, a part of the nixpkgs package set has dedicated wrappers for some packages such as GIMP, Inkscape, and Blender.] and I sometimes configure programs through wrappers instead of the typical module system. +It has its use cases such as quickly creating variants of the same program for specific reasons (for example, creating specialized versions of yt-dlp for downloading audio, video, and more). +But why not create something more than that? +And that's how wrapper-manager-fds came to be. + +[#installation] +== Installation + +[#installation-channels] +=== Channels + +You can install wrapper-manager-fds with https://zero-to-nix.com/concepts/channels[Nix channels]. + +[source, shell, subs=attributes] +---- +nix-channel --add {remote-git-repo}/archive/master.tar.gz wrapper-manager-fds +nix-channel --update +---- + +Then in your environment configuration, you'll have to import the user entrypoint. +For more details, see <>. + +[#installation-pinning-tool] +=== Pinning tool + +A recommended (non-flakes) way to install Nix dependencies is to use a pinning tool. +There are a handful of pinning tool out there but in this case, we'll use https://github.com/andir/npins[npins] as our tool of choice. +Assuming you have already initialized npins, you can simply add wrapper-manager-fds to your Nix project with the following command. + +[source, shell, subs="attributes+"] +---- +npins add --name wrapper-manager github foo-dogsquared {github-repo} --at {current-version} +---- + +Similar to channels installation, you'll have to import the <> object. + +[#installation-manual-pinning] +=== Manual pinning + +Though not recommended, you could manually pin the Nix library yourself and then import the <> like in the following code. + +[source, nix, subs="attributes+"] +---- +{ pkgs, ... }: + +let + wrapper-manager-fds-src = builtins.fetchTarball "{remote-git-repo}/archive/{current-version}.tar.gz"; + wrapper-manager = import wrapper-manager-fds-src { }; + wrapperManagerLib = import wrapper-manager.wrapperManagerLib { inherit pkgs; } +in +wrapperManagerLib.env.build { } +---- + +[#installation-flakes] +=== Flakes + +This project also has a https://zero-to-nix.com/concepts/flakes[flake object]. +In your flake definition, just import it as one of the inputs. +Unlike the other methods, the flake output is the user entrypoint so no need to import it or anything. + +[source, nix, subs="attributes+"] +---- +{ + inputs.wrapper-manager-fds.url = "github:{github-full}/{current-version}"; + + outputs = { nixpkgs, ... }@inputs: { + nixosConfigurations.desktop = nixpkgs.lib.nixosSystem { + modules = [ + ./hosts/desktop.nix + inputs.wrapper-manager-fds.nixosModules.default + ]; + }; + }; +} +---- + +[#user-entrypoint] +=== User entrypoint + +Most of the things you need from the project are all retrieveable from the entrypoint of this project (`default.nix` in project root) which is an attribute set closely structured from a typical Nix flake that you see. +For example, if you want the NixOS module for wrapper-manager, you could refer to `nixosModules.default`. +Here's the breakdown of the attrset entries in the entrypoint. + +* `lib` is an attribute set containing the main functions: `eval` and `build`. +(More details to use them are in <>.) + +* `nixosModules` contains a set of NixOS modules for wrapper-manager-fds integration. +You could get the main module with the `default` attribute. + +* `homeModules` are for home-manager modules and similarly structured to `nixosModules` attribute. + +* `wrapperManagerLib` contains a path intended to be imported within your Nix code. +It simply contains the library set that can be used outside of the wrapper-manager-fds module environment. +To use it, it only requires a nixpkgs instance like in the following code. ++ +[source, nix, subs="attributes+"] +---- +{ pkgs, ... }: + +let + wrapper-manager-fds-src = builtins.fetchTarball "{remote-git-repo}/archive/master.tar.gz"; + wrapper-manager = import wrapper-manager-fds-src { }; + wrapperManagerLib = import wrapper-manager.wrapperManagerLib { inherit pkgs; } +in +wrapperManagerLib.env.build { } +---- + +* `overlays` is a set of nixpkgs overlays to be applied by the user. +So far, there's only one overlay called `default` containing the wrapper-manager library set. + + + +[#getting-started] +== Getting started + +Now that you have wrapper-manager-fds on the go, let's have a breakdown of what it is, exactly. +The project itself is made of different parts which you can use for different purposes. + +[#the-module-environment] +=== The module environment + +One part of the project is the module environment. +Just like https://github.com/nix-community/home-manager[home-manager] and https://github.com/nix-community/disko[disko] and https://github.com/viperML/wrapper-manager[the original source], wrapper-manager-fds comes with its own module environment. +Instead of a home environment from home-manager, an entire operating system from NixOS, or an installation script from disko, wrapper-manager-fds module environment evaluates to a package similar to how certain environments treats them (e.g., `environment.systemPackages` for NixOS, `home.packages` for home-manager). + +Much of the module environment relies on `makeWrapper`. +In fact, this can be thought of as a declarative layer over `makeWrapper` with some other integrations. + +If you want to view the module options, you can see it in +ifdef::env-hugo[link:./wrapper-manager-env-options/[wrapper-manager module options].] +ifndef::env-hugo[{docs-site}/wrapper-manager-env-options[wrapper-manager documentation site].] + +Here's a very simple example of a wrapper for Neofetch. + +[source, nix] +---- +{ lib, pkgs, ... }: + +{ + wrappers.neofetch = { + arg0 = lib.getExe' pkgs.neofetch "neofetch"; + appendArgs = [ + "--ascii_distro" "guix" + "--title_fqdn" "off" + "--os_arch" "off" + ]; + }; +} +---- + +Or if you want fastfetch... + +[source, nix] +---- +{ lib, pkgs, ... }: + +{ + wrappers.fastfetch = { + arg0 = lib.getExe' pkgs.fastfetch "fastfetch"; + appendArgs = [ "--logo" "Guix" ]; + env.NO_COLOR.value = "1"; + }; +} +---- + +Or even both in the same configuration (which you can do). +If evaluated, this should result in a single derivation that contains two executables in `$out/bin/{fastfetch, neofetch}`. + +[source, nix] +---- +{ + imports = [ + ./fastfetch.nix + ./neofetch.nix + ]; +} +---- + +You could even create https://specifications.freedesktop.org/desktop-entry-spec/latest/[XDG desktop entry] files useful for the application to be launched through an application launcher/menu. +For example, you could create an executable and a desktop entry to launch a custom Firefox profile in your home-manager configuration. + +.Creating a custom Firefox desktop entry launching a custom profile +[source, nix] +---- +{ config, lib, pkgs, ... }: + +{ + programs.firefox.profiles.custom-profile = { + # Put some profile-specific settings here. + }; + + wrapper-manager.packages.browsers = { + wrappers.firefox-custom-profile = { + arg0 = lib.getExe' config.programs.firefox.package "firefox"; + prependArgs = [ + "-P" "custom-profile" + ]; + xdg.desktopEntry = { + enable = true; + settings = { + desktopName = "Firefox (custom-profile)"; + startupNotify = true; + startupWMClass = "firefox"; + icon = "firefox"; + mimeTypes = [ + "text/html" + "application/xhtml+xml" + "application/vnd.mozilla.xul+xml" + "x-scheme-handler/http" + "x-scheme-handler/https" + ]; + }; + }; + }; + }; +} +---- + +[#as-a-library] +=== As a library + +wrapper-manager also comes with a library set which you can use to evaluate and build wrapper-manager packages yourself. +This is found in the `wrapperManagerLib` attribute from the user entrypoint where it needs an attribute set containing a nixpkgs instance in `pkgs`. + +[#src:example-lib-build] +.An example of importing wrapper-manager library +[source, nix] +---- +{ pkgs }: + +let + wrapper-manager = import (builtins.fetchgit { }) { }; + + wmLib = import wrapper-manager.wrapperManagerLib { inherit pkgs; }; +in +wmLib.env.build { + inherit pkgs; + modules = [ ./fastfetch.nix ]; + specialArgs.yourMomName = "Joe Mama"; +} +---- + +Here's a quick rundown of what you can do with the library. + +* Evaluate a wrapper-manager module with `env.eval` where it accepts an attrset similar to the <> containing a list of additional modules, the nixpkgs instance to be used, and `specialArgs` to be passed on to the `lib.evalModules` from nixpkgs. + +* Build a wrapper through `env.build` returning a derivation of the wrapper. +It accepts the same arguments as `env.eval`. + +There is also `lib` attribute if all you want to do is to build and/or evaluate a wrapper-manager configuration. +It only contains the function from `env` subset which contains `build` and `eval`. + +[#as-a-composable-module] +=== As a composable module + +The most user-friendly way of using wrapper-manager would be as a composable nixpkgs module of an existing environment. +wrapper-manager provides a Nix module specifically for NixOS and home-manager environment. footnote:[Any other environments are basically unsupported and if you like to use it outside of NixOS and home-manager, you're on your own.] +You can import them through the `{nixos,home}Modules.default` from the user entrypoint of the project. + +You can view the module options for each environment. + +* For NixOS, you can view it in +ifdef::env-hugo[link:./wrapper-manager-nixos-module/[NixOS module integration options].] +ifndef::env-hugo[{docs-site}/wrapper-manager-nixos-module/[documentation site].] + +* For home-manager, you can view it in +ifdef::env-hugo[link:./wrapper-manager-home-manager-module/[home-manager module integration options].] +ifndef::env-hugo[{docs-site}/wrapper-manager-home-manager-module/[documentation site].] + +Most of the things set up here are implemented to make declaring wrappers ergonomic with the environment. +For a start, wrapper-manager-fds sets up a module namespace in `wrapper-manager`. +Here's a quick breakdown of the features that the module has. + +* Passes the wrapper-manager library through `wrapperManagerLib` module argument. +This is nice if you want to only use wrapper-manager to quickly create wrappers inside of the configuration without using the wrapper-manager NixOS/home-manager integration module. + +* You could declare wrappers through `wrapper-manager.packages.` where each of the attribute value is expected to be a wrapper-manager configuration to be added in its respective wider-scope environment. + +* You could include other modules through `wrapper-manager.sharedModules`. +This is useful for extending wrapper-manager inside of the configuration environment. + +Here's an example of adding wrappers through wrapper-manager inside of a home-manager configuration. +The following configuration will create a wrapped package for yt-dlp with an additional wrapper script named `yt-dlp-audio` and `yt-dlp-video`. + +.Installing yt-dlp with custom variants of it inside of a home-manager configuration +[source, nix] +---- +{ config, lib, pkgs, ... }: + +{ + home.packages = with pkgs; [ + flowtime + blanket + ]; + + wrapper-manager.packages = { + music-setup = { + basePackages = [ pkgs.yt-dlp ]; + wrappers.yt-dlp-audio = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/audio.conf + ]; + }; + wrappers.yt-dlp-video = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/video.conf + ]; + }; + }; + }; +} +---- + + +[#development] +== Development + +If you want to hack this hack, you'll need either Nix with flakes enabled (`experimental-features = nix-command flakes` in `nix.conf`) or not. +Either way, this should be enough to cater to both flake- and non-flake users. + +This project supports the current stable and unstable version of NixOS. +Specifically, we're looking out for the nixpkgs instance both of these versions has. +As an implementation detail, we pin these branches through https://github.com/andir/npins[npins] which both flakes- and non-flake-based setups uses. +Just be familiar with it and you'll be fine for the most part. +Most likely, you don't even need to interact with it since handling update cadence is handled automatically through the remote CI. + +Setting up the development environment should be easy enough. + +* For flake users, you can just reproduce the development environment with `nix develop`. +* For non-flake users, you can do the same with `nix-develop`. + +As an additional note, it is recommended to use something like direnv with `use flake` or `use nix` depending on your personal preferences to use flake or not. + +Take note there is a `Makefile` full of commands intended for easily interacting with the project but it is heavily assumed you're in the development environment of the project. + +[#development-library-set-and-modules] +=== Library set and modules + +This Nix project has a test infrastructure set up at +ifdef::env-hugo[github:{github-full}[test directory, rev=main, path=tests]] +ifndef::env-hugo[link:./tests[`./tests`]] +covering the library set and the wrapper-manager module environment. +For its library set, it makes use of the nixpkgs library and a JSON schema to validate if it passes the whole test suite. +To make use of it, just run the following commands. + +* For flake users, you can run `nix flake check`. +* For non-flake users, you can do the same with `nix-build tests/ -A libTestPkg` or `nix build -f tests/ libTestPkg`. + +The derivation output should be successfully built if all of the tests in the suite passes. +Otherwise, it should fail and you'll have to see the build log containing all of the tests that failed. + +On another note, there is a quicker way of checking the test suite with `nix eval -f tests lib` (or `nix-instantiate --eval --strict tests/ -A lib`) where it contains the raw test data which is useful if you don't want to essentially build a new derivation each time. +It is also quicker to eyeball results in this way especially if you're always working with the tests anyways. + +[#development-website] +=== Website + +This project also has a website set up with https://gohugo.io/[Hugo]. +The files that you need to see are in +ifdef::env-hugo[github:{github-full}[`docs`, rev=main, path=docs]] +ifndef::env-hugo[link:./docs[`./docs`]] +directory. + +* For flake users, you can build the website with `nix build .#website`. +* For non-flake users, you can do the same with `nix-build docs/`. + +There is also a dedicated development environment placed in `docs/shell.nix` but this should be a part of the primary development environment already. +You can enter it with `nix develop .#website` or `nix-shell docs/`. + +Just take note that the website also requires the NixOS options which comes in a JSON file. +This should be already taken care of in the package definition of the website but otherwise it is something that you'll have to be aware of. + +The more important task to developing this part of the project is continuously getting feedback from it. +You can do so simply with the following commands: + +* For flake users, `nix develop --command hugo -s ./docs serve`. +* For non-flake users, `nix-shell docs --command hugo -s ./docs serve`. +* If you're using `Makefile` of this project, `make docs-serve`. + +[#development-nix] +=== Nix environment + +As for developing the environment with Nix itself, it is very much preferred to make wrapper-manager-fds work with non-flake setups. +This also includes the workflow of the development itself for the purpose of easier time bootstrapping wrapper-manager-fds. + +Due to the unfortunate situation with flakes as an experimental feature, it is more like a second-class citizen in terms of support. +This is because it is pretty easy to make a flake with non-flake tools compared to vice versa. footnote:[flake-compat is great and all but it holds back wrapper-manager-fds in making it easy to bootstrap if we rely on it.] + +Here's an exhaustive guidelines that you have to keep in mind when developing related files within the project: + +* This project uses https://calver.org/[calendar versioning]. + +* Only the unstable branch of NixOS is currently supported. +Support for the stable versions are unfortunately secondary and more incidental (at least at the moment). + +* There shouldn't be any user consumables that requires anything from the npins sources. + + +[#goals-and-non-goals] +== Goals and non-goals + +As a Nix project, wrapper-manager-fds aims for the following goals. + +* Create an ecosystem of creating them wrappers, mainly through its library set and the module environment. + +* Make creating wrappers ergonomic for its users. +Not necessarily user-friendly but it should easy enough to get started while allowing some flexibility, yeah? + +* Make a nice environment for creating custom wrappers which is already quite possible thanks to the heavy lifting of the nixpkgs module system. + +For now, wrapper-manager-fds does not focus on the following ideas; +the main focus for now (as of 2024-07-31) is the core attributes needed to make wrapper-manager extensible for third-party module authors. +Take note, these are all ideas that are considered but may or may not be out of the blacklisted ideas at some point in the future for a variety of reasons. +Think of them as a list of possibilities for what may come within wrapper-manager-fds. + +* Create an environment similar to NixOS and home-manager. +wrapper-manager-fds' endgoal is to create a derivation typically composed as part of an environment (e.g., `mkShell` for devshells, `environment.systemPackages` for NixOS, `home.packages` for home-manager). +Otherwise, we're creating a poor man's version of them and it'll quickly creep in scope. + +* Support for multiple nixpkgs releases. +Up until I put some elbow grease for release engineering and to make testing between multiple branches easy, only the unstable branch of nixpkgs is officially supported for now. + +* Integrating with sandboxing frameworks such as https://github.com/containers/bubblewrap[Bubblewrap] and https://github.com/queer/boxxy[Boxxy]. footnote:[That said, the author does have custom wrapper-manager modules that does exactly that so this being ruled out may be ruled out in the future ;p] +This is too big of a task so it isn't considered for now. +Plus, having this would now require creating additional support which the author does not have time for it. + +* Create an ecosystem of modules that would allow to create quick configurations for different programs similarly found on other module environments such as in NixOS and home-manager. +Specifically, we're talking about modules in `programs` namespace (e.g., `programs.kitty`, `programs.alacritty`, `programs.nixvim`). +This would also require having a support cadence so not much is going to happen here. +Instead, I would encourage to have a separately-maintained project containing those for now. + +* Focus on hardware-related configuration for the wrappers. +For now, it isn't possible within wrapper-manager (or Nix, really). +Some possible ideas include creating our own version of nixpkgs' `makeWrapper`, creating a specialized launcher for it, or something in the middle. +Would be a fun idea to make though. :) + + +[#faq] +== Frequently asked questions (FAQ) + +[qanda] +Is this compatible with the original wrapper-manager?:: +Nope. +It is a reimagining with a completely different way of using it so it won't be fully compatible with it from the start. + +Why reimplement this anyways?:: +For funsies and also because there are some things I find not so great with using the project. +https://github.com/viperML/wrapper-manager/tree/307eb5c38c8b5102c39617a59b63929efac7b1a7[As of this writing], using wrapper-manager to simply create wrappers anywhere is a pain. + +Why not just incorporate the wanted changes into the original implementation?:: +While it could be done, there will be some unwanted major changes into the project which would cause inconvenience to its users anyways so it isn't a good idea. +Plus it also justifies me implementing a bunch of features that would otherwise be deemed inconsistent with the project. + +Can't you just create a wrapper with `pkgs.makeWrapper` and such from nixpkgs?:: +Yeah, you can. +There's nobody stopping you from doing so and surely there's no hitman preparing to assissinate right behind you as you about to deny wrapper-manager-fds and smugly type `make` in `makeWrapper`. +In fact, wrapper-manager uses `makeWrapper` as the main ingredient. +Just think of wrapper-manager as a declarative version of that among the bajillion ways of making wrappers in the Nix ecosystem. ++ +As an additional point, there are still use cases for it even with a simple `pkgs.writeShellScriptBin`. +In fact, if you have a situation like say having to create a one-off wrapper script to be added in a NixOS system, you can simply do the following: ++ +[source, nix] +---- +let + ytdlpAudio = pkgs.writeScriptBin "yt-dlp-audio" '' + ${pkgs.yt-dlp}/bin/yt-dlp --config-location "${../../config/yt-dlp/audio.conf}" $@ + ''; +in +{ + environment.systemPackages = [ ytdlpAudio ]; +} +---- ++ +BAM! +No need for wrapper-manager! + +Why use the module system?:: +Because screw you, that's why!!! +Am I stupid and lazy for basically using a battle-hardened configuration system library such as nixpkgs module system? footnote:[The answer is yes to both!] ++ +Seriously though, the main reason is pretty simple: it is quite established and a battle-hardened part in the Nix ecosystem. +It has gone through the test of time and the numerous 339 users of the entire Nix ecosystem are quite adamant in the declarative aspect of the Nix thingy. +So... why not use it. + +Any problems (and impending explosions) when using this project?:: +As far as I can tell, not much (especially explosions) but there are a few caveats you need to know. +Just know this is something the author is trying to resolve. ++ +-- +* wrapper-manager-fds is not great at handling double wrappers. +It just naively wraps a package and goes on its merry way. + +* wrapper-manager-fds is strongly biased towards Linux (and Unix-adjacent) ecosystem. + +* wrapper-manager-fds doesn't handle any replacement for the related files very well. +This is especially noticeable in large desktop-adjacent packages such as Inkscape, Firefox, and Blender with a bunch of plugins and whatnot where they have their own wrappers. +This means you cannot set `programs.NAME.package` or something similar with it. + +* The build step isn't enough to completely let the user replace the arguments found in `programs..package` (e.g., `programs.kitty.package = wrapperManagerLib.env.build { }`). +For now, the project focuses on making a nice declarative environment allowing the user to create a wrapper meant to work without adding configuration files into arbitrary locations in the filesystem (e.g., `$XDG_CONFIG_HOME`). +-- + + +[#acknowledgements] +== Acknowledgements + +I found a bunch of things for inspiration (READ: to steal ideas from). +Here's a list of resources I've found. + +* The original source of the reimagining, of course: https://github.com/viperML/wrapper-manager[wrapper-manager]. + +* https://github.com/NixOS/rfcs/pull/75[Nix RFC 75] which also comes https://github.com/NixOS/nixpkgs/pull/85103[with its implementation and discussion around what works and whatnot]. + +* https://discourse.nixos.org/t/pre-rfc-module-system-for-wrappers-in-nixpkgs/42281[This NixOS Discourse post loudly thinking about the same idea.] + + +[#copyright] +== Copyright + +This project is licensed under MIT License (SPDX identifier: https://spdx.org/licenses/MIT.html[`MIT`]). +Just see +ifdef::env-hugo[github:{github-full}[license file, rev=main, path=LICENSE]] +ifndef::env-hugo[link:./LICENSE[`./LICENSE`]] +for full text and details and whatnot. + +The documentation (except for the code examples), on the other hand, is licensed under https://www.gnu.org/licenses/fdl-1.3.txt[GNU Free Documentation License] v1.3 only with no "Invariants" section (SPDX identifier: https://spdx.org/licenses/GFDL-1.3-no-invariants-only[`GFDL-1.3-no-invariants-only`]) +You can see either the link or +ifdef::env-hugo[github:{github-full}[license file, rev=main, path=docs/LICENSE]] +ifndef::env-hugo[link:./docs/LICENSE[`./docs/LICENSE`]] +for more info. +The code examples, similar to the project codebase, are licensed under MIT with the same conditions apply and all that jazz. diff --git a/subprojects/wrapper-manager-fds/docs/website/go.mod b/subprojects/wrapper-manager-fds/docs/website/go.mod new file mode 100644 index 00000000..93709b1f --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/go.mod @@ -0,0 +1,8 @@ +module github.com/foo-dogsquared/wrapper-manager-fds + +go 1.22.3 + +require ( + github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20240518105144-dd35649b15e2 // indirect + github.com/foo-dogsquared/website v0.0.0-20240714011201-799cfa313e36 // indirect +) diff --git a/subprojects/wrapper-manager-fds/docs/website/go.sum b/subprojects/wrapper-manager-fds/docs/website/go.sum new file mode 100644 index 00000000..5dde5ec2 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/go.sum @@ -0,0 +1,16 @@ +github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20230426231746-ef27600d22f3/go.mod h1:11iN6ArO6sro187xxOeDYAFMENfUNd+Vopn+qqVkCbw= +github.com/foo-dogsquared/hugo-mod-simple-icons v0.0.0-20231025231637-36998f86bbf2/go.mod h1:8HnVc0SlzI7LCEU4sITYS5MQTq0Bct/nFr/7LdsHYVQ= +github.com/foo-dogsquared/hugo-mod-web-feeds v0.0.3-0.20220613123653-e0bc8e58159d/go.mod h1:V7UXom6wuFrWj1lBUCXQA3HguwfDhQA+tQNxyRxdClk= +github.com/foo-dogsquared/hugo-theme-contentful v1.2.1-0.20220513103455-d83c3f8c6954/go.mod h1:BL7L5CENEhUx+miRRaOZ9SVC92j9MAMztirBWtTpiPc= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.0 h1:N+U5CshaEko6batgTHa6GBfl2bg/1RbG1dAX6EkndVM= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.0/go.mod h1:BpUC3zBnnsil2SkU6bULvcDvAEs6FdDDEM8uB0oCpho= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20231028090155-ee19cd7714b4 h1:wpeb4k29ZbQirMIWtCkitTrLERHvztJUSLsTYi3gOmM= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20231028090155-ee19cd7714b4/go.mod h1:RgD3YpinFJyZhtn0iVLNs8eRa0nSs2VA+o1jBpe4zBs= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20240518105144-dd35649b15e2 h1:BvkVSiI6jXUhUyuRnBY6gSnmb2Th/7FaEwBStbw36Qk= +github.com/foo-dogsquared/hugo-theme-more-contentful v0.7.1-0.20240518105144-dd35649b15e2/go.mod h1:RgD3YpinFJyZhtn0iVLNs8eRa0nSs2VA+o1jBpe4zBs= +github.com/foo-dogsquared/website v0.0.0-20240714011201-799cfa313e36 h1:/NBeAydxYqmnPpyDP4kEzdPSHOZVMEK2W1vFcjZ8uPU= +github.com/foo-dogsquared/website v0.0.0-20240714011201-799cfa313e36/go.mod h1:zJw9MC6Ajnx5Bom/52LR9Xib40toK9d2tG9FeVqJN3U= +github.com/refactoringui/heroicons v2.0.17+incompatible/go.mod h1:82HsLWQga7MkEl5aK8TctxPPIBlXrsyWcVTB57uipuk= +github.com/refactoringui/heroicons v2.0.18+incompatible/go.mod h1:82HsLWQga7MkEl5aK8TctxPPIBlXrsyWcVTB57uipuk= +github.com/simple-icons/simple-icons v0.0.0-20230423030844-cd4f7d2bf53c/go.mod h1:oOgUUt8yVYOso/wEBi2ojfZP2MU/xxiNccIpaE+jCvE= +github.com/simple-icons/simple-icons v0.0.0-20231022005333-fdbaaa2d5f99/go.mod h1:oOgUUt8yVYOso/wEBi2ojfZP2MU/xxiNccIpaE+jCvE= diff --git a/subprojects/wrapper-manager-fds/docs/website/layouts/index.html b/subprojects/wrapper-manager-fds/docs/website/layouts/index.html new file mode 100644 index 00000000..3877670d --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/layouts/index.html @@ -0,0 +1 @@ +{{ with .GetPage "/project-overview" }}{{ .Render "single" }}{{ end }} diff --git a/subprojects/wrapper-manager-fds/docs/website/shell.nix b/subprojects/wrapper-manager-fds/docs/website/shell.nix new file mode 100644 index 00000000..05aa3ee2 --- /dev/null +++ b/subprojects/wrapper-manager-fds/docs/website/shell.nix @@ -0,0 +1,24 @@ +let + sources = import ../../npins; +in +{ + pkgs ? import sources.nixos-unstable { }, +}: + +let + docs = import ../. { inherit pkgs; }; +in +pkgs.mkShell { + inputsFrom = [ docs.website ]; + + packages = with pkgs; [ + nodePackages.prettier + vscode-langservers-extracted + ]; + + shellHook = '' + install -Dm0644 ${docs.wmOptionsDoc.optionsAsciiDoc} ./content/en/wrapper-manager-env-options.adoc + install -Dm0644 ${docs.wmNixosDoc.optionsAsciiDoc} ./content/en/wrapper-manager-nixos-module.adoc + install -Dm0644 ${docs.wmHmDoc.optionsAsciiDoc} ./content/en/wrapper-manager-home-manager-module.adoc + ''; +} diff --git a/subprojects/wrapper-manager-fds/flake.nix b/subprojects/wrapper-manager-fds/flake.nix new file mode 100644 index 00000000..0b8d53d0 --- /dev/null +++ b/subprojects/wrapper-manager-fds/flake.nix @@ -0,0 +1,69 @@ +# As a design restriction, this flake shouldn't have any inputs whatsoever. +# We're already using the Nix projects through pinning with npins. +{ + description = "wrapper-manager-fds flake"; + outputs = + { ... }: + let + sources = import ./npins; + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + eachSystem = + systems: f: + let + # Merge together the outputs for all systems. + op = + attrs: system: + let + ret = f system; + op = + attrs: key: + attrs + // { + ${key} = (attrs.${key} or { }) // { + ${system} = ret.${key}; + }; + }; + in + builtins.foldl' op attrs (builtins.attrNames ret); + in + builtins.foldl' op { } ( + systems + # add the current system if --impure is used + ++ ( + if builtins ? currentSystem then + if builtins.elem builtins.currentSystem systems then [ ] else [ builtins.currentSystem ] + else + [ ] + ) + ); + in + import ./. { } + // (eachSystem systems ( + system: + let + pkgs = import sources.nixos-unstable { inherit system; }; + inherit (pkgs) lib; + tests = import ./tests { inherit pkgs; }; + docs = import ./docs { inherit pkgs; }; + in + { + devShells = { + default = import ./shell.nix { inherit pkgs; }; + website = import ./docs/website/shell.nix { inherit pkgs; }; + }; + + packages = { + manpage-reference = docs.outputs.manpage; + html-reference = docs.outputs.html; + website = docs.website; + }; + + checks = + { inherit (tests) lib; } + // lib.mapAttrs' (n: v: lib.nameValuePair "config-test-${n}" v) tests.configs; + } + )); +} diff --git a/subprojects/wrapper-manager-fds/lib/default.nix b/subprojects/wrapper-manager-fds/lib/default.nix new file mode 100644 index 00000000..6638733b --- /dev/null +++ b/subprojects/wrapper-manager-fds/lib/default.nix @@ -0,0 +1,31 @@ +# The wrapper-manager library set. It should only require a nixpkgs instance to +# make initializing this set easier. This what makes it possible to be used as +# part of the module environments and as a standalone library. +# +# Since this library set is typically modularly set in nixpkgs module +# environments, we'll have to make sure it doesn't contain any functions that +# should return a nixpkgs module or anything of the sort. Basically, this +# should remain as a utility function that is usable outside of the nixpkgs +# module. +{ pkgs }: + +pkgs.lib.makeExtensible ( + self: + let + callLibs = + file: + import file { + inherit (pkgs) lib; + inherit pkgs self; + }; + in + { + env = import ./env.nix; + utils = callLibs ./utils.nix; + modules = callLibs ./modules.nix; + + inherit (self.env) build eval; + inherit (self.utils) getBin getLibexec getXdgDataDirs getXdgConfigDirs; + inherit (self.modules) makeWraparound; + } +) diff --git a/subprojects/wrapper-manager-fds/lib/env.nix b/subprojects/wrapper-manager-fds/lib/env.nix new file mode 100644 index 00000000..b31a4b05 --- /dev/null +++ b/subprojects/wrapper-manager-fds/lib/env.nix @@ -0,0 +1,34 @@ +rec { + /* + Given the attrset for evaluating a wrapper-manager module, return a + derivation containing the wrapper. + */ + build = args: (eval args).config.build.toplevel; + + # Evaluate a wrapper-manager configuration. + eval = + { + pkgs, + lib ? pkgs.lib, + modules ? [ ], + specialArgs ? { }, + }: + lib.evalModules { + specialArgs = specialArgs // { + modulesPath = builtins.toString ../modules/wrapper-manager; + }; + modules = [ + ../modules/wrapper-manager + + # Setting pkgs modularly. This would make setting up wrapper-manager + # with different nixpkgs instances possible but it isn't something that + # is explicitly supported. + ( + { lib, ... }: + { + config._module.args.pkgs = lib.mkDefault pkgs; + } + ) + ] ++ modules; + }; +} diff --git a/subprojects/wrapper-manager-fds/lib/modules.nix b/subprojects/wrapper-manager-fds/lib/modules.nix new file mode 100644 index 00000000..a8905828 --- /dev/null +++ b/subprojects/wrapper-manager-fds/lib/modules.nix @@ -0,0 +1,52 @@ +# These are functions that are only meant to be invoked inside of a +# wrapper-manager environment. +# +# On a note for wrapper-manager developer(s), due to how tedious it can be to +# test library functions like that, we're putting them inside of the test +# configs instead of the typical library test suite. +{ + pkgs, + lib, + self, +}: + +rec { + /* + Make a wrapper-manager wrapper config containing a sub-wrapper that wraps + another program. Several examples of this includes sudo, Bubblewrap, and + Gamescope. + */ + makeWraparound = { + arg0, + under, + underFlags ? [ ], + underSeparator ? "", + ... + }@module: + let + # These are the attrnames that would be overtaken with the function and + # will be merged anyways so... + functionArgs = builtins.functionArgs makeWraparound; + module' = lib.removeAttrs module (lib.attrNames functionArgs); + in + lib.mkMerge [ + { + arg0 = under; + + # This should be the very first things to be in the arguments so + # we're just making sure that it is the case. The priority is chosen + # arbitrarily just in case the user already has `prependArgs` values + # with `lib.mkBefore` for the original arg0. + prependArgs = lib.mkOrder 250 ( + underFlags + ++ lib.optionals (underSeparator != "") [ underSeparator ] + ++ [ arg0 ] + ); + } + + # It's constructed like this to make it ergonomic to use. The user can + # simply delete the makeWraparound exclusive arguments and still work + # normally. + module' + ]; +} diff --git a/subprojects/wrapper-manager-fds/lib/utils.nix b/subprojects/wrapper-manager-fds/lib/utils.nix new file mode 100644 index 00000000..d7499133 --- /dev/null +++ b/subprojects/wrapper-manager-fds/lib/utils.nix @@ -0,0 +1,31 @@ +{ + pkgs, + lib, + self, +}: + +rec { + /* + Given a list of derivations, return a list of the store path with the `bin` + output (or at least with "/bin" in each of the paths). + */ + getBin = drvs: builtins.map (v: lib.getBin v) drvs; + + /* + Given a list of derivations, return a list of the store paths with the + `libexec` appended. + */ + getLibexec = drvs: builtins.map (v: "${v}/libexec") drvs; + + /* + Given a list of derivations, return a list of the store paths appended with + `/etc/xdg` suitable as part of the XDG_CONFIG_DIRS environment variable. + */ + getXdgConfigDirs = drvs: builtins.map (v: "${v}/etc/xdg") drvs; + + /* + Given a list of derivations, return a list of store paths appended with + `/share` suitable as part of the XDG_DATA_DIRS environment variable. + */ + getXdgDataDirs = drvs: builtins.map (v: "${v}/share") drvs; +} diff --git a/subprojects/wrapper-manager-fds/modules/env/common.nix b/subprojects/wrapper-manager-fds/modules/env/common.nix new file mode 100644 index 00000000..8f253437 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/env/common.nix @@ -0,0 +1,154 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.wrapper-manager; + + wrapperManagerModule = lib.types.submoduleWith { + description = "wrapper-manager module"; + class = "wrapperManager"; + specialArgs = cfg.extraSpecialArgs; + modules = [ + ../wrapper-manager + + ( + { lib, ... }: + { + config._module.args.pkgs = lib.mkDefault pkgs; + } + ) + ] ++ cfg.sharedModules; + }; +in +{ + imports = [ + # Bringing all of the arguments from the wrapper-manager environment for + # convenience. It would also allow its users for full control without using + # the integration module itself. + ../wrapper-manager/extra-args.nix + ]; + + options.wrapper-manager = { + sharedModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + default = [ ]; + example = lib.literalExpression '' + [ + { + config.build = { + variant = "shell"; + }; + } + ] + ''; + description = '' + Extra modules to be added to all of the wrapper-manager configurations. + ''; + }; + + packages = lib.mkOption { + type = lib.types.attrsOf wrapperManagerModule; + description = '' + A set of wrappers to be added into the environment configuration. + ''; + default = { }; + visible = "shallow"; + example = lib.literalExpression '' + { + custom-ricing = { lib, pkgs, ... }: { + wrappers.neofetch = { + arg0 = lib.getExe' pkgs.neofetch "neofetch"; + appendArgs = [ + "--ascii-distro" "guix" + "--config" ./config/neofetch/config + ]; + }; + + wrappers.fastfetch = { + arg0 = lib.getExe' pkgs.fastfetch "fastfetch"; + appendArgs = [ + "--config" ./config/fastfetch/config + "--logo" "Guix" + ]; + env.NO_COLOR = 1; + }; + }; + + music-setup = { lib, pkgs, ... }: { + wrappers.yt-dlp-audio = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/audio.conf + ]; + }; + + wrappers.yt-dlp-video = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/video.conf + ]; + }; + + wrappers.beets-fds = { + arg0 = lib.getExe' pkgs.beet "beet"; + prependArgs = [ + "--config" ./config/beets/config + ]; + }; + }; + + writing = { lib, pkgs, ... }: { + wrappers.asciidoctor-fds = { + arg = lib.getExe' pkgs.asciidoctor-with-extensions "asciidoctor"; + executableName = "asciidoctor"; + prependArgs = + builtins.map (v: "-r ''${v}") [ + "asciidoctor-diagram" + "asciidoctor-bibtex" + ]; + }; + }; + } + ''; + }; + + extraSpecialArgs = lib.mkOption { + type = with lib.types; attrsOf anything; + default = { }; + description = '' + Additional set of module arguments to be passed to `specialArgs` of + the wrapper module evaluation. + ''; + example = { + yourMomName = "Joe Mama"; + }; + }; + + # They're all disabled by default to let wrapper-manager not get out of the + # way. wrapper-manager configurations are meant to be a part of other + # environments and we're trying not to make a spotlight for wrapper-manager + # in whatever form including exporting the documentation. + documentation = { + manpage.enable = lib.mkEnableOption "manpage output"; + html.enable = lib.mkEnableOption "HTML output"; + + extraModules = lib.mkOption { + type = with lib.types; listOf deferredModule; + description = '' + List of extra wrapper-manager modules to be included as part of the + documentation. + ''; + default = [ ]; + example = lib.literalExpression '' + [ + ./modules/wrapper-manager + ] + ''; + }; + }; + }; +} diff --git a/subprojects/wrapper-manager-fds/modules/env/home-manager/default.nix b/subprojects/wrapper-manager-fds/modules/env/home-manager/default.nix new file mode 100644 index 00000000..daa409ff --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/env/home-manager/default.nix @@ -0,0 +1,41 @@ +{ + config, + lib, + pkgs, + ... +}@moduleArgs: + +let + cfg = config.wrapper-manager; + wmDocs = import ../../../docs { inherit pkgs; inherit (cfg.documentation) extraModules; }; +in +{ + imports = [ ../common.nix ]; + + config = lib.mkMerge [ + { + home.packages = + lib.optionals cfg.documentation.manpage.enable [ wmDocs.outputs.manpage ] + ++ lib.optionals cfg.documentation.html.enable [ wmDocs.outputs.html ]; + + wrapper-manager.extraSpecialArgs.hmConfig = config; + } + + (lib.mkIf (moduleArgs ? nixosConfig) { + wrapper-manager.sharedModules = [ + ( + { lib, ... }: + { + # NixOS already has the option to set the locale so we don't need to + # have this. + config.locale.enable = lib.mkDefault false; + } + ) + ]; + }) + + (lib.mkIf (cfg.packages != { }) { + home.packages = lib.mapAttrsToList (_: wrapper: wrapper.build.toplevel) cfg.packages; + }) + ]; +} diff --git a/subprojects/wrapper-manager-fds/modules/env/nixos/default.nix b/subprojects/wrapper-manager-fds/modules/env/nixos/default.nix new file mode 100644 index 00000000..cb618d2a --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/env/nixos/default.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.wrapper-manager; + wmDocs = import ../../../docs { inherit pkgs; inherit (cfg.documentation) extraModules; }; +in +{ + imports = [ ../common.nix ]; + + config = lib.mkMerge [ + { + environment.systemPackages = + lib.optionals cfg.documentation.manpage.enable [ wmDocs.outputs.manpage ] + ++ lib.optionals cfg.documentation.html.enable [ wmDocs.outputs.html ]; + + wrapper-manager.extraSpecialArgs.nixosConfig = config; + + wrapper-manager.sharedModules = [ + ( + { lib, ... }: + { + # NixOS already has the option to set the locale so we don't need to + # have this. + config.locale.enable = lib.mkDefault false; + } + ) + ]; + } + + (lib.mkIf (cfg.packages != { }) { + environment.systemPackages = + lib.mapAttrsToList (_: wrapper: wrapper.build.toplevel) cfg.packages; + }) + ]; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/README.adoc b/subprojects/wrapper-manager-fds/modules/wrapper-manager/README.adoc new file mode 100644 index 00000000..aa1238c7 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/README.adoc @@ -0,0 +1,17 @@ += wrapper-manager modules +:toc: + +This is the module set of the wrapper-manager module environment. +Just take note that we're following the runtime shell of nixpkgs which is GNU Bash as of 2024-06-30. + +Also, take note of several design decisions when making the modules. + +* Typically, several options are designed around one option. +The most prominent example of this is `wrappers..makeWrapperArgs` where we basically create those `makeWrapper` arguments from other options. + +* Another common design here is most of the interaction happens around in individual wrappers so individual-wrapper-wide options are typically accompanied with a environment-wide version of that option. +An example of that is `environment.variables` and `environment.pathAdd` where it's basically a global set/list of variables and search paths to be put in each wrapper (that is, `wrappers..env` and `wrappers..pathAdd`). + +* When constructing modules with a `listOf ` that is going to be set some other options, typically it is better to have them set in the individual wrapper and nothing else. +An example of that can be seen in `xdg.dataDirs` and `wrappers..xdg.dataDirs` implementation. +This is designed like that so the user can override the entire thing if they choose. diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix new file mode 100644 index 00000000..55c8ea3f --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix @@ -0,0 +1,282 @@ +{ + config, + lib, + options, + ... +}: + +let + envConfig = config; + + toStringType = (with lib.types; coercedTo (oneOf [str path int float bool]) (x: "${x}") str) // { + description = "string and select types (numbers, boolean, and path) convertible to it"; + }; + envSubmodule = + { + config, + lib, + name, + ... + }: + { + options = { + action = lib.mkOption { + type = lib.types.enum [ + "unset" + "set" + "set-default" + "prefix" + "suffix" + ]; + description = '' + Sets the appropriate action for the environment variable. + + * `unset`... unsets the given variable. + + * `set-default` only sets the variable with the given value if + not already set. + + * `set` forcibly sets the variable with given value. + + * `prefix` and `suffix` prepends and appends the environment + variable containing a given separator-delimited list of values + respectively. It requires the `value` to be a list of string and a + `separator` value. + ''; + default = "set"; + example = "unset"; + }; + + value = lib.mkOption { + type = with lib.types; either toStringType (listOf toStringType); + description = '' + The value of the variable that is holding. + + ::: {.note} + It accepts a list of values only for `prefix` and `suffix` action. + ::: + ''; + example = "HELLO THERE"; + }; + + separator = lib.mkOption { + type = lib.types.str; + description = '' + Separator used to create a character-delimited list of the + environment variable holding a list of values. + + ::: {.note} + Only used for `prefix` and `suffix` action. + ::: + ''; + default = ":"; + example = ";"; + }; + }; + }; + + wrapperType = + { + name, + lib, + config, + pkgs, + ... + }: + let + flagType = with lib.types; listOf toStringType; + in + { + options = { + prependArgs = lib.mkOption { + type = flagType; + description = '' + A list of arguments to be prepended to the user-given argument for the + wrapper script. + ''; + default = [ ]; + example = lib.literalExpression '' + [ + "--config" ./config.conf + ] + ''; + }; + + appendArgs = lib.mkOption { + type = flagType; + description = '' + A list of arguments to be appended to the user-given argument for the + wrapper script. + ''; + default = [ ]; + example = lib.literalExpression '' + [ + "--name" "doggo" + "--location" "Your mom's home" + ] + ''; + }; + + arg0 = lib.mkOption { + type = lib.types.str; + description = '' + The first argument of the wrapper script. + ''; + example = lib.literalExpression "lib.getExe' pkgs.neofetch \"neofetch\""; + }; + + executableName = lib.mkOption { + type = lib.types.nonEmptyStr; + description = "The name of the executable."; + default = name; + example = "custom-name"; + }; + + env = options.environment.variables; + pathAdd = options.environment.pathAdd; + + preScript = lib.mkOption { + type = lib.types.lines; + description = '' + Script fragments to run before the main executable. + + ::: {.note} + This option is only used when {option}`build.variant` is set to + `shell`. + ::: + ''; + default = ""; + example = lib.literalExpression '' + echo "HELLO WORLD!" + ''; + }; + + # makeWrapperArgs are unescaped, a third-party module author can take + # advantage of that with runtime expansion values (if using the shell + # wrapper). + makeWrapperArgs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + A list of extra arguments to be passed as part of `makeWrapper` + build step. + ''; + example = [ "--inherit-argv0" ]; + }; + }; + + config = lib.mkMerge [ + { + env = envConfig.environment.variables; + pathAdd = envConfig.environment.pathAdd; + + makeWrapperArgs = + lib.mapAttrsToList ( + n: v: + if v.action == "unset" then + "--${v.action} ${lib.escapeShellArg n}" + else if lib.elem v.action [ "prefix" "suffix" ] then + "--${v.action} ${lib.escapeShellArg n} ${lib.escapeShellArg v.separator} ${lib.escapeShellArg (lib.concatStringsSep v.separator v.value)}" + else + "--${v.action} ${lib.escapeShellArg n} ${lib.escapeShellArg v.value}" + ) config.env + ++ (builtins.map (v: "--add-flags ${lib.escapeShellArg v}") config.prependArgs) + ++ (builtins.map (v: "--append-flags ${lib.escapeShellArg v}") config.appendArgs) + ++ (lib.optionals (envConfig.build.variant == "shell" && config.preScript != "") ( + let + preScript = + pkgs.runCommand "wrapper-script-prescript-${config.executableName}" { } + config.preScript; + in + [ + "--run" + preScript + ] + )); + } + + (lib.mkIf (config.pathAdd != [ ]) { + env.PATH.value = lib.lists.map builtins.toString config.pathAdd; + env.PATH.action = "prefix"; + }) + ]; + }; +in +{ + options = { + wrappers = lib.mkOption { + type = with lib.types; attrsOf (submodule wrapperType); + description = '' + A set of wrappers to be included in the resulting derivation from + wrapper-manager evaluation. + ''; + default = { }; + example = lib.literalExpression '' + { + yt-dlp-audio = { + arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp"; + prependArgs = [ + "--config-location" ./config/yt-dlp/audio.conf + ]; + }; + } + ''; + }; + + basePackages = lib.mkOption { + type = with lib.types; either package (listOf package); + description = '' + Packages to be included in the wrapper package. However, there are + differences in behavior when given certain values. + + * When the value is a bare package, the build process will use + `$PACKAGE.overrideAttrs` to create the package. This makes it suitable + to be used as part of `programs..package` typically found on + other environments (e.g., NixOS). Take note this means a rebuild of the + package. + + * When the value is a list of packages, the build process will use + `symlinkJoin` as the builder to create the derivation. + ''; + default = [ ]; + example = lib.literalExpression '' + with pkgs; [ + yt-dlp + ] + ''; + }; + + environment.variables = lib.mkOption { + type = with lib.types; attrsOf (submodule envSubmodule); + description = '' + A global set of environment variables and their actions to be applied + per-wrapper. + ''; + default = { }; + example = lib.literalExpression '' + { + "FOO_TYPE".value = "custom"; + "FOO_LOG_STYLE" = { + action = "set-default"; + value = "systemd"; + }; + "USELESS_VAR".action = "unset"; + } + ''; + }; + + environment.pathAdd = lib.mkOption { + type = with lib.types; listOf path; + description = '' + A global list of paths to be added per-wrapper as part of the `PATH` + environment variable. + ''; + default = [ ]; + example = lib.literalExpression '' + wrapperManagerLib.getBin (with pkgs; [ + yt-dlp + gallery-dl + ]) + ''; + }; + }; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix new file mode 100644 index 00000000..84d0a9ed --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix @@ -0,0 +1,100 @@ +{ + config, + lib, + pkgs, + ... +}: + +{ + options.build = { + variant = lib.mkOption { + type = lib.types.enum [ "binary" "shell" ]; + description = '' + Indicates the type of wrapper to be made. By default, wrapper-manager + sets this to `binary`. + ''; + default = "binary"; + example = "shell"; + }; + + extraSetup = lib.mkOption { + type = lib.types.lines; + description = '' + Additional script for setting up the wrapper script derivation. + ''; + default = ""; + }; + + extraPassthru = lib.mkOption { + type = with lib.types; attrsOf anything; + description = '' + Set of data to be passed through `passthru` of the resulting + derivation. + ''; + default = { }; + }; + + toplevel = lib.mkOption { + type = lib.types.package; + readOnly = true; + internal = true; + description = "A derivation containing the wrapper script."; + }; + }; + + config = { + build = { + toplevel = + let + inherit (config.build) variant; + makeWrapperArg0 = + if variant == "binary" then "makeBinaryWrapper" + else if variant == "shell" then "makeShellWrapper" + else "makeWrapper"; + + mkWrapBuild = + wrappers: + lib.concatMapStrings (v: '' + ${makeWrapperArg0} "${v.arg0}" "${builtins.placeholder "out"}/bin/${v.executableName}" ${lib.concatStringsSep " " v.makeWrapperArgs} + '') wrappers; + + mkDesktopEntries = desktopEntries: builtins.map (entry: pkgs.makeDesktopItem entry) desktopEntries; + + desktopEntries = mkDesktopEntries (lib.attrValues config.xdg.desktopEntries); + in + if lib.isList config.basePackages then + pkgs.symlinkJoin { + passthru = config.build.extraPassthru; + name = "wrapper-manager-fds-wrapped-package"; + paths = desktopEntries ++ config.basePackages; + nativeBuildInputs = + if variant == "binary" then [ pkgs.makeBinaryWrapper ] + else if variant == "shell" then [ pkgs.makeShellWrapper ] + else [ ]; + postBuild = '' + ${config.build.extraSetup} + ${mkWrapBuild (lib.attrValues config.wrappers)} + ''; + } + else + config.basePackages.overrideAttrs (final: prev: { + nativeBuildInputs = + (prev.nativeBuildInputs or [ ]) + ++ ( + if variant == "binary" then [ pkgs.makeBinaryWrapper ] + else if variant == "shell" then [ pkgs.makeShellWrapper ] + else [ ] + ) + ++ lib.optionals (config.xdg.desktopEntries != { }) [ pkgs.copyDesktopItems ]; + desktopItems = (prev.desktopItems or [ ]) ++ desktopEntries; + postFixup = '' + ${prev.postFixup or ""} + ${mkWrapBuild (lib.attrValues config.wrappers)} + ''; + passthru = lib.recursiveUpdate (prev.passthru or { }) (config.build.extraPassthru // { + unwrapped = config.basePackages; + }); + }); + }; + }; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix new file mode 100644 index 00000000..b462b823 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix @@ -0,0 +1,11 @@ +{ + imports = [ + ./base.nix + ./files.nix + ./xdg-desktop-entries.nix + ./xdg-dirs.nix + ./locale.nix + ./build.nix + ./extra-args.nix + ]; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/extra-args.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/extra-args.nix new file mode 100644 index 00000000..0982f3b8 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/extra-args.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: + +{ + _module.args = { + wrapperManagerLib = import ../../lib { inherit pkgs; }; + }; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/files.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/files.nix new file mode 100644 index 00000000..f2beb150 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/files.nix @@ -0,0 +1,98 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.files; + + filesModule = { name, lib, config, options, ... }: { + options = { + target = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + Path of the file relative to the derivation output path. + ''; + default = name; + example = "share/applications/org.example.App1.desktop"; + }; + + source = lib.mkOption { + type = lib.types.path; + description = "Path of the file to be linked."; + }; + + text = lib.mkOption { + type = with lib.types; nullOr lines; + description = '' + Text content of the given filesystem path. + ''; + default = null; + example = '' + key=value + hello=world + ''; + }; + + mode = lib.mkOption { + type = lib.types.strMatching "[0-7]{0,4}"; + default = "0644"; + example = "0600"; + description = '' + Permissions to be given to the file. By default, it is given with a + symlink. + ''; + }; + }; + + config = { + source = lib.mkIf (config.text != null) ( + let + name' = "wrapper-manager-filesystem-${lib.replaceStrings ["/"] ["-"] name}"; + in lib.modules.mkDerivedConfig options.text (pkgs.writeText name') + ); + }; + }; +in +{ + options.files = lib.mkOption { + type = with lib.types; attrsOf (submodule filesModule); + description = '' + A set of files to be exported within the derivation. + ''; + default = { }; + example = lib.literalExpression '' + { + "share/example-app/docs".source = ./docs; + "etc/xdg".source = ./config; + + "share/example-app/example-config".text = '''''' + hello=world + location=your-home + ''''''; + } + ''; + }; + + config = lib.mkIf (cfg != { }) { + build.extraSetup = let + installFiles = acc: n: v: let + source = lib.escapeShellArg v.source; + target = lib.escapeShellArg v.target; + target' = "$out/${target}"; + installFile = let + type = lib.filesystem.pathType v.source; + in + if type == "directory" then '' + mkdir -p $(basename ${target'}) && cp --recursive ${source} ${target'} + '' else if type == "symlink" then '' + ln --symbolic --force ${source} ${target'} + '' else '' + install -D --mode=${v.mode} ${source} ${target'} + ''; + in '' + ${acc} + ${installFile} + ''; + in lib.mkBefore '' + ${lib.foldlAttrs installFiles "" cfg} + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/locale.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/locale.nix new file mode 100644 index 00000000..4c7a1c45 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/locale.nix @@ -0,0 +1,66 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.locale; + + localeModuleFactory = + { + isGlobal ? false, + }: + { + enable = lib.mkOption { + type = lib.types.bool; + default = if isGlobal then true else cfg.enable; + example = false; + description = + if isGlobal then + '' + Whether to enable explicit glibc locale support. This is recommended + for Nix-built applications. + '' + else + '' + Whether to enable locale support for this wrapper. Recommended for + Nix-built applications. + ''; + }; + + package = lib.mkOption { + type = lib.types.package; + default = if isGlobal then (pkgs.glibcLocales.override { allLocales = true; }) else cfg.package; + description = '' + The package containing glibc locales. + ''; + }; + }; +in +{ + options.locale = localeModuleFactory { isGlobal = true; }; + + options.wrappers = + let + localeSubmodule = + { + config, + lib, + name, + ... + }: + let + submoduleCfg = config.locale; + in + { + options.locale = localeModuleFactory { isGlobal = false; }; + + config = lib.mkIf submoduleCfg.enable { + env.LOCALE_ARCHIVE.value = "${submoduleCfg.package}/lib/locale/locale-archive"; + }; + }; + in + lib.mkOption { type = with lib.types; attrsOf (submodule localeSubmodule); }; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix new file mode 100644 index 00000000..d343c5a2 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix @@ -0,0 +1,164 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + # We're only setting up options for the most common keys typically used to + # set up a desktop entry. Everything else is acceptable under a freeform + # module anyways. + xdgDesktopEntry = + { + name, + lib, + pkgs, + ... + }: + { + freeformType = with lib.types; attrsOf anything; + + options = { + name = lib.mkOption { + type = lib.types.nonEmptyStr; + description = "The name of the desktop file."; + default = name; + example = "firefox"; + }; + + desktopName = lib.mkOption { + type = lib.types.nonEmptyStr; + description = "Specific name of the application."; + default = name; + example = "Firefox"; + }; + + exec = lib.mkOption { + type = with lib.types; nullOr nonEmptyStr; + description = "Program with execute along with its arguments."; + default = null; + example = "firefox %U"; + }; + + genericName = lib.mkOption { + type = with lib.types; nullOr nonEmptyStr; + description = "Generic name of the application."; + default = null; + example = "Web browser"; + }; + + terminal = lib.mkOption { + type = lib.types.bool; + description = "Whether the program runs in a terminal window."; + default = false; + example = true; + }; + + categories = lib.mkOption { + type = with lib.types; listOf nonEmptyStr; + description = "List of categories should the application be shown in a menu."; + default = [ ]; + example = [ + "Applications" + "Network" + ]; + }; + + mimeTypes = lib.mkOption { + type = with lib.types; listOf nonEmptyStr; + description = "The MIME types supported by the application."; + default = [ ]; + example = [ + "text/html" + "text/xml" + ]; + }; + }; + }; +in +{ + options.xdg.desktopEntries = lib.mkOption { + type = with lib.types; attrsOf (submodule xdgDesktopEntry); + description = '' + A set of desktop entries to be exported along with the wrapped package. + The attribute name will be used as the filename of the generated desktop + entry file. + ''; + default = { }; + example = lib.literalExpression '' + { + firefox = { + name = "Firefox"; + genericName = "Web browser"; + exec = "firefox %u"; + terminal = false; + categories = [ "Application" "Network" "WebBrowser" ]; + mimeTypes = [ "text/html" "text/xml" ]; + extraConfig."X-GNOME-Autostart-Phase" = "WindowManager"; + keywords = [ "Web" "Browser" ]; + startupNotify = false; + startupWMClass = "MyOwnClass"; + }; + } + ''; + }; + + options.wrappers = lib.mkOption { + type = + let + xdgDesktopEntryWrapperSubmodule = + { + name, + config, + lib, + ... + }: + { + options.xdg.desktopEntry = { + enable = lib.mkEnableOption "automatic creation of a desktop entry for the wrapper"; + settings = lib.mkOption { + type = lib.types.submodule xdgDesktopEntry; + description = '' + Settings to be passed to the `makeDesktopItem` builder. + ''; + example = lib.literalExpression '' + { + mimeTypes = [ "text/html" "text/xml" ]; + categories = [ "Applications" "Network" ]; + } + ''; + }; + }; + + config.xdg.desktopEntry.settings = lib.mkIf config.xdg.desktopEntry.enable { + name = lib.mkDefault config.executableName; + desktopName = lib.mkDefault name; + type = lib.mkDefault "Application"; + + # Welp, we could set it to the absolute location of the wrapper + # executable in the final output but it's a big pain the ass to do + # so we're opting to the executable name instead. This current + # way of doing it is simply the next best (and the simplest) thing. + # We just have to make sure the build step for the wrapper script + # is consistent throughout the entire module environment. + # + # Besides, if the user wants a desktop entry along with the wrapper + # script, it will be included alongside in whatever environment + # they are using it for anyways. + exec = config.executableName; + }; + }; + in + with lib.types; + attrsOf (submodule xdgDesktopEntryWrapperSubmodule); + }; + + config = { + xdg.desktopEntries = + let + wrappersWithDesktopEntries = lib.filterAttrs (_: v: v.xdg.desktopEntry.enable) config.wrappers; + in + lib.mapAttrs (_: v: v.xdg.desktopEntry.settings) wrappersWithDesktopEntries; + }; +} diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-dirs.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-dirs.nix new file mode 100644 index 00000000..80913d98 --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-dirs.nix @@ -0,0 +1,76 @@ +{ config, lib, ... }: + +let + cfg = config.xdg; + + xdgDirsOption = { + configDirs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + A list of paths to be appended as part of the `XDG_CONFIG_DIRS` + environment to be applied per-wrapper. + ''; + default = [ ]; + example = lib.literalExpression '' + wrapperManagerLib.getXdgConfigDirs (with pkgs; [ + yt-dlp + neofetch + ]) + ''; + }; + + dataDirs = lib.mkOption { + type = with lib.types; listOf str; + description = '' + A list of paths to be appended as part of the `XDG_DATA_DIRS` + environment to be applied per-wrapper. + ''; + default = [ ]; + example = lib.literalExpression '' + wrapperManagerLib.getXdgDataDirs (with pkgs; [ + yt-dlp + neofetch + ]) + ''; + }; + }; +in +{ + options.xdg = xdgDirsOption; + + options.wrappers = lib.mkOption { + type = + let + xdgDirsType = + { + name, + lib, + config, + ... + }: + { + options.xdg = xdgDirsOption; + + config = lib.mkMerge [ + { + # When set this way, we could allow the user to override everything. + xdg.configDirs = cfg.configDirs; + xdg.dataDirs = cfg.dataDirs; + } + + (lib.mkIf (config.xdg.configDirs != [ ]) { + env.XDG_CONFIG_DIRS.value = lib.lists.map builtins.toString config.xdg.configDirs; + env.XDG_CONFIG_DIRS.action = "prefix"; + }) + + (lib.mkIf (config.xdg.dataDirs != [ ]) { + env.XDG_DATA_DIRS.value = lib.lists.map builtins.toString config.xdg.dataDirs; + env.XDG_DATA_DIRS.action = "prefix"; + }) + ]; + }; + in + with lib.types; + attrsOf (submodule xdgDirsType); + }; +} diff --git a/subprojects/wrapper-manager-fds/npins/default.nix b/subprojects/wrapper-manager-fds/npins/default.nix new file mode 100644 index 00000000..5e7d086e --- /dev/null +++ b/subprojects/wrapper-manager-fds/npins/default.nix @@ -0,0 +1,80 @@ +# Generated by npins. Do not modify; will be overwritten regularly +let + data = builtins.fromJSON (builtins.readFile ./sources.json); + version = data.version; + + mkSource = + spec: + assert spec ? type; + let + path = + if spec.type == "Git" then + mkGitSource spec + else if spec.type == "GitRelease" then + mkGitSource spec + else if spec.type == "PyPi" then + mkPyPiSource spec + else if spec.type == "Channel" then + mkChannelSource spec + else + builtins.throw "Unknown source type ${spec.type}"; + in + spec // { outPath = path; }; + + mkGitSource = + { + repository, + revision, + url ? null, + hash, + branch ? null, + ... + }: + assert repository ? type; + # At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository + # In the latter case, there we will always be an url to the tarball + if url != null then + (builtins.fetchTarball { + inherit url; + sha256 = hash; # FIXME: check nix version & use SRI hashes + }) + else + assert repository.type == "Git"; + let + urlToName = + url: rev: + let + matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url; + + short = builtins.substring 0 7 rev; + + appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else ""; + in + "${if matched == null then "source" else builtins.head matched}${appendShort}"; + name = urlToName repository.url revision; + in + builtins.fetchGit { + url = repository.url; + rev = revision; + inherit name; + # hash = hash; + }; + + mkPyPiSource = + { url, hash, ... }: + builtins.fetchurl { + inherit url; + sha256 = hash; + }; + + mkChannelSource = + { url, hash, ... }: + builtins.fetchTarball { + inherit url; + sha256 = hash; + }; +in +if version == 3 then + builtins.mapAttrs (_: mkSource) data.pins +else + throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`" diff --git a/subprojects/wrapper-manager-fds/npins/sources.json b/subprojects/wrapper-manager-fds/npins/sources.json new file mode 100644 index 00000000..25a12181 --- /dev/null +++ b/subprojects/wrapper-manager-fds/npins/sources.json @@ -0,0 +1,65 @@ +{ + "pins": { + "home-manager-stable": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "home-manager" + }, + "branch": "release-24.05", + "revision": "e1391fb22e18a36f57e6999c7a9f966dc80ac073", + "url": "https://github.com/nix-community/home-manager/archive/e1391fb22e18a36f57e6999c7a9f966dc80ac073.tar.gz", + "hash": "0c83di08nhkzq0cwc3v7aax3x8y5m7qahyzxppinzwxi3r8fnjq3" + }, + "home-manager-unstable": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "home-manager" + }, + "branch": "master", + "revision": "471e3eb0a114265bcd62d11d58ba8d3421ee68eb", + "url": "https://github.com/nix-community/home-manager/archive/471e3eb0a114265bcd62d11d58ba8d3421ee68eb.tar.gz", + "hash": "1smfj6fb3jc80gbavdf603nz782fb96d9k5w36g61zliw5g2qfvz" + }, + "nixos-stable": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "NixOS", + "repo": "nixpkgs" + }, + "branch": "nixos-24.05", + "revision": "6e99f2a27d600612004fbd2c3282d614bfee6421", + "url": "https://github.com/NixOS/nixpkgs/archive/6e99f2a27d600612004fbd2c3282d614bfee6421.tar.gz", + "hash": "1qwbrn2cb1x9clkhqmdnx5r8v11168p3nx14h3r9wcml0bgblpvr" + }, + "nixos-unstable": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "NixOS", + "repo": "nixpkgs" + }, + "branch": "nixos-unstable", + "revision": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", + "url": "https://github.com/NixOS/nixpkgs/archive/12228ff1752d7b7624a54e9c1af4b222b3c1073b.tar.gz", + "hash": "1dmng7f5rv4hgd0b61chqx589ra7jajsrzw21n8gp8makw5khvb2" + }, + "website": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "foo-dogsquared", + "repo": "website" + }, + "branch": "master", + "revision": "1195855a64b2fe010caad45fe518af986db7afb7", + "url": "https://github.com/foo-dogsquared/website/archive/1195855a64b2fe010caad45fe518af986db7afb7.tar.gz", + "hash": "1dhai90in478d2ax2s927nsf95cf7xngkmfy55ws3hl2pfycan5f" + } + }, + "version": 3 +} \ No newline at end of file diff --git a/subprojects/wrapper-manager-fds/release.json b/subprojects/wrapper-manager-fds/release.json new file mode 100644 index 00000000..6a3252ea --- /dev/null +++ b/subprojects/wrapper-manager-fds/release.json @@ -0,0 +1,3 @@ +{ + "version": "0.1.0" +} diff --git a/subprojects/wrapper-manager-fds/shell.nix b/subprojects/wrapper-manager-fds/shell.nix new file mode 100644 index 00000000..f338268c --- /dev/null +++ b/subprojects/wrapper-manager-fds/shell.nix @@ -0,0 +1,23 @@ +let + sources = import ./npins; +in +{ + pkgs ? import sources.nixos-unstable { }, +}: + +let + docs = import ./docs { inherit pkgs; }; +in +pkgs.mkShell { + inputsFrom = [ docs.website ]; + + packages = with pkgs; [ + npins + treefmt + nixfmt-rfc-style + + # For easy validation of the test suite. + yajsv + jq + ]; +} diff --git a/subprojects/wrapper-manager-fds/tests/configs/default.nix b/subprojects/wrapper-manager-fds/tests/configs/default.nix new file mode 100644 index 00000000..9aac2c62 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/configs/default.nix @@ -0,0 +1,21 @@ +let + sources = import ../../npins; +in +{ + pkgs ? import sources.nixos-unstable { }, +}: + +let + wmLib = (import ../../. { }).lib; + build = args: wmLib.build (args // { inherit pkgs; }); +in +{ + fastfetch = build { modules = [ ./wrapper-fastfetch.nix ]; }; + neofetch = build { + modules = [ ./wrapper-neofetch.nix ]; + specialArgs.yourMomName = "Yor mom"; + }; + single-basepackage = build { modules = [ ./single-basepackage.nix ]; }; + neofetch-with-additional-files = build { modules = [ ./neofetch-with-additional-files.nix ]; }; + lib-modules-make-wraparound = build { modules = [ ./lib-modules-subset/make-wraparound.nix ]; }; +} diff --git a/subprojects/wrapper-manager-fds/tests/configs/lib-modules-subset/make-wraparound.nix b/subprojects/wrapper-manager-fds/tests/configs/lib-modules-subset/make-wraparound.nix new file mode 100644 index 00000000..4ba00c7a --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/configs/lib-modules-subset/make-wraparound.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, wrapperManagerLib, ... }: + +let + inherit (wrapperManagerLib) makeWraparound; +in +{ + build.variant = "shell"; + wrappers.tmux = makeWraparound { + under = lib.getExe' pkgs.boxxy "boxxy"; + underFlags = [ "--rule" "~/.tmux.conf:~/.config/tmux/tmux.conf" ]; + underSeparator = "--"; + + arg0 = lib.getExe' pkgs.tmux "tmux"; + }; + + build.extraPassthru.wrapperManagerTests = { + actuallyBuilt = + let + wrapper = config.build.toplevel; + tmux = lib.getExe' wrapper "tmux"; + in + pkgs.runCommand "wrapper-manager-tmux-actually-built" { } '' + [ -x "${tmux}" ] && touch $out + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/configs/neofetch-with-additional-files.nix b/subprojects/wrapper-manager-fds/tests/configs/neofetch-with-additional-files.nix new file mode 100644 index 00000000..91dd9530 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/configs/neofetch-with-additional-files.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +{ + wrappers.neofetch = { + arg0 = lib.getExe' pkgs.neofetch "neofetch"; + appendArgs = [ + "--ascii_distro" + "guix" + "--title_fqdn" + "off" + "--os_arch" + "off" + ]; + }; + + # Testing out a simple file. + files."share/nix/hello".text = '' + WHOA THERE! + ''; + + # A file target with an "absolute" path. + files."/absolute/path".text = '' + WHAAAAAAAT! + ''; + + # Testing out source. + files."share/nix/aloha".source = config.files."share/nix/hello".source; + + # Testing out an executable file. + files."share/nix/example" = { + text = "WHOA"; + mode = "0755"; + }; + + # Testing out a directory. + files."share/whoa".source = pkgs.writeTextDir "/what/is/this.txt" '' + WHAT + ''; + + build.extraPassthru.wrapperManagerTests = { + actuallyBuilt = + let + wrapper = config.build.toplevel; + in + pkgs.runCommand "wrapper-manager-neofetch-actually-built" { } '' + [ -x "${wrapper}/bin/${config.wrappers.neofetch.executableName}" ] \ + && [ -f "${wrapper}/share/nix/hello" ] \ + && [ -f "${wrapper}/share/nix/aloha" ] \ + && [ -x "${wrapper}/share/nix/example" ] \ + && [ -d "${wrapper}/share/whoa" ] \ + && [ -f "${wrapper}/absolute/path" ] \ + && touch $out + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/configs/single-basepackage.nix b/subprojects/wrapper-manager-fds/tests/configs/single-basepackage.nix new file mode 100644 index 00000000..7d2aac07 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/configs/single-basepackage.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +{ + basePackages = pkgs.fastfetch; + + wrappers.fastfetch-guix = { + arg0 = lib.getExe' pkgs.fastfetch "fastfetch"; + appendArgs = [ + "--logo" + "Guix" + ]; + env.NO_COLOR.value = "1"; + xdg.desktopEntry.enable = true; + }; + + build.extraPassthru.wrapperManagerTests = { + singleBasePackage = + let + wrapper = config.build.toplevel; + in + pkgs.runCommand "wrapper-manager-fastfetch-actually-built" { } '' + [ -e "${wrapper}/share/applications/fastfetch-guix.desktop" ] && [ -x "${wrapper}/bin/${config.wrappers.fastfetch-guix.executableName}" ] && touch $out + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/configs/wrapper-fastfetch.nix b/subprojects/wrapper-manager-fds/tests/configs/wrapper-fastfetch.nix new file mode 100644 index 00000000..99808530 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/configs/wrapper-fastfetch.nix @@ -0,0 +1,35 @@ +{ + config, + lib, + pkgs, + wrapperManagerLib, + ... +}: + +{ + build.variant = "shell"; + + wrappers.fastfetch = { + arg0 = lib.getExe' pkgs.fastfetch "fastfetch"; + appendArgs = [ + "--logo" + "Guix" + ]; + env.NO_COLOR.value = "1"; + xdg.desktopEntry.enable = true; + }; + + environment.pathAdd = wrapperManagerLib.getBin (with pkgs; [ + hello + ]); + + build.extraPassthru.wrapperManagerTests = { + actuallyBuilt = + let + wrapper = config.build.toplevel; + in + pkgs.runCommand "wrapper-manager-fastfetch-actually-built" { } '' + [ -e "${wrapper}/share/applications/fastfetch.desktop" ] && [ -x "${wrapper}/bin/${config.wrappers.fastfetch.executableName}" ] && touch $out + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/configs/wrapper-neofetch.nix b/subprojects/wrapper-manager-fds/tests/configs/wrapper-neofetch.nix new file mode 100644 index 00000000..7e3041a7 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/configs/wrapper-neofetch.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + pkgs, + yourMomName, + ... +}: + +{ + wrappers.neofetch = { + arg0 = lib.getExe' pkgs.neofetch "neofetch"; + executableName = yourMomName; + appendArgs = [ + "--ascii_distro" + "guix" + "--title_fqdn" + "off" + "--os_arch" + "off" + ]; + }; + + build.extraPassthru.wrapperManagerTests = { + actuallyBuilt = + let + wrapper = config.build.toplevel; + in + pkgs.runCommand "wrapper-manager-neofetch-actually-built" { } '' + [ -x "${wrapper}/bin/${config.wrappers.neofetch.executableName}" ] && touch $out + ''; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/default.nix b/subprojects/wrapper-manager-fds/tests/default.nix new file mode 100644 index 00000000..f23bc47e --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/default.nix @@ -0,0 +1,32 @@ +let + sources = import ../npins; +in +{ + pkgs ? import sources.nixos-unstable { }, +}: + +let + wrapperManagerLibTests = import ./lib { inherit pkgs; }; + inherit (pkgs) lib; +in +{ + configs = let + configs' = import ./configs { inherit pkgs; }; + updateTestName = configName: package: lib.mapAttrs' (n: v: lib.nameValuePair "${configName}-${n}" v) package.wrapperManagerTests; + in + lib.concatMapAttrs updateTestName configs'; + + lib = + pkgs.runCommand "wrapper-manager-fds-lib-test" + { + testData = builtins.toJSON wrapperManagerLibTests; + passAsFile = [ "testData" ]; + nativeBuildInputs = with pkgs; [ + yajsv + jq + ]; + } + '' + yajsv -s "${./lib/tests.schema.json}" "$testDataPath" && touch $out || jq . "$testDataPath" + ''; +} diff --git a/subprojects/wrapper-manager-fds/tests/lib/default.nix b/subprojects/wrapper-manager-fds/tests/lib/default.nix new file mode 100644 index 00000000..ce4f6c8f --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/lib/default.nix @@ -0,0 +1,16 @@ +{ pkgs }: + +let + lib = import ../../lib { inherit pkgs; }; + callLib = + file: + import file { + inherit (pkgs) lib; + inherit pkgs; + self = lib; + }; +in +{ + env = callLib ./env; + utils = callLib ./utils.nix; +} diff --git a/subprojects/wrapper-manager-fds/tests/lib/env/default.nix b/subprojects/wrapper-manager-fds/tests/lib/env/default.nix new file mode 100644 index 00000000..c3cef521 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/lib/env/default.nix @@ -0,0 +1,63 @@ +{ + pkgs, + lib, + self, +}: + +let + neofetchWrapper = ../../configs/wrapper-neofetch.nix; + fastfetchWrapper = ../../configs/wrapper-fastfetch.nix; +in +lib.runTests { + testsEvaluateSampleConfiguration = { + expr = + let + sampleConf = self.env.eval { + inherit pkgs; + modules = [ neofetchWrapper ]; + specialArgs.yourMomName = "Joe Mama"; + }; + in + lib.isDerivation sampleConf.config.build.toplevel; + expected = true; + }; + + testsEvaluateSampleConfiguration2 = { + expr = + let + sampleConf = self.env.eval { + inherit pkgs; + modules = [ fastfetchWrapper ]; + specialArgs.yourMomName = "Joe Mama"; + }; + in + lib.isDerivation sampleConf.config.build.toplevel; + expected = true; + }; + + testsBuildSampleConfiguration = { + expr = + let + sampleConf = self.env.build { + inherit pkgs; + modules = [ neofetchWrapper ]; + specialArgs.yourMomName = "Joe Mama"; + }; + in + lib.isDerivation sampleConf; + expected = true; + }; + + testsBuildSampleConfiguration2 = { + expr = + let + sampleConf = self.env.build { + inherit pkgs; + modules = [ fastfetchWrapper ]; + specialArgs.yourMomName = "Joe Mama"; + }; + in + lib.isDerivation sampleConf; + expected = true; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/lib/tests.schema.json b/subprojects/wrapper-manager-fds/tests/lib/tests.schema.json new file mode 100644 index 00000000..d1e97e1b --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/lib/tests.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "wrapper-manager-fds Nix test object", + "type": "object", + "patternProperties": { + "^\\w+$": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 0, + "maxItems": 0 + }, + "required": true + } +} diff --git a/subprojects/wrapper-manager-fds/tests/lib/utils.nix b/subprojects/wrapper-manager-fds/tests/lib/utils.nix new file mode 100644 index 00000000..08bd69f5 --- /dev/null +++ b/subprojects/wrapper-manager-fds/tests/lib/utils.nix @@ -0,0 +1,51 @@ +{ + pkgs, + lib, + self, +}: + +lib.runTests { + testsUtilsGetBin = { + expr = self.utils.getBin [ + ../../lib + ../../modules + ]; + expected = [ + (lib.getBin ../../lib) + (lib.getBin ../../modules) + ]; + }; + + testsUtilsGetLibexec = { + expr = self.utils.getLibexec [ + ../../lib + ../../modules + ]; + expected = [ + "${../../lib}/libexec" + "${../../modules}/libexec" + ]; + }; + + testsUtilsGetXdgConfigDirs = { + expr = self.utils.getXdgConfigDirs [ + ../../lib + ../../modules + ]; + expected = [ + "${../../lib}/etc/xdg" + "${../../modules}/etc/xdg" + ]; + }; + + testsUtilsGetXdgDataDirs = { + expr = self.utils.getXdgDataDirs [ + ../../lib + ../../modules + ]; + expected = [ + "${../../lib}/share" + "${../../modules}/share" + ]; + }; +} diff --git a/subprojects/wrapper-manager-fds/treefmt.toml b/subprojects/wrapper-manager-fds/treefmt.toml new file mode 100644 index 00000000..4deb3fd4 --- /dev/null +++ b/subprojects/wrapper-manager-fds/treefmt.toml @@ -0,0 +1,8 @@ +[global] +excludes = [ + "npins/default.nix" +] + +[formatter.nix] +command = "nixfmt" +includes = [ "*.nix" ] diff --git a/templates/rust-app/default.nix b/templates/rust-app/default.nix index 9d896be9..c715365b 100644 --- a/templates/rust-app/default.nix +++ b/templates/rust-app/default.nix @@ -11,7 +11,7 @@ rustPlatform.buildRustPackage { src = lib.fileset.toSource { root = ./.; - fileset = lib.fs.unions [ + fileset = lib.fileset.unions [ ./Cargo.lock ./Cargo.toml ./LICENSE diff --git a/tests/README.adoc b/tests/README.adoc index d0eb76d9..9ee323f8 100644 --- a/tests/README.adoc +++ b/tests/README.adoc @@ -3,7 +3,9 @@ Yes, tests! -We have tests for the major components of this NixOS configuration including the link:../lib[custom library], link:../modules/nixos[our custom NixOS modules], link:../modules/home-manager[custom home-manager modules], and so on. +Because apparently, letting desktop users BE the developers of their own operating system is such as a GOOOOOOOOD idea... + +Anyways, as part of cosplaying of a wannabe developer, we have tests for the major components of this NixOS configuration including the link:../lib[custom library], link:../modules/nixos[our custom NixOS modules], link:../modules/home-manager[custom home-manager modules], and so on. Each of the test suite follows how the upstream does their tests. For example, our home-manager module tests just copies what the upstream is doing. @@ -14,10 +16,16 @@ You should be able to test them with the following command: ---- # These commands assume you're in the project root. -# This test is for home-manager module tests. +# This test is for home-manager module tests because it is using nix-lib-nmt +# which is only working in pure mode. nix-shell --pure ./tests/modules/home-manager -A list # This is for the library. nix eval -f ./tests lib + +# This is for the wrapper-manager modules but it should be best done with the +# tests passthru attribute. We just don't have easy way of testing with them +# yet. +nix build -f ./tests/modules/wrapper-manager ---- diff --git a/tests/default.nix b/tests/default.nix index cadd0c70..bd738ac4 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -1,5 +1,17 @@ -{ pkgs ? import { } }: +let + flakeUtils = import ../lib/flake.nix; + flake = flakeUtils.importFlakeMetadata ../flake.lock; +in +{ pkgs ? import (flakeUtils.fetchTree flake "nixos-unstable") { } }: +let + utils = import ./utils.nix { inherit pkgs; }; +in { - lib = import ./lib { inherit pkgs; }; + lib = import ./lib { inherit pkgs utils; }; + modules = { + home-manager = import ./modules/home-manager { inherit pkgs utils; }; + nixos = import ./modules/nixos { inherit pkgs utils; }; + wrapper-manager = import ./modules/wrapper-manager { inherit pkgs utils; }; + }; } diff --git a/tests/lib/builders.nix b/tests/lib/builders.nix new file mode 100644 index 00000000..060e4918 --- /dev/null +++ b/tests/lib/builders.nix @@ -0,0 +1,105 @@ +{ pkgs, lib, self }: + +let + sampleDesktopName = "horizontal-hunger"; +in +lib.runTests { + testsBuilderMakeSampleXDGAssociationList = { + expr = + let + xdgAssociations = self.builders.makeXDGMimeAssociationList { + defaultApplications = { + "application/pdf" = "firefox.desktop"; + }; + }; + in builtins.readFile "${xdgAssociations}/share/applications/mimeapps.list"; + expected = + builtins.readFile ./data/fixtures/xdg-mime-sample-mimeapps.list; + }; + + # This should only create the "Default Applications" section of the + # specific-desktop mimeapps.list. + testsBuilderMakeSampleDesktopSpecificXDGAssociationList = { + expr = + let + xdgAssociations = self.builders.makeXDGMimeAssociationList { + desktopName = sampleDesktopName; + defaultApplications = { + "application/pdf" = "firefox.desktop"; + }; + }; + in builtins.readFile "${xdgAssociations}/share/applications/${sampleDesktopName}-mimeapps.list"; + expected = + builtins.readFile ./data/fixtures/xdg-mime-sample-desktop-specific-mimeapps.list; + }; + + testsBuilderMakeSampleXDGPortalCommonConfig = { + expr = + let + xdgPortalConf = self.builders.makeXDGPortalConfiguration { + config.preferred = { + default = "gtk"; + "org.freedesktop.impl.portal.Screencast" = "gnome"; + }; + }; + in + builtins.readFile "${xdgPortalConf}/share/xdg-desktop-portal/portals.conf"; + expected = + builtins.readFile ./data/fixtures/xdg-portal.conf; + }; + + # We're just testing out if the destination is correct at this point. + testsBuilderMakeSampleXDGPortalDesktopSpecificConfig = { + expr = + let + xdgPortalConf = self.builders.makeXDGPortalConfiguration { + desktopName = sampleDesktopName; + config.preferred = { + default = "gtk"; + "org.freedesktop.impl.portal.Screencast" = "gnome"; + }; + }; + in + builtins.readFile "${xdgPortalConf}/share/xdg-desktop-portal/${sampleDesktopName}-portals.conf"; + expected = + builtins.readFile ./data/fixtures/xdg-portal.conf; + }; + + # We're just testing out if the destination is correct at this point. + testsBuilderMakeSampleXDGDesktopEntry = { + expr = + let + xdgDesktopEntry = self.builders.makeXDGDesktopEntry { + name = sampleDesktopName; + validate = false; + config = { + "Desktop Entry".Exec = "Hello"; + }; + }; + in + builtins.readFile "${xdgDesktopEntry}/share/applications/${sampleDesktopName}.desktop"; + expected = + builtins.readFile ./data/fixtures/xdg-desktop-entry.desktop; + }; + + # We're just testing out if the destination is correct at this point. + testsBuilderMakeSampleDesktopSessionFile = { + expr = + let + xdgDesktopEntry = self.builders.makeXDGDesktopEntry { + name = sampleDesktopName; + validate = false; + destination = "/share/wayland-sessions/${sampleDesktopName}.desktop"; + config = { + "Desktop Entry" = { + Exec = "Hello"; + DesktopNames = [ "GNOME" "Sway" ]; + }; + }; + }; + in + builtins.readFile "${xdgDesktopEntry}/share/wayland-sessions/${sampleDesktopName}.desktop"; + expected = + builtins.readFile ./data/fixtures/xdg-desktop-session.desktop; + }; +} diff --git a/tests/lib/data/data/sample.json b/tests/lib/data/data/sample.json new file mode 100644 index 00000000..742222ae --- /dev/null +++ b/tests/lib/data/data/sample.json @@ -0,0 +1,9 @@ +{ + "hello": "world", + "whoa": 4566, + "list-of-names": [ + "Cheesy", + "Angry", + "Ash" + ] +} diff --git a/tests/lib/data/data/sample.yaml b/tests/lib/data/data/sample.yaml new file mode 100644 index 00000000..25c95e60 --- /dev/null +++ b/tests/lib/data/data/sample.yaml @@ -0,0 +1,6 @@ +hello: world +whoa: 4566 +list-of-names: + - Cheesy + - Angry + - Ash diff --git a/tests/lib/data/default.nix b/tests/lib/data/default.nix new file mode 100644 index 00000000..05ce7a48 --- /dev/null +++ b/tests/lib/data/default.nix @@ -0,0 +1,42 @@ +{ pkgs, lib, self }: + +lib.runTests { + testImportYAML = { + expr = self.data.importYAML ./data/sample.yaml; + expected = { + hello = "world"; + whoa = 4566; + list-of-names = [ + "Cheesy" "Angry" "Ash" + ]; + }; + }; + + testImportYAMLAsJSON = { + expr = self.data.importYAML ./data/sample.json; + expected = { + hello = "world"; + whoa = 4566; + list-of-names = [ + "Cheesy" "Angry" "Ash" + ]; + }; + }; + + testRenderTeraTemplate = { + expr = builtins.readFile (self.data.renderTeraTemplate { + template = ./templates/sample.tera; + context = lib.importJSON ./data/sample.json; + }); + expected = builtins.readFile ./fixtures/sample.tera; + }; + + testRenderMustacheTemplate = { + expr = builtins.readFile (self.data.renderTeraTemplate { + template = ./templates/sample.mustache; + context = lib.importJSON ./data/sample.json; + }); + # There the same lol. + expected = builtins.readFile ./fixtures/sample.tera; + }; +} diff --git a/tests/lib/data/fixtures/sample.tera b/tests/lib/data/fixtures/sample.tera new file mode 100644 index 00000000..cc628ccd --- /dev/null +++ b/tests/lib/data/fixtures/sample.tera @@ -0,0 +1 @@ +world diff --git a/tests/lib/data/fixtures/xdg-desktop-entry.desktop b/tests/lib/data/fixtures/xdg-desktop-entry.desktop new file mode 100644 index 00000000..00cf3f53 --- /dev/null +++ b/tests/lib/data/fixtures/xdg-desktop-entry.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Exec=Hello diff --git a/tests/lib/data/fixtures/xdg-desktop-session.desktop b/tests/lib/data/fixtures/xdg-desktop-session.desktop new file mode 100644 index 00000000..66fe60a0 --- /dev/null +++ b/tests/lib/data/fixtures/xdg-desktop-session.desktop @@ -0,0 +1,3 @@ +[Desktop Entry] +DesktopNames=GNOME;Sway +Exec=Hello diff --git a/tests/lib/data/fixtures/xdg-mime-sample-desktop-specific-mimeapps.list b/tests/lib/data/fixtures/xdg-mime-sample-desktop-specific-mimeapps.list new file mode 100644 index 00000000..c0ec4545 --- /dev/null +++ b/tests/lib/data/fixtures/xdg-mime-sample-desktop-specific-mimeapps.list @@ -0,0 +1,2 @@ +[Default Applications] +application/pdf=firefox.desktop diff --git a/tests/lib/data/fixtures/xdg-mime-sample-mimeapps.list b/tests/lib/data/fixtures/xdg-mime-sample-mimeapps.list new file mode 100644 index 00000000..11b84a81 --- /dev/null +++ b/tests/lib/data/fixtures/xdg-mime-sample-mimeapps.list @@ -0,0 +1,6 @@ +[Added Associations] + +[Default Applications] +application/pdf=firefox.desktop + +[Removed Associations] diff --git a/tests/lib/data/fixtures/xdg-portal.conf b/tests/lib/data/fixtures/xdg-portal.conf new file mode 100644 index 00000000..682d9ce7 --- /dev/null +++ b/tests/lib/data/fixtures/xdg-portal.conf @@ -0,0 +1,3 @@ +[preferred] +default=gtk +org.freedesktop.impl.portal.Screencast=gnome diff --git a/tests/lib/data/templates/sample.mustache b/tests/lib/data/templates/sample.mustache new file mode 100644 index 00000000..8fe25f99 --- /dev/null +++ b/tests/lib/data/templates/sample.mustache @@ -0,0 +1 @@ +{{ hello }} diff --git a/tests/lib/data/templates/sample.tera b/tests/lib/data/templates/sample.tera new file mode 100644 index 00000000..8fe25f99 --- /dev/null +++ b/tests/lib/data/templates/sample.tera @@ -0,0 +1 @@ +{{ hello }} diff --git a/tests/lib/default.nix b/tests/lib/default.nix index 0e8a3a35..4ce462b6 100644 --- a/tests/lib/default.nix +++ b/tests/lib/default.nix @@ -1,6 +1,6 @@ # For the environment-specific subset, we'll be simulating the configurations # as a simple attribute set since that's what they are anyways. -{ pkgs ? import { } }: +{ pkgs ? import { }, utils ? import ../utils.nix { inherit pkgs; } }: let inherit (pkgs) lib; @@ -9,15 +9,18 @@ let callLib = file: import file { inherit pkgs lib; self = prev; }; in { - nixos = callLib ../../lib/nixos.nix; - home-manager = callLib ../../lib/home-manager.nix; - nixvim = callLib ../../lib/nixvim.nix; + nixos = callLib ../../lib/env-specific/nixos.nix; + home-manager = callLib ../../lib/env-specific/home-manager.nix; + nixvim = callLib ../../lib/env-specific/nixvim.nix; }); callLib = file: import file { inherit pkgs lib; self = foodogsquaredLib; }; in { + builders = callLib ./builders.nix; trivial = callLib ./trivial.nix; + data = callLib ./data; + math = callLib ./math.nix; # Environment-specific subset. home-manager = callLib ./home-manager.nix; diff --git a/tests/lib/fetchers.nix b/tests/lib/fetchers.nix new file mode 100644 index 00000000..c74abecb --- /dev/null +++ b/tests/lib/fetchers.nix @@ -0,0 +1,21 @@ +{ + pkgs ? import { }, + lib ? pkgs.lib, + self ? import ../../lib { inherit pkgs; }, +}: + +{ + testsInternetArchiveFetcher = + self.fetchers.fetchInternetArchive { + id = "md_music_sonic_the_hedgehog"; + file = "01 - Title Theme - Masato Nakamura.flac"; + hash = "sha256-kGjsVjtjXK9imqyi4GF6qkFVmobiTAe/ZAeEwiouqS4="; + }; + + testsInternetArchiveFetcher2 = + self.fetchers.fetchInternetArchive { + id = "md_music_sonic_the_hedgehog"; + formats = [ "TEXT" "PNG" ]; + hash = "sha256-xbhasJ/wEgcY+EcBAJp5UoYB4N4It3QV/iIeGGdCET8="; + }; +} diff --git a/tests/lib/math.nix b/tests/lib/math.nix new file mode 100644 index 00000000..32ec4d14 --- /dev/null +++ b/tests/lib/math.nix @@ -0,0 +1,34 @@ +{ pkgs, lib, self }: + + +lib.runTests { + testMathAbsoluteValue = { + expr = self.math.abs 5493; + expected = 5493; + }; + + testMathAbsoluteValue2 = { + expr = self.math.abs (-435354); + expected = 435354; + }; + + testMathPowPositive = { + expr = self.math.pow 2 8; + expected = 256; + }; + + testMathPowNegative = { + expr = self.math.pow 2.0 (-1); + expected = 0.5; + }; + + testMathPowZero = { + expr = self.math.pow 31 0; + expected = 1; + }; + + testsMathPowWithFloat = { + expr = self.math.pow 2 7.0; + expected = 128.0; + }; +} diff --git a/tests/lib/trivial.nix b/tests/lib/trivial.nix index 1248bcbc..ae63e92a 100644 --- a/tests/lib/trivial.nix +++ b/tests/lib/trivial.nix @@ -1,6 +1,16 @@ { pkgs, lib, self }: lib.runTests { + testToFloat = { + expr = self.trivial.toFloat 4; + expected = 4.0; + }; + + testToFloat2 = { + expr = self.trivial.toFloat 5.5; + expected = 5.5; + }; + testCountAttrs = { expr = self.trivial.countAttrs (n: v: v?enable && v.enable) { hello.enable = true; @@ -13,8 +23,111 @@ lib.runTests { expected = 2; }; - testGetConfig = { - expr = self.trivial.getConfig "home-manager" "foo-dogsquared"; - expected = ../../configs/home-manager/foo-dogsquared; + testFilterAttrs' = { + expr = self.trivial.filterAttrs' (n: v: v == 4) { + e = 5; + f = 7; + a = 4; + }; + expected = { + ok = { a = 4; }; + notOk = { e = 5; f = 7; }; + }; + }; + + testSIPrefixExponent = { + expr = self.trivial.SIPrefixExponent "M"; + expected = 6; + }; + + testSIPrefixExponent2 = { + expr = self.trivial.SIPrefixExponent "G"; + expected = 9; + }; + + testMetricPrefixMultiplier = { + expr = self.trivial.metricPrefixMultiplier "M"; + expected = 1000000; + }; + + testMetricPrefixMultiplier2 = { + expr = self.trivial.metricPrefixMultiplier "G"; + expected = 1000000000; + }; + + testBinaryPrefixMultiplier = { + expr = self.trivial.binaryPrefixMultiplier "M"; + expected = 1048576; + }; + + testBinaryPrefixExponent = { + expr = self.trivial.binaryPrefixExponent "M"; + expected = 20; + }; + + testBinaryPrefixExponent2 = { + expr = self.trivial.binaryPrefixExponent "G"; + expected = 30; + }; + + testBinaryPrefixMultiplier2 = { + expr = self.trivial.binaryPrefixMultiplier "K"; + expected = 1024; + }; + + testBinaryPrefixMultiplier3 = { + expr = self.trivial.binaryPrefixMultiplier "G"; + expected = 1073741824; + }; + + testParseBytesSizeIntoInt = { + expr = self.trivial.parseBytesSizeIntoInt "3GB"; + expected = 3 * (self.trivial.metricPrefixMultiplier "G"); + }; + + testParseBytesSizeIntoInt2 = { + expr = self.trivial.parseBytesSizeIntoInt "5MiB"; + expected = 5 * (self.trivial.binaryPrefixMultiplier "M"); + }; + + testParseBytesSizeIntoInt3 = { + expr = self.trivial.parseBytesSizeIntoInt "5MB"; + expected = 5 * (self.trivial.metricPrefixMultiplier "M"); + }; + + testParseBytesSizeIntoInt4 = { + expr = self.trivial.parseBytesSizeIntoInt "2 TiB"; + expected = 2 * (self.trivial.binaryPrefixMultiplier "T"); + }; + + testParseBytesSizeIntoInt5 = { + expr = self.trivial.parseBytesSizeIntoInt "2 Tib"; + expected = 2 * (self.trivial.binaryPrefixMultiplier "T") / 8; + }; + + testUnitsToInt = { + expr = self.trivial.unitsToInt { + size = 4.5; + prefix = "G"; + type = "metric"; + }; + expected = 4500000000; + }; + + testUnitsToInt2 = { + expr = self.trivial.unitsToInt { + size = 4.5; + prefix = "G"; + }; + expected = 4831838208; + }; + + testUnitsToInt3 = { + expr = self.trivial.unitsToInt { + size = 532; + prefix = "M"; + type = "metric"; + }; + expected = 532000000; }; } diff --git a/tests/modules/home-manager/default.nix b/tests/modules/home-manager/default.nix index 45567800..6c15faa3 100644 --- a/tests/modules/home-manager/default.nix +++ b/tests/modules/home-manager/default.nix @@ -1,6 +1,7 @@ # We're basically reimplmenting parts from the home-manager test suite here # just with our own modules included. { pkgs ? import { } +, utils ? import ../../utils.nix { inherit pkgs; } , homeManagerSrc ? , enableBig ? true }: @@ -50,7 +51,9 @@ in import nmt { inherit pkgs lib modules; testedAttrPath = [ "home" "activationPackage" ]; + # TODO: Fix nmt to accept specialArgs or something. tests = builtins.foldl' (a: b: a // (import b)) { } ([ + #./programs/borgmatic ./programs/neovide ./programs/pipewire ./programs/pop-launcher @@ -58,8 +61,11 @@ import nmt { ] ++ lib.optionals isLinux [ ./services/archivebox + #./services/borgmatic ./services/bleachbit ./services/gallery-dl + ./services/gonic + ./services/ludusavi ./services/matcha ./services/plover ./services/yt-dlp diff --git a/tests/modules/home-manager/programs/borgmatic/basic.nix b/tests/modules/home-manager/programs/borgmatic/basic.nix new file mode 100644 index 00000000..27fd3dff --- /dev/null +++ b/tests/modules/home-manager/programs/borgmatic/basic.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +{ + programs.borgmatic = { + enable = true; + backups = { + personal.settings = { + hello = "WORLD"; + }; + + bizness.settings = { + hello = "MONEY"; + }; + }; + }; + + test.stubs.borgmatic = { }; + + nmt.script = '' + assertFileExists home-files/.config/borgmatic.d/personal.yaml + assertFileExists home-files/.config/borgmatic.d/bizness.yaml + ''; +} diff --git a/tests/modules/home-manager/programs/borgmatic/default.nix b/tests/modules/home-manager/programs/borgmatic/default.nix new file mode 100644 index 00000000..853cc69c --- /dev/null +++ b/tests/modules/home-manager/programs/borgmatic/default.nix @@ -0,0 +1,4 @@ +{ + borgmatic-basic = ./basic.nix; + borgmatic-multiple-configurations = ./multiple-configurations.nix; +} diff --git a/tests/modules/home-manager/services/borgmatic/basic.nix b/tests/modules/home-manager/services/borgmatic/basic.nix new file mode 100644 index 00000000..1a36ade0 --- /dev/null +++ b/tests/modules/home-manager/services/borgmatic/basic.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +{ + services.borgmatic.jobs.personal = { + settings = { + hello = "WORLD"; + }; + }; + + test.stubs.borgmatic = { }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/borgmatic-job-personal.service + assertFileExists home-files/.config/systemd/user/borgmatic-job-personal.timer + ''; +} diff --git a/tests/modules/home-manager/services/borgmatic/default.nix b/tests/modules/home-manager/services/borgmatic/default.nix new file mode 100644 index 00000000..18bc62d4 --- /dev/null +++ b/tests/modules/home-manager/services/borgmatic/default.nix @@ -0,0 +1,4 @@ +{ + borgmatic-service-basic = ./basic.nix; + borgmatic-service-with-program-config = ./with-program-config.nix; +} diff --git a/tests/modules/home-manager/services/borgmatic/with-program-config.nix b/tests/modules/home-manager/services/borgmatic/with-program-config.nix new file mode 100644 index 00000000..8943b4ce --- /dev/null +++ b/tests/modules/home-manager/services/borgmatic/with-program-config.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +{ + programs.borgmatic.enable = true; + + programs.borgmatic.backups.personal = { + settings.hello = "WORLD"; + initService.enable = true; + }; + + test.stubs.borgmatic = { }; + + nmt.script = '' + assertFileExists home-files/.config/borgmatic.d/personal.yaml + assertFileExists home-files/.config/systemd/user/borgmatic-job-borgmatic-config-personal.service + assertFileExists home-files/.config/systemd/user/borgmatic-job-borgmatic-config-personal.timer + ''; +} diff --git a/tests/modules/home-manager/services/gonic/basic.nix b/tests/modules/home-manager/services/gonic/basic.nix new file mode 100644 index 00000000..ab0daa7a --- /dev/null +++ b/tests/modules/home-manager/services/gonic/basic.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +{ + services.gonic = { + enable = true; + package = pkgs.gonic; + + settings = { + music-path = [ config.xdg.userDirs.music ]; + podcast-path = [ "${config.xdg.userDirs.music}/Podcasts" ]; + }; + }; + + test.stubs.gonic = { }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/gonic.service + ''; +} diff --git a/tests/modules/home-manager/services/gonic/default.nix b/tests/modules/home-manager/services/gonic/default.nix new file mode 100644 index 00000000..10ef0b68 --- /dev/null +++ b/tests/modules/home-manager/services/gonic/default.nix @@ -0,0 +1,3 @@ +{ + gonic-basic = ./basic.nix; +} diff --git a/tests/modules/home-manager/services/ludusavi/basic.nix b/tests/modules/home-manager/services/ludusavi/basic.nix new file mode 100644 index 00000000..0179e568 --- /dev/null +++ b/tests/modules/home-manager/services/ludusavi/basic.nix @@ -0,0 +1,24 @@ +{ config, ... }: + +{ + services.ludusavi = { + enable = true; + extraArgs = [ + "--force" + "--compression zstd" + "--compression-level 15" + ]; + settings = { + manifest.url = "https://raw.githubusercontent.com/mtkennerly/ludusavi-manifest/master/data/manifest.yaml"; + backup.path = "${config.xdg.cacheHome}/ludusavi/backups"; + restore.path = "${config.xdg.cacheHome}/ludusavi/backups"; + }; + }; + + test.stubs.ludusavi = { }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/ludusavi.service + assertFileExists home-files/.config/systemd/user/ludusavi.timer + ''; +} diff --git a/tests/modules/home-manager/services/ludusavi/default.nix b/tests/modules/home-manager/services/ludusavi/default.nix new file mode 100644 index 00000000..15183c4b --- /dev/null +++ b/tests/modules/home-manager/services/ludusavi/default.nix @@ -0,0 +1,3 @@ +{ + ludusavi-basic = ./basic.nix; +} diff --git a/tests/modules/wrapper-manager/README.adoc b/tests/modules/wrapper-manager/README.adoc new file mode 100644 index 00000000..40dc3ffe --- /dev/null +++ b/tests/modules/wrapper-manager/README.adoc @@ -0,0 +1,6 @@ += wrapper-manager-fds custom module tests +:toc: + +The test infrastructure for my custom wrapper-manager modules. +This should handle both the public and private modules. +The main file you should be paying attention first and foremost is in link:./default.nix[./default.nix] where it sets up the entire test for all of them. diff --git a/tests/modules/wrapper-manager/dconf/basic.nix b/tests/modules/wrapper-manager/dconf/basic.nix new file mode 100644 index 00000000..bd32dff3 --- /dev/null +++ b/tests/modules/wrapper-manager/dconf/basic.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +let + section = "one/foodogsquared/SomeMadeUpCrap"; + key = "somemadeupkey"; + value = true; +in +{ + wrappers.dconf-test = { + arg0 = lib.getExe' pkgs.dconf "dconf"; + dconf = { + enable = true; + settings.${section}.${key} = value; + }; + }; + + build.extraPassthru.tests = { + dconfCheck = pkgs.runCommand "dconf-wrapped-test" { } '' + export HOME=$TMPDIR + + # We've hardcoded the value for now since Nix toString function makes the + # boolean either "1" or an empty string. + [ "$(${lib.getExe' config.build.toplevel "dconf-test"} read '/${section}/${key}')" = 'true' ] && touch $out + ''; + }; +} diff --git a/tests/modules/wrapper-manager/dconf/default.nix b/tests/modules/wrapper-manager/dconf/default.nix new file mode 100644 index 00000000..7fff7787 --- /dev/null +++ b/tests/modules/wrapper-manager/dconf/default.nix @@ -0,0 +1,3 @@ +{ + basic = ./basic.nix; +} diff --git a/tests/modules/wrapper-manager/default.nix b/tests/modules/wrapper-manager/default.nix new file mode 100644 index 00000000..fe29b381 --- /dev/null +++ b/tests/modules/wrapper-manager/default.nix @@ -0,0 +1,25 @@ +{ pkgs ? import { }, utils ? import ../../utils.nix { inherit pkgs; } }: + +let + inherit (pkgs) lib; + wrapperManager = import ../../../subprojects/wrapper-manager-fds { }; + wrapperManagerEval = module: args: wrapperManager.lib.build (args // { + pkgs = args.pkgs or pkgs; + modules = args.extraModules or [ ] ++ [ + module + ../../../modules/wrapper-manager + ../../../modules/wrapper-manager/_private + ]; + }); + + runTests = path: args: + lib.mapAttrs (_: v: wrapperManagerEval v args) (import path); +in +{ + neovim = runTests ./programs/neovim { }; + bubblewrap = runTests ./sandboxing/bubblewrap { }; + boxxy = runTests ./sandboxing/boxxy { }; + zellij = runTests ./programs/zellij { }; + jujutsu = runTests ./programs/jujutsu { }; + dconf = runTests ./dconf { }; +} diff --git a/tests/modules/wrapper-manager/programs/jujutsu/basic.nix b/tests/modules/wrapper-manager/programs/jujutsu/basic.nix new file mode 100644 index 00000000..19fdb285 --- /dev/null +++ b/tests/modules/wrapper-manager/programs/jujutsu/basic.nix @@ -0,0 +1,21 @@ +{ config, lib, pkgs, ... }: + +{ + programs.jujutsu = { + enable = true; + settings = { + user.name = "Your name"; + user.email = "yourname@example.com"; + }; + }; + + build.extraPassthru.tests = { + runWithJujutsu = let + wrapper = config.build.toplevel; + in pkgs.runCommand '' + [ -x ${lib.getExe' wrapper "jj"} ] && touch $out + ''; + }; +} + + diff --git a/tests/modules/wrapper-manager/programs/jujutsu/default.nix b/tests/modules/wrapper-manager/programs/jujutsu/default.nix new file mode 100644 index 00000000..7fff7787 --- /dev/null +++ b/tests/modules/wrapper-manager/programs/jujutsu/default.nix @@ -0,0 +1,3 @@ +{ + basic = ./basic.nix; +} diff --git a/tests/modules/wrapper-manager/programs/neovim/basic.nix b/tests/modules/wrapper-manager/programs/neovim/basic.nix new file mode 100644 index 00000000..c53b0772 --- /dev/null +++ b/tests/modules/wrapper-manager/programs/neovim/basic.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + programs.neovim = { + enable = true; + }; + + build.extraPassthru.tests = { + runWithNeovim = let + wrapper = config.build.toplevel; + in pkgs.runCommand '' + [ -x ${lib.getExe' wrapper "nvim"} ] && touch $out + ''; + }; +} diff --git a/tests/modules/wrapper-manager/programs/neovim/default.nix b/tests/modules/wrapper-manager/programs/neovim/default.nix new file mode 100644 index 00000000..7fff7787 --- /dev/null +++ b/tests/modules/wrapper-manager/programs/neovim/default.nix @@ -0,0 +1,3 @@ +{ + basic = ./basic.nix; +} diff --git a/tests/modules/wrapper-manager/programs/zellij/basic.nix b/tests/modules/wrapper-manager/programs/zellij/basic.nix new file mode 100644 index 00000000..3a7a5b58 --- /dev/null +++ b/tests/modules/wrapper-manager/programs/zellij/basic.nix @@ -0,0 +1,14 @@ +{ config, lib, pkgs, ... }: + +{ + programs.zellij.enable = true; + programs.zellij.configFile = ./config/config.kdl; + + build.extraPassthru.tests = { + checkZellijConfigDir = let + wrapper = lib.getExe' config.build.toplevel "zellij"; + in pkgs.runCommandLocal "zellij-check-config-dir" { } '' + [ $(${wrapper} setup --check | awk -F':' '/^\[LOOKING FOR CONFIG FILE FROM]/ { gsub(/"|\s/, "", $2); print $2; }') = ${./config/config.kdl} ] && touch $out + ''; + }; +} diff --git a/tests/modules/wrapper-manager/programs/zellij/config/config.kdl b/tests/modules/wrapper-manager/programs/zellij/config/config.kdl new file mode 100644 index 00000000..0d49686e --- /dev/null +++ b/tests/modules/wrapper-manager/programs/zellij/config/config.kdl @@ -0,0 +1,365 @@ +// If you'd like to override the default keybindings completely, be sure to change "keybinds" to "keybinds clear-defaults=true" +keybinds { + normal { + // uncomment this and adjust key if using copy_on_select=false + // bind "Alt c" { Copy; } + } + locked { + bind "Ctrl g" { SwitchToMode "Normal"; } + } + resize { + bind "Ctrl n" { SwitchToMode "Normal"; } + bind "h" "Left" { Resize "Increase Left"; } + bind "j" "Down" { Resize "Increase Down"; } + bind "k" "Up" { Resize "Increase Up"; } + bind "l" "Right" { Resize "Increase Right"; } + bind "H" { Resize "Decrease Left"; } + bind "J" { Resize "Decrease Down"; } + bind "K" { Resize "Decrease Up"; } + bind "L" { Resize "Decrease Right"; } + bind "=" "+" { Resize "Increase"; } + bind "-" { Resize "Decrease"; } + } + pane { + bind "Ctrl p" { SwitchToMode "Normal"; } + bind "h" "Left" { MoveFocus "Left"; } + bind "l" "Right" { MoveFocus "Right"; } + bind "j" "Down" { MoveFocus "Down"; } + bind "k" "Up" { MoveFocus "Up"; } + bind "p" { SwitchFocus; } + bind "n" { NewPane; SwitchToMode "Normal"; } + bind "d" { NewPane "Down"; SwitchToMode "Normal"; } + bind "r" { NewPane "Right"; SwitchToMode "Normal"; } + bind "x" { CloseFocus; SwitchToMode "Normal"; } + bind "f" { ToggleFocusFullscreen; SwitchToMode "Normal"; } + bind "z" { TogglePaneFrames; SwitchToMode "Normal"; } + bind "w" { ToggleFloatingPanes; SwitchToMode "Normal"; } + bind "e" { TogglePaneEmbedOrFloating; SwitchToMode "Normal"; } + bind "c" { SwitchToMode "RenamePane"; PaneNameInput 0;} + } + move { + bind "Ctrl h" { SwitchToMode "Normal"; } + bind "n" "Tab" { MovePane; } + bind "p" { MovePaneBackwards; } + bind "h" "Left" { MovePane "Left"; } + bind "j" "Down" { MovePane "Down"; } + bind "k" "Up" { MovePane "Up"; } + bind "l" "Right" { MovePane "Right"; } + } + tab { + bind "Ctrl t" { SwitchToMode "Normal"; } + bind "r" { SwitchToMode "RenameTab"; TabNameInput 0; } + bind "h" "Left" "Up" "k" { GoToPreviousTab; } + bind "l" "Right" "Down" "j" { GoToNextTab; } + bind "n" { NewTab; SwitchToMode "Normal"; } + bind "x" { CloseTab; SwitchToMode "Normal"; } + bind "s" { ToggleActiveSyncTab; SwitchToMode "Normal"; } + bind "b" { BreakPane; SwitchToMode "Normal"; } + bind "]" { BreakPaneRight; SwitchToMode "Normal"; } + bind "[" { BreakPaneLeft; SwitchToMode "Normal"; } + bind "1" { GoToTab 1; SwitchToMode "Normal"; } + bind "2" { GoToTab 2; SwitchToMode "Normal"; } + bind "3" { GoToTab 3; SwitchToMode "Normal"; } + bind "4" { GoToTab 4; SwitchToMode "Normal"; } + bind "5" { GoToTab 5; SwitchToMode "Normal"; } + bind "6" { GoToTab 6; SwitchToMode "Normal"; } + bind "7" { GoToTab 7; SwitchToMode "Normal"; } + bind "8" { GoToTab 8; SwitchToMode "Normal"; } + bind "9" { GoToTab 9; SwitchToMode "Normal"; } + bind "Tab" { ToggleTab; } + } + scroll { + bind "Ctrl s" { SwitchToMode "Normal"; } + bind "e" { EditScrollback; SwitchToMode "Normal"; } + bind "s" { SwitchToMode "EnterSearch"; SearchInput 0; } + bind "Ctrl c" { ScrollToBottom; SwitchToMode "Normal"; } + bind "j" "Down" { ScrollDown; } + bind "k" "Up" { ScrollUp; } + bind "Ctrl f" "PageDown" "Right" "l" { PageScrollDown; } + bind "Ctrl b" "PageUp" "Left" "h" { PageScrollUp; } + bind "d" { HalfPageScrollDown; } + bind "u" { HalfPageScrollUp; } + // uncomment this and adjust key if using copy_on_select=false + // bind "Alt c" { Copy; } + } + search { + bind "Ctrl s" { SwitchToMode "Normal"; } + bind "Ctrl c" { ScrollToBottom; SwitchToMode "Normal"; } + bind "j" "Down" { ScrollDown; } + bind "k" "Up" { ScrollUp; } + bind "Ctrl f" "PageDown" "Right" "l" { PageScrollDown; } + bind "Ctrl b" "PageUp" "Left" "h" { PageScrollUp; } + bind "d" { HalfPageScrollDown; } + bind "u" { HalfPageScrollUp; } + bind "n" { Search "down"; } + bind "p" { Search "up"; } + bind "c" { SearchToggleOption "CaseSensitivity"; } + bind "w" { SearchToggleOption "Wrap"; } + bind "o" { SearchToggleOption "WholeWord"; } + } + entersearch { + bind "Ctrl c" "Esc" { SwitchToMode "Scroll"; } + bind "Enter" { SwitchToMode "Search"; } + } + renametab { + bind "Ctrl c" { SwitchToMode "Normal"; } + bind "Esc" { UndoRenameTab; SwitchToMode "Tab"; } + } + renamepane { + bind "Ctrl c" { SwitchToMode "Normal"; } + bind "Esc" { UndoRenamePane; SwitchToMode "Pane"; } + } + session { + bind "Ctrl o" { SwitchToMode "Normal"; } + bind "Ctrl s" { SwitchToMode "Scroll"; } + bind "d" { Detach; } + bind "w" { + LaunchOrFocusPlugin "session-manager" { + floating true + move_to_focused_tab true + }; + SwitchToMode "Normal" + } + } + tmux { + bind "[" { SwitchToMode "Scroll"; } + bind "Ctrl b" { Write 2; SwitchToMode "Normal"; } + bind "\"" { NewPane "Down"; SwitchToMode "Normal"; } + bind "%" { NewPane "Right"; SwitchToMode "Normal"; } + bind "z" { ToggleFocusFullscreen; SwitchToMode "Normal"; } + bind "c" { NewTab; SwitchToMode "Normal"; } + bind "," { SwitchToMode "RenameTab"; } + bind "p" { GoToPreviousTab; SwitchToMode "Normal"; } + bind "n" { GoToNextTab; SwitchToMode "Normal"; } + bind "Left" { MoveFocus "Left"; SwitchToMode "Normal"; } + bind "Right" { MoveFocus "Right"; SwitchToMode "Normal"; } + bind "Down" { MoveFocus "Down"; SwitchToMode "Normal"; } + bind "Up" { MoveFocus "Up"; SwitchToMode "Normal"; } + bind "h" { MoveFocus "Left"; SwitchToMode "Normal"; } + bind "l" { MoveFocus "Right"; SwitchToMode "Normal"; } + bind "j" { MoveFocus "Down"; SwitchToMode "Normal"; } + bind "k" { MoveFocus "Up"; SwitchToMode "Normal"; } + bind "o" { FocusNextPane; } + bind "d" { Detach; } + bind "Space" { NextSwapLayout; } + bind "x" { CloseFocus; SwitchToMode "Normal"; } + } + shared_except "locked" { + bind "Ctrl g" { SwitchToMode "Locked"; } + bind "Ctrl q" { Quit; } + bind "Alt n" { NewPane; } + bind "Alt i" { MoveTab "Left"; } + bind "Alt o" { MoveTab "Right"; } + bind "Alt h" "Alt Left" { MoveFocusOrTab "Left"; } + bind "Alt l" "Alt Right" { MoveFocusOrTab "Right"; } + bind "Alt j" "Alt Down" { MoveFocus "Down"; } + bind "Alt k" "Alt Up" { MoveFocus "Up"; } + bind "Alt =" "Alt +" { Resize "Increase"; } + bind "Alt -" { Resize "Decrease"; } + bind "Alt [" { PreviousSwapLayout; } + bind "Alt ]" { NextSwapLayout; } + } + shared_except "normal" "locked" { + bind "Enter" "Esc" { SwitchToMode "Normal"; } + } + shared_except "pane" "locked" { + bind "Ctrl p" { SwitchToMode "Pane"; } + } + shared_except "resize" "locked" { + bind "Ctrl n" { SwitchToMode "Resize"; } + } + shared_except "scroll" "locked" { + bind "Ctrl s" { SwitchToMode "Scroll"; } + } + shared_except "session" "locked" { + bind "Ctrl o" { SwitchToMode "Session"; } + } + shared_except "tab" "locked" { + bind "Ctrl t" { SwitchToMode "Tab"; } + } + shared_except "move" "locked" { + bind "Ctrl h" { SwitchToMode "Move"; } + } + shared_except "tmux" "locked" { + bind "Ctrl b" { SwitchToMode "Tmux"; } + } +} + +plugins { + tab-bar location="zellij:tab-bar" + status-bar location="zellij:status-bar" + strider location="zellij:strider" + compact-bar location="zellij:compact-bar" + session-manager location="zellij:session-manager" + welcome-screen location="zellij:session-manager" { + welcome_screen true + } + filepicker location="zellij:strider" { + cwd "/" + } +} + +// Choose what to do when zellij receives SIGTERM, SIGINT, SIGQUIT or SIGHUP +// eg. when terminal window with an active zellij session is closed +// Options: +// - detach (Default) +// - quit +// +// on_force_close "quit" + +// Send a request for a simplified ui (without arrow fonts) to plugins +// Options: +// - true +// - false (Default) +// +// simplified_ui true + +// Choose the path to the default shell that zellij will use for opening new panes +// Default: $SHELL +// +// default_shell "fish" + +// Choose the path to override cwd that zellij will use for opening new panes +// +// default_cwd "" + +// Toggle between having pane frames around the panes +// Options: +// - true (default) +// - false +// +// pane_frames true + +// Toggle between having Zellij lay out panes according to a predefined set of layouts whenever possible +// Options: +// - true (default) +// - false +// +// auto_layout true + +// Whether sessions should be serialized to the cache folder (including their tabs/panes, cwds and running commands) so that they can later be resurrected +// Options: +// - true (default) +// - false +// +// session_serialization false + +// Whether pane viewports are serialized along with the session, default is false +// Options: +// - true +// - false (default) +// serialize_pane_viewport true + +// Scrollback lines to serialize along with the pane viewport when serializing sessions, 0 +// defaults to the scrollback size. If this number is higher than the scrollback size, it will +// also default to the scrollback size. This does nothing if `serialize_pane_viewport` is not true. +// +// scrollback_lines_to_serialize 10000 + +// Define color themes for Zellij +// For more examples, see: https://github.com/zellij-org/zellij/tree/main/example/themes +// Once these themes are defined, one of them should to be selected in the "theme" section of this file +// +// themes { +// dracula { +// fg 248 248 242 +// bg 40 42 54 +// red 255 85 85 +// green 80 250 123 +// yellow 241 250 140 +// blue 98 114 164 +// magenta 255 121 198 +// orange 255 184 108 +// cyan 139 233 253 +// black 0 0 0 +// white 255 255 255 +// } +// } + +// Choose the theme that is specified in the themes section. +// Default: default +// +// theme "default" + +// The name of the default layout to load on startup +// Default: "default" +// +// default_layout "compact" + +// Choose the mode that zellij uses when starting up. +// Default: normal +// +// default_mode "locked" + +// Toggle enabling the mouse mode. +// On certain configurations, or terminals this could +// potentially interfere with copying text. +// Options: +// - true (default) +// - false +// +// mouse_mode false + +// Configure the scroll back buffer size +// This is the number of lines zellij stores for each pane in the scroll back +// buffer. Excess number of lines are discarded in a FIFO fashion. +// Valid values: positive integers +// Default value: 10000 +// +// scroll_buffer_size 10000 + +// Provide a command to execute when copying text. The text will be piped to +// the stdin of the program to perform the copy. This can be used with +// terminal emulators which do not support the OSC 52 ANSI control sequence +// that will be used by default if this option is not set. +// Examples: +// +// copy_command "xclip -selection clipboard" // x11 +// copy_command "wl-copy" // wayland +// copy_command "pbcopy" // osx + +// Choose the destination for copied text +// Allows using the primary selection buffer (on x11/wayland) instead of the system clipboard. +// Does not apply when using copy_command. +// Options: +// - system (default) +// - primary +// +// copy_clipboard "primary" + +// Enable or disable automatic copy (and clear) of selection when releasing mouse +// Default: true +// +// copy_on_select false + +// Path to the default editor to use to edit pane scrollbuffer +// Default: $EDITOR or $VISUAL +// +// scrollback_editor "/usr/bin/vim" + +// When attaching to an existing session with other users, +// should the session be mirrored (true) +// or should each user have their own cursor (false) +// Default: false +// +// mirror_session true + +// The folder in which Zellij will look for layouts +// +// layout_dir "/path/to/my/layout_dir" + +// The folder in which Zellij will look for themes +// +// theme_dir "/path/to/my/theme_dir" + +// Enable or disable the rendering of styled and colored underlines (undercurl). +// May need to be disabled for certain unsupported terminals +// Default: true +// +// styled_underlines false + +// Enable or disable writing of session metadata to disk (if disabled, other sessions might not know +// metadata info on this session) +// Default: false +// +// disable_session_metadata true diff --git a/tests/modules/wrapper-manager/programs/zellij/default.nix b/tests/modules/wrapper-manager/programs/zellij/default.nix new file mode 100644 index 00000000..7fff7787 --- /dev/null +++ b/tests/modules/wrapper-manager/programs/zellij/default.nix @@ -0,0 +1,3 @@ +{ + basic = ./basic.nix; +} diff --git a/tests/modules/wrapper-manager/sandboxing/boxxy/basic.nix b/tests/modules/wrapper-manager/sandboxing/boxxy/basic.nix new file mode 100644 index 00000000..4b6a2181 --- /dev/null +++ b/tests/modules/wrapper-manager/sandboxing/boxxy/basic.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +{ + build.isBinary = false; + locale.enable = true; + + wrappers.tmux = { + sandboxing.variant = "boxxy"; + sandboxing.wraparound.arg0 = lib.getExe' pkgs.tmux "tmux"; + sandboxing.boxxy.rules = { + "~/.config/tmux/tmux.conf".source = "~/.tmux.conf"; + }; + }; + + wrappers.zellij = { + sandboxing.variant = "boxxy"; + sandboxing.wraparound.arg0 = lib.getExe' pkgs.zellij "zellij"; + sandboxing.boxxy.rules = { + "$XDG_CONFIG_HOME/zellij/hello.kdl".source = "$XDG_CONFIG_HOME/zellij/config.kdl"; + }; + }; +} diff --git a/tests/modules/wrapper-manager/sandboxing/boxxy/default.nix b/tests/modules/wrapper-manager/sandboxing/boxxy/default.nix new file mode 100644 index 00000000..7fff7787 --- /dev/null +++ b/tests/modules/wrapper-manager/sandboxing/boxxy/default.nix @@ -0,0 +1,3 @@ +{ + basic = ./basic.nix; +} diff --git a/tests/modules/wrapper-manager/sandboxing/bubblewrap/basic-app-with-dbus-filter.nix b/tests/modules/wrapper-manager/sandboxing/bubblewrap/basic-app-with-dbus-filter.nix new file mode 100644 index 00000000..de24c2df --- /dev/null +++ b/tests/modules/wrapper-manager/sandboxing/bubblewrap/basic-app-with-dbus-filter.nix @@ -0,0 +1,18 @@ +# Based from the examples from NixPak. +{ config, lib, pkgs, ... }: + +{ + build.isBinary = false; + wrappers.hello = { + sandboxing.variant = "bubblewrap"; + sandboxing.wraparound.arg0 = lib.getExe' pkgs.hello "hello"; + sandboxing.bubblewrap.dbus = { + enable = true; + filter.addresses = { + "org.freedesktop.systemd1".policies.level = "talk"; + "org.gtk.vfs.*".policies.level = "talk"; + "org.gtk.vfs".policies.level = "talk"; + }; + }; + }; +} diff --git a/tests/modules/wrapper-manager/sandboxing/bubblewrap/basic-zellij.nix b/tests/modules/wrapper-manager/sandboxing/bubblewrap/basic-zellij.nix new file mode 100644 index 00000000..c952f98b --- /dev/null +++ b/tests/modules/wrapper-manager/sandboxing/bubblewrap/basic-zellij.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +{ + locale.enable = true; + wrappers.zellij = { + sandboxing.variant = "bubblewrap"; + sandboxing.wraparound.arg0 = lib.getExe' pkgs.zellij "zellij"; + }; + build.extraPassthru.tests = { + zellijWrapperCheck = + let + wrapper = config.build.toplevel; + in pkgs.runCommand { } '' + [ -x ${lib.getExe' wrapper "zellij"} ] && touch $out + + ''; + }; +} diff --git a/tests/modules/wrapper-manager/sandboxing/bubblewrap/default.nix b/tests/modules/wrapper-manager/sandboxing/bubblewrap/default.nix new file mode 100644 index 00000000..7a1f7db4 --- /dev/null +++ b/tests/modules/wrapper-manager/sandboxing/bubblewrap/default.nix @@ -0,0 +1,4 @@ +{ + basic-zellij = ./basic-zellij.nix; + basic-app-with-dbus-filter = ./basic-app-with-dbus-filter.nix; +} diff --git a/tests/utils.nix b/tests/utils.nix new file mode 100644 index 00000000..81601164 --- /dev/null +++ b/tests/utils.nix @@ -0,0 +1,20 @@ +# A set of functions to facilitate testing in the project. +{ pkgs }: + +let + nixpkgsPath = pkgs.path; + nixosLib = import "${nixpkgsPath}/nixos/lib" { }; +in +rec { + # We're not using this to test the hosts configuration (that would be + # atrocious). We're only using this for NixOS modules. + nixosTest = test: + nixosLib.runTest { + imports = [ test ]; + hostPkgs = pkgs; + specialArgs = { + foodogsquaredUtils = import ../lib/utils/nixos.nix { inherit pkgs; }; + foodogsquaredModulesPath = builtins.toString ../modules/nixos; + }; + }; +} diff --git a/treefmt.toml b/treefmt.toml index 639a5837..ea8b335f 100644 --- a/treefmt.toml +++ b/treefmt.toml @@ -1,6 +1,7 @@ [global] excludes = [ "pkgs/firefox-addons/default.nix" + "subprojects" ] [formatter.lua] @@ -8,7 +9,7 @@ command = "stylua" includes = [ "*.lua" ] [formatter.nix] -command = "nixpkgs-fmt" +command = "nixfmt" includes = [ "*.nix" ] [formatter.python]