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)
+ clean -i, --init Scan even if no manifest found (DANGEROUS with --force)
Git Protocol Commands (for debugging):
capabilities List remote helper capabilities
while [ $# -gt 0 ]; do
case "$1" in
--force|-f) FORCE_CLEAN=yes ;;
+ --init|-i) FORCE_INIT=yes ;;
-*) echo "Unknown option: $1" >&2; exit 1 ;;
*)
if [ -z "$URL" ]; then
print_debug "read_config done"
}
+early_safety_check()
+{
+ local check_files="" early_bad_files=""
+
+ # EARLY SAFETY CHECK for gitception backends:
+ # Before GPG validation, check if the remote has unencrypted files.
+ if [ "$NAME" = "gcrypt-clean" ]; then
+ return 0
+ fi
+ if isurl sftp "$URL" || isurl rsync "$URL" || isurl rclone "$URL" || islocalrepo "$URL"; then
+ return 0
+ fi
+
+ git fetch --quiet "$URL" "refs/heads/master:refs/gcrypt/safety-check" 2>/dev/null ||
+ git fetch --quiet "$URL" "refs/heads/main:refs/gcrypt/safety-check" 2>/dev/null || true
+
+ if ! git rev-parse --verify "refs/gcrypt/safety-check" >/dev/null 2>&1; then
+ return 0
+ fi
+
+ check_files=$(git ls-tree --name-only "refs/gcrypt/safety-check" 2>/dev/null || :)
+ git update-ref -d "refs/gcrypt/safety-check" 2>/dev/null || true
+
+ if isnull "$check_files"; then
+ return 0
+ fi
+
+ early_bad_files=$(echo "$check_files" | grep -v -E '^[a-f0-9]{56}$|^[a-f0-9]{64}$|^[a-f0-9]{96}$|^[a-f0-9]{128}$' || :)
+ if isnull "$early_bad_files"; then
+ return 0
+ fi
+
+ if [ "$(git config --bool gcrypt.allow-unencrypted-remote)" = "true" ]; then
+ return 0
+ fi
+
+ echo_info "ERROR: Remote repository contains unencrypted or unknown files!"
+ echo_info "To protect your privacy, git-remote-gcrypt will NOT push to this remote."
+ echo_info "Found unexpected files: $(echo "$early_bad_files" | head -n 3 | tr '\n' ' ')"
+ echo_info "To see unencrypted files, use: git-remote-gcrypt clean $URL"
+ echo_info "To fix and remove these files, use: git-remote-gcrypt clean --force $URL"
+ exit 1
+}
+
ensure_connected()
{
local manifest_="" r_repoid="" r_name="" url_frag="" r_sigmatch="" r_signers="" \
then
return
fi
-
- # EARLY SAFETY CHECK for gitception backends:
- # Before GPG validation, check if the remote has unencrypted files.
- if [ "$NAME" != "gcrypt-clean" ] && ! isurl sftp "$URL" && ! isurl rsync "$URL" && ! isurl rclone "$URL" && ! islocalrepo "$URL"; then
- local check_files=""
- git fetch --quiet "$URL" "refs/heads/master:refs/gcrypt/safety-check" 2>/dev/null ||
- git fetch --quiet "$URL" "refs/heads/main:refs/gcrypt/safety-check" 2>/dev/null || true
-
- if git rev-parse --verify "refs/gcrypt/safety-check" >/dev/null 2>&1; then
- check_files=$(git ls-tree --name-only "refs/gcrypt/safety-check" 2>/dev/null || :)
- git update-ref -d "refs/gcrypt/safety-check" 2>/dev/null || true
-
- if isnonnull "$check_files"; then
- early_bad_files=$(echo "$check_files" | grep -v -E '^[a-f0-9]{56}$|^[a-f0-9]{64}$|^[a-f0-9]{96}$|^[a-f0-9]{128}$' || :)
- if isnonnull "$early_bad_files"; then
- if [ "$(git config --bool gcrypt.allow-unencrypted-remote)" != "true" ]; then
- echo_info "ERROR: Remote repository contains unencrypted or unknown files!"
- echo_info "To protect your privacy, git-remote-gcrypt will NOT push to this remote."
- echo_info "Found unexpected files: $(echo "$early_bad_files" | head -n 3 | tr '\n' ' ')"
- echo_info "To see unencrypted files, use: git-remote-gcrypt clean $URL"
- echo_info "To fix and remove these files, use: git-remote-gcrypt clean --force $URL"
- exit 1
- fi
- fi
- fi
- fi
- fi
-
+
+ early_safety_check
+
Did_find_repo=no
print_debug "Calling read_config"
read_config @r_sigmatch @r_signers
done
}
-if [ "$NAME" = "gcrypt-check" ]; then
- resolve_url check
- 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" = "gcrypt-clean" ]; then
- resolve_url clean
- echo_info "Checking remote: $URL"
- setup
+cmd_clean()
+{
+ local remote_files="" valid_files="" bad_files="" f=""
+
if ! ensure_connected; then
echo_die "Could not connect to $URL."
fi
if [ "$Did_find_repo" != "yes" ]; then
- echo_die "Error: No gcrypt manifest found on remote '$URL'." \
- "Aborting clean to prevent accidental data loss."
+ if [ "${FORCE_INIT:-}" = "yes" ]; then
+ echo_info "WARNING: No gcrypt manifest found, but --init specified."
+ echo_info "WARNING: Proceeding to scan/clean potential unencrypted files."
+ else
+ echo_die "Error: No gcrypt manifest found on remote '$URL'." \
+ "Aborting clean to prevent accidental data loss."
+ fi
fi
# Get all files in the remote
git remote remove "$NAME" 2>/dev/null || true
echo_info "Done. Remote cleaned."
exit 0
+}
+
+if [ "$NAME" = "gcrypt-check" ]; then
+ resolve_url check
+ 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" = "gcrypt-clean" ]; then
+ resolve_url clean
+ echo_info "Checking remote: $URL"
+ setup
+ cmd_clean
elif [ "$1" = --version ] || [ "$1" = -v ]; then
echo "git-remote-gcrypt version $VERSION"
exit 0
# 1. Initialize a valid gcrypt repo
mkdir "$tempdir/valid.git" && cd "$tempdir/valid.git" && $GIT init --bare >/dev/null
+$GIT config user.email "test@test.com"
+$GIT config user.name "Test"
cd "$tempdir/client"
$GIT config user.name "Test"
$GIT config user.email "test@test.com"
# 2. Inject garbage file into the remote git index/tree
cd "$tempdir/valid.git"
-GREF="refs/gcrypt/gitception"
+GREF="refs/heads/master"
if ! $GIT rev-parse --verify "$GREF" >/dev/null 2>&1; then
print_err "Gref $GREF not found in remote!"
exit 1
assert_grep "gcrypt: Checking remote:" "$output" "check command is recognized"
print_success "All clean/check command tests passed!"
+
+# --------------------------------------------------
+# Test 7: clean --init (Bypass manifest check)
+# --------------------------------------------------
+print_info "Test 7: clean --init (Bypass manifest check)..."
+
+# Reuse the dirty remote from earlier ($tempdir/remote.git) which has secret1.txt and secret2.txt
+
+# 1. Standard clean should fail (as tested in Test 2)
+output=$("$SCRIPT_DIR/git-remote-gcrypt" clean "gcrypt::$tempdir/remote.git" 2>&1 || :)
+assert_grep "Error: No gcrypt manifest found" "$output" "standard clean fails on dirty remote"
+
+# 2. Clean with --init should succeed (scan only)
+output=$("$SCRIPT_DIR/git-remote-gcrypt" clean --init "gcrypt::$tempdir/remote.git" 2>&1 || :)
+assert_grep "WARNING: No gcrypt manifest found, but --init specified" "$output" "--init warns about missing manifest"
+assert_grep "Found the following files to remove" "$output" "--init scan found files"
+assert_grep "secret1.txt" "$output" "--init found secret1.txt"
+
+# 3. Clean with --init --force should remove files
+"$SCRIPT_DIR/git-remote-gcrypt" clean --init --force "gcrypt::$tempdir/remote.git" >/dev/null 2>&1
+
+cd "$tempdir/remote.git"
+if $GIT ls-tree HEAD | grep -q "secret1.txt"; then
+ print_err "--init --force FAILED to remove secret1.txt"
+ exit 1
+else
+ print_success "--init --force removed unencrypted files"
+fi