Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 225 additions & 0 deletions bash_modules.d/sentinel_git_tui.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#!/usr/bin/env bash
# SENTINEL MODULE
# Name: Git TUI
# ID: sentinel_git_tui
# Version: 0.1.0
# Description: Minimal Git control panel TUI (status, diff, commit, pull, push, log, branches, stash, submodules)
# Requires: git
# Category: vcs

# Prevent double loading
if [[ -n "${_SENTINEL_GIT_TUI_LOADED:-}" ]]; then
return 0
fi
export _SENTINEL_GIT_TUI_LOADED=1

# Optional: if SENTINEL has a registration API, hook into it
if command -v sentinel_register_app >/dev/null 2>&1; then
sentinel_register_app "Git TUI" "sentinel_git_tui_main" "Git / VCS"
fi

_sent_git_color() {
local code="$1"; shift
printf "\033[%sm%s\033[0m" "$code" "$*"
}

_sent_git_header() {
echo
_sent_git_color "1;36" "=== Git TUI :: ${PWD} ==="
echo
}

_sent_git_press_enter() {
echo
read -rp "Press Enter to continue..." _
}

_sent_git_check_repo() {
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
_sent_git_color "1;31" "[!] Not inside a Git repository."
echo
return 1
fi
return 0
}

_sent_git_status() {
_sent_git_header
git status
_sent_git_press_enter
}

_sent_git_diff() {
_sent_git_header
git diff | "${PAGER:-less}"
}

_sent_git_log() {
_sent_git_header
git log --oneline --graph --decorate --all | "${PAGER:-less}"
}

_sent_git_branches() {
_sent_git_header
git branch -a
_sent_git_press_enter
}

_sent_git_checkout() {
_sent_git_header
git branch -a
echo
read -rp "Branch to checkout: " br
[ -z "$br" ] && return 0
git checkout "$br"
_sent_git_press_enter
}

_sent_git_commit() {
_sent_git_header
git status
echo
_sent_git_color "1;33" "Commit all tracked changes (git commit -am)?"
echo
read -rp "Commit message: " msg
[ -z "$msg" ] && return 0
git commit -am "$msg"
_sent_git_press_enter
}

_sent_git_pull() {
_sent_git_header
_sent_git_color "1;33" "Pull from default remote (git pull --ff-only)"
echo
read -rp "Proceed? [y/N]: " ans
case "$ans" in
y|Y) git pull --ff-only ;;
*) echo "Skipped." ;;
esac
_sent_git_press_enter
}

_sent_git_push() {
_sent_git_header
_sent_git_color "1;33" "Push to default remote (git push)"
echo
read -rp "Proceed? [y/N]: " ans
case "$ans" in
y|Y) git push ;;
*) echo "Skipped." ;;
esac
_sent_git_press_enter
}

_sent_git_submodules() {
_sent_git_header
_sent_git_color "1;33" "Update submodules (git submodule update --init --recursive)"
echo
read -rp "Proceed? [y/N]: " ans
case "$ans" in
y|Y) git submodule update --init --recursive ;;
*) echo "Skipped." ;;
esac
_sent_git_press_enter
}

_sent_git_stash_menu() {
while true; do
_sent_git_header
_sent_git_color "1;35" "[Stash menu]"
echo
echo "1) Stash current changes"
echo "2) List stashes"
echo "3) Apply latest stash"
echo "4) Drop latest stash"
echo "b) Back"
echo
read -rp "Choice: " s
case "$s" in
1)
read -rp "Stash message (optional): " sm
if [ -z "$sm" ]; then
git stash
else
git stash push -m "$sm"
fi
_sent_git_press_enter
;;
2)
git stash list
_sent_git_press_enter
;;
3)
git stash apply
_sent_git_press_enter
;;
4)
git stash drop
_sent_git_press_enter
;;
b|B|'')
break
;;
*)
;;
esac
done
}

sentinel_git_tui_main() {
local repo_dir="${1:-$PWD}"

if ! command -v git >/dev/null 2>&1; then
_sent_git_color "1;31" "[!] git is not installed or not in PATH."
echo
return 1
fi

if [ ! -d "$repo_dir/.git" ] && ! (cd "$repo_dir" && git rev-parse --is-inside-work-tree >/dev/null 2>&1); then
_sent_git_color "1;31" "[!] $repo_dir is not a Git repository."
echo
return 1
fi

cd "$repo_dir" || return 1

while true; do
_sent_git_header
_sent_git_check_repo || return 1

_sent_git_color "1;32" "Select an action:"
echo
echo "1) Status"
echo "2) Diff"
echo "3) Commit (all tracked)"
echo "4) Pull"
echo "5) Push"
echo "6) Log (graph)"
echo "7) Branches"
echo "8) Checkout branch"
echo "9) Submodules (init/update recursive)"
echo "s) Stash menu"
echo "q) Quit"
echo
read -rp "Choice: " c
case "$c" in
1) _sent_git_status ;;
2) _sent_git_diff ;;
3) _sent_git_commit ;;
4) _sent_git_pull ;;
5) _sent_git_push ;;
6) _sent_git_log ;;
7) _sent_git_branches ;;
8) _sent_git_checkout ;;
9) _sent_git_submodules ;;
s|S) _sent_git_stash_menu ;;
q|Q|'') break ;;
*) ;;
esac
done
}

# Allow direct invocation if sourced manually
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
sentinel_git_tui_main "$@"
fi
1 change: 1 addition & 0 deletions install