Spaces:
Running
Running
| param( | |
| [string]$Message = "", | |
| [switch]$PullOnly, | |
| [switch]$Verbose | |
| ) | |
| if ($Message -eq "" -and -not $PullOnly) { | |
| $Message = "Update " + (Get-Date -Format "yyyy-MM-dd HH:mm:ss") | |
| } | |
| # Check HF_TOKEN | |
| if (-not $env:HF_TOKEN -or $env:HF_TOKEN.Trim().Length -lt 10) { | |
| Write-Host "Error: HF_TOKEN not set or invalid" | |
| Write-Host "Set with: [Environment]::SetEnvironmentVariable('HF_TOKEN','YOUR_TOKEN','User')" | |
| exit 1 | |
| } | |
| $repoRoot = git rev-parse --show-toplevel 2>$null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Error: Not a git repository" | |
| exit 1 | |
| } | |
| Set-Location $repoRoot | |
| # Get HF info from remote | |
| $hfRemote = git remote get-url huggingface 2>$null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Error: Hugging Face remote not configured" | |
| exit 1 | |
| } | |
| if ($hfRemote -match 'huggingface\.co/spaces/([^/]+)/(.+?)(?:\.git)?$') { | |
| $hfUser = $Matches[1] | |
| $hfSpace = $Matches[2] | |
| } else { | |
| Write-Host "Error: Cannot parse HF remote" | |
| exit 1 | |
| } | |
| Write-Host "`n=== 3-Way Sync: Local <-> GitHub <-> HF ===`n" | |
| function Get-RemoteCommit($remote) { | |
| $commit = git rev-parse "$remote/main" 2>$null | |
| if ($LASTEXITCODE -eq 0) { return $commit } | |
| return $null | |
| } | |
| function Get-RemoteDate($remote) { | |
| $date = git log $remote/main -1 --format=%ci 2>$null | |
| if ($LASTEXITCODE -eq 0) { return [datetime]$date } | |
| return [datetime]::MinValue | |
| } | |
| # Stage any local changes | |
| git add -A | |
| # Fetch from both remotes | |
| Write-Host "Fetching from remotes..." | |
| git fetch github 2>$null | |
| $ghExists = $LASTEXITCODE -eq 0 | |
| git fetch huggingface 2>$null | |
| $hfExists = $LASTEXITCODE -eq 0 | |
| if (-not $ghExists -and -not $hfExists) { | |
| Write-Host "No remotes found (first push)" | |
| $isFirstPush = $true | |
| } else { | |
| $isFirstPush = $false | |
| } | |
| # Check for local uncommitted changes | |
| git diff HEAD --quiet | |
| $hasLocalChanges = $LASTEXITCODE -ne 0 | |
| # TRUE 3-WAY SYNC: Merge both remotes | |
| if (-not $isFirstPush) { | |
| $localCommit = git rev-parse HEAD 2>$null | |
| $ghCommit = Get-RemoteCommit "github" | |
| $hfCommit = Get-RemoteCommit "huggingface" | |
| $ghDate = Get-RemoteDate "github" | |
| $hfDate = Get-RemoteDate "huggingface" | |
| Write-Host "Status:" | |
| if ($ghExists) { Write-Host " GitHub: $($ghDate.ToString('yyyy-MM-dd HH:mm'))" } | |
| if ($hfExists) { Write-Host " HuggingFace: $($hfDate.ToString('yyyy-MM-dd HH:mm'))" } | |
| Write-Host "" | |
| # Check if we need to merge GitHub | |
| if ($ghExists -and $ghCommit -and $localCommit -ne $ghCommit) { | |
| Write-Host "Merging from GitHub..." | |
| if ($hasLocalChanges) { | |
| git commit -m "Local changes before merge" 2>$null | Out-Null | |
| } | |
| git merge github/main --no-edit 2>&1 | Out-Null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "[!] Merge conflict with GitHub. Keeping local version..." | |
| git merge --abort 2>$null | |
| } else { | |
| Write-Host "[OK] Merged from GitHub" | |
| } | |
| } | |
| # Check if we need to merge HuggingFace | |
| $localCommit = git rev-parse HEAD 2>$null | |
| if ($hfExists -and $hfCommit -and $localCommit -ne $hfCommit) { | |
| Write-Host "Merging from HuggingFace..." | |
| git diff HEAD --quiet | |
| if ($LASTEXITCODE -ne 0) { | |
| git commit -m "Local changes before HF merge" 2>$null | Out-Null | |
| } | |
| git merge huggingface/main --no-edit 2>&1 | Out-Null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "[!] Merge conflict with HuggingFace. Keeping local version..." | |
| git merge --abort 2>$null | |
| } else { | |
| Write-Host "[OK] Merged from HuggingFace" | |
| } | |
| } | |
| # Check if everything is in sync | |
| $localCommit = git rev-parse HEAD 2>$null | |
| if ($ghCommit -and $hfCommit -and $localCommit -eq $ghCommit -and $localCommit -eq $hfCommit) { | |
| Write-Host "[OK] All locations in sync" | |
| } | |
| } | |
| if ($PullOnly) { | |
| Write-Host "`n[OK] Pull complete`n" | |
| exit 0 | |
| } | |
| # Commit any remaining changes | |
| git diff HEAD --quiet | |
| if ($LASTEXITCODE -ne 0) { | |
| git commit -m $Message | |
| Write-Host "[OK] Committed: $Message" | |
| } else { | |
| # Check if we have commits to push | |
| $localCommit = git rev-parse HEAD 2>$null | |
| $needsPush = $false | |
| if ($ghExists) { | |
| $ghCommit = Get-RemoteCommit "github" | |
| if ($localCommit -ne $ghCommit) { $needsPush = $true } | |
| } else { | |
| $needsPush = $true | |
| } | |
| if ($hfExists) { | |
| $hfCommit = Get-RemoteCommit "huggingface" | |
| if ($localCommit -ne $hfCommit) { $needsPush = $true } | |
| } else { | |
| $needsPush = $true | |
| } | |
| if (-not $needsPush) { | |
| Write-Host "`n[OK] Already up-to-date, nothing to push`n" | |
| exit 0 | |
| } | |
| } | |
| # Push to both remotes | |
| Write-Host "`nPushing to remotes..." | |
| # Push to GitHub | |
| git push github main 2>&1 | Out-Null | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Host "[OK] GitHub" | |
| } else { | |
| git push github main --force 2>&1 | Out-Null | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Host "[OK] GitHub (forced)" | |
| } else { | |
| Write-Host "[ERROR] GitHub failed" | |
| } | |
| } | |
| # Push to HuggingFace | |
| $hfUrl = "https://${hfUser}:$($env:HF_TOKEN)@huggingface.co/spaces/${hfUser}/${hfSpace}" | |
| if ($Verbose) { | |
| Write-Host "Debug: Pushing to spaces/${hfUser}/${hfSpace}" | |
| git push $hfUrl main --force 2>&1 | |
| } else { | |
| git push $hfUrl main --force 2>&1 | Out-Null | |
| } | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Host "[OK] Hugging Face: spaces/${hfUser}/${hfSpace}" | |
| } else { | |
| Write-Host "[ERROR] Hugging Face FAILED!" | |
| Write-Host "`nTroubleshooting:" | |
| Write-Host "1. Does the space exist? https://huggingface.co/spaces/${hfUser}/${hfSpace}" | |
| Write-Host "2. Is your token valid? (HF Settings > Access Tokens)" | |
| Write-Host "3. Does your token have write permission?" | |
| Write-Host "4. Run with -Verbose flag for details" | |
| exit 1 | |
| } | |
| Write-Host "`n[OK] Sync complete`n" |