about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hm/soispha/pkgs/scripts.nix17
-rwxr-xr-xhm/soispha/pkgs/scripts/apps/git-edit-index.sh95
2 files changed, 112 insertions, 0 deletions
diff --git a/hm/soispha/pkgs/scripts.nix b/hm/soispha/pkgs/scripts.nix
index 5bcb82e0..6598880d 100644
--- a/hm/soispha/pkgs/scripts.nix
+++ b/hm/soispha/pkgs/scripts.nix
@@ -105,6 +105,22 @@
     };
   };
 
+  git-edit-index-scr = write_shell {
+    name = "git-edit-index";
+    path = "apps";
+    # This starts neovim, wich might want to shell out
+    keepPath = true;
+    dependencies = builtins.attrValues {
+      inherit
+        (pkgs)
+        git
+        gnused
+        # $EDITOR
+
+        ;
+    };
+  };
+
   hibernate-scr = write_shell {
     name = "hibernate";
     path = "wrappers";
@@ -309,6 +325,7 @@ in [
   con2pdf-scr
   description-scr
   fupdate-scr
+  git-edit-index-scr
   hibernate-scr
   ll-scr
   lock-scr
diff --git a/hm/soispha/pkgs/scripts/apps/git-edit-index.sh b/hm/soispha/pkgs/scripts/apps/git-edit-index.sh
new file mode 100755
index 00000000..368b99dc
--- /dev/null
+++ b/hm/soispha/pkgs/scripts/apps/git-edit-index.sh
@@ -0,0 +1,95 @@
+#!/usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.0.13" . %SHELL_LIBRARY_PATH
+
+# needed for help() and version
+# shellcheck disable=2034
+AUTHORS="Soispha"
+# shellcheck disable=2034
+YEARS="2024"
+# shellcheck disable=2034
+VERSION="1.0.0"
+
+# NAME is from the wrapper
+# shellcheck disable=SC2269
+NAME="$NAME"
+
+help() {
+    cat <<EOF
+Edit a file from the index. This script does not touch the unstaged variant of the file.
+
+Usage:
+    $NAME [OPTIONS] [--] FILES
+
+OPTIONS:
+    --
+                            Ignore all flags after this point.
+
+    --help | -h
+                            Display this help and exit.
+
+    --version | -v
+                            Display version and copyright information and exit.
+ARGUMENTS:
+    FILES := [[ git diff --name-only --cached --diff-filter=AM ]]
+                            The files to edit.
+
+EOF
+}
+
+GIT_DIR="$(git rev-parse --show-toplevel)";
+materialize_file() {
+    git diff --cached "$1" > "$GIT_DIR/.git/EDIT_INDEX_PATCH"
+
+    git add "$1"
+    git restore --staged "$1"
+    cat "$1" > "$GIT_DIR/.git/EDIT_INDEX_FILE"
+    git restore "$1"
+
+    git apply "$GIT_DIR/.git/EDIT_INDEX_PATCH"
+    "$EDITOR" "$1"
+
+    git add "$1"
+    mv "$GIT_DIR/.git/EDIT_INDEX_FILE" "$1"
+}
+
+edit() {
+    files_to_add="$(mktmp)";
+    realpath --relative-to=. "$@" >"$files_to_add";
+
+    index_files="$(mktmp)";
+    git diff --name-only --cached --diff-filter=AM >"$index_files"
+
+    while read -r file; do
+        if grep -q "$file" "$files_to_add"; then
+            sed -i "s|$file||" "$files_to_add";
+            materialize_file "$file";
+        fi
+    done <"$index_files"
+
+    files_to_check="$(mktmp)";
+    clean "$files_to_add" > "$files_to_check"
+    if [ "$(wc -l < "$files_to_check")" -gt 0 ]; then
+        warn "Could not edit every file:"
+        cat "$files_to_add";
+    fi
+}
+
+for arg in "$@"; do
+    case "$arg" in
+        "--help" | "-h")
+            help;
+            ;;
+        "--version" | "-v")
+            version;
+            ;;
+        "--")
+            break;
+        ;;
+    esac
+done
+
+edit "$@"
+
+# vim: ft=sh