functions/git/Get-GitUrl.ps1

function Get-GitUrl {
    <#
.SYNOPSIS
Retrieves the download URL for the latest Git for Windows release from GitHub.
 
.DESCRIPTION
The Get-GitUrl function queries the official Git for Windows GitHub repository and returns
the appropriate download URL for the latest release, based on selected architecture,
variant (Minimal, Portable, Busybox), and file format.
 
.PARAMETER Architecture
Specifies the desired system architecture. Valid values are '64', '32', or 'arm64'.
Defaults to '64'.
 
.PARAMETER Minimal
If specified, selects the minimal Git version (MinGit).
Only available in format 'zip'.
 
.PARAMETER Busybox
If specified, selects the busybox-based MinGit build.
Only available for minimal 64-bit and 32-bit architectures and format 'zip'.
 
.PARAMETER Portable
If specified, selects the portable Git version (PortableGit).
Only available in format 'exe'.
 
.PARAMETER Format
Specifies the file extension/format. Valid values are 'zip', 'exe', or 'tar.bz2'.
Defaults to 'exe'. Format 'tar.bz2' is only available for the default (full) Git variant.
 
.EXAMPLE
Get-GitUrl
Returns the URL for the latest 64-bit full Git installer as exe (Git-*-64-bit.exe).
 
.EXAMPLE
Get-GitUrl -Minimal -Architecture 64
Returns the URL for the latest 64-bit MinGit as zip.
 
.EXAMPLE
Get-GitUrl -Busybox -Architecture 32
Returns the URL for the latest 32-bit busybox-based MinGit as zip.
 
.EXAMPLE
Get-GitUrl -Portable
Returns the URL for the latest 64-bit PortableGit in .7z.exe format.
 
.EXAMPLE
Get-GitUrl -Format tar.bz2 -Architecture arm64
Returns the URL for the latest arm64 Git tar.bz2 archive (default Git, no MinGit/Portable).
 
.NOTES
Author: Jascha Vincke
GitHub API used: https://api.github.com/repos/git-for-windows/git/releases/latest
 
Supported combinations:
- MinGit (.zip) → 64/32/arm64
- MinGit + Busybox (.zip) → 64/32 only
- PortableGit (.7z.exe) → 64/arm64 only
- tar.bz2 → only full Git, 64/arm64, no MinGit/Portable
 
.LINK
https://github.com/git-for-windows/git
#>

    [CmdletBinding()]
    param (
        [ValidateSet('64', '32', 'arm64')]
        [string]$Architecture = '64',

        [switch]$Minimal,
        [switch]$Busybox,
        [switch]$Portable,

        [ValidateSet('zip', 'exe', 'tar.bz2')]
        [string]$Format = 'exe'
    )

    # Auto-correct invalid combinations with warnings
    if ($Busybox -and -not $Minimal) {
        Write-Warning "-Busybox implies -Minimal. Enabling -Minimal."
        $Minimal = $true
    }

    if ($Busybox -and $Architecture -eq 'arm64') {
        throw "-Busybox variant is only available for 32-bit and 64-bit architectures."
    }

    if ($Minimal -and $Architecture -eq 'arm64') {
        throw "MinGit is not available for arm64 architecture."
    }

    if ($Portable -and $Architecture -eq '32') {
        throw "PortableGit is not available for 32-bit architecture."
    }

    if ($Portable -and $Architecture -eq 'arm64' -and $Format -ne 'exe') {
        throw "PortableGit for arm64 is only available as '.7z.exe'. Use -Format exe."
    }


    if ($Format -eq 'tar.bz2' -and ($Minimal -or $Portable -or $Busybox)) {
        Write-Warning "Format 'tar.bz2' is only available for the full Git variant (no -Minimal, -Portable, or -Busybox). Switching format to 'exe'."
        $Format = 'exe'
    }

    if ($Busybox -and $Format -ne 'zip') {
        Write-Warning "-Busybox is only supported with format 'zip'. Switching format to 'zip'."
        $Format = 'zip'
    }

    if ($Minimal -and $Format -ne 'zip') {
        Write-Warning "-Minimal is only supported with format 'zip'. Switching format to 'zip'."
        $Format = 'zip'
    }

    if ($Portable -and $Format -ne 'exe') {
        Write-Warning "-Portable is only supported with format 'exe'. Switching format to 'exe'."
        $Format = 'exe'
    }

    if (-not $Minimal -and -not $Portable -and $Format -eq 'zip' -and $Architecture -eq '32') {
        Write-Warning "Default Git for 32-bit does not exist in .zip format. Enabling -Minimal."
        $Minimal = $true
    }

    if (-not $Minimal -and -not $Portable -and $Format -eq 'exe' -and $Architecture -eq '32') {
        Write-Warning "Default Git installer (.exe) is not available for 32-bit. Enabling -Minimal and switching format to 'zip'."
        $Minimal = $true
        $Format = 'zip'
    }

    # Build pattern
    if ($Architecture -ne 'arm64') { $arch = "$Architecture-bit" } else { $arch = $Architecture }
    $pattern = switch ($true) {
        $Minimal {
            if ($Busybox) {
                "MinGit-*-busybox-$arch.$Format"
            }
            else {
                "MinGit-*$arch.$Format"
            }
        }
        $Portable {
            "PortableGit-*$arch.7z.$Format"
        }
        default {
            if ($Format -eq 'tar.bz2') {
                "Git-*$arch.$Format"
            }
            else {
                "Git-*$arch.$Format"
            }
        }
    }

    # Query GitHub release
    $latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/git-for-windows/git/releases/latest"
    $asset = $latestRelease.assets | Where-Object { $_.name -like $pattern } | Select-Object -First 1

    if (-not $asset) {
        throw "No matching Git download found for pattern '$pattern'."
    }

    return $asset.browser_download_url
}