<# .SYNOPSIS Wire a local git repo to Gitea and push the current branch headlessly. .DESCRIPTION 1. Ensures the target Gitea repo exists (creates it if -CreateIfMissing). 2. Adds (or updates) a git remote pointing at Gitea. Default remote name is 'gitea' so it sits alongside a GitHub 'origin' without conflict. 3. Pushes the current branch with a one-shot Authorization header so the Gitea token is NOT persisted into .git/config or wincred. The token is injected via `git -c http.extraHeader=...` for the single push invocation only. credential.helper is blanked for that push so the helper does not prompt and does not cache the header. .PARAMETER AppPath Path to the local git working copy. Defaults to current directory. .PARAMETER Name Repository name on Gitea. Defaults to the basename of AppPath. .PARAMETER Owner Owner (user or org). Defaults to the authenticated Gitea user. .PARAMETER RemoteName Remote name to add/update. Default 'gitea'. .PARAMETER Branch Branch to push. Defaults to the current HEAD of AppPath. .PARAMETER CreateIfMissing Create the Gitea repo if it does not exist. If omitted and the repo is missing, the script aborts with a clear message. .PARAMETER Private Only used when -CreateIfMissing creates a new repo. .PARAMETER Force Skip the interactive confirmation before pushing. .EXAMPLE .\Sync-GiteaRemote.ps1 -AppPath .\my-app -CreateIfMissing .\Sync-GiteaRemote.ps1 -Name Proxmox-Coolify-Manager -RemoteName origin -Force #> param( [string]$AppPath = (Get-Location).Path, [string]$Name, [string]$Owner, [string]$RemoteName = "gitea", [string]$Branch, [switch]$CreateIfMissing, [switch]$Private, [switch]$Force ) $ErrorActionPreference = "Stop" $here = Split-Path -Parent $MyInvocation.MyCommand.Path $api = Join-Path $here "Invoke-GiteaApi.ps1" $newRepo = Join-Path $here "New-GiteaRepo.ps1" if ([string]::IsNullOrWhiteSpace($env:GITEA_TOKEN)) { throw "Set GITEA_TOKEN (and GITEA_URL) before running this. Load .\.env.local.ps1." } $repoPath = (Resolve-Path -LiteralPath $AppPath).ProviderPath if (-not (Test-Path -LiteralPath (Join-Path $repoPath ".git"))) { throw "Not a git repository: $repoPath" } $me = & $api -Path "/user" $effectiveOwner = if ($Owner) { $Owner } else { $me.login } $effectiveName = if ($Name) { $Name } else { (Split-Path -Leaf $repoPath) } if (-not $Branch) { $Branch = (& git -C $repoPath rev-parse --abbrev-ref HEAD).Trim() } if ([string]::IsNullOrWhiteSpace($Branch) -or $Branch -eq "HEAD") { throw "Could not determine current branch in $repoPath. Pass -Branch explicitly." } Write-Host "[*] repo=$effectiveOwner/$effectiveName branch=$Branch remote=$RemoteName" -ForegroundColor Cyan $repo = $null try { $repo = & $api -Path "/repos/$effectiveOwner/$effectiveName" } catch { if ($_.Exception.Message -notmatch "404") { throw } $repo = $null } if (-not $repo) { if (-not $CreateIfMissing) { throw "Gitea repo $effectiveOwner/$effectiveName does not exist. Re-run with -CreateIfMissing, or create it first with New-GiteaRepo.ps1." } Write-Host "[*] Creating missing repo $effectiveOwner/$effectiveName ..." -ForegroundColor Cyan & $newRepo -Name $effectiveName -Owner $effectiveOwner -Private:$Private -NoAutoInit | Out-Null $repo = & $api -Path "/repos/$effectiveOwner/$effectiveName" } $giteaHost = if ($env:GITEA_URL) { $env:GITEA_URL.TrimEnd("/") } else { "https://gitea-hjwh0svsoo9p5w5kj2j6b1bd.urieljareth.org" } $remoteUrl = "$giteaHost/$effectiveOwner/$effectiveName.git" $existingRemote = $null try { $existingRemote = & git -C $repoPath remote get-url $RemoteName 2>$null } catch { $existingRemote = $null } if ($existingRemote) { if ($existingRemote.Trim() -ne $remoteUrl) { Write-Host "[*] Updating remote '$RemoteName' URL -> $remoteUrl" -ForegroundColor Yellow & git -C $repoPath remote set-url $RemoteName $remoteUrl } else { Write-Host "[*] Remote '$RemoteName' already -> $remoteUrl" -ForegroundColor DarkGray } } else { Write-Host "[*] Adding remote '$RemoteName' -> $remoteUrl" -ForegroundColor Cyan & git -C $repoPath remote add $RemoteName $remoteUrl } if (-not $Force) { $answer = Read-Host "Push '$Branch' to $RemoteName ($effectiveOwner/$effectiveName)? [y/N]" if ($answer -notmatch '^[yY]') { Write-Host "Aborted (no push)." -ForegroundColor Yellow return } } Write-Host "[*] Pushing $Branch -> $RemoteName ..." -ForegroundColor Cyan $env:GIT_TERMINAL_PROMPT = "0" & git -C $repoPath ` -c "http.extraHeader=Authorization: token $env:GITEA_TOKEN" ` -c "credential.helper=" ` push -u $RemoteName $Branch $pushExit = $LASTEXITCODE if ($pushExit -ne 0) { throw "git push failed (exit $pushExit). Check the token scopes (needs 'write:repository')." } Write-Host "" Write-Host "[OK] Pushed to $($repo.html_url)" -ForegroundColor Green Write-Host " remote '$RemoteName' -> $remoteUrl"