From: Shane Jaroch Date: Sat, 17 Jan 2026 01:00:51 +0000 (-0500) Subject: add command to list/stat remote; update completions X-Git-Url: https://git.nutra.tk/v2?a=commitdiff_plain;h=1979747f66ebc40438a0eaba2b3ede5ae8af2490;p=gamesguru%2Fgit-remote-gcrypt.git add command to list/stat remote; update completions --- diff --git a/README.rst b/README.rst index ca4fed9..134d4a4 100644 --- a/README.rst +++ b/README.rst @@ -62,7 +62,7 @@ Command Reference clean [URL|REMOTE] Scan/Clean unencrypted files from remote clean -f, --force Actually delete files (default is scan only) clean -i, --init Scan even if no manifest found (DANGEROUS with --force) - + stat [URL|REMOTE] Show diagnostics (file counts, tracked vs untracked) Git Protocol Commands (for debugging): capabilities List remote helper capabilities list List refs in remote repository diff --git a/completions/bash/git-remote-gcrypt b/completions/bash/git-remote-gcrypt index 3479aa5..a9fe8f1 100644 --- a/completions/bash/git-remote-gcrypt +++ b/completions/bash/git-remote-gcrypt @@ -7,7 +7,7 @@ _git_remote_gcrypt() { cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD - 1]}" opts="-h --help -v --version" - commands="capabilities check clean fetch list push" + commands="check clean stat" # 1. First argument: complete commands and global options if [[ $COMP_CWORD -eq 1 ]]; then @@ -22,10 +22,10 @@ _git_remote_gcrypt() { case "${COMP_WORDS[1]}" in clean) local remotes=$( git remote -v 2>/dev/null | grep 'gcrypt::' | awk '{print $1}' | sort -u || : ) - COMPREPLY=( $( compgen -W " $remotes" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "-f --force -i --init $remotes" -- "$cur" ) ) return 0 ;; - check) + check|stat) local remotes=$( git remote 2>/dev/null || : ) COMPREPLY=( $( compgen -W "$remotes" -- "$cur" ) ) return 0 diff --git a/completions/fish/git-remote-gcrypt.fish b/completions/fish/git-remote-gcrypt.fish index c5441aa..583101a 100644 --- a/completions/fish/git-remote-gcrypt.fish +++ b/completions/fish/git-remote-gcrypt.fish @@ -5,16 +5,14 @@ complete -c git-remote-gcrypt -s h -l help -d 'Show help message' complete -c git-remote-gcrypt -s v -l version -d 'Show version information' # Subcommands -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from capabilities check clean fetch list push" -a 'check' -d 'Check if URL is a gcrypt repository' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from capabilities check clean fetch list push" -a 'clean' -d 'Scan/Clean unencrypted files from remote' +complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from check clean stat" -a 'check' -d 'Check if URL is a gcrypt repository' +complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from check clean stat" -a 'clean' -d 'Scan/Clean unencrypted files from remote' +complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from check clean stat" -a 'stat' -d 'Show diagnostics' complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from clean" -a "(git remote -v 2>/dev/null | grep 'gcrypt::' | awk '{print \$1}' | sort -u)" -d 'Gcrypt Remote' complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from check" -a "(git remote 2>/dev/null)" -d 'Git Remote' +complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from stat" -a "(git remote 2>/dev/null)" -d 'Git Remote' # Clean flags +complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -s f -l force -d 'Flag'; +complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -s i -l init -d 'Flag'; - -# Git protocol commands -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from capabilities check clean fetch list push" -a 'capabilities' -d 'Show git remote helper capabilities' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from capabilities check clean fetch list push" -a 'list' -d 'List refs in remote repository' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from capabilities check clean fetch list push" -a 'push' -d 'Push refs to remote repository' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from capabilities check clean fetch list push" -a 'fetch' -d 'Fetch refs from remote repository' diff --git a/completions/gen_docs.sh b/completions/gen_docs.sh index 85691ff..93b2a92 100755 --- a/completions/gen_docs.sh +++ b/completions/gen_docs.sh @@ -33,12 +33,12 @@ COMMANDS_HELP=$(echo "$RAW_HELP" | sed -n '/^Options:/,$p' | sed 's/^/ /') # 2. Parse Commands and Flags for Completions # Extract command names (first word after 2 spaces) -COMMANDS_LIST=$(echo "$RAW_HELP" | awk '/^ [a-z]+ / {print $1}' | grep -vE "^(help|version)$" | sort | tr '\n' ' ' | sed 's/ $//') +COMMANDS_LIST=$(echo "$RAW_HELP" | awk '/^ [a-z]+ / {print $1}' | grep -vE "^(help|version|capabilities|list|push|fetch)$" | sort | tr '\n' ' ' | sed 's/ $//') # Extract clean flags # Text: " clean -f, --force Actually delete files..." # We want: "-f --force -i --init" for Bash -CLEAN_FLAGS_RAW=$(echo "$RAW_HELP" | grep "^ clean -" | awk -F' ' '{print $2}' | sed 's/,//g') +CLEAN_FLAGS_RAW=$(echo "$RAW_HELP" | grep "^ clean -" | awk '{print $2, $3}' | sed 's/,//g') CLEAN_FLAGS_BASH=$(echo "$CLEAN_FLAGS_RAW" | tr '\n' ' ' | sed 's/ $//') # For Zsh: we want simple list for now as per plan, user asked for dynamic but safe. diff --git a/completions/templates/bash.in b/completions/templates/bash.in index dcfe0cb..dcf66f8 100644 --- a/completions/templates/bash.in +++ b/completions/templates/bash.in @@ -25,7 +25,7 @@ _git_remote_gcrypt() { COMPREPLY=( $( compgen -W "{clean_flags_bash} $remotes" -- "$cur" ) ) return 0 ;; - check) + check|stat) local remotes=$( git remote 2>/dev/null || : ) COMPREPLY=( $( compgen -W "$remotes" -- "$cur" ) ) return 0 diff --git a/completions/templates/fish.in b/completions/templates/fish.in index f8f187c..be8fa0a 100644 --- a/completions/templates/fish.in +++ b/completions/templates/fish.in @@ -7,14 +7,10 @@ complete -c git-remote-gcrypt -s v -l version -d 'Show version information' # Subcommands complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'check' -d 'Check if URL is a gcrypt repository' complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'clean' -d 'Scan/Clean unencrypted files from remote' +complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'stat' -d 'Show diagnostics' complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from clean" -a "(git remote -v 2>/dev/null | grep 'gcrypt::' | awk '{print \$1}' | sort -u)" -d 'Gcrypt Remote' complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from check" -a "(git remote 2>/dev/null)" -d 'Git Remote' +complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from stat" -a "(git remote 2>/dev/null)" -d 'Git Remote' # Clean flags {clean_flags_fish} - -# Git protocol commands -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'capabilities' -d 'Show git remote helper capabilities' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'list' -d 'List refs in remote repository' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'push' -d 'Push refs to remote repository' -complete -c git-remote-gcrypt -f -n "not __fish_seen_subcommand_from {not_sc_list}" -a 'fetch' -d 'Fetch refs from remote repository' diff --git a/completions/templates/zsh.in b/completions/templates/zsh.in index 60641e3..69bac26 100644 --- a/completions/templates/zsh.in +++ b/completions/templates/zsh.in @@ -17,7 +17,7 @@ _git_remote_gcrypt() { _arguments {clean_flags_zsh} \ '*:gcrypt URL: _alternative "remotes:gcrypt remote:($(git remote -v 2>/dev/null | grep "gcrypt::" | awk "{print \$1}" | sort -u))" "files:file:_files"' ;; - check) + check|stat) _arguments \ '*:gcrypt URL: _alternative "remotes:git remote:($(git remote 2>/dev/null))" "files:file:_files"' ;; diff --git a/completions/zsh/_git-remote-gcrypt b/completions/zsh/_git-remote-gcrypt index 14a8400..acda347 100644 --- a/completions/zsh/_git-remote-gcrypt +++ b/completions/zsh/_git-remote-gcrypt @@ -7,17 +7,17 @@ _git_remote_gcrypt() { args=( '(- *)'{-h,--help}'[show help message]' '(- *)'{-v,--version}'[show version information]' - '1:command:(capabilities check clean fetch list push)' + '1:command:(check clean stat)' '*::subcommand arguments:->args' ) _arguments -s -S $args case $line[1] in clean) - _arguments \ + _arguments '(-f --force -i --init)'{-f,--force,-i,--init}'[flag]' \ '*:gcrypt URL: _alternative "remotes:gcrypt remote:($(git remote -v 2>/dev/null | grep "gcrypt::" | awk "{print \$1}" | sort -u))" "files:file:_files"' ;; - check) + check|stat) _arguments \ '*:gcrypt URL: _alternative "remotes:git remote:($(git remote 2>/dev/null))" "files:file:_files"' ;; diff --git a/git-remote-gcrypt b/git-remote-gcrypt index 334c44c..3bc1970 100755 --- a/git-remote-gcrypt +++ b/git-remote-gcrypt @@ -48,7 +48,7 @@ Options: clean [URL|REMOTE] Scan/Clean unencrypted files from remote clean -f, --force Actually delete files (default is scan only) clean -i, --init Scan even if no manifest found (DANGEROUS with --force) - + stat [URL|REMOTE] Show diagnostics (file counts, tracked vs untracked) Git Protocol Commands (for debugging): capabilities List remote helper capabilities list List refs in remote repository @@ -102,6 +102,19 @@ while [ $# -gt 0 ]; do done break # Stop parsing outer loop ;; + stat) + NAME=gcrypt-stat + shift + if [ $# -gt 0 ]; then + if [ -z "$URL" ]; then + URL="$1" + else + echo "Error: Multiple URLs/remotes provided to stat" >&2 + exit 1 + fi + shift + fi + ;; -*) echo "Unknown option: $1" >&2 exit 1 @@ -1510,6 +1523,54 @@ cmd_clean() exit 0 } +cmd_stat() +{ + local remote_files="" file_count=0 tracked_count=0 untracked_count=0 valid_files="" f="" + + if ! ensure_connected; then + echo_die "Could not connect to $URL." + fi + + get_remote_file_list @remote_files || echo_die "Failed to list remote files." + file_count=$(line_count "$remote_files") + if isnull "$remote_files"; then + file_count=0 + fi + + echo "Remote: $URL" + echo "Total files: $file_count" + + if [ "$Did_find_repo" = "yes" ]; then + echo "Gcrypt repository: detected" + echo "Manifest: found" + + # Build whitelist of valid gcrypt files to count tracked + valid_files="$Manifestfile" + for f in $(xecho "$Packlist" | cut -d: -f3 | cut -d' ' -f1); do + valid_files="$valid_files$Newline$f" + done + + tracked_count=0 + for f in $remote_files; do + if xfeed "$valid_files" grep -qxF "$f"; then + tracked_count=$((tracked_count + 1)) + fi + done + untracked_count=$((file_count - tracked_count)) + + echo "Tracked files: $tracked_count" + echo "Untracked files: $untracked_count" + else + echo "Gcrypt repository: not detected (no manifest)" + echo "Tracked files: 0" + echo "Untracked files: $file_count" + fi + + CLEAN_FINAL "$URL" + git remote remove "$NAME" 2>/dev/null || true + exit 0 +} + if [ "$NAME" = "gcrypt-check" ]; then resolve_url check echo_info "Checking remote: $URL" @@ -1526,6 +1587,11 @@ elif [ "$NAME" = "gcrypt-clean" ]; then echo_info "Checking remote: $URL" setup cmd_clean +elif [ "$NAME" = "gcrypt-stat" ]; then + resolve_url stat + echo_info "Getting statistics for remote: $URL" + setup + cmd_stat elif [ "$1" = --version ] || [ "$1" = -v ]; then echo "git-remote-gcrypt version $VERSION" exit 0 diff --git a/tests/test-completions.sh b/tests/test-completions.sh new file mode 100644 index 0000000..0aa9466 --- /dev/null +++ b/tests/test-completions.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# tests/test-completions.sh +# Verifies that bash completion script offers correct commands and excludes plumbing. + +# Mock commands if necessary? +# The completion script calls `git remote` etc. We can mock git. + +# Setup +TEST_DIR=$(dirname "$0") +COMP_FILE="$TEST_DIR/../completions/bash/git-remote-gcrypt" + +if [ ! -f "$COMP_FILE" ]; then + echo "FAIL: Completion file not found at $COMP_FILE" + exit 1 +fi + +# shellcheck source=/dev/null +source "$COMP_FILE" + +# Mock variables used by completion +COMP_WORDS=() +COMP_CWORD=0 +COMPREPLY=() + +# --- Mock git --- +# shellcheck disable=SC2329 +git() { + if [[ $1 == "remote" ]]; then + echo "origin" + echo "backup" + fi +} +export -f git + +# --- Helper to run completion --- +run_completion() { + COMP_WORDS=("$@") + COMP_CWORD=$((${#COMP_WORDS[@]} - 1)) + COMPREPLY=() + _git_remote_gcrypt +} + +# --- Tests --- + +FAILURES=0 + +echo "Test 1: Top-level commands (git-remote-gcrypt [TAB])" +run_completion "git-remote-gcrypt" "" +# Expect: check clean stat -h --help -v --version +# Expect NO: capabilities list push fetch +EXPECTED="check clean stat" +FORBIDDEN="capabilities list push fetch" + +OUTPUT="${COMPREPLY[*]}" + +for cmd in $EXPECTED; do + if [[ ! $OUTPUT =~ $cmd ]]; then + echo " FAIL: Expected '$cmd' in completion output." + FAILURES=$((FAILURES + 1)) + fi +done + +for cmd in $FORBIDDEN; do + if [[ $OUTPUT =~ $cmd ]]; then + echo " FAIL: Forbidden '$cmd' found in completion output." + FAILURES=$((FAILURES + 1)) + fi +done + +if [[ $OUTPUT =~ check ]] && [[ ! $OUTPUT =~ capabilities ]]; then + echo " PASS: Top-level commands look correct." +fi + +echo "Test 2: 'stat' subcommand (git-remote-gcrypt stat [TAB])" +run_completion "git-remote-gcrypt" "stat" "" +# Should complete remotes (mocked as origin backup) +OUTPUT="${COMPREPLY[*]}" +if [[ $OUTPUT =~ "origin" ]] && [[ $OUTPUT =~ "backup" ]]; then + echo " PASS: 'stat' completes remotes." +else + echo " FAIL: 'stat' did not complete remotes. Got: $OUTPUT" + FAILURES=$((FAILURES + 1)) +fi + +echo "Test 3: 'clean' subcommand flags (git-remote-gcrypt clean [TAB])" +run_completion "git-remote-gcrypt" "clean" "" +# Should have -f --force etc. +OUTPUT="${COMPREPLY[*]}" +if [[ $OUTPUT =~ "--force" ]] && [[ $OUTPUT =~ "--init" ]]; then + echo " PASS: 'clean' completes flags." +else + echo " FAIL: 'clean' missing flags. Got: $OUTPUT" + FAILURES=$((FAILURES + 1)) +fi + +if [ "$FAILURES" -eq 0 ]; then + echo "--------------------------" + echo "All completion tests passed." + exit 0 +else + echo "--------------------------" + echo "$FAILURES completion tests FAILED." + exit 1 +fi diff --git a/utils/gen_docs.sh b/utils/gen_docs.sh index 7e29256..d14b84d 100755 --- a/utils/gen_docs.sh +++ b/utils/gen_docs.sh @@ -33,12 +33,12 @@ COMMANDS_HELP=$(echo "$RAW_HELP" | sed -n '/^Options:/,$p' | sed 's/^/ /' | s # 2. Parse Commands and Flags for Completions # Extract command names (first word after 2 spaces) -COMMANDS_LIST=$(echo "$RAW_HELP" | awk '/^ [a-z]+ / {print $1}' | grep -vE "^(help|version)$" | sort | tr '\n' ' ' | sed 's/ $//') +COMMANDS_LIST=$(echo "$RAW_HELP" | awk '/^ [a-z]+ / {print $1}' | grep -vE "^(help|version|capabilities|list|push|fetch)$" | sort | tr '\n' ' ' | sed 's/ $//') # Extract clean flags # Text: " clean -f, --force Actually delete files..." # We want: "-f --force -i --init" for Bash -CLEAN_FLAGS_RAW=$(echo "$RAW_HELP" | grep "^ clean -" | awk -F' ' '{print $2}' | sed 's/,//g') +CLEAN_FLAGS_RAW=$(echo "$RAW_HELP" | grep "^ clean -" | awk '{print $2, $3}' | sed 's/,//g') CLEAN_FLAGS_BASH=$(echo "$CLEAN_FLAGS_RAW" | tr '\n' ' ' | sed 's/ $//') # For Zsh: we want simple list for now as per plan, user asked for dynamic but safe. @@ -68,7 +68,8 @@ for line in $CLEAN_FLAGS_RAW; do short=$(echo "$line" | awk '{print $1}' | sed 's/-//') long=$(echo "$line" | awk '{print $2}' | sed 's/--//') # Escape quotes if needed (none usually) - CLEAN_FLAGS_FISH="${CLEAN_FLAGS_FISH}complete -c git-remote-gcrypt -f -n \"__fish_seen_subcommand_from clean\" -s $short -l $long -d 'Flag';\n" + CLEAN_FLAGS_FISH="${CLEAN_FLAGS_FISH}complete -c git-remote-gcrypt -f -n \"__fish_seen_subcommand_from clean\" -s $short -l $long -d 'Flag'; +" done unset IFS