TM-PSGitHubGistManagement.psm1

using namespace System

function Get-GistScript {
<#
    .SYNOPSIS
    Downloads the contents of a specified GitHub Gist file.
 
    .PARAMETER GistUri
    The GitHub Gist URL.
 
    .PARAMETER FileName
    The file to select from within the Gist.
#>

    [CmdletBinding()]
    [OutputType([Void])]
    param (
        [Parameter(Mandatory)]
        [string]$GistUri,

        [Parameter(Mandatory)]
        [string]$FileName
    )
    if (($GistUri -match '^https://gist.github.com/*') -and ($GistUri -match '\/(?<guid>\w*)$')) {
        $GistUri = "https://api.github.com/gists/$($matches.guid)"
    }
    $gist = Invoke-RestMethod $gistUri -ErrorAction Stop
    return $gist.Files.$FileName.Content
}


function Update-GistScript {
<#
    .SYNOPSIS
    Updates a local script file with the content of a GitHub Gist.
 
    .DESCRIPTION
    Compares the local script version number to the version in the remote Gist, and updates the local script
    if the Gist version is newer.
 
    .PARAMETER Path
    Local script file path
 
    .PARAMETER ScriptPath
    Full path of the local script file (Alias: FullName)
 
    .OUTPUTS
    Returns a boolean value indicating whether the local Gist script has been updated.
#>

    [CmdletBinding()]
    [OutputType([Boolean])]
    param (
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            ParameterSetName = 'FileInfo',
            Position = 0
        )]
        [IO.FileInfo]$Path,

        [Alias('FullName')]
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ParameterSetName = 'String',
            ValueFromPipelineByPropertyName,
            Position = 0
        )]
        [string]$ScriptPath
    )

    begin {
        $projectUriRegEx = '\.PROJECTURI\r?\n\s*(?<ProjectUri>https?:.*)'
        $versionRegEx = '\.VERSION\r?\n\s*(?<Version>\d+\.\d+\.\d+)'
        $FilePath = switch ($PSCmdlet.ParameterSetName) {
            'String' { $ScriptPath }
            'FileInfo' { $Path.FullName }
        }
        $FileName = [IO.Path]::GetFileName($FilePath)
    }

    process {
        [string]$BadVerNum = '0.0.0'
        [string]$ScriptContent = [IO.File]::ReadAllText($FilePath)
        [version]$currentVersion = if ($ScriptContent -match $versionRegEx) { $matches.Version } else { $BadVerNum }
        [string]$projectUri = [string]::Empty
        if ($ScriptContent -match $projectUriRegEx) { $projectUri = $matches.ProjectUri.Trim() }

        if ($projectUri -ne [string]::Empty) {
            try {
                $gistScript = Get-GistScript -GistUri $projectUri -FileName $FileName
                [version]$gistVersion = if ($gistScript -match $versionRegEx) { $matches.Version } else { $BadVerNum }

                if ($gistVersion -gt $currentVersion) {
                    Microsoft.PowerShell.Utility\Write-Host (
                        "Updating '$FileName' from v$currentVersion to v$gistVersion."
                    )
                    Set-Content -Path $FilePath -Value $gistScript
                    return $true
                } elseif ($gistVersion -eq $BadVerNum) {
                    Microsoft.PowerShell.Utility\Write-Warning (
                        "Unsuccessful gist version parse. v$gistVersion in '$FilePath' is invalid."
                    )
                } elseif ($gistVersion -lt $currentVersion) {
                    Microsoft.PowerShell.Utility\Write-Host (
                        "Local copy of '$FileName' is v$currentVersion which is newer than the gist (v$gistVersion). " +
                        "Don't forget to update the gist when you're done editing!"
                    )
                }
            } catch {
                Microsoft.PowerShell.Utility\Write-Warning "Failed to update gist. Error: $($_.Exception.Message)"
            }
        } else {
            Microsoft.PowerShell.Utility\Write-Warning (
                "'$FilePath' does not contain the required ProjectUri, or it is in an invalid format."
            )
        }
        return $false
    }
}