Modules/businessdev.ALbuild.Core/Private/Get-BcHighestClaimedVersion.ps1

function Get-BcHighestClaimedVersion {
    <#
    .SYNOPSIS
        Returns the highest build/<Major>.<Minor>.* version already claimed on the remote.
    .DESCRIPTION
        Internal helper for Invoke-BcBuildVersionStamp. Build branches are never merged back, so the
        version in app.json lags behind the versions already claimed as build/* branches. Reading the
        highest existing branch for the target Major.Minor lets the stamp start just above it instead
        of re-probing from the app.json version one push at a time every build.
 
        Read-only and failure-tolerant: a missing remote, no matching branches, or a git error returns
        $null, and the caller keeps its computed start version (the claim loop still covers conflicts).
    .PARAMETER RepositoryRoot
        The git working tree.
    .PARAMETER Remote
        The remote to query.
    .PARAMETER BranchPrefix
        Build branch name prefix (e.g. 'build/').
    .PARAMETER Major
        Major version to match. Ignored with -AcrossLines.
    .PARAMETER Minor
        Minor version to match. Ignored with -AcrossLines.
    .PARAMETER AcrossLines
        Drop the Major.Minor filter and return the branch with the highest BUILD component across every
        build branch in the repository (ties broken by the full version). This is what a continuous build
        number needs: the counter must survive a Major.Minor bump, where the new line has no branch yet
        and a line-scoped lookup would restart it at 1. The returned version can therefore belong to a
        different line than the caller's - only its Build component is meaningful then.
    #>

    [CmdletBinding()]
    [OutputType([version])]
    param(
        [Parameter(Mandatory)] [string] $RepositoryRoot,
        [Parameter(Mandatory)] [string] $Remote,
        [Parameter(Mandatory)] [string] $BranchPrefix,
        [Parameter(Mandatory)] [int] $Major,
        [Parameter(Mandatory)] [int] $Minor,
        [switch] $AcrossLines
    )

    $ls = Invoke-BcGit -RepositoryRoot $RepositoryRoot -Arguments @('ls-remote', '--heads', $Remote, "$BranchPrefix*") -AllowFailure
    if (-not $ls.Success -or [string]::IsNullOrWhiteSpace($ls.StdOut)) { return $null }

    # Each line is "<sha>\trefs/heads/<BranchPrefix><version>"; keep the versions for this Major.Minor.
    $refPrefix = "refs/heads/$BranchPrefix"
    $highest = $null
    foreach ($line in ($ls.StdOut -split "`r?`n")) {
        $trimmed = $line.Trim()
        if (-not $trimmed) { continue }
        $idx = $trimmed.IndexOf($refPrefix)
        if ($idx -lt 0) { continue }
        $name = $trimmed.Substring($idx + $refPrefix.Length).Trim()
        $parsed = $null
        if (-not [version]::TryParse($name, [ref] $parsed)) { continue }
        if (-not $AcrossLines -and ($parsed.Major -ne $Major -or $parsed.Minor -ne $Minor)) { continue }
        if ($null -eq $highest) { $highest = $parsed; continue }
        # Across lines the comparison is on the BUILD component alone - a plain version comparison would
        # pick 19.0.2.0 over 18.12.540.0 and hand the caller a counter that goes backwards.
        $isHigher = if ($AcrossLines) {
            $candidate = [Math]::Max($parsed.Build, 0)
            $incumbent = [Math]::Max($highest.Build, 0)
            ($candidate -gt $incumbent) -or ($candidate -eq $incumbent -and $parsed -gt $highest)
        }
        else { $parsed -gt $highest }
        if ($isHigher) { $highest = $parsed }
    }
    return $highest
}