BladeSzaSza's picture
upodate Claude code and hf upload file
5086899 verified
Raw
History Blame
3.17 kB
#!/usr/bin/env bash
# Upload the FormScout source tree to both the model repo and the Space.
#
# Usage:
# ./scripts/hf_upload.sh # message from last git commit
# ./scripts/hf_upload.sh "feat: my change" # custom message
#
# Pushes to:
# silas-therapy/small-functional-movement-screening (model repo)
# spaces/silas-therapy/small-functional-movement-screening (Gradio Space)
#
# `hf upload` does NOT read .hfignore β€” it only honors .gitignore, and only at
# commit time (after hashing and pre-uploading everything). So we parse
# .hfignore ourselves into --exclude globs and pass them explicitly.
#
# If the filtered file count still exceeds LARGE_THRESHOLD, we fall back to
# `hf upload-large-folder` (resumable, multi-threaded). Caveats of that mode:
# no --create-pr and no custom commit message β€” it commits directly to main
# in multiple commits.
set -euo pipefail
cd "$(dirname "$0")/.."
MODEL_REPO="silas-therapy/small-functional-movement-screening"
SPACE_REPO="spaces/silas-therapy/small-functional-movement-screening"
MSG="${1:-$(git log -1 --pretty=%s)}"
LARGE_THRESHOLD="${FORMSCOUT_HF_LARGE_THRESHOLD:-500}"
# Belt-and-suspenders extras on top of .hfignore. `.cache/` is the resume
# state upload-large-folder writes into the folder being uploaded.
PATTERNS=(
"*.pdf"
"**/node_modules/**"
".cache/**"
)
# Parse .hfignore into fnmatch-style globs. fnmatch's `*` crosses `/`, but a
# bare name like `.DS_Store` or `dir/` only matches at the root, so emit both
# the rooted and `**/`-prefixed forms.
while IFS= read -r line; do
line="${line%%#*}"
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
[[ -z "$line" ]] && continue
if [[ "$line" == */ ]]; then
PATTERNS+=("${line}**" "**/${line}**")
else
PATTERNS+=("$line" "**/$line")
fi
done < .hfignore
EXCLUDES=()
for p in "${PATTERNS[@]}"; do
EXCLUDES+=(--exclude="$p")
done
# Count what would actually be uploaded, using the same filter the hub client
# applies, so the mode decision matches reality.
N_FILES=$(python3 - "${PATTERNS[@]}" <<'EOF'
import sys
from pathlib import Path
from huggingface_hub.utils import filter_repo_objects
patterns = sys.argv[1:]
files = (
str(p) for p in Path(".").rglob("*")
if p.is_file() and p.parts[0] != ".git"
)
print(len(list(filter_repo_objects(files, ignore_patterns=patterns))))
EOF
)
echo "── $N_FILES files to upload after .hfignore filtering"
if (( N_FILES == 0 )); then
echo "βœ— nothing to upload β€” check .hfignore" >&2
exit 1
fi
upload_repo() {
local repo="$1"
if (( N_FILES > LARGE_THRESHOLD )); then
echo "── $repo: $N_FILES files > $LARGE_THRESHOLD, using upload-large-folder"
echo " (resumable; commits directly to main β€” no PR, no custom message)"
hf upload-large-folder "$repo" . "${EXCLUDES[@]}"
else
echo "── uploading to: $repo"
hf upload "$repo" . . \
"${EXCLUDES[@]}" \
--create-pr \
--commit-message="$MSG"
fi
}
upload_repo "$MODEL_REPO"
upload_repo "$SPACE_REPO"
echo "βœ“ done"