Functions/Send-HgChangeset.ps1


function Send-HgChangeset
{
    <#
    .SYNOPSIS
    Pushes changes to a central repository, optionally merging with any incoming changes.
     
    .DESCRIPTION
    Uses Mercurial's push command to push outgoing changes to the repository's source.
     
    If there are unsynced changes, the push will fail. Use the `Sync-HgRepository` function to synchronize (i.e. pull/merge/commit) changes in the remote repository.
 
    If the push is successful, the `$PsHg?` variable will be set to `$true`. If the push failed, `$PsHg?` will be `$false`.
 
    Returns the output from Mercurial. Since this output contains prompts, it is important that you not redirect or capture this output, but instead, let it flow to the user.
     
    ALIASES
      sdhgc, hgpush
       
    .OUTPUTS
    PsHg.PushResult.
 
    .LINK
    Get-HgOutgoingChangeset
     
    .LINK
    Sync-HgRepository
     
    .LINK
    Test-HgOutgoingChangeset
     
    .EXAMPLE
    Send-HgChangeset
     
    Pushes outgoing changes from the local repository.
     
    .EXAMPLE
    Send-HgChangesets -Revision stable
     
    Pushes outgoing changes for the `stable` branch. All unpushed ancestors of the `stable` branch are pushed.
    #>

    [CmdletBinding()]
    [OutputType([string[]])]
    param(
        [string]
        # The revision to push. It and all its ancestors will be pushed.
        $Revision,
        
        [string]
        # The bookmark to push.
        $Bookmark,
        
        [Switch]
        # Should be set if pushing a new branch.
        $NewBranch,
        
        [Parameter()]
        [string]
        # The path to the repository to push to.
        $Destination,

        [Switch]
        # Perform the push in non-interactive mode. This passes the `--noninteractive` flag to Mercurial so that it fails if it needs to prompt for any information.
        $NonInteractive,

        [Alias('Path')]
        [string]
        # The path to the repository being published. Defaults to the current directory.
        $RepoRoot = (Resolve-Path .)
    )

    Set-StrictMode -Version 'Latest'
    
    $repoDir = Resolve-HgRoot -Path $RepoRoot

    if( -not $repoDir )
    {
        return
    }
    
    $revisionArg = ''
    if( $Revision )
    {
        $revisionArg = '-r{0}' -f $Revision
    }

    $bookmarkArg = ''
    if ( $Bookmark )
    {
        $bookmarkArg = '-B{0}' -f $Bookmark
    }

    $newBranchArg = ''
    if( $NewBranch )
    {
        $newBranchArg = '--new-branch'
    }
    
    $destinationArg = ''
    if ( $Destination )
    {
        $destinationArg = '{0}' -f $Destination
    }

    $nonInteractiveArg = ''
    if( $NonInteractive )
    {
        $nonInteractiveArg = '--noninteractive'
    }

    Push-Location $repoDir

    $ignoreErrors = $false
    $errCount = 0
    if( $ErrorActionPreference -eq 'Ignore' )
    {
        $ignoreErrors = $true
        $ErrorActionPreference = 'SilentlyContinue'
        $errCount = $Global:Error.Count
    }

    try
    {
        $pushArgs = @(
                        $revisionArg,
                        $bookmarkArg,
                        $newBranchArg,
                        $destinationArg,
                        $nonInteractiveArg
                     )

        $Script:PsHg? = $false
        hg push $pushArgs 
        $hgExitCode = $LASTEXITCODE

        if( $hgExitCode -eq 0 )
        {
            $Script:PsHg? = $true
        }
        elseif( $hgExitCode -eq 1 )
        {
            # Mercurial returns 1 if a server-side hook fails, so we need to detect if the changes are still local or not
            if( -not (hg outgoing $destinationArg $revisionArg $bookmarkArg --template '{node}' -q) )
            {
                $Script:PsHg? = $true
            }
        }

        if( $ignoreErrors )
        {
            $ErrorActionPreference = 'Ignore'
            while( $Global:Error.Count -gt $errCount )
            {
                $Global:Error.RemoveAt(0)
            }
        }
    }
    finally
    {
        Pop-Location
    }
}

Set-Alias -Name 'Send-HgChangesets' -Value 'Send-HgChangeset'
Set-Alias -Name 'hgpush' -Value 'Send-HgChangeset'
Set-Alias -Name 'sdhgc' -Value 'Send-HgChangeset'