From 3f9ff06e96f9f941979b83086118c91afdda8e77 Mon Sep 17 00:00:00 2001 From: Shane Jaroch Date: Wed, 14 Jan 2026 11:06:10 -0500 Subject: [PATCH] update/fix stuff. tidy. --- .editorconfig | 4 ++-- .github/workflows/coverage.yaml | 3 +-- .github/workflows/lint.yaml | 3 +++ Makefile | 9 +++++++-- README.rst | 2 +- completions/templates/bash.in | 4 ++-- completions/templates/zsh.in | 2 +- completions/zsh/_git-remote-gcrypt | 4 ++-- git-remote-gcrypt | 20 +++++++++++--------- install.sh | 2 +- tests/coverage_report.py | 8 ++++++++ tests/system-test-multikey.sh | 2 +- tests/system-test-repack.sh | 2 +- tests/system-test.sh | 6 +++--- tests/test-clean-command.sh | 2 +- tests/test-gc.sh | 2 +- tests/test-install-logic.sh | 7 +++++-- tests/test-privacy-leaks.sh | 4 ++-- uninstall.sh | 12 ++++++++++++ utils/gen_docs.sh | 4 ++-- 20 files changed, 67 insertions(+), 35 deletions(-) diff --git a/.editorconfig b/.editorconfig index 13b95c3..606a808 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,10 +1,10 @@ [[bash]] # For extension-less files (i.e., git-remote-gcrypt) indent_style=tab -indent=4 +indent_size=4 [*.sh] # For bash scripts with .sh extension indent_style=tab -indent=4 +indent_size=4 diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index cb2d5ab..4c25036 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -23,7 +23,6 @@ jobs: # python3-docutils enables rst2man - name: Install kcov Dependencies - if: steps.cache-kcov.outputs.cache-hit != 'true' run: | sudo apt-get update sudo apt-get install -y binutils-dev build-essential cmake git \ @@ -35,7 +34,7 @@ jobs: - name: Build and Install kcov if: steps.cache-kcov.outputs.cache-hit != 'true' run: | - git clone https://github.com/SimonKagstrom/kcov.git + git clone --branch v42 --depth 1 https://github.com/SimonKagstrom/kcov.git cd kcov mkdir build && cd build cmake .. diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index c4866c7..1cf0c1e 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -13,6 +13,9 @@ name: lint schedule: - cron: "0 0 * * 0" # Sunday at 12 AM +permissions: + contents: read + jobs: # Handles Ubuntu and macOS install-unix: diff --git a/Makefile b/Makefile index 8ddfcc7..1bb405e 100644 --- a/Makefile +++ b/Makefile @@ -42,10 +42,15 @@ define print_success printf "\033[1;34m✓ %s\033[0m\n" "$(1)" endef + define print_info printf "\033[1;36m%s\033[0m\n" "$(1)" endef +define print_target +printf "\033[1;35m-> %s\033[0m\n" "$(1)" +endef + .PHONY: check/deps check/deps: ##H Verify kcov & shellcheck @@ -96,7 +101,7 @@ test/: ##H Run tests (purity checks only if kcov missing) @if command -v kcov >/dev/null 2>&1; then \ $(MAKE) test/installer test/system test/cov; \ else \ - $(call print_warn,kcov not found: skipping coverage/bash tests.); \ + printf "\033[1;33mkcov not found: skipping coverage/bash tests.\033[0m\n"; \ $(MAKE) test/purity; \ fi @@ -128,7 +133,7 @@ test/system: ##H Run logic tests (with bash & coverage) @rm -rf $(COV_SYSTEM) @mkdir -p $(COV_SYSTEM) @export GPG_TTY=$$(tty); \ - [ -n "$(DEBUG)$(V)" ] && export GCRYPT_DEBUG=1 && print_warn "Debug mode enabled"; \ + [ -n "$(DEBUG)$(V)" ] && export GCRYPT_DEBUG=1 && printf "\033[1;33mDebug mode enabled\033[0m\n"; \ export GIT_CONFIG_PARAMETERS="'gcrypt.gpg-args=--pinentry-mode loopback --no-tty'"; \ sed -i 's|^#!/bin/sh|#!/bin/bash|' git-remote-gcrypt; \ trap "sed -i 's|^#!/bin/bash|#!/bin/sh|' git-remote-gcrypt" EXIT; \ diff --git a/README.rst b/README.rst index 2b59a80..00d5557 100644 --- a/README.rst +++ b/README.rst @@ -288,7 +288,7 @@ To detect if a git url is a gcrypt repo, use:: (Legacy syntax ``--check`` is also supported). -Exit status is 0 +Exit status is 0 if the remote uses gcrypt and was decrypted successfully, 1 if it uses gcrypt but could not be decrypted, and 100 if the repo is not encrypted with gcrypt (or could not be accessed). diff --git a/completions/templates/bash.in b/completions/templates/bash.in index 32956ad..d132927 100644 --- a/completions/templates/bash.in +++ b/completions/templates/bash.in @@ -21,12 +21,12 @@ _git_remote_gcrypt() { # 2. Handle subcommands case "${COMP_WORDS[1]}" in clean) - local remotes=$(git remote -v 2>/dev/null | grep 'gcrypt::' | awk '{print $1}' | sort -u || :) + local remotes=$(git remote -v 2>/dev/null | grep 'gcrypt::' | awk '{print $1}' | sort -u || : COMPREPLY=($(compgen -W "{clean_flags_bash} $remotes" -- "$cur")) return 0 ;; check) - local remotes=$(git remote 2>/dev/null || :) + local remotes=$(git remote 2>/dev/null || : COMPREPLY=($(compgen -W "$remotes" -- "$cur")) return 0 ;; diff --git a/completions/templates/zsh.in b/completions/templates/zsh.in index 7d2794d..b357d1f 100644 --- a/completions/templates/zsh.in +++ b/completions/templates/zsh.in @@ -12,7 +12,7 @@ _git_remote_gcrypt() { ) _arguments -s -S $args - case $words[1] in + case $line[1] in clean) _arguments \ {clean_flags_zsh} \ diff --git a/completions/zsh/_git-remote-gcrypt b/completions/zsh/_git-remote-gcrypt index 46b09af..87e0987 100644 --- a/completions/zsh/_git-remote-gcrypt +++ b/completions/zsh/_git-remote-gcrypt @@ -12,10 +12,10 @@ _git_remote_gcrypt() { ) _arguments -s -S $args - case $words[1] in + case $line[1] in clean) _arguments \ - '()' {} '[flag]' \ + {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) diff --git a/git-remote-gcrypt b/git-remote-gcrypt index 951d7c2..05b6643 100755 --- a/git-remote-gcrypt +++ b/git-remote-gcrypt @@ -1398,7 +1398,7 @@ get_remote_file_list() if isurl rsync "$URL"; then r_files=$(rsync --no-motd --list-only "$(rsynclocation "$URL")/" | awk '{print $NF}' | grep -vE '^\.$|^\.\.$') || return 1 elif isurl rclone "$URL"; then - r_files=$(rclone lsf "$(rclonelocation "$URL")") || return 1 + r_files=$(rclone lsf "${URL#rclone://}") || return 1 elif isurl sftp "$URL"; then r_files=$(curl -s -S -k "$URL/" | grep -vE '^\.$|^\.\.$') || return 1 elif islocalrepo "$URL"; then @@ -1409,15 +1409,17 @@ get_remote_file_list() r_files="" fi else - # Git backend: Check safety-check ref first (most reliable if early_safety_check ran) - # Or try to fetch master? - # If early_safety_check ran, it fetched to refs/gcrypt/safety-check. - if git rev-parse --verify "refs/gcrypt/safety-check" >/dev/null 2>&1; then - r_files=$(git ls-tree -r --name-only "refs/gcrypt/safety-check") || return 1 + # Git backend: + # We need to fetch the remote state to list its files. + # Try fetching master and main to a temporary ref. + if git fetch --quiet "$URL" "refs/heads/master:refs/gcrypt/list-files" 2>/dev/null || \ + git fetch --quiet "$URL" "refs/heads/main:refs/gcrypt/list-files" 2>/dev/null; then + r_files=$(git ls-tree -r --name-only "refs/gcrypt/list-files") || return 1 + git update-ref -d "refs/gcrypt/list-files" else - # Try fetching default branch? - # If we can't verify emptiness, we should return error to prevent implicit init. - # Using $Gref (refs/gcrypt/gitception...) might be empty if we haven't pushed yet. + # Could not fetch, or remote is empty. + # If checking, this might be fine, but for clean it's an issue if we expected files. + # Returning 1 is safer. return 1 fi fi diff --git a/install.sh b/install.sh index f83d353..ef42ede 100755 --- a/install.sh +++ b/install.sh @@ -34,7 +34,7 @@ else fi VERSION=$(grep ^git-remote-gcrypt debian/changelog | head -n 1 | awk '{print $2}' | tr -d '()') fi -VERSION="$VERSION (deb running on $OS_IDENTIFIER)" +VERSION="$VERSION ($OS_IDENTIFIER)" echo "Detected version: $VERSION" diff --git a/tests/coverage_report.py b/tests/coverage_report.py index b7ba127..77a5e11 100644 --- a/tests/coverage_report.py +++ b/tests/coverage_report.py @@ -13,6 +13,14 @@ import xml.etree.ElementTree as E xml_file = os.environ.get("XML_FILE") patt = os.environ.get("PATT") +if not xml_file: + print("Error: XML_FILE environment variable is not set.") + sys.exit(1) + +if not patt: + print("Error: PATT environment variable is not set.") + sys.exit(1) + tree = E.parse(xml_file) missed = [] total_lines = 0 diff --git a/tests/system-test-multikey.sh b/tests/system-test-multikey.sh index 2024a13..324be51 100755 --- a/tests/system-test-multikey.sh +++ b/tests/system-test-multikey.sh @@ -193,7 +193,7 @@ print_info "Step 5: Unhappy Path - Test clone with NO matching keys..." ( set +e if git clone -b "${default_branch}" "gcrypt::${tempdir}/second.git#${default_branch}" -- "${tempdir}/fail_test"; then - print_info "ERROR: Clone succeeded unexpectedly with empty keyring!" + print_err "ERROR: Clone succeeded unexpectedly with empty keyring!" exit 1 fi ) 2>&1 | indent diff --git a/tests/system-test-repack.sh b/tests/system-test-repack.sh index 02e819c..ef876ac 100755 --- a/tests/system-test-repack.sh +++ b/tests/system-test-repack.sh @@ -118,7 +118,7 @@ print_info "Step 2: Creating repository with large random files..." random_data_index=$((file_index * random_data_per_file)) echo "Writing large file $((file_index + 1))/${total_files} ($((random_data_per_file / 1024 / 1024)) MiB)" head -c "${random_data_per_file}" >"$((file_index)).data" < \ - <(tail -c "+${random_data_index}" "${random_data_file}" || :) + <(tail -c "+$((random_data_index + 1))" "${random_data_file}" || :) done git add -- "${tempdir}/first" git commit -m "Commit #${i}" diff --git a/tests/system-test.sh b/tests/system-test.sh index ba476f9..f51a791 100755 --- a/tests/system-test.sh +++ b/tests/system-test.sh @@ -76,7 +76,8 @@ trap "rm -Rf -- '${tempdir}'" EXIT repo_root=$(git rev-parse --show-toplevel) test_version=$(git describe --tags --always --dirty 2>/dev/null || echo "test") cp "$repo_root/git-remote-gcrypt" "$tempdir/git-remote-gcrypt" -sed -i "s/@@DEV_VERSION@@/$test_version/" "$tempdir/git-remote-gcrypt" +sed "s/@@DEV_VERSION@@/$test_version/" "$tempdir/git-remote-gcrypt" > "$tempdir/git-remote-gcrypt.tmp" +mv "$tempdir/git-remote-gcrypt.tmp" "$tempdir/git-remote-gcrypt" chmod +x "$tempdir/git-remote-gcrypt" PATH=$tempdir:${PATH} readonly PATH @@ -127,7 +128,6 @@ random_data_size=$(( total_files * random_data_per_file )) random_data_file="${tempdir}/data" head -c "${random_data_size}" "${random_source}" > "${random_data_file}" -# Create gpg key and subkey. # Create gpg key and subkey. print_info "Step 1: Creating a new GPG key and subkey to use for testing:" ( @@ -386,7 +386,7 @@ print_info "Step 9: Network Failure Guard Test (manifest unavailable):" # DEBUG: Dump directory listing to stdout print_info "DEBUG: Listing ${tempdir}/second.git contents:" - find "${tempdir}/second.git" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort | indent + find "${tempdir}/second.git" -mindepth 1 -maxdepth 1 -exec basename {} \; | sort | indent # Use find to robustly locate manifest files (56-64 hex chars) # matching basename explicitly via grep. Using sed for portable basename extraction. diff --git a/tests/test-clean-command.sh b/tests/test-clean-command.sh index 11dc50b..84de92b 100755 --- a/tests/test-clean-command.sh +++ b/tests/test-clean-command.sh @@ -102,7 +102,7 @@ rm index.dirty COMMIT=$(echo "Dirty commit with nested files" | $GIT commit-tree "$TREE") $GIT update-ref refs/heads/master "$COMMIT" -print_info "Created dirty remote with 2 unencrypted files" +print_info "Created dirty remote with 4 unencrypted files" # Test helper assert_grep() { diff --git a/tests/test-gc.sh b/tests/test-gc.sh index 44af71e..1562cf4 100755 --- a/tests/test-gc.sh +++ b/tests/test-gc.sh @@ -46,7 +46,7 @@ dd if=/dev/urandom of=largeblob bs=1K count=100 2>/dev/null # 100KB is enough to $GIT add largeblob $GIT commit -m "Add large blob" >/dev/null echo "Pushing initial data..." -git push origin master >/dev/null 2>&1 || { +$GIT push origin master >/dev/null 2>&1 || { echo "Push failed" exit 1 } diff --git a/tests/test-install-logic.sh b/tests/test-install-logic.sh index 8b44cbf..cc97fcc 100755 --- a/tests/test-install-logic.sh +++ b/tests/test-install-logic.sh @@ -84,7 +84,7 @@ else fi # Use the identified OS for the expected string -EXPECTED_TAG="5.5.5-1 (deb running on $OS_IDENTIFIER)" +EXPECTED_TAG="5.5.5-1 ($OS_IDENTIFIER)" assert_version "$EXPECTED_TAG" @@ -94,7 +94,10 @@ rm -rf "${SANDBOX:?}/usr" export DESTDIR="$SANDBOX/pkg_root" export prefix="/usr" -"bash" "$INSTALLER" >/dev/null 2>&1 +"bash" "$INSTALLER" >/dev/null 2>&1 || { + print_err "Installer FAILED" + exit 1 +} if [ -f "$SANDBOX/pkg_root/usr/bin/git-remote-gcrypt" ]; then printf " ✓ %s\n" "DESTDIR honored" diff --git a/tests/test-privacy-leaks.sh b/tests/test-privacy-leaks.sh index 316318a..9fce029 100755 --- a/tests/test-privacy-leaks.sh +++ b/tests/test-privacy-leaks.sh @@ -17,7 +17,8 @@ trap 'rm -Rf -- "$tempdir"' EXIT repo_root=$(git rev-parse --show-toplevel) test_version=$(git describe --tags --always --dirty 2>/dev/null || echo "test") cp "$repo_root/git-remote-gcrypt" "$tempdir/git-remote-gcrypt" -sed -i "s/@@DEV_VERSION@@/$test_version/" "$tempdir/git-remote-gcrypt" +sed "s/@@DEV_VERSION@@/$test_version/" "$tempdir/git-remote-gcrypt" >"$tempdir/git-remote-gcrypt.tmp" +mv "$tempdir/git-remote-gcrypt.tmp" "$tempdir/git-remote-gcrypt" chmod +x "$tempdir/git-remote-gcrypt" PATH=$tempdir:${PATH} export PATH @@ -82,7 +83,6 @@ git remote add origin "gcrypt::${tempdir}/remote-repo" git config remote.origin.gcrypt-participants "test@example.com" git config remote.origin.gcrypt-signingkey "test@example.com" -# Force push is required to initialize gcrypt over an existing repo # Force push is required to initialize gcrypt over an existing repo # Now EXPECT FAILURE because of our new safety check! print_info "Attempting push to dirty repo (should fail due to safety check)..." diff --git a/uninstall.sh b/uninstall.sh index 7d8d52b..7cc6ae5 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -25,4 +25,16 @@ else echo "Man page not found: $MAN_PATH" fi +# Completions +COMP_BASH="$DESTDIR$prefix/share/bash-completion/completions/git-remote-gcrypt" +COMP_ZSH="$DESTDIR$prefix/share/zsh/site-functions/_git-remote-gcrypt" +COMP_FISH="$DESTDIR$prefix/share/fish/vendor_completions.d/git-remote-gcrypt.fish" + +for f in "$COMP_BASH" "$COMP_ZSH" "$COMP_FISH"; do + if [ -f "$f" ]; then + verbose rm -f "$f" + echo "Removed completion: $f" + fi +done + echo "Uninstallation complete." diff --git a/utils/gen_docs.sh b/utils/gen_docs.sh index 85691ff..878ccc2 100755 --- a/utils/gen_docs.sh +++ b/utils/gen_docs.sh @@ -70,7 +70,7 @@ unset IFS # 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}/$(echo "$COMMANDS_HELP" | sed 's/[\/&]/\\&/g' | awk '{printf "%s\\n", $0}')/" "$README_TMPL" >"$README_OUT" # 4. Generate Bash echo "Generating Bash completions..." @@ -81,7 +81,7 @@ echo "Generating Zsh completions..." # Zsh substitution is tricky with the complex string. # We'll stick to replacing {commands} and {clean_flags_zsh} # Need to escape special chars for sed -SAFE_CMDS=$(echo "$COMMANDS_LIST" | sed 's/ / /g') # just space separated +# safe_cmds removed as unused # For clean_flags_zsh, since it contains quotes and braces, we need care. # We'll read the template line by line? No, sed is standard. # We use a temp file for the replacement string to avoid sed escaping hell for large blocks? -- 2.52.0