Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 13 additions & 19 deletions scripts/clean-gh-pages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,30 @@ set -e # Exit on error

echo "Starting gh-pages branch cleanup..."

REMOVE_PATHS_FILE="/tmp/remove-paths.txt"
> "$REMOVE_PATHS_FILE"

dirs_with_visible_files=$(git ls-tree -r origin/gh-pages:pr-preview --name-only 2>/dev/null | \
grep -v '/\.' | \
cut -d/ -f1 | \
sort -u || true)

all_dirs=$(git ls-tree -d origin/gh-pages:pr-preview --name-only 2>/dev/null || true)

if [ -z "$all_dirs" ]; then
echo "No directories found in pr-preview or pr-preview does not exist"
rm "$REMOVE_PATHS_FILE"
exit 0
fi

while IFS= read -r dir; do
if [ -n "$dir" ]; then
if ! echo "$dirs_with_visible_files" | grep -q "^${dir}$"; then
dir_path="pr-preview/$dir"
echo "Found directory to remove: $dir_path"
echo "$dir_path" >> "$REMOVE_PATHS_FILE"
fi
fi
done <<< "$all_dirs"

Comment on lines 13 to 20
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable all_dirs is used in the while loop but is never defined. The line that previously defined it (all_dirs=$(git ls-tree -d origin/gh-pages:pr-preview --name-only 2>/dev/null || true)) was removed in this change. This will cause the while loop to process an empty string, making lines 13-20 effectively dead code that never executes.

Copilot uses AI. Check for mistakes.
if [ ! -s "$REMOVE_PATHS_FILE" ]; then
echo "No empty or hidden-file-only directories found. Nothing to clean up."
rm "$REMOVE_PATHS_FILE"
exit 0
fi

uvx git-filter-repo@2.47.0 --paths-from-file "$REMOVE_PATHS_FILE" --invert-paths --refs origin/gh-pages
CALLBACK="
root, *rest = filename.split(b'/')
keep = b'''$dirs_with_visible_files'''.splitlines()
if root != b'pr-preview':
# keep anything outside of pr-preview
return filename
elif rest and rest[0] not in keep:
return None
else:
return filename
"
Comment on lines +21 to +31
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Embedding dirs_with_visible_files directly into the CALLBACK Python snippet via b'''$dirs_with_visible_files''' allows unescaped directory names from origin/gh-pages:pr-preview to become executable Python code. A malicious directory name containing a sequence like '''; __import__('os').system('...') # could break out of the bytes literal and execute arbitrary commands in the context of uvx git-filter-repo. To fix this, avoid inlining raw directory names into the callback code and instead pass them as data (for example via an environment variable, temp file, or proper escaping) so they are not interpreted as Python source.

Copilot uses AI. Check for mistakes.

uvx git-filter-repo@2.47.0 --filename-callback "$CALLBACK" --refs origin/gh-pages
Loading