more fixes/lint/test tidying up.
authorShane Jaroch <chown_tee@proton.me>
Sat, 17 Jan 2026 05:57:51 +0000 (00:57 -0500)
committerShane Jaroch <chown_tee@proton.me>
Sat, 17 Jan 2026 05:57:51 +0000 (00:57 -0500)
.github/workflows/lint.yaml
.github/workflows/termux-android.yml [new file with mode: 0644]
Makefile
completions/fish/git-remote-gcrypt.fish
completions/gen_docs.sh
completions/zsh/_git-remote-gcrypt
install.sh
tests/system-test-clean-command.sh
tests/system-test-clean-repack.sh
utils/gen_docs.sh [deleted file]

index eb63f245ced7659510d973e6d2546ed58310a93f..8690d55fa96c5b3c4cef35bbae9fc5e297b8ea6b 100644 (file)
@@ -114,3 +114,18 @@ jobs:
 
       - name: Lint [make lint]
         run: make lint
+
+      - name: Check Formatting [make format]
+        # Requires shfmt and black.
+        # Assuming environment has them or we install them.
+        # ubuntu-latest has python3, we need shfmt.
+        run: |
+          sudo snap install shfmt
+          pip3 install black
+          make format
+          git diff --exit-code
+
+      - name: Check Generation [make generate]
+        run: |
+          make generate
+          git diff --exit-code
diff --git a/.github/workflows/termux-android.yml b/.github/workflows/termux-android.yml
new file mode 100644 (file)
index 0000000..4437696
--- /dev/null
@@ -0,0 +1,39 @@
+---
+name: Test on Termux
+
+"on":
+  push:
+  workflow_dispatch:
+    inputs:
+      debug:
+        description: "Enable debug logging (GCRYPT_DEBUG=1)"
+        required: false
+        type: boolean
+        default: false
+  schedule:
+    - cron: "0 0 * * 0" # Sunday at 12 AM
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+
+    steps:
+      # 1. Checkout code on the Ubuntu Host (Ubuntu has glibc)
+      - uses: actions/checkout@v4
+        with:
+          repository: gamesguru/git-remote-gcrypt
+          fetch-depth: 1
+
+      # 2. Run your tests inside Termux using manual Docker execution
+      - name: Run tests in Termux
+        run: |
+          # We mount the current directory ($PWD) to /data inside the container
+          # We set the working directory (-w) to /data
+          docker run --rm \
+            -v "$PWD":/data \
+            -w /data \
+            termux/termux-docker:latest \
+            sh -c "pkg update && pkg install -y git make \
+              && make install
+              && make check/install
+              && git-remote-gcrypt --version"
index f3cb385ca166cd54ae5b5f251e6ce2afdfa31738..576edefce8b21d15c45fa04cd18defa02e867f1e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -63,12 +63,13 @@ check/deps: ##H Verify kcov & shellcheck
 
 LINT_LOCS_PY ?= $(shell git ls-files '*.py')
 LINT_LOCS_SH ?= $(shell git ls-files '*.sh' ':!tests/system-test.sh')
+FORMAT_LOCS_SH ?= completions/**
 
 .PHONY: format
 format:        ##H Format scripts
        @$(call print_target,format)
        @$(call print_info,Formatting shell scripts...)
-       shfmt -ci -bn -s -w $(LINT_LOCS_SH)
+       shfmt -ci -bn -s -w $(LINT_LOCS_SH) $(FORMAT_LOCS_SH)
        @$(call print_success,OK.)
        @$(call print_info,Formatting Python scripts...)
        -black $(LINT_LOCS_PY)
@@ -193,7 +194,7 @@ __VERSION__ := $(shell git describe --tags --always --dirty 2>/dev/null || echo
 .PHONY: generate
 generate:      ##H Autogen man docs & shell completions
        @$(call print_info,Generating documentation and completions...)
-       ./utils/gen_docs.sh
+       ./completions/gen_docs.sh
        @$(call print_success,Generated.)
 
 
index bdb8d42f4aa392ba3d5d7be567a680245134e591..0bb8751cee541a123cce78ada5452b2566106eeb 100644 (file)
@@ -13,6 +13,6 @@ complete -c git-remote-gcrypt -n "__fish_seen_subcommand_from check" -a "(git re
 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" -l force -d 'Flag'
-complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -l init -d 'Flag'
-complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -l hard -d 'Flag'
+complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -l force -d 'Flag';
+complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -l init -d 'Flag';
+complete -c git-remote-gcrypt -f -n "__fish_seen_subcommand_from clean" -l hard -d 'Flag';
index a6355002114dee9695a23a7cf3e265379afbb27c..00d5d5d641c5c7a9babc08e7a94b9925ee571a4c 100755 (executable)
@@ -29,7 +29,7 @@ RAW_HELP=$(sed -n "/^$SCRIPT_KEY=\"/,/\"$/p" "$SRC" | sed "s/^$SCRIPT_KEY=\"//;s
 
 # 1. Prepare {commands_help} for README (Indented for RST)
 # We want the Options and Git Protocol Commands sections
-COMMANDS_HELP=$(echo "$RAW_HELP" | sed -n '/^Options:/,$p' | sed 's/^/    /')
+COMMANDS_HELP=$(printf '%s\n' "$RAW_HELP" | sed -n '/^Options:/,$p' | sed 's/^/    /')
 
 # 2. Parse Commands and Flags for Completions
 # Extract command names (first word after 2 spaces)
@@ -145,7 +145,7 @@ rm .fish_tmp
 
 # 3. Generate README
 echo "Generating $README_OUT..."
-sed "s/{commands_help}/$(echo "$COMMANDS_HELP" | sed 's/[\/&]/\\&/g' | sed ':a;N;$!ba;s/\n/\\n/g')/" "$README_TMPL" >"$README_OUT"
+sed "s/{commands_help}/$(printf '%s\n' "$COMMANDS_HELP" | sed 's/[\/&]/\\&/g' | sed ':a;N;$!ba;s/\n/\\n/g')/" "$README_TMPL" >"$README_OUT"
 
 # 4. Generate Bash
 echo "Generating Bash completions..."
index 0b86da0044c54f27b32ecc09f93487cdaaa465ea..d38d020d136b5e743521af6a130c059ec90d930a 100644 (file)
@@ -14,7 +14,7 @@ _git_remote_gcrypt() {
 
        case $line[1] in
        clean)
-               _arguments '(--force --init --hard)'{--force,--init,--hard}'[flag]' \
+               _arguments  --force'[Flag]' --init'[Flag]' --hard'[Flag]' \
                        '*:gcrypt URL: _alternative "remotes:gcrypt remote:($(git remote -v 2>/dev/null | grep "gcrypt::" | awk "{print \$1}" | sort -u))" "files:file:_files"'
                ;;
        check | stat)
index f410675a76fc223fccfb79195ef430d787f97ded..db7d3639cbc28e6b4054dfc61d63c0e6978516be 100755 (executable)
@@ -65,7 +65,7 @@ trap 'rm -rf "$BUILD_DIR"' EXIT
 sed "s|@@DEV_VERSION@@|$VERSION|g" git-remote-gcrypt >"$BUILD_DIR/git-remote-gcrypt"
 
 # --- GENERATION ---
-verbose ./utils/gen_docs.sh
+verbose ./completions/gen_docs.sh
 
 # --- INSTALLATION ---
 # This is where the 'Permission denied' happens if not sudo
index 43f35e5c72efe6edd807e4f7020ba3e51dda59cf..68c712de129588d6bebc6f4a76259ff0211765c5 100755 (executable)
@@ -26,7 +26,7 @@ unset GIT_CONFIG_PARAMETERS
 
 # Suppress git advice messages
 # Note: git-remote-gcrypt reads actual config files, not just CLI -c options
-GIT="git -c advice.defaultBranchName=false -c commit.gpgSign=false"
+GIT="git -c advice.defaultBranchName=false -c commit.gpgSign=false -c init.defaultBranch=master"
 
 # --------------------------------------------------
 # Set up test environment
index 8491ddc8e33eced0eb484375d7d9798e2a77e717..1af05364e5d918d265383aa2f6efcdfe21f0c1c1 100755 (executable)
@@ -44,24 +44,22 @@ EOF
 chmod +x "${GNUPGHOME}/gpg"
 
 # Git config isolation
+# Git config isolation (Strict: no global config)
 export GIT_CONFIG_SYSTEM=/dev/null
-export GIT_CONFIG_GLOBAL="$TEST_DIR/gitconfig"
-git config user.email "test@test.com"
-git config user.name "Test"
-git config init.defaultBranch "master"
+export GIT_CONFIG_GLOBAL=/dev/null
 
 echo "Generating GPG key..."
 gpg --batch --passphrase "" --quick-generate-key "Test <test@test.com>"
 
 # Initialize repo
 cd "$REPO_DIR"
-git init
+git -c init.defaultBranch=master init
 git config user.email "test@test.com"
 git config user.name "Test User"
 git config advice.defaultBranchName false
 
 # Initialize local remote
-git init --bare "$REMOTE_DIR"
+git -c init.defaultBranch=master init --bare "$REMOTE_DIR"
 git remote add origin "gcrypt::$REMOTE_DIR"
 git config remote.origin.gcrypt-participants "test@test.com"
 git config remote.origin.gcrypt-signingkey "test@test.com"
@@ -74,20 +72,20 @@ export PATH="$PROJECT_ROOT:$PATH"
 echo "Push 1"
 echo "data 1" >file1.txt
 git add file1.txt
-git commit -m "Commit 1" --no-gpg-sign
+git commit -m "Commit 1"
 # Initial push needs force to initialize remote gcrypt repo
 git push origin +master
 
 echo "Push 2"
 echo "data 2" >file2.txt
 git add file2.txt
-git commit -m "Commit 2" --no-gpg-sign
+git commit -m "Commit 2"
 git push origin master
 
 echo "Push 3"
 echo "data 3" >file3.txt
 git add file3.txt
-git commit -m "Commit 3" --no-gpg-sign
+git commit -m "Commit 3"
 git push origin master
 
 # Verify we have multiple pack files in remote
@@ -129,7 +127,9 @@ echo "Created garbage blob: $GARBAGE_BLOB"
 cd "$TEST_DIR/raw_backend"
 echo "Garbage Data" >".garbage (file)"
 git add ".garbage (file)"
-git commit -m "Inject unencrypted garbage" --no-gpg-sign
+git config user.email "test@test.com"
+git config user.name "Test User"
+git commit -m "Inject unencrypted garbage"
 git push origin master
 
 # Verify garbage exists
diff --git a/utils/gen_docs.sh b/utils/gen_docs.sh
deleted file mode 100755 (executable)
index 217beda..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/bin/sh
-set -e
-
-# gen_docs.sh
-# Generates documentation and shell completions from git-remote-gcrypt source.
-# Strictly POSIX sh compliant.
-
-SCRIPT_KEY="HELP_TEXT"
-SRC="git-remote-gcrypt"
-README_TMPL="completions/templates/README.rst.in"
-README_OUT="README.rst"
-BASH_TMPL="completions/templates/bash.in"
-BASH_OUT="completions/bash/git-remote-gcrypt"
-ZSH_TMPL="completions/templates/zsh.in"
-ZSH_OUT="completions/zsh/_git-remote-gcrypt"
-FISH_TMPL="completions/templates/fish.in"
-FISH_OUT="completions/fish/git-remote-gcrypt.fish"
-
-# Ensure we're in the project root
-if [ ! -f "$SRC" ]; then
-       echo "Error: Must be run from project root" >&2
-       exit 1
-fi
-
-# Extract HELP_TEXT variable content
-# Using sed to capture lines between double quotes of HELP_TEXT="..."
-# Assumes HELP_TEXT="..." is a single block.
-RAW_HELP=$(sed -n "/^$SCRIPT_KEY=\"/,/\"$/p" "$SRC" | sed "s/^$SCRIPT_KEY=\"//;s/\"$//")
-
-# 1. Prepare {commands_help} for README (Indented for RST)
-# We want the Options and Git Protocol Commands sections
-COMMANDS_HELP=$(echo "$RAW_HELP" | sed -n '/^Options:/,$p' | sed 's/^/    /' | sed '$d')
-
-# 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|capabilities|list|push|fetch)$" | sort | tr '\n' ' ' | sed 's/ $//')
-
-# Extract clean flags
-# Text: "    clean --force        Actually delete files..."
-# We want: "--force --init --hard"
-CLEAN_FLAGS_RAW=$(echo "$RAW_HELP" | grep "^    clean -" | awk '{print $2}')
-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.
-# Constructing a simple list of flags requires parsing.
-# The previous python script just injected them.
-CLEAN_FLAGS_ZSH=""
-# We'll just provide the flags as a list for _arguments
-# ZSH format roughly: '(-f --force)'{-f,--force}'[desc]'
-# Only generate if there are actual flags
-COMMA_FLAGS=$(echo "$CLEAN_FLAGS_BASH" | tr ' ' ',')
-if [ -n "$CLEAN_FLAGS_BASH" ]; then
-       # zsh _arguments requires format: '(exclusion)'{-f,--long}'[desc]' as ONE string (no spaces)
-       # Since we only have one flag per line now (long only), exclusion is just itself or list of all?
-       # Mutually exclusive? Maybe. For now, simple list.
-       # Actually, with single flags, no need for the {...} brace expansion for aliases.
-       # Just list them.
-       CLEAN_FLAGS_ZSH="'(${CLEAN_FLAGS_BASH})'{${COMMA_FLAGS}}'[flag]'"
-else
-       CLEAN_FLAGS_ZSH=""
-fi
-
-CLEAN_FLAGS_FISH=""
-# Use a loop over the raw lines
-IFS="
-"
-newline="
-"
-sep=""
-for line in $CLEAN_FLAGS_RAW; do
-       # line is just "--force" now
-       long="${line#--}"
-       # Escape quotes if needed (none usually)
-       CLEAN_FLAGS_FISH="${CLEAN_FLAGS_FISH}${sep}complete -c git-remote-gcrypt -f -n \"__fish_seen_subcommand_from clean\" -l $long -d 'Flag'"
-       sep="$newline"
-done
-unset IFS
-
-# Helper for template substitution using awk
-# Usage: replace_template "TEMPLATE_FILE" "OUT_FILE" "KEY1=VALUE1" "KEY2=VALUE2" ...
-replace_template() {
-       _tmpl="$1"
-       _out="$2"
-       shift 2
-       _awk_script=""
-       for _kv in "$@"; do
-               _key="${_kv%%=*}"
-               _val="${_kv#*=}"
-               # Export the value so awk can access it via ENVIRON
-               export "REPLACE_$_key"="$_val"
-               _awk_script="${_awk_script} gsub(/\{${_key}\}/, ENVIRON[\"REPLACE_$_key\"]);"
-       done
-       awk "{ $_awk_script print }" "$_tmpl" >"$_out"
-}
-
-# 3. Generate README
-echo "Generating $README_OUT..."
-replace_template "$README_TMPL" "$README_OUT" "commands_help=$COMMANDS_HELP"
-
-# 4. Generate Bash
-echo "Generating Bash completions..."
-replace_template "$BASH_TMPL" "$BASH_OUT" "commands=$COMMANDS_LIST" "clean_flags_bash=$CLEAN_FLAGS_BASH"
-
-# 5. Generate Zsh
-echo "Generating Zsh completions..."
-replace_template "$ZSH_TMPL" "$ZSH_OUT" "commands=$COMMANDS_LIST" "clean_flags_zsh=$CLEAN_FLAGS_ZSH"
-
-# 6. Generate Fish
-echo "Generating Fish completions..."
-# Fish needs {not_sc_list} which matches {commands} (space separated)
-replace_template "$FISH_TMPL" "$FISH_OUT" "not_sc_list=$COMMANDS_LIST" "clean_flags_fish=$CLEAN_FLAGS_FISH"
-
-echo "Done."