about summary refs log tree commit diff stats
path: root/sys/nixpkgs/pkgs/scripts/source/apps/git-edit-index.sh
blob: 0010718b956c6926ab838dda35834f974525b18f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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:
    --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
        exit 0
        ;;
    "--version" | "-v")
        version
        exit 0
        ;;
    "--")
        end_of_cli_options=true
        ;;
    esac
    [ "$end_of_cli_options" = "true" ] && break
done

edit "$@"

# vim: ft=sh