update clean tests/edge cases
authorShane Jaroch <chown_tee@proton.me>
Sat, 17 Jan 2026 01:59:35 +0000 (20:59 -0500)
committerShane Jaroch <chown_tee@proton.me>
Sat, 17 Jan 2026 01:59:35 +0000 (20:59 -0500)
git-remote-gcrypt
tests/system-test-clean-cmd.sh [new file with mode: 0644]

index ff1e9283037a44b04de25da7f618c5ab32d98f5a..9490aeb275c7db1a2e0708af0a3a3df7194c5ca5 100755 (executable)
@@ -388,7 +388,7 @@ update_tree()
        local tab_="    "
        # $2 is a filename from the repo format
        (set +e;
-               git ls-tree "$1" | xgrep -v -E '\b'"$2"'$';
+               git -c core.quotePath=false ls-tree "$1" | awk -F'\t' -v f="$2" '$2 != f'
                xecho "100644 blob $3$tab_$2"
        ) | git mktree
 }
@@ -408,11 +408,21 @@ gitception_put()
 # depends on previous GET like put
 gitception_remove()
 {
-       local tree_id="" commit_id="" tab_="    "
-       # $2 is a filename from the repo format
-       tree_id=$(git ls-tree "$Gref" | awk -F'\t' -v f="$2" '$2 != f' | git mktree) &&
-               commit_id=$(anon_commit "$tree_id") &&
-               git update-ref "$Gref" "$commit_id"
+       local tree_id="" commit_id="" temp_index=""
+       temp_index=$(mktemp)
+       
+       # Use temporary index to cleanly remove file (handles recursion)
+       (
+               export GIT_INDEX_FILE="$temp_index"
+               git read-tree "$Gref"
+               git rm --cached --ignore-unmatch -q "$2"
+               tree_id=$(git write-tree)
+               if [ "$tree_id" != "$(git rev-parse "$Gref^{tree}")" ]; then
+                       commit_id=$(anon_commit "$tree_id") &&
+                       git update-ref "$Gref" "$commit_id"
+               fi
+       )
+       rm -f "$temp_index"
 }
 
 gitception_new_repo()
diff --git a/tests/system-test-clean-cmd.sh b/tests/system-test-clean-cmd.sh
new file mode 100644 (file)
index 0000000..930bd3e
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+# tests/test-clean-complex.sh
+# Verifies clean command on filenames with spaces and parentheses.
+
+TEST_DIR=$(dirname "$0")
+BIN="$TEST_DIR/../git-remote-gcrypt"
+git_remote_gcrypt() {
+       bash "$BIN" "$@"
+}
+
+# Setup temp environment
+TMPDIR=$(mktemp -d)
+trap 'rm -rf "$TMPDIR"' EXIT
+
+# Create a "remote" bare repo to simulate git backend
+REMOTE_REPO="$TMPDIR/remote.git"
+git init --bare "$REMOTE_REPO" >/dev/null
+
+# Create a commit in the remote with "garbage" files
+# We need to simulate how git-remote-gcrypt stores files (in refs/gcrypt/...)
+# or just in master if it's a raw repo being cleaned?
+# If we run clean --init, we are cleaning a raw repo. So files are in HEAD (or master/main).
+
+# Helper to create commit
+(
+       cd "$TMPDIR" || exit 1
+       mkdir worktree
+       cd worktree || exit 1
+       git init >/dev/null
+       git remote add origin "$REMOTE_REPO"
+
+       # Create files with spaces and parens
+       mkdir -p ".csv"
+       touch ".csv/sheet-shanes-secondary-sheets-Univ Grades (OU).csv"
+       touch "normal.txt"
+
+       git add .
+       git commit -m "Initial commit with garbage" >/dev/null
+       git push origin master >/dev/null
+)
+
+URL="file://$REMOTE_REPO"
+
+echo "--- Status before clean ---"
+# We can use git ls-tree on remote to verify
+git --git-dir="$REMOTE_REPO" ls-tree -r master --name-only
+
+echo "--- Running clean --init --force ---"
+OUTPUT=$(git_remote_gcrypt clean --init --force "$URL" 2>&1)
+EXIT_CODE=$?
+echo "$OUTPUT"
+
+if [ $EXIT_CODE -ne 0 ]; then
+       echo "FAIL: clean command failed."
+       exit 1
+fi
+
+echo "--- Status after clean ---"
+FILES=$(git --git-dir="$REMOTE_REPO" ls-tree -r master --name-only)
+echo "$FILES"
+
+if [[ $FILES == *".csv"* ]]; then
+       # We expect the file to be GONE.
+       # Note: clean --init --force deletes ALL files (because map is not found)
+       # So if there are ANY files left, it's a fail.
+       # But clean command actually updates the refs (typically master or refs/gcrypt/...).
+       # Wait, git-remote-gcrypt clean cleans "refs/heads/master" or "refs/heads/main" if mapped?
+       # No, it checks what files are there.
+       # If standard remote, it might be cleaning HEAD?
+
+       # Let's check if the file persists.
+       if echo "$FILES" | grep -q "Univ Grades"; then
+               echo "FAIL: The complex filename was NOT removed."
+               exit 1
+       fi
+fi
+
+if [ -z "$FILES" ]; then
+       echo "PASS: All files removed."
+else
+       # It might leave an empty tree or commit?
+       echo "FAIL: Files persist: $FILES"
+       exit 1
+fi