From d1d49c330bb8cab3aa5cfb2bffb64d2b41701072 Mon Sep 17 00:00:00 2001 From: Shane Jaroch Date: Thu, 8 Jan 2026 15:32:44 -0500 Subject: [PATCH] wip URL resolution logic? or too complicated? --- git-remote-gcrypt | 113 ++++++++++++++++++++++-------------- tests/test-clean-command.sh | 80 +++++++++++++++++++------ 2 files changed, 133 insertions(+), 60 deletions(-) diff --git a/git-remote-gcrypt b/git-remote-gcrypt index c54de98..ff7c1cc 100755 --- a/git-remote-gcrypt +++ b/git-remote-gcrypt @@ -43,12 +43,11 @@ Usage: Automatically invoked by git when using gcrypt:: URLs Or: https://github.com/spwhitton/git-remote-gcrypt Options: - -h, --help Show this help message - -v, --version Show version information - --check Check if URL is a gcrypt repository - --clean Remove unencrypted files from remote (with confirmation) - --clean --dry-run Show what would be deleted without deleting - --clean --force Delete without confirmation + help Show this help message + version Show version information + check [URL] Check if URL is a gcrypt repository + clean [URL|REMOTE] Scan/Clean unencrypted files from remote + clean -f, --force Actually delete files (default is scan only) Git Protocol Commands (for debugging): capabilities List remote helper capabilities @@ -63,27 +62,68 @@ Environment Variables: EOF } -# Handle subcommands early (before getopts consumes them) -# These are not options but subcommands that need their own argument handling +# Handle subcommands early case "$1" in - --check) + check|--check) NAME=dummy-gcrypt-check URL=$2 # Will be handled at the end of the script ;; - --clean) + clean|--clean) NAME=dummy-gcrypt-clean - URL=$2 + shift FORCE_CLEAN= - DRY_RUN= - if [ "$3" = "--force" ] || [ "$3" = "-f" ]; then - FORCE_CLEAN=yes - fi - if [ "$3" = "--dry-run" ] || [ "$3" = "-n" ]; then - DRY_RUN=yes + URL= + while [ $# -gt 0 ]; do + case "$1" in + --force|-f) FORCE_CLEAN=yes ;; + -*) echo "Unknown option: $1" >&2; exit 1 ;; + *) + if [ -z "$URL" ]; then + URL="$1" + else + echo "Error: Multiple URLs/remotes provided to clean" >&2 + exit 1 + fi + ;; + esac + shift + done + + # URL resolution logic + if [ -z "$URL" ]; then + # Auto-detect all gcrypt remotes + remotes=$(git remote -v | grep 'gcrypt::' | awk '{print $1}' | sort -u || :) + if [ -z "$remotes" ]; then + echo "Usage: git-remote-gcrypt clean [URL|REMOTE] [-f]" >&2 + echo "Error: No gcrypt remotes found and no URL/remote specified." >&2 + exit 1 + fi + num_remotes=$(printf "%s\n" "$remotes" | grep -v '^$' | wc -l | tr -d ' ') + if [ "$num_remotes" -eq 1 ]; then + URL=$(git config --get "remote.$remotes.url") + elif [ "$num_remotes" -gt 1 ]; then + echo "Error: Multiple gcrypt remotes found. Please specify one:" >&2 + echo "$remotes" | sed 's/^/ /' >&2 + exit 1 + fi + elif ! echo "$URL" | grep -q -E '://|::'; then + # Not a URL, check if it's a remote name + potential_url=$(git config --get "remote.$URL.url" || :) + if [ -n "$potential_url" ]; then + URL="$potential_url" + fi fi # Will be handled at the end of the script ;; + help|--help|-h) + show_help + exit 0 + ;; + version|--version|-v) + echo "git-remote-gcrypt version $VERSION" >&2 + exit 0 + ;; esac # Parse flags @@ -1347,27 +1387,24 @@ gcrypt_main_loop() } if [ "$NAME" = "dummy-gcrypt-check" ]; then - # NAME and URL were set at the top of the script + # Check command: NAME and URL were set at the top + echo_info "Checking remote: $URL" setup ensure_connected + CLEAN_FINAL "$URL" git remote remove "$NAME" 2>/dev/null || true if iseq "$Did_find_repo" "no" then exit 100 fi elif [ "$NAME" = "dummy-gcrypt-clean" ]; then - # Cleanup command: NAME, URL, FORCE_CLEAN, DRY_RUN were set at the top + # Cleanup command: NAME, URL, FORCE_CLEAN were set at the top + echo_info "Checking remote: $URL" - if isnull "$URL"; then - echo_info "Usage: git-remote-gcrypt --clean [--force|--dry-run]" - echo_info " Removes unencrypted files from the remote repository." - echo_info " --force, -f Don't ask for confirmation" - echo_info " --dry-run, -n Show what would be deleted without deleting" - exit 1 - fi - setup - ensure_connected + if ! ensure_connected; then + echo_die "Could not connect to $URL." + fi # Get all files in the remote remote_files=$(git ls-tree --name-only "$Gref" 2>/dev/null || :) @@ -1407,24 +1444,14 @@ elif [ "$NAME" = "dummy-gcrypt-clean" ]; then echo_info "Found the following files to remove:" xecho "$bad_files" | sed 's/^/ /' >&2 - if isnonnull "$DRY_RUN"; then - echo_info "(Dry run - no files were deleted)" - CLEAN_FINAL "$URL" - git remote remove "$NAME" 2>/dev/null || true - exit 0 - fi - if isnull "$FORCE_CLEAN"; then echo_info "" - echo_info "WARNING: This will permanently delete these files from the remote!" - echo_info "Make sure you have a backup (e.g., git clone $URL backup-repo)" + echo_info "NOTE: This is a scan of unencrypted files on the remote." + echo_info "To actually delete these files, use: git-remote-gcrypt clean $URL --force" echo_info "" - printf "Delete these files? [y/N] " >&2 - read -r ans - case "$ans" in - [Yy]*) ;; - *) echo_info "Aborted."; exit 1 ;; - esac + CLEAN_FINAL "$URL" + git remote remove "$NAME" 2>/dev/null || true + exit 0 fi echo_info "Removing files..." diff --git a/tests/test-clean-command.sh b/tests/test-clean-command.sh index b9bce31..67e7726 100755 --- a/tests/test-clean-command.sh +++ b/tests/test-clean-command.sh @@ -45,37 +45,72 @@ $GIT update-ref refs/heads/master "$COMMIT" print_info "Created dirty remote with 2 unencrypted files" -# Test 1: --clean without URL shows usage +# Test 1: clean without URL/remotes shows usage print_info "Test 1: Usage message..." -if "$SCRIPT_DIR/git-remote-gcrypt" --clean 2>&1 | grep -q "Usage"; then - print_success "--clean shows usage when URL missing" +# First, ensure no gcrypt remotes in a fresh tmp repo +mkdir "$tempdir/no-remotes" +cd "$tempdir/no-remotes" +$GIT init >/dev/null +output=$("$SCRIPT_DIR/git-remote-gcrypt" clean 2>&1 || :) +if echo "$output" | grep -q "Usage: git-remote-gcrypt clean"; then + print_success "clean shows usage when no URL/remote found" else - print_err "--clean should show usage when URL missing" + print_err "clean should show usage when no URL/remote found" + echo "$output" exit 1 fi -# Test 2: --clean --dry-run shows files without deleting -print_info "Test 2: Dry run mode..." -output=$("$SCRIPT_DIR/git-remote-gcrypt" --clean "$tempdir/remote.git" --dry-run 2>&1) -if echo "$output" | grep -q "secret1.txt" && echo "$output" | grep -q "Dry run"; then - print_success "--clean --dry-run shows files and doesn't delete" +# Test 2: clean (default) is scan-only +print_info "Test 2: Default scan-only mode..." +# Go to the remote repo (it is a git repo, so git-remote-gcrypt can run) +cd "$tempdir/remote.git" +output=$("$SCRIPT_DIR/git-remote-gcrypt" clean "$tempdir/remote.git" 2>&1) +if echo "$output" | grep -q "secret1.txt" && echo "$output" | grep -q "NOTE: This is a scan"; then + print_success "clean defaults to scan-only? OK." else - print_err "--clean --dry-run failed" + print_err "clean defaults scan? Failed!" echo "$output" exit 1 fi # Verify files still exist if $GIT -C "$tempdir/remote.git" ls-tree HEAD | grep -q "secret1.txt"; then - print_success "Files still exist after dry run" + print_success "Files still exist after default scan" else - print_err "Dry run incorrectly deleted files!" + print_err "Default scan incorrectly deleted files!" exit 1 fi -# Test 3: --clean --force deletes files -print_info "Test 3: Force cleanup..." -"$SCRIPT_DIR/git-remote-gcrypt" --clean "$tempdir/remote.git" --force 2>&1 +# Test 3: Scan by remote name... +print_info "Test 3: Scan by remote name..." +$GIT init "$tempdir/client" >/dev/null +cd "$tempdir/client" +$GIT remote add origin "$tempdir/remote.git" +output=$("$SCRIPT_DIR/git-remote-gcrypt" clean origin 2>&1) +if echo "$output" | grep -q "Checking remote: $tempdir/remote.git"; then + print_success "clean resolved 'origin' to URL" +else + print_err "clean failed to resolve 'origin'" + echo "$output" + exit 1 +fi + +# Test 4: clean (no args) automatic discovery +print_info "Test 4: Automatic discovery..." +# Add a gcrypt:: remote to enable discovery +$GIT remote add gcrypt-origin "gcrypt::$tempdir/remote.git" +output=$("$SCRIPT_DIR/git-remote-gcrypt" clean 2>&1) +if echo "$output" | grep -q "Checking remote: gcrypt::$tempdir/remote.git"; then + print_success "clean discovered gcrypt remotes automatically" +else + print_err "clean failed automatic discovery" + echo "$output" + exit 1 +fi + +# Test 5: clean --force deletes files +print_info "Test 5: Force cleanup..." +"$SCRIPT_DIR/git-remote-gcrypt" clean "$tempdir/remote.git" --force 2>&1 # Verify files are gone if $GIT -C "$tempdir/remote.git" ls-tree HEAD 2>/dev/null | grep -q "secret"; then @@ -83,7 +118,18 @@ if $GIT -C "$tempdir/remote.git" ls-tree HEAD 2>/dev/null | grep -q "secret"; th $GIT -C "$tempdir/remote.git" ls-tree HEAD exit 1 else - print_success "Files removed after --clean --force" + print_success "Files removed after clean --force" +fi + +# Test 6: check command is recognized +print_info "Test 6: check command..." +output=$("$SCRIPT_DIR/git-remote-gcrypt" check "$tempdir/remote.git" 2>&1 || :) +if echo "$output" | grep -q "gcrypt: Checking remote:"; then + print_success "check command is recognized" +else + print_err "check command failed" + echo "$output" + exit 1 fi -print_success "All --clean command tests passed!" +print_success "All clean/check command tests passed!" -- 2.52.0