Functions/Save-HgChangeset.ps1


function Save-HgChangeset
{
    <#
    .SYNOPSIS
    Commits changes in a Mercurial repository.
     
    .DESCRIPTION
    Commits all uncommitted changes at the paths passed to the -Path parameter. If no path parameter is given, commits everything under the current directory.
     
    ALIASES
      svhgc, hgci, hgcommit
 
    .OUTPUTS
    PsHg.ChangesetInfo.
       
    .EXAMPLE
    Save-HgChanges -Message "Here are some changes!"
     
    Commits all uncommitted changes under the current directory.
     
    .EXAMPLE
    Save-HgChanges -Message "And some more changes!" -Path .\Website,.\Libraries
     
    Commits all uncommitted changes under the current directory.
     
    .EXAMPLE
    Save-HgChanges -Message "And some more changes over there!" -Path C:\Projects\psHg\Test
     
    Commits all committed changes in the psHg repository's Test directory.
    #>

    [CmdletBinding(SupportsShouldProcess=$true,DefaultParameterSetName='AllChanges')]
    [OutputType([PsHg.ChangesetInfo])]
    param(
        [Parameter(Mandatory=$true,Position=1)]
        [Alias('m')]
        [string]
        # The commit message.
        $Message,
        
        [Parameter(Mandatory=$true,ParameterSetName='SomeChanges',Position=2)]
        [string[]]
        # The paths to commit. They must all point to the same repository. Default is everything in the current repository.
        $Path,
        
        [string]
        # The user to record for the commit.
        $User,
        
        [Switch]
        # Close the current branch.
        $CloseBranch,
        
        [string[]]
        # Files/patterns to include.
        $Include,

        [string[]]
        # Files/patterns to exclude.
        $Exclude,

        [Parameter(ParameterSetName='AllChanges')]
        [string]
        # Commit all changes in this repository. Default is the current repository.
        $RepoRoot = (Get-Location).Path
    )

    $includeParam = @()
    if ( $Include )
    {
        $includeParam = $Include | ForEach-Object {"-I{0}" -f $_}
    }

    $excludeParam = @()
    if ( $Exclude )
    {
        $excludeParam = $Exclude | ForEach-Object {"-X{0}" -f $_} 
    }

    if( $pscmdlet.ParameterSetName -eq 'AllChanges' )
    {
        $RepoRoot = Resolve-HgRoot -Path $RepoRoot
        if( -not $RepoRoot )
        {
            return
        }
    }
    else
    {
        $RepoRoot = $null
        foreach( $commitPath in $Path )
        {
            if( -not $RepoRoot )
            {
                $RepoRoot = Resolve-HgRoot -Path $commitPath
                if( -not $RepoRoot )
                {
                    return
                }
            }
            else
            {
                $otherRepoRoot = Resolve-HgRoot -Path $commitPath
                if( $RepoRoot -ne $otherRepoRoot )
                {
                    Write-Error ("Can't commit to multiple repositories: {0} <=> {1}" -f $RepoRoot,$otherRepoRoot)
                    return
                }
            }
        }
    }
        
    $userArgName = ''
    $userArgValue = ''
    if( $User )
    {
        $userArgName = '--user'
        $userArgValue = $User
    }
    
    Push-Location $RepoRoot
    try
    {

        $hgPaths = @()
        if( $pscmdlet.ParameterSetName -eq 'SomeChanges' )
        {
            $pathIsRepoRoot = $Path | Where-Object { Test-Path -Path $_ } | Resolve-Path | Where-Object { $_.Path -eq $RepoRoot }
            if( -not $pathIsRepoRoot )
            {            
                $Path | 
                    Resolve-HgPath -ErrorAction Stop | 
                    ForEach-Object { Write-Verbose ('Checking {0} for uncommitted changes.' -f $_) ; $_ } |
                    Where-Object { Test-HgUncommittedChangeset -Path $_ } | 
                    Tee-Object -Variable hgPaths |
                    ForEach-Object { Write-Verbose ('{0} has uncommitted changes.' -f $_) }
                        
                if( -not $hgPaths )
                {
                    Write-Warning ('There are no uncommitted changes in {0}.' -f ($Path -join ', '))
                    return
                }
            }
        }
                
        $closeBranchArg = ''
        if( $CloseBranch )
        {
            $closeBranchArg = '--close-branch'
        }
        
        if( $pscmdlet.ShouldProcess( $hgPaths, 'hg commit' ) )
        {
            Write-Verbose "hg commit $closeBranchArg -m ""$Message"" $userArgName $userArgValue $hgPaths"
            hg commit $closeBranchArg -m $Message $userArgName $userArgValue $includeParam $excludeParam $hgPaths | Write-Verbose
            
            $hgExitCode = $LastExitCode

            if( $hgExitCode -eq 0 )
            {
                Get-HgChangeset -Revision "tag('tip')" -Force
            }
            elseif( $hgExitCode -eq 1 )
            {
                Write-Warning ('Nothing changed.')
                return
            }
            else
            {
                Write-Error ("Failed to commit changes in {0}: {1}." -f $repoRoot,$hgExitCode)
                return
            }
            
        }
    }
    finally
    {
        Pop-Location
    }
    
}

Set-Alias -Name 'Save-HgChanges' -Value 'Save-HgChangeset'
Set-Alias -Name 'hgci' -Value 'Save-HgChangeset'
Set-Alias -Name 'hgcommit' -Value 'Save-hgChangeset'
Set-Alias -Name 'svhgc' -Value 'Save-HgChangeset'