g-fork-setup.ps1

param(
    [Parameter(Position=0, ValueFromPipeline)]
    [string]$Upstream = ""
)

. (Join-Path $PSScriptRoot 'g-registry.ps1')

$repoRoot = Get-Location
$inRepo   = (git -C $repoRoot rev-parse --is-inside-work-tree 2>$null) -eq 'true'

function Get-UpstreamBase {
    param([string]$UpstreamRepo)
    $defaultBase = gh repo view $UpstreamRepo --json defaultBranchRef -q .defaultBranchRef.name 2>$null
    if (-not $defaultBase) { $defaultBase = 'main' }
    $null = gh api "repos/$UpstreamRepo/branches/develop" 2>$null
    if ($LASTEXITCODE -eq 0) { return 'develop' }
    return $defaultBase
}

function Write-ForkConfig {
    param([string]$Dir, [string]$UpstreamRepo, [string]$BaseBranch)
    $cfg = [ordered]@{ BaseBranch = $BaseBranch; Upstream = $UpstreamRepo; MergeStrategy = 'squash' }
    $cfg | ConvertTo-Json | Set-Content (Join-Path $Dir '.gitbox.json') -Encoding UTF8
}

if ($inRepo) {
    $existingCfg = Get-GitboxConfig -RepoPath $repoRoot
    if ($existingCfg.Upstream -and -not $Upstream) {
        Write-Host "fork mode already configured; upstream = $($existingCfg.Upstream)"
        exit 0
    }

    $upRemoteUrl = git -C $repoRoot remote get-url upstream 2>$null
    if (-not $Upstream) {
        if ($upRemoteUrl -match 'github\.com[:/]([^/]+/[^/]+?)(?:\.git)?$') {
            $Upstream = $Matches[1]
        } else {
            $originUrl = git -C $repoRoot remote get-url origin 2>$null
            if ($originUrl -match 'github\.com[:/]([^/]+/[^/]+?)(?:\.git)?$') {
                $Upstream = $Matches[1]
            }
        }
    }
    if (-not $Upstream) {
        Write-Host "fork-setup: cannot detect upstream; pass it explicitly: gitbox fork owner/repo"
        exit 1
    }

    if (-not $upRemoteUrl) {
        # Create the fork only. Letting gh wire the remotes (--remote) names them
        # using the configured git_protocol, which is 'ssh' on many machines and
        # breaks when gh is authenticated with an https token and the account has
        # no usable ssh key. We set https remotes ourselves below so push works.
        $forkOut = gh repo fork $Upstream --remote=false 2>&1
        if ($LASTEXITCODE -ne 0) {
            Write-Host "fork failed"
            if ($VerbosePreference -ne 'SilentlyContinue') { $forkOut | ForEach-Object { Write-Host " $_" } }
            exit 1
        }
        $me       = gh api user -q .login 2>$null
        if (-not $me) { Write-Host "fork-setup: cannot resolve your github login; run gh auth status"; exit 1 }
        $repoName = $Upstream -split '/' | Select-Object -Last 1
        # origin currently points at the parent (the clone source); repurpose it
        # as 'upstream' and point origin at the fork, both over https.
        $null = git -C $repoRoot remote add upstream "https://github.com/$Upstream.git" 2>&1
        $null = git -C $repoRoot remote set-url origin "https://github.com/$me/$repoName.git"
    } else {
        Write-Host "upstream remote already exists; skipping fork"
    }

    $baseBranch = Get-UpstreamBase -UpstreamRepo $Upstream
    Write-ForkConfig -Dir $repoRoot -UpstreamRepo $Upstream -BaseBranch $baseBranch
    Write-Host "fork ready |origin = fork |upstream = $Upstream |base = $baseBranch"
    exit 0
}

# Outside a repo: fork + clone
if (-not $Upstream) {
    Write-Host "fork-setup: provide upstream repo: gitbox fork owner/repo"
    exit 1
}

# Create the fork only. gh's --clone uses the configured git_protocol to build
# the clone URL; when that is 'ssh' (the common default) the clone fails for a
# token-authenticated user with no ssh key, leaving the fork on GitHub but
# nothing on disk. We clone over https explicitly so it works under token auth.
$forkOut = gh repo fork $Upstream --clone=false 2>&1
if ($LASTEXITCODE -ne 0) {
    Write-Host "fork failed"
    if ($VerbosePreference -ne 'SilentlyContinue') { $forkOut | ForEach-Object { Write-Host " $_" } }
    exit 1
}

$me         = gh api user -q .login 2>$null
if (-not $me) { Write-Host "fork-setup: cannot resolve your github login; run gh auth status"; exit 1 }
$repoName   = $Upstream -split '/' | Select-Object -Last 1
$newDir     = Join-Path $repoRoot $repoName

$cloneOut = git clone "https://github.com/$me/$repoName.git" $newDir 2>&1
if ($LASTEXITCODE -ne 0) {
    Write-Host "fork created but clone failed"
    if ($VerbosePreference -ne 'SilentlyContinue') { $cloneOut | ForEach-Object { Write-Host " $_" } }
    exit 1
}

# Clone set origin to the fork; add the parent as upstream so sync-fork works.
$null = git -C $newDir remote add upstream "https://github.com/$Upstream.git" 2>&1

$baseBranch = Get-UpstreamBase -UpstreamRepo $Upstream
Write-ForkConfig -Dir $newDir -UpstreamRepo $Upstream -BaseBranch $baseBranch

Write-Host "fork ready |cd $repoName"
exit 0