├── .gitignore ├── modules └── default.nix ├── overlays └── default.nix ├── lib └── default.nix ├── .github ├── dependabot.yml └── workflows │ └── build.yml ├── pkgs ├── nix-verify │ ├── default.nix │ └── nix-verify ├── gpg-clean-up │ ├── default.nix │ └── gpg-clean-up ├── chroot-enter │ ├── default.nix │ ├── chroot-enter.sh │ └── os-enter.sh ├── nixify │ ├── default.nix │ ├── shell.nix │ ├── nixify │ └── envrc ├── download-archiver │ ├── default.nix │ └── download-archiver.rb ├── ls-colors │ └── default.nix ├── shrinkpdf │ └── default.nix ├── rbrowser │ ├── default.nix │ └── bin │ │ └── rbrowser └── swm │ └── default.nix ├── overlay.nix ├── flake.lock ├── flake.nix ├── LICENSE ├── default.nix ├── ci.nix └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | result-* 3 | 4 | -------------------------------------------------------------------------------- /modules/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | # Add your NixOS modules here 3 | # 4 | # my-module = ./my-module; 5 | } 6 | -------------------------------------------------------------------------------- /overlays/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | # Add your overlays here 3 | # 4 | # my-overlay = import ./my-overlay; 5 | } 6 | -------------------------------------------------------------------------------- /lib/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: 2 | 3 | with pkgs.lib; { 4 | # Add your library functions here 5 | # 6 | # hexint = x: hexvals.${toLower x}; 7 | } 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /pkgs/nix-verify/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv }: 2 | 3 | stdenv.mkDerivation rec { 4 | name = "nix-verify"; 5 | 6 | src = ./.; 7 | 8 | phases = [ "installPhase" "fixupPhase" ]; 9 | 10 | installPhase = '' 11 | install -Dm755 $src/nix-verify $out/bin/nix-verify 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /pkgs/gpg-clean-up/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv }: 2 | 3 | stdenv.mkDerivation rec { 4 | name = "gpg-clean-up-${version}"; 5 | version = "0.0.1"; 6 | src = ./.; 7 | phases = [ "installPhase" "fixupPhase" ]; 8 | installPhase = '' 9 | install -Dm755 $src/gpg-clean-up $out/bin/gpg-clean-up 10 | ''; 11 | } 12 | -------------------------------------------------------------------------------- /pkgs/chroot-enter/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv }: 2 | 3 | stdenv.mkDerivation rec { 4 | name = "chroot-enter-${version}"; 5 | version = "0.0.1"; 6 | 7 | src = ./.; 8 | 9 | installPhase = '' 10 | install -Dm755 $src/chroot-enter.sh $out/bin/chroot-enter 11 | install -Dm755 $src/os-enter.sh $out/bin/os-enter 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /pkgs/nix-verify/nix-verify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | PS4="$ " 5 | set -x 6 | # Destroys most of the environment to reduce 7 | # risks of oopsies coming from overlays or system nixpkgs. 8 | # Enables unfree only as a convenience. 9 | exec env -i \ 10 | NIXPKGS_ALLOW_UNFREE=1 \ 11 | nix-build "$@" 12 | -------------------------------------------------------------------------------- /pkgs/chroot-enter/chroot-enter.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | mountPoint=/mnt 6 | 7 | args=("$@") 8 | for i in $(seq 0 $#); do 9 | case "${args[$i]}" in 10 | --root) 11 | mountPoint="$1" 12 | esac 13 | done 14 | 15 | 16 | if [[ -e $mountPoint/etc/NIXOS ]]; then 17 | exec nixos-enter "$@" 18 | else 19 | exec os-enter "$@" 20 | fi 21 | -------------------------------------------------------------------------------- /pkgs/nixify/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv }: 2 | 3 | stdenv.mkDerivation rec { 4 | name = "nixify"; 5 | version = "1.0.1"; 6 | src = ./.; 7 | 8 | installPhase = '' 9 | install -Dm755 $src/nixify $out/bin/nixify 10 | install -Dm644 $src/envrc $out/share/nixify/templates/envrc 11 | install -Dm644 $src/shell.nix $out/share/nixify/templates/shell.nix 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /pkgs/download-archiver/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, stdenv }: 2 | 3 | 4 | stdenv.mkDerivation rec { 5 | name = "download-archiver-${version}"; 6 | version = "0.0.1"; 7 | 8 | src = ./.; 9 | 10 | phases = [ "installPhase" "fixupPhase" ]; 11 | 12 | installPhase = '' 13 | install -Dm755 $src/download-archiver.rb $out/bin/download-archiver 14 | 15 | substituteInPlace $out/bin/download-archiver \ 16 | --subst-var-by ruby_bin ${pkgs.ruby}/bin/ruby 17 | ''; 18 | } 19 | -------------------------------------------------------------------------------- /overlay.nix: -------------------------------------------------------------------------------- 1 | # You can use this file as a nixpkgs overlay. This is useful in the 2 | # case where you don't want to add the whole NUR namespace to your 3 | # configuration. 4 | 5 | self: super: 6 | let 7 | isReserved = n: n == "lib" || n == "overlays" || n == "modules"; 8 | nameValuePair = n: v: { name = n; value = v; }; 9 | nurAttrs = import ./default.nix { pkgs = super; }; 10 | 11 | in 12 | builtins.listToAttrs 13 | (map (n: nameValuePair n nurAttrs.${n}) 14 | (builtins.filter (n: !isReserved n) 15 | (builtins.attrNames nurAttrs))) 16 | -------------------------------------------------------------------------------- /pkgs/nixify/shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | # Look here for information about how to generate `nixpkgs-version.json`. 3 | # → https://nixos.wiki/wiki/FAQ/Pinning_Nixpkgs 4 | pinnedVersion = builtins.fromJSON (builtins.readFile ./.nixpkgs-version.json); 5 | pinnedPkgs = import 6 | (builtins.fetchGit { 7 | inherit (pinnedVersion) url rev; 8 | 9 | ref = "{{ref}}"; 10 | }) 11 | { }; 12 | in 13 | 14 | # This allows overriding pkgs by passing `--arg pkgs ...` 15 | { pkgs ? pinnedPkgs }: 16 | 17 | with pkgs; 18 | 19 | mkShell { 20 | buildInputs = [ 21 | # put packages here. 22 | ]; 23 | } 24 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1712449641, 6 | "narHash": "sha256-U9DDWMexN6o5Td2DznEgguh8TRIUnIl9levmit43GcI=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "600b15aea1b36eeb43833a50b0e96579147099ff", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "nixpkgs-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "My personal NUR repository"; 3 | inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | outputs = { self, nixpkgs }: 5 | let 6 | systems = [ 7 | "x86_64-linux" 8 | "i686-linux" 9 | "x86_64-darwin" 10 | "aarch64-linux" 11 | "armv6l-linux" 12 | "armv7l-linux" 13 | ]; 14 | forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); 15 | in 16 | { 17 | legacyPackages = forAllSystems (system: import ./default.nix { 18 | pkgs = import nixpkgs { inherit system; }; 19 | }); 20 | packages = forAllSystems (system: nixpkgs.lib.filterAttrs (_: v: nixpkgs.lib.isDerivation v) self.legacyPackages.${system}); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /pkgs/nixify/nixify: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env nix-shell 2 | #! nix-shell -i bash -p nix-prefetch-git 3 | 4 | # vim:ft=sh: 5 | 6 | set -euo pipefail 7 | 8 | if [[ "${#}" -lt 1 ]]; then 9 | echo "USAGE: nixify [rev]" 10 | echo "Path must exist and must be a directory" 11 | echo "You can optionally provide the rev of nixpkgs-channels, defaults to refs/heads/nixos-unstable" 12 | exit 1 13 | fi 14 | 15 | if [[ ! -d "${1}" ]]; then 16 | echo "ERR: ${1} is not directory" 17 | exit 1 18 | fi 19 | 20 | readonly here="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)" 21 | readonly template_dir="$(cd "${here}/../share/nixify/templates" && pwd)" 22 | readonly location="$(cd "${1}" && pwd)" 23 | readonly ref="${2:-refs/heads/nixos-unstable}" 24 | 25 | cp "${template_dir}/envrc" "${location}/.envrc" 26 | cp "${template_dir}/shell.nix" "${location}/shell.nix" 27 | sed -e "s:{{ref}}:$(basename ${ref}):g" -i "${location}/shell.nix" 28 | 29 | nix-prefetch-git https://github.com/NixOS/nixpkgs-channels.git "${ref}" > "${location}/.nixpkgs-version.json" 30 | 31 | chmod 644 ${location}/{.envrc,shell.nix,.nixpkgs-version.json} 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Francesco Gazzetta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | # This file describes your repository contents. 2 | # It should return a set of nix derivations 3 | # and optionally the special attributes `lib`, `modules` and `overlays`. 4 | # It should NOT import . Instead, you should take pkgs as an argument. 5 | # Having pkgs default to is fine though, and it lets you use short 6 | # commands such as: 7 | # nix-build -A mypackage 8 | 9 | { pkgs ? import { } }: 10 | 11 | { 12 | # The `lib`, `modules`, and `overlays` names are special 13 | lib = import ./lib { inherit pkgs; }; # functions 14 | modules = import ./modules; # NixOS modules 15 | overlays = import ./overlays; # nixpkgs overlays 16 | 17 | chroot-enter = pkgs.callPackage ./pkgs/chroot-enter { }; 18 | download-archiver = pkgs.callPackage ./pkgs/download-archiver { }; 19 | gpg-clean-up = pkgs.callPackage ./pkgs/gpg-clean-up { }; 20 | ls-colors = pkgs.callPackage ./pkgs/ls-colors { }; 21 | nix-verify = pkgs.callPackage ./pkgs/nix-verify { }; 22 | nixify = pkgs.callPackage ./pkgs/nixify { }; 23 | rbrowser = pkgs.callPackage ./pkgs/rbrowser { }; 24 | shrinkpdf = pkgs.callPackage ./pkgs/shrinkpdf { }; 25 | swm = pkgs.callPackage ./pkgs/swm { }; 26 | 27 | # some-qt5-package = pkgs.libsForQt5.callPackage ./pkgs/some-qt5-package { }; 28 | # ... 29 | } 30 | -------------------------------------------------------------------------------- /pkgs/gpg-clean-up/gpg-clean-up: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | set -e 3 | 4 | # 5 | # Credit to [Warren 6 | # Lavallee](https://superuser.com/users/403968/warren-lavallee) for this script 7 | # https://superuser.com/questions/594116/clean-up-my-gnupg-keyring/859739#859739 8 | 9 | # 10 | # Clean up the GPG Keyring. Keep it tidy. 11 | # blog.lavall.ee 12 | 13 | echo -n "Expired Keys: " 14 | for expiredKey in $(gpg2 --list-keys | awk '/^pub.* \[expired\: / {id=$2; sub(/^.*\//, "", id); print id}' | fmt -w 999 ); do 15 | echo -n "$expiredKey" 16 | gpg2 --batch --quiet --delete-keys $expiredKey >/dev/null 2>&1 17 | if [ $? -eq 0 ]; then 18 | echo -n "(OK), " 19 | else 20 | echo -n "(FAIL), " 21 | fi 22 | done 23 | echo done. 24 | 25 | echo -n "Update Keys: " 26 | for keyid in $(gpg -k | grep ^pub | grep -v expired: | grep -v revoked: | cut -d/ -f2 | cut -d' ' -f1); do 27 | echo -n "$keyid" 28 | gpg2 --batch --quiet --edit-key "$keyid" check clean cross-certify save quit > /dev/null 2>&1 29 | if [ $? -eq 0 ]; then 30 | echo -n "(OK), " 31 | else 32 | echo -n "(FAIL), " 33 | fi 34 | done 35 | echo done. 36 | 37 | gpg2 --batch --quiet --refresh-keys > /dev/null 2>&1 38 | if [ $? -eq 0 ]; then 39 | echo "Refresh OK" 40 | else 41 | echo "Refresh FAIL." 42 | fi 43 | -------------------------------------------------------------------------------- /pkgs/ls-colors/default.nix: -------------------------------------------------------------------------------- 1 | { stdenvNoCC, fetchFromGitHub, lib }: 2 | 3 | stdenvNoCC.mkDerivation rec { 4 | pname = "lscolors-unstable"; 5 | version = "2021-07-27"; 6 | 7 | src = fetchFromGitHub { 8 | owner = "trapd00r"; 9 | repo = "LS_COLORS"; 10 | rev = "2957904dbd4156b7980e3450233f811073132023"; 11 | sha256 = "sha256-46UR3lKOAoMdcIolVzyqMyGs+Q2DXeq7xUubTLxS3/I="; 12 | }; 13 | 14 | buildPhase = '' 15 | dircolors -b $src/LS_COLORS > bourne-shell.sh 16 | dircolors -c $src/LS_COLORS > c-shell.sh 17 | ''; 18 | 19 | installPhase = '' 20 | mkdir -p $out/ls-colors 21 | mv bourne-shell.sh c-shell.sh $out/ls-colors/ 22 | ''; 23 | 24 | meta = { 25 | description = "A collection of LS_COLORS definitions; needs your contribution!"; 26 | longDescription = '' 27 | This is a collection of extension:color mappings, suitable to use as your 28 | LS_COLORS environment variable. Most of them use the extended color map, 29 | described in the ECMA-48 document; in other words, you'll need a terminal 30 | with capabilities of displaying 256 colors. 31 | ''; 32 | homepage = https://github.com/trapd00r/LS_COLORS; 33 | license = lib.licenses.artistic1; 34 | platforms = lib.platforms.all; 35 | maintainers = [ lib.maintainers.kalbasit ]; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /pkgs/shrinkpdf/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, stdenv, fetchurl }: 2 | 3 | stdenv.mkDerivation rec { 4 | name = "shrinkpdf-${version}"; 5 | version = "0.0.1"; 6 | src = fetchurl { 7 | url = "https://web.archive.org/web/20180730010407/http://www.alfredklomp.com/programming/shrinkpdf/shrinkpdf.sh"; 8 | sha256 = "1iycn5l37m2ymyh3fs9x3gdrfdb45x7mah28f24c1r0wx13kwcdz"; 9 | }; 10 | 11 | preferLocalBuild = true; 12 | 13 | unpackPhase = "true"; 14 | 15 | installPhase = '' 16 | install -Dm755 $src $out/bin/shrinkpdf 17 | substituteInPlace $out/bin/shrinkpdf \ 18 | --replace gs ${pkgs.ghostscript}/bin/gs 19 | ''; 20 | 21 | meta = with lib; { 22 | description = "shrink PDF files with Ghostscript"; 23 | longDescription = '' 24 | A simple wrapper around Ghostscript to shrink PDFs (as in reduce 25 | filesize) under Linux. Inspired by some code I found in an OpenOffice 26 | Python script (I think). The script feeds a PDF through Ghostscript, 27 | which performs lossy recompression by such methods as downsampling the 28 | images to 72dpi. The result should be (but not always is) a much smaller 29 | file. 30 | ''; 31 | homepage = http://www.alfredklomp.com/programming/shrinkpdf/; 32 | license = licenses.bsd3; 33 | platforms = platforms.all; 34 | maintainers = with maintainers; [ kalbasit ]; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /pkgs/rbrowser/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, pkgs, makeDesktopItem }: 2 | 3 | let 4 | desktopItem = makeDesktopItem { 5 | categories = [ 6 | "GTK" 7 | "Network" 8 | "WebBrowser" 9 | ]; 10 | desktopName = "Relay Browser"; 11 | exec = "rbrowser %U"; 12 | genericName = "Web Browser"; 13 | icon = "chromium"; 14 | mimeTypes = [ 15 | "application/xhtml+xml" 16 | "text/html" 17 | "text/mml" 18 | "text/xml" 19 | "x-scheme-handler/about" 20 | "x-scheme-handler/http" 21 | "x-scheme-handler/https" 22 | "x-scheme-handler/unknown" 23 | ]; 24 | name = "rbrowser"; 25 | }; 26 | 27 | in 28 | stdenv.mkDerivation rec { 29 | name = "rbrowser"; 30 | 31 | phases = [ "installPhase" "fixupPhase" ]; 32 | 33 | preferLocalBuild = true; 34 | 35 | src = ./.; 36 | 37 | installPhase = '' 38 | install -D -m755 $src/bin/rbrowser $out/bin/rbrowser 39 | substituteInPlace $out/bin/rbrowser \ 40 | --subst-var-by chromium_bin ${pkgs.chromium}/bin/chromium \ 41 | --subst-var-by firefox_bin ${pkgs.firefox}/bin/firefox \ 42 | --subst-var-by brave_bin ${pkgs.brave}/bin/brave \ 43 | --subst-var-by rofi_bin ${pkgs.rofi}/bin/rofi \ 44 | --subst-var-by zsh_bin ${pkgs.zsh}/bin/zsh 45 | 46 | install -dm755 $out/share/applications 47 | ln -s ${desktopItem}/share/applications/* $out/share/applications/ 48 | ''; 49 | } 50 | -------------------------------------------------------------------------------- /pkgs/swm/default.nix: -------------------------------------------------------------------------------- 1 | { buildGoModule 2 | , fetchFromGitHub 3 | , fzf 4 | , git 5 | , installShellFiles 6 | , lib 7 | , tmux 8 | , procps 9 | }: 10 | 11 | buildGoModule rec { 12 | pname = "swm"; 13 | version = "0.4.0-alpha6"; 14 | 15 | src = fetchFromGitHub { 16 | owner = "kalbasit"; 17 | repo = "swm"; 18 | rev = "v${version}"; 19 | sha256 = "sha256-eFPr8tdKhyITQcogiEeP3BYtEKDjy55MSle80xjmFQA="; 20 | }; 21 | 22 | vendorHash = null; 23 | 24 | ldflags = [ "-X=github.com/kalbasit/swm/cmd.version=${version}" ]; 25 | 26 | nativeBuildInputs = [ fzf git tmux procps installShellFiles ]; 27 | 28 | postInstall = '' 29 | for shell in bash zsh fish; do 30 | $out/bin/swm auto-complete $shell > swm.$shell 31 | installShellCompletion swm.$shell 32 | done 33 | 34 | $out/bin/swm gen-doc man --path ./man 35 | installManPage man/*.7 36 | ''; 37 | 38 | doCheck = true; 39 | preCheck = '' 40 | export HOME=$NIX_BUILD_TOP/home 41 | mkdir -p $HOME 42 | 43 | git config --global user.email "nix-test@example.com" 44 | git config --global user.name "Nix Test" 45 | ''; 46 | 47 | meta = with lib; { 48 | homepage = "https://github.com/kalbasit/swm"; 49 | description = "swm (Story-based Workflow Manager) is a Tmux session manager specifically designed for Story-based development workflow"; 50 | license = licenses.mit; 51 | maintainers = [ maintainers.kalbasit ]; 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /pkgs/chroot-enter/os-enter.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | # Re-exec ourselves in a private mount namespace so that our bind 6 | # mounts get cleaned up automatically. 7 | if [ -z "$OS_ENTER_REEXEC" ]; then 8 | export OS_ENTER_REEXEC=1 9 | if [ "$(id -u)" != 0 ]; then 10 | extraFlags="-r" 11 | fi 12 | exec unshare --fork --mount --uts --mount-proc --pid $extraFlags -- "$0" "$@" 13 | else 14 | mount --make-rprivate / 15 | fi 16 | 17 | mountPoint=/mnt 18 | 19 | while [ "$#" -gt 0 ]; do 20 | i="$1"; shift 1 21 | case "$i" in 22 | --root) 23 | mountPoint="$1"; shift 1 24 | ;; 25 | --help) 26 | exec man nixos-enter 27 | exit 1 28 | ;; 29 | --command|-c) 30 | command=("$@") 31 | shift 1 32 | ;; 33 | --) 34 | command=("$@") 35 | break 36 | ;; 37 | *) 38 | echo "$0: unknown option \`$i'" 39 | exit 1 40 | ;; 41 | esac 42 | done 43 | 44 | if [[ -z "${command}" ]]; then 45 | if [[ -x "${mountPoint}/bin/bash" ]]; then 46 | command=("/bin/bash") 47 | elif [[ -x "${mountPoint}/usr/bin/bash" ]]; then 48 | command=("/usr/bin/bash") 49 | else 50 | echo "ERR: cannot find bash!" 51 | exit 1 52 | fi 53 | 54 | command=(${command[@]} "--login") 55 | fi 56 | 57 | mkdir -m 0755 -p "$mountPoint/proc" "$mountPoint/dev" "$mountPoint/sys" 58 | mount --rbind /proc "$mountPoint/proc" 59 | mount --rbind /dev "$mountPoint/dev" 60 | mount --rbind /sys "$mountPoint/sys" 61 | mount --rbind /etc/resolv.conf "$mountPoint/etc/resolv.conf" 62 | 63 | exec chroot "$mountPoint" "${command[@]}" 64 | -------------------------------------------------------------------------------- /ci.nix: -------------------------------------------------------------------------------- 1 | # This file provides all the buildable and cacheable packages and 2 | # package outputs in your package set. These are what gets built by CI, 3 | # so if you correctly mark packages as 4 | # 5 | # - broken (using `meta.broken`), 6 | # - unfree (using `meta.license.free`), and 7 | # - locally built (using `preferLocalBuild`) 8 | # 9 | # then your CI will be able to build and cache only those packages for 10 | # which this is possible. 11 | 12 | { pkgs ? import { } }: 13 | 14 | with builtins; 15 | let 16 | isReserved = n: n == "lib" || n == "overlays" || n == "modules"; 17 | isDerivation = p: isAttrs p && p ? type && p.type == "derivation"; 18 | isBuildable = p: !(p.meta.broken or false) && p.meta.license.free or true; 19 | isCacheable = p: !(p.preferLocalBuild or false); 20 | shouldRecurseForDerivations = p: isAttrs p && p.recurseForDerivations or false; 21 | 22 | nameValuePair = n: v: { name = n; value = v; }; 23 | 24 | concatMap = builtins.concatMap or (f: xs: concatLists (map f xs)); 25 | 26 | flattenPkgs = s: 27 | let 28 | f = p: 29 | if shouldRecurseForDerivations p then flattenPkgs p 30 | else if isDerivation p then [ p ] 31 | else [ ]; 32 | in 33 | concatMap f (attrValues s); 34 | 35 | outputsOf = p: map (o: p.${o}) p.outputs; 36 | 37 | nurAttrs = import ./default.nix { inherit pkgs; }; 38 | 39 | nurPkgs = 40 | flattenPkgs 41 | (listToAttrs 42 | (map (n: nameValuePair n nurAttrs.${n}) 43 | (filter (n: !isReserved n) 44 | (attrNames nurAttrs)))); 45 | 46 | in 47 | rec { 48 | buildPkgs = filter isBuildable nurPkgs; 49 | cachePkgs = filter isCacheable buildPkgs; 50 | 51 | buildOutputs = concatMap outputsOf buildPkgs; 52 | cacheOutputs = concatMap outputsOf cachePkgs; 53 | } 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nur-packages-template 2 | 3 | **A template for [NUR](https://github.com/nix-community/NUR) repositories** 4 | 5 | ## Setup 6 | 7 | 1. Click on [Use this template](https://github.com/nix-community/nur-packages-template/generate) to start a repo based on this template. (Do _not_ fork it.) 8 | 2. Add your packages to the [pkgs](./pkgs) directory and to 9 | [default.nix](./default.nix) 10 | * Remember to mark the broken packages as `broken = true;` in the `meta` 11 | attribute, or travis (and consequently caching) will fail! 12 | * Library functions, modules and overlays go in the respective directories 13 | 3. Choose your CI: Depending on your preference you can use github actions (recommended) or [Travis ci](https://travis-ci.com). 14 | - Github actions: Change your NUR repo name and optionally add a cachix name in [.github/workflows/build.yml](./.github/workflows/build.yml) and change the cron timer 15 | to a random value as described in the file 16 | - Travis ci: Change your NUR repo name and optionally your cachix repo name in 17 | [.travis.yml](./.travis.yml). Than enable travis in your repo. You can add a cron job in the repository settings on travis to keep your cachix cache fresh 18 | 5. Change your travis and cachix names on the README template section and delete 19 | the rest 20 | 6. [Add yourself to NUR](https://github.com/nix-community/NUR#how-to-add-your-own-repository) 21 | 22 | ## README template 23 | 24 | # nur-packages 25 | 26 | **My personal [NUR](https://github.com/nix-community/NUR) repository** 27 | 28 | 29 | ![Build and populate cache](https://github.com//nur-packages/workflows/Build%20and%20populate%20cache/badge.svg) 30 | 31 | 36 | [![Cachix Cache](https://img.shields.io/badge/cachix--blue.svg)](https://.cachix.org) 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build and populate cache" 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | # rebuild everyday at 2:51 10 | # TIP: Choose a random time here so not all repositories are build at once: 11 | # https://www.random.org/clock-times/?num=1&earliest=01%3A00&latest=08%3A00&interval=5&format=html&rnd=new 12 | - cron: '51 2 * * *' 13 | jobs: 14 | tests: 15 | strategy: 16 | matrix: 17 | # Set this to notify the global nur package registry that changes are 18 | # available. 19 | # 20 | # The repo name as used in 21 | # https://github.com/nix-community/NUR/blob/master/repos.json 22 | nurRepo: 23 | - kalbasit 24 | # Set this to cache your build results in cachix for faster builds 25 | # in CI and for everyone who uses your cache. 26 | # 27 | # Format: Your cachix cache host name without the ".cachix.org" suffix. 28 | # Example: mycache (for mycache.cachix.org) 29 | # 30 | # For this to work, you also need to set the CACHIX_SIGNING_KEY or 31 | # CACHIX_AUTH_TOKEN secret in your repository secrets settings in 32 | # Github found at 33 | # https://github.com//nur-packages/settings/secrets 34 | cachixName: 35 | - yl 36 | nixPath: 37 | - nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/heads/nixpkgs-unstable.tar.gz 38 | - nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/heads/nixos-unstable.tar.gz 39 | - nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/heads/nixos-24.05.tar.gz 40 | runs-on: ubuntu-latest 41 | steps: 42 | - name: Checkout repository 43 | uses: actions/checkout@v6 44 | - name: Install nix 45 | uses: cachix/install-nix-action@v31 46 | with: 47 | nix_path: "${{ matrix.nixPath }}" 48 | extra_nix_config: | 49 | experimental-features = nix-command flakes 50 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 51 | - name: Show nixpkgs version 52 | run: nix-instantiate --eval -E '(import {}).lib.version' 53 | - name: Setup cachix 54 | uses: cachix/cachix-action@v16 55 | # Don't replace here! 56 | if: ${{ matrix.cachixName != '' }} 57 | with: 58 | name: ${{ matrix.cachixName }} 59 | signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' 60 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 61 | - name: Check evaluation 62 | run: | 63 | nix-env -f . -qa \* --meta --xml \ 64 | --allowed-uris https://static.rust-lang.org \ 65 | --option restrict-eval true \ 66 | --option allow-import-from-derivation true \ 67 | --drv-path --show-trace \ 68 | -I nixpkgs=$(nix-instantiate --find-file nixpkgs) \ 69 | -I $PWD 70 | - name: Build nix packages 71 | run: nix shell -f '' nix-build-uncached -c nix-build-uncached ci.nix -A cacheOutputs 72 | - name: Trigger NUR update 73 | # Don't replace here! 74 | if: ${{ matrix.nurRepo != '' }} 75 | run: curl -XPOST "https://nur-update.nix-community.org/update?repo=${{ matrix.nurRepo }}" 76 | -------------------------------------------------------------------------------- /pkgs/download-archiver/download-archiver.rb: -------------------------------------------------------------------------------- 1 | #! @ruby_bin@ 2 | # 3 | # Copyright (c) 2014-2017 Wael Nasreddine 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | # 23 | 24 | require 'fileutils' 25 | require 'digest/md5' 26 | 27 | class DownloadArchiver 28 | 29 | attr_reader :files 30 | attr_reader :md5_to_files 31 | 32 | def initialize(dir) 33 | @base_dir = dir 34 | _scan_for_files 35 | _hash_files 36 | end 37 | 38 | def remove_duplicates 39 | @md5_to_files.each_value do |v| 40 | if v.size > 1 41 | for i in 1..v.size - 1 42 | @removed_files ||= Array.new 43 | @removed_files << v[i] 44 | FileUtils.rm v[i] 45 | end 46 | end 47 | end 48 | puts "#{@removed_files.size} files were removed" if @removed_files && @removed_files.size > 0 49 | @md5_to_files.clear 50 | # Re-scan the folder to update the internal list of files. 51 | # TODO: remove manually from self to speed it up 52 | _scan_for_files 53 | end 54 | 55 | def archive 56 | _archive_files_by_date 57 | end 58 | 59 | private 60 | 61 | def _scan_for_files 62 | @files = Array.new 63 | @md5_to_files = Hash.new 64 | Dir.glob(@base_dir + File::Separator + '*').each do |f| 65 | if !File.directory? f 66 | @files << f 67 | end 68 | end 69 | end 70 | 71 | def _hash_files 72 | @files.each do |f| 73 | digest = Digest::MD5.hexdigest(File.read f) 74 | @md5_to_files[digest] ||= Array.new 75 | @md5_to_files[digest] << f 76 | end 77 | end 78 | 79 | def _archive_files_by_date 80 | # Register today's date 81 | today = Time.new() 82 | 83 | @files.each do |f| 84 | fh = File.new(f) 85 | if !File.directory?(f) && (fh.mtime.year != today.year || fh.mtime.month != today.month) 86 | f_year_path = @base_dir + File::Separator + fh.mtime.year.to_s 87 | f_month_path = f_year_path + File::Separator + fh.mtime.month.to_s 88 | 89 | FileUtils.mkdir f_year_path if !File::exists?(f_year_path) || !File.directory?(f_year_path) 90 | FileUtils.mkdir f_month_path if !File::exists?(f_month_path) || !File.directory?(f_month_path) 91 | 92 | FileUtils.mv(f, f_month_path + File::Separator + File.basename(f)) 93 | end 94 | end 95 | end 96 | 97 | end 98 | 99 | # Register the base downloads path 100 | downloads_path = ENV['HOME'] + '/Downloads' 101 | 102 | da = DownloadArchiver.new(downloads_path) 103 | da.remove_duplicates 104 | da.archive 105 | -------------------------------------------------------------------------------- /pkgs/rbrowser/bin/rbrowser: -------------------------------------------------------------------------------- 1 | #! @zsh_bin@ 2 | # 3 | # vim:ft=sh: 4 | # 5 | # Copyright (c) 2010-2017 Wael Nasreddine 6 | # 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 | # USA. 21 | # 22 | 23 | set -eo pipefail 24 | 25 | function help() 26 | { 27 | echo -e "USAGE: rbrowser [options] " 28 | echo -e "\t -h, --help - this message" 29 | echo -e "\t -p, --profile - the profile to use" 30 | echo -e "\t -b, --browser - the browser to use. Default: chromium" 31 | } 32 | 33 | chromium="@chromium_bin@" 34 | firefox="@firefox_bin@" 35 | brave="@brave_bin@" 36 | 37 | log_depth="0" 38 | args="" 39 | browser="chromium" 40 | 41 | while [[ $# -ge 1 ]]; do 42 | case "${1}" in 43 | -h|--help) 44 | help 45 | exit 0 46 | ;; 47 | -p|--profile) 48 | profile="${2}" 49 | if [[ -z "${profile}" ]]; then 50 | echo -e "ERR: --profile requires an argument" 51 | help 52 | exit 1 53 | fi 54 | shift 2 55 | ;; 56 | -b|--browser) 57 | browser="${2}" 58 | if [[ -z "${browser}" ]]; then 59 | echo -e "ERR: --browser requires an argument" 60 | help 61 | exit 1 62 | fi 63 | shift 2 64 | ;; 65 | *) 66 | args=( ${@} ) 67 | break 68 | ;; 69 | esac 70 | done 71 | 72 | # the profile paths per browser 73 | BRAVE_PROFILES_PATH="${HOME}/.config/brave/profiles" 74 | CHROMIUM_PROFILES_PATH="${HOME}/.config/chromium/profiles" 75 | FIREFOX_PROFILES_PATH="${HOME}/.mozilla/firefox/profiles" 76 | 77 | # make sure we have both profile and a browser. 78 | if [[ -n "${profile}" ]] && [[ -z "${browser}" ]]; then 79 | echo -e "ERR: the profile was set to ${profile}, but the browser is empty. The browser is required with --profile, aborting..." 80 | exit 1 81 | fi 82 | 83 | if [[ -z "${profile}" ]]; then 84 | items="" 85 | sep="" 86 | if [[ -d "$BRAVE_PROFILES_PATH" ]]; then 87 | for i in $BRAVE_PROFILES_PATH/*; do; 88 | if [[ -d "${i}" ]]; then 89 | items="${items}${sep}brave@$(basename "${i}")" 90 | sep="\n" 91 | fi 92 | done 93 | fi 94 | if [[ -d "$CHROMIUM_PROFILES_PATH" ]]; then 95 | for i in $CHROMIUM_PROFILES_PATH/*; do; 96 | if [[ -d "${i}" ]]; then 97 | items="${items}${sep}chromium@$(basename "${i}")" 98 | sep="\n" 99 | fi 100 | done 101 | fi 102 | if [[ -d "$FIREFOX_PROFILES_PATH" ]]; then 103 | for i in $FIREFOX_PROFILES_PATH/*; do; 104 | if [[ -d "${i}" ]]; then 105 | items="${items}${sep}firefox@$(basename "${i}")" 106 | sep="\n" 107 | fi 108 | done 109 | fi 110 | if [[ -z "${items}" ]]; then 111 | echo -e "No profiles found, please run it with the <-b> and <-p> options to create the first profiles" 112 | exit 1 113 | fi 114 | entry="$(@rofi_bin@ -dmenu < <(echo -e "${items}"))" 115 | browser="$(echo "${entry}" | cut -d@ -f1)" 116 | profile="$(echo "${entry}" | cut -d@ -f2)" 117 | fi 118 | 119 | case "${browser}" in 120 | "brave") 121 | PROFILES_PATH="${BRAVE_PROFILES_PATH}" 122 | ;; 123 | "chromium") 124 | PROFILES_PATH="${CHROMIUM_PROFILES_PATH}" 125 | ;; 126 | "firefox") 127 | PROFILES_PATH="${FIREFOX_PROFILES_PATH}" 128 | ;; 129 | *) 130 | echo -e "ERR: the browser ${browser} is not supported" 131 | exit 1 132 | ;; 133 | esac 134 | 135 | if [[ -z "${profile}" ]]; then 136 | echo -e "ERR: no profile was selected, aborting..." 137 | exit 1 138 | fi 139 | 140 | if [[ ! -d "${PROFILES_PATH}/${profile}" ]]; then 141 | echo -e "WARN: the selected profile does not exists, creating one" 142 | mkdir -p "${PROFILES_PATH}/${profile}" 143 | fi 144 | 145 | if [[ -f "${PROFILES_PATH}/${profile}/.cmdline_args" ]]; then 146 | args=(${args[@]} $(cat "${PROFILES_PATH}/${profile}/.cmdline_args")) 147 | fi 148 | 149 | case "${browser}" in 150 | "brave") 151 | (exec "${brave}" --user-data-dir="${PROFILES_PATH}/${profile}" "${args[@]}" &>/dev/null)& 152 | ;; 153 | "chromium") 154 | (exec "${chromium}" --user-data-dir="${PROFILES_PATH}/${profile}" "${args[@]}" &>/dev/null)& 155 | ;; 156 | "firefox") 157 | (exec "${firefox}" --profile "${PROFILES_PATH}/${profile}" --new-tab "${args[@]}" &>/dev/null)& 158 | ;; 159 | *) 160 | echo -e "ERR: the browser ${browser} is not supported" 161 | exit 1 162 | ;; 163 | esac 164 | -------------------------------------------------------------------------------- /pkgs/nixify/envrc: -------------------------------------------------------------------------------- 1 | # Load environment variables from `nix-shell` and export it out. 2 | # 3 | # Usage: use_nix [-s ] [-w ] [-w ] ... 4 | # -s nix-expression: The nix expression to use for building the shell environment. 5 | # -w path: watch a file for changes. It can be specified multiple times. The 6 | # shell specified with -s is automatically watched. 7 | # 8 | # If no nix-expression were given with -s, it will attempt to find and load 9 | # the shell using the following files in order: shell.nix and default.nix. 10 | # 11 | # Example: 12 | # - use_nix 13 | # - use_nix -s shell.nix -w .nixpkgs-version.json 14 | # 15 | # The dependencies pulled by nix-shell are added to Nix's garbage collector 16 | # roots, such that the environment remains persistent. 17 | # 18 | # Nix-shell is invoked only once per environment, and the output is cached for 19 | # better performance. If any of the watched files change, then the environment 20 | # is rebuilt. 21 | # 22 | # To remove old environments, and allow the GC to collect their dependencies: 23 | # rm -f .direnv 24 | # 25 | use_nix() { 26 | if ! validate_version; then 27 | echo "This .envrc requires direnv version 2.18.2 or above." 28 | exit 1 29 | fi 30 | 31 | # define all local variables 32 | local shell 33 | local files_to_watch=() 34 | 35 | local opt OPTARG OPTIND # define vars used by getopts locally 36 | while getopts ":n:s:w:" opt; do 37 | case "${opt}" in 38 | s) 39 | shell="${OPTARG}" 40 | files_to_watch=("${files_to_watch[@]}" "${shell}") 41 | ;; 42 | w) 43 | files_to_watch=("${files_to_watch[@]}" "${OPTARG}") 44 | ;; 45 | :) 46 | fail "Invalid option: $OPTARG requires an argument" 47 | ;; 48 | \?) 49 | fail "Invalid option: $OPTARG" 50 | ;; 51 | esac 52 | done 53 | shift $((OPTIND -1)) 54 | 55 | if [[ -z "${shell}" ]]; then 56 | if [[ -f shell.nix ]]; then 57 | shell=shell.nix 58 | files_to_watch=("${files_to_watch[@]}" shell.nix) 59 | elif [[ -f default.nix ]]; then 60 | shell=default.nix 61 | files_to_watch=("${files_to_watch[@]}" default.nix) 62 | else 63 | fail "ERR: no shell was given" 64 | fi 65 | fi 66 | 67 | local f 68 | for f in "${files_to_watch[@]}"; do 69 | if ! [[ -f "${f}" ]]; then 70 | fail "cannot watch file ${f} because it does not exist" 71 | fi 72 | done 73 | 74 | # compute the hash of all the files that makes up the development environment 75 | local env_hash="$(hash_contents "${files_to_watch[@]}")" 76 | 77 | # define the paths 78 | local dir="$(direnv_layout_dir)" 79 | local wd="${dir}/wd-${env_hash}" 80 | local drv="${wd}/env.drv" 81 | local dump="${wd}/dump.env" 82 | 83 | # Generate the environment if we do not have one generated already. 84 | if [[ ! -f "${drv}" ]]; then 85 | mkdir -p "${wd}" 86 | 87 | log_status "use nix: deriving new environment" 88 | IN_NIX_SHELL=1 nix-instantiate --add-root "${drv}" --indirect "${shell}" > /dev/null 89 | nix-store -r $(nix-store --query --references "${drv}") --add-root "${wd}/dep" --indirect > /dev/null 90 | if [[ "${?}" -ne 0 ]] || [[ ! -f "${drv}" ]]; then 91 | rm -rf "${wd}" 92 | fail "use nix: was not able to derive the new environment. Please run 'direnv reload' to try again." 93 | fi 94 | 95 | log_status "use nix: updating cache" 96 | nix-shell --pure "${drv}" --show-trace --run "$(join_args "$direnv" dump bash)" > "${dump}" 97 | if [[ "${?}" -ne 0 ]] || [[ ! -f "${dump}" ]] || ! grep -q IN_NIX_SHELL "${dump}"; then 98 | rm -rf "${wd}" 99 | fail "use nix: was not able to update the cache of the environment. Please run 'direnv reload' to try again." 100 | fi 101 | fi 102 | 103 | # evaluate the dump created by nix-shell earlier, but have to merge the PATH 104 | # with the current PATH 105 | # NOTE: we eval the dump here as opposed to direnv_load it because we don't 106 | # want to persist environment variables coming from the shell at the time of 107 | # the dump. See https://github.com/direnv/direnv/issues/405 for context. 108 | local path_backup="${PATH}" 109 | eval $(cat "${dump}") 110 | export PATH="${PATH}:${path_backup}" 111 | 112 | # cleanup the environment of variables that are not requried, or are causing issues. 113 | unset shellHook # when shellHook is present, then any nix-shell'd script will execute it! 114 | 115 | # watch all the files we were asked to watch for the environment 116 | for f in "${files_to_watch[@]}"; do 117 | watch_file "${f}" 118 | done 119 | } 120 | 121 | fail() { 122 | log_error "${@}" 123 | exit 1 124 | } 125 | 126 | hash_contents() { 127 | if has md5sum; then 128 | cat "${@}" | md5sum | cut -c -32 129 | elif has md5; then 130 | cat "${@}" | md5 -q 131 | fi 132 | } 133 | 134 | hash_file() { 135 | if has md5sum; then 136 | md5sum "${@}" | cut -c -32 137 | elif has md5; then 138 | md5 -q "${@}" 139 | fi 140 | } 141 | 142 | validate_version() { 143 | local version="$("${direnv}" version)" 144 | local major="$(echo "${version}" | cut -d. -f1)" 145 | local minor="$(echo "${version}" | cut -d. -f2)" 146 | local patch="$(echo "${version}" | cut -d. -f3)" 147 | 148 | if [[ "${major}" -gt 2 ]]; then return 0; fi 149 | if [[ "${major}" -eq 2 ]] && [[ "${minor}" -gt 18 ]]; then return 0; fi 150 | if [[ "${major}" -eq 2 ]] && [[ "${minor}" -eq 18 ]] && [[ "${patch}" -ge 2 ]]; then return 0; fi 151 | return 1 152 | } 153 | 154 | use_nix -s shell.nix -w .nixpkgs-version.json 155 | --------------------------------------------------------------------------------