- 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
--- /dev/null
+---
+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"
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)
.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.)
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';
# 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)
# 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..."
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)
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
# 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
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"
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
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
+++ /dev/null
-#!/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."