From 6954e75a5cb5dfa56223919ed337377f2abddf80 Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 14:36:04 +0200 Subject: [PATCH 1/7] pkgs/grow-last-partition-and-filesystem: Automatically move GPT backup header to end of device --- pkgs/grow-last-partition-and-filesystem/default.nix | 1 + .../grow-last-partition-and-filesystem.sh | 3 +++ 2 files changed, 4 insertions(+) diff --git a/pkgs/grow-last-partition-and-filesystem/default.nix b/pkgs/grow-last-partition-and-filesystem/default.nix index 06dac05..2ae2144 100644 --- a/pkgs/grow-last-partition-and-filesystem/default.nix +++ b/pkgs/grow-last-partition-and-filesystem/default.nix @@ -10,6 +10,7 @@ writeShellApplication { text = builtins.readFile ./grow-last-partition-and-filesystem.sh; runtimeInputs = [ e2fsprogs + gptfdisk jq parted ]; diff --git a/pkgs/grow-last-partition-and-filesystem/grow-last-partition-and-filesystem.sh b/pkgs/grow-last-partition-and-filesystem/grow-last-partition-and-filesystem.sh index 864b035..54847c8 100755 --- a/pkgs/grow-last-partition-and-filesystem/grow-last-partition-and-filesystem.sh +++ b/pkgs/grow-last-partition-and-filesystem/grow-last-partition-and-filesystem.sh @@ -11,6 +11,9 @@ fi DEVICE="$1" +echo "Move GTP backup header to end of disk" +sgdisk "${DEVICE}" --move-second-header + PARTITIONDATA="$(parted --script --json --fix "${DEVICE}" print)" PARTNUMBER="$(echo "${PARTITIONDATA}" | jq -r '.disk.partitions | last | .number')" PARTNAME="$(echo "${PARTITIONDATA}" | jq -r '.disk.partitions | last | .name')" From 23629e06623494976347b49ff4c2db7f24336aa8 Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 16:58:15 +0200 Subject: [PATCH 2/7] pkgs/build-support: writePythonScript add runtimeInput option --- pkgs/build-support/writePythonScript.nix | 37 ++++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/pkgs/build-support/writePythonScript.nix b/pkgs/build-support/writePythonScript.nix index c670818..337eb67 100644 --- a/pkgs/build-support/writePythonScript.nix +++ b/pkgs/build-support/writePythonScript.nix @@ -1,6 +1,7 @@ { python3, - writeTextFile, + makeWrapper, + runCommand, lib, }: @@ -9,6 +10,7 @@ text, runtimePackages ? ps: [], pythonPackage ? python3, + runtimeInputs ? [], meta ? {}, passthru ? {}, derivationArgs ? {}, @@ -18,13 +20,17 @@ let pythonWithPackages = pythonPackage.withPackages runtimePackages; -in writeTextFile { - inherit - name - meta - passthru - derivationArgs - ; +in runCommand name ({ + passAsFile = [ "text" ] ++ (derivationArgs.passAsFile or []); + + meta = { + mainProgram = name; + } // meta // (derivationArgs.meta or {}); + + passthru = passthru // (derivationArgs.passthru or {}); + + nativeBuildInputs = [ makeWrapper ] ++ (derivationArgs.nativeBuildInputs or []); + executable = true; destination = "/bin/${name}"; allowSubstitutes = true; @@ -34,4 +40,17 @@ in writeTextFile { ${text} ''; -} +} // ( + builtins.removeAttrs derivationArgs [ "passAsFile" "meta" "passthru" "nativeBuildInputs" ] +)) +'' +mkdir -p $out/bin + +target=$out/bin/${lib.escapeShellArg name} + +cp "$textPath" "$target" + +chmod +x "$target" + +wrapProgram "$target" --prefix PATH : "${lib.makeBinPath runtimeInputs}" +'' From ce99bb114ba0aa5b27cbc1847ba616852216ea87 Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 17:06:36 +0200 Subject: [PATCH 3/7] pkgs/convert-flac-dir-to-mp3: Add script for coverting music libraries --- .../convert-flac-dir-to-mp3.py | 96 +++++++++++++++++++ pkgs/convert-flac-dir-to-mp3/default.nix | 8 ++ pkgs/overlay.nix | 1 + 3 files changed, 105 insertions(+) create mode 100644 pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py create mode 100644 pkgs/convert-flac-dir-to-mp3/default.nix diff --git a/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py b/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py new file mode 100644 index 0000000..fd7cc5a --- /dev/null +++ b/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +import argparse +from pathlib import Path +from progress.bar import Bar +import shutil +import subprocess + +def files_and_dirs_for_directory(path): + filepaths = [] + dirpaths = [] + + for dirpath, dirnames, filenames in path.walk(): + dirpaths.append(dirpath) + + for filename in filenames: + filepath = dirpath / filename + filepaths.append(filepath) + + return set(filepaths), set(dirpaths) + +def make_paths_relative(paths, relative_to_path): + return set(path.relative_to(relative_to_path) for path in paths) + +def replace_suffix(path, suffix): + return path.with_name(path.stem + suffix) + +def convert_filepath(path): + if path.suffix == ".flac": + return replace_suffix(path, ".mp3") + + return path + +def ffmpeg_flac_to_mp3(in_path, out_path): + print("") + subprocess.run(["ffmpeg", "-hide_banner", "-loglevel", "warning", "-stats", "-i", in_path, "-ab", "320k", "-map_metadata", "0", "-id3v2_version", "3", out_path], check=True) + print("") + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(prog="convert-flac-dir-to-mp3") + parser.add_argument("from_dir", type=Path) + parser.add_argument("to_dir", type=Path) + + args = parser.parse_args() + + from_path = args.from_dir.absolute() + to_path = args.to_dir.absolute() + + if not from_path.exists(): + raise Exception("from_path does not exist") + + if not to_path.exists(): + raise Exception("to_path does not exist") + + if not from_path.is_dir(): + raise Exception("from_path is not a directory") + + if not to_path.is_dir(): + raise Exception("to_path is not a directory") + + print(f"Converting {from_path} to {to_path}…") + + from_filepaths, from_dirpaths = files_and_dirs_for_directory(from_path) + to_filepaths, to_dirpaths = files_and_dirs_for_directory(to_path) + + + relative_from_filepaths = make_paths_relative(from_filepaths, from_path) + relative_to_filepaths = make_paths_relative(to_filepaths, to_path) + + converted_from_filepaths = set(convert_filepath(filepath) for filepath in relative_from_filepaths) + + filepaths_missing_in_to_path = converted_from_filepaths - relative_to_filepaths + + + relative_from_dirpaths = make_paths_relative(from_dirpaths, from_path) + relative_to_dirpaths = make_paths_relative(to_dirpaths, to_path) + + dirpaths_missing_in_to_path = relative_from_dirpaths - relative_to_dirpaths + + print(f"Missing {len(filepaths_missing_in_to_path)} files and {len(dirpaths_missing_in_to_path)} directories") + + if len(dirpaths_missing_in_to_path) > 0: + for dirpath in Bar("Creating directories").iter(dirpaths_missing_in_to_path): + (to_path / dirpath).mkdir(parents=True, exist_ok=True) + + if len(filepaths_missing_in_to_path) > 0: + for filepath in Bar("Creating files").iter(filepaths_missing_in_to_path): + if filepath in relative_from_filepaths: + # Just copy the file + shutil.copy(from_path / filepath, to_path / filepath) + elif filepath.suffix == ".mp3" and replace_suffix(filepath, ".flac") in relative_from_filepaths: + # Convert from flac + ffmpeg_flac_to_mp3(from_path / replace_suffix(filepath, ".flac"), to_path / filepath) + else: + raise Exception("Unable to figure out how to get {to_path / filepath} from {from_path}") diff --git a/pkgs/convert-flac-dir-to-mp3/default.nix b/pkgs/convert-flac-dir-to-mp3/default.nix new file mode 100644 index 0000000..05f4a83 --- /dev/null +++ b/pkgs/convert-flac-dir-to-mp3/default.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: + +pkgs.clerie-build-support.writePythonScript { + name = "convert-flac-dir-to-mp3"; + runtimePackages = ps: with ps; [ progress ]; + runtimeInputs = [ pkgs.ffmpeg-headless ]; + text = builtins.readFile ./convert-flac-dir-to-mp3.py; +} diff --git a/pkgs/overlay.nix b/pkgs/overlay.nix index 1e67ae0..aa4cd40 100644 --- a/pkgs/overlay.nix +++ b/pkgs/overlay.nix @@ -12,6 +12,7 @@ final: prev: { clerie-sops-edit = final.callPackage ./clerie-sops/clerie-sops-edit.nix {}; clerie-update-nixfiles = final.callPackage ./clerie-update-nixfiles/clerie-update-nixfiles.nix {}; chromium-incognito = final.callPackage ./chromium-incognito {}; + convert-flac-dir-to-mp3 = final.callPackage ./convert-flac-dir-to-mp3 {}; curl-timings = final.callPackage ./curl-timings {}; factorio-launcher = final.callPackage ./factorio-launcher {}; feeds-dir = final.callPackage ./feeds-dir {}; From 165839be0735ad356a773c85f6f2615ac4106a8c Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 17:18:08 +0200 Subject: [PATCH 4/7] pkgs/convert-flac-dir-to-mp3: Use tmpfile for ffmpeg so we don't have broken files laying around --- .../convert-flac-dir-to-mp3.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py b/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py index fd7cc5a..3fab28a 100644 --- a/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py +++ b/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py @@ -91,6 +91,19 @@ if __name__ == "__main__": shutil.copy(from_path / filepath, to_path / filepath) elif filepath.suffix == ".mp3" and replace_suffix(filepath, ".flac") in relative_from_filepaths: # Convert from flac - ffmpeg_flac_to_mp3(from_path / replace_suffix(filepath, ".flac"), to_path / filepath) + print("") + print(f"Converting {to_path / filepath}…") + + # Tempfile for ffmpeg + tmpfilepath = filepath.with_name(".~" + filepath.name) + (to_path / tmpfilepath).unlink(missing_ok=True) + + print(f"Using tempfile for ffmpeg {to_path / tmpfilepath}…") + + # Convert + ffmpeg_flac_to_mp3(from_path / replace_suffix(filepath, ".flac"), to_path / tmpfilepath) + + # Rename tempfile + (to_path / tmpfilepath).rename(to_path / filepath) else: raise Exception("Unable to figure out how to get {to_path / filepath} from {from_path}") From 50b575dcb37ecfea6cbdfa913a53e10b4a6ee8a8 Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 18:01:46 +0200 Subject: [PATCH 5/7] hosts/storage-2: Convert em to mp3 --- hosts/storage-2/em.nix | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hosts/storage-2/em.nix b/hosts/storage-2/em.nix index d08affa..1091c69 100644 --- a/hosts/storage-2/em.nix +++ b/hosts/storage-2/em.nix @@ -11,7 +11,28 @@ with lib; }; users.groups.data-em = {}; + users.users.data-em-mp3 = { + group = "data-em-mp3"; + home = "/data/em-mp3"; + useDefaultShell = true; + isSystemUser = true; + }; + users.groups.data-em-mp3 = {}; + systemd.tmpfiles.rules = [ "d /data/em - data-em data-em - -" + "d /data/em-mp3 - data-em-mp3 data-em-mp3 - -" ]; + + systemd.services.convert-flac-dir-to-mp3 = { + serviceConfig = { + Type = "oneshot"; + ExecStart = "${lib.getExe pkgs.convert-flac-dir-to-mp3} /data/em /data/em-mp3"; + StateDirectory = "convert-flac-dir-to-mp3"; + WorkingDirectory = "/var/lib/convert-flac-dir-to-mp3"; + User = "data-em-mp3"; + Group = "data-em-mp3"; + }; + startAt = "*-*-* 03:47:00"; + }; } From 9659885079b9f85156a06c1955cc46e8c729ef6b Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 18:02:14 +0200 Subject: [PATCH 6/7] pkgs/grow-last-partition-and-filesystem: Add missing dependency reference --- pkgs/grow-last-partition-and-filesystem/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/grow-last-partition-and-filesystem/default.nix b/pkgs/grow-last-partition-and-filesystem/default.nix index 2ae2144..4075609 100644 --- a/pkgs/grow-last-partition-and-filesystem/default.nix +++ b/pkgs/grow-last-partition-and-filesystem/default.nix @@ -1,5 +1,6 @@ { e2fsprogs, + gptfdisk, jq, parted, writeShellApplication, From 6015026d4f27edbec2a3969d02220dbf97dcdd87 Mon Sep 17 00:00:00 2001 From: Flake Update Bot Date: Mon, 22 Sep 2025 03:04:17 +0200 Subject: [PATCH 7/7] Update nixpkgs 2025-09-22-01-03 --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 73832b0..80cbaea 100644 --- a/flake.lock +++ b/flake.lock @@ -666,11 +666,11 @@ }, "nixpkgs_5": { "locked": { - "lastModified": 1753549186, - "narHash": "sha256-Znl7rzuxKg/Mdm6AhimcKynM7V3YeNDIcLjBuoBcmNs=", + "lastModified": 1758277210, + "narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "17f6bd177404d6d43017595c5264756764444ab8", + "rev": "8eaee110344796db060382e15d3af0a9fc396e0e", "type": "github" }, "original": {