diff --git a/Formatters/GitHubGistComments.Format.ps1xml b/Formatters/GitHubGistComments.Format.ps1xml
new file mode 100644
index 00000000..b2035fca
--- /dev/null
+++ b/Formatters/GitHubGistComments.Format.ps1xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+ GitHub.GistComment
+
+ GitHub.GistComment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+
+ $_.user.login
+
+
+
+ body
+
+
+ created_at
+
+
+ updated_at
+
+
+
+
+
+
+
+
diff --git a/Formatters/GitHubGists.Format.ps1xml b/Formatters/GitHubGists.Format.ps1xml
new file mode 100644
index 00000000..3e02fa85
--- /dev/null
+++ b/Formatters/GitHubGists.Format.ps1xml
@@ -0,0 +1,241 @@
+
+
+
+
+
+ GitHub.Gist
+
+ GitHub.Gist
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+
+ $_.owner.login
+
+
+
+ description
+
+
+ public
+
+
+
+ ($_.files |
+ Get-Member -MemberType NoteProperty |
+ Select-Object -ExpandProperty Name) -join ', '
+
+
+
+ created_at
+
+
+ updated_at
+
+
+
+
+
+
+
+
+ GitHub.GistCommit
+
+ GitHub.GistCommit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GistId
+
+
+ version
+
+
+
+ ($_.user.login)
+
+
+
+ committed_at
+
+
+
+
+
+
+
+
+ GitHub.GistDetail
+
+ GitHub.GistDetail
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+
+ ($_.owner.login)
+
+
+
+ description
+
+
+ public
+
+
+
+ ($_.files |
+ Get-Member -MemberType NoteProperty |
+ Select-Object -ExpandProperty Name) -join ', '
+
+
+
+
+ ($_.forks.Count)
+
+
+
+ created_at
+
+
+ updated_at
+
+
+
+
+
+
+
+
+ GitHub.GistFork
+
+ GitHub.GistFork
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+
+ # There appears to be a bug in the GitHub API.
+ # Documentation says that the property should alway be "user",
+ # but it switches between "owner" and "user" depending on if it's a property
+ # of a gist, or the direct result from a gist forks query.
+ # https://github.community/t/gist-api-v3-documentation-incorrect-for-forks/122545
+ if ($null -eq $_.user)
+ {
+ $_.owner.login
+ }
+ else
+ {
+ $_.user.login
+ }
+
+
+
+ created_at
+
+
+ updated_at
+
+
+
+
+
+
+
+
diff --git a/GitHubCore.ps1 b/GitHubCore.ps1
index 02c887fd..4ea6fabd 100644
--- a/GitHubCore.ps1
+++ b/GitHubCore.ps1
@@ -329,6 +329,15 @@ function Invoke-GHRestMethod
$finalResult = $finalResult | ConvertFrom-Json
}
}
+ catch [InvalidOperationException]
+ {
+ # In some cases, the returned data might have two different keys of the same characters
+ # but different casing (this can happen with gists with two files named 'a.txt' and 'A.txt').
+ # PowerShell 6 introduced the -AsHashtable switch to work around this issue, but this
+ # module wants to be compatible down to PowerShell 4, so we're unable to use that feature.
+ Write-Log -Message 'The returned object likely contains keys that differ only in casing. Unable to convert to an object. Returning the raw JSON as a fallback.' -Level Warning
+ $finalResult = $finalResult
+ }
catch [ArgumentException]
{
# The content must not be JSON (which is a legitimate situation).
diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1
new file mode 100644
index 00000000..b8d43b31
--- /dev/null
+++ b/GitHubGistComments.ps1
@@ -0,0 +1,495 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+@{
+ GitHubGistCommentTypeName = 'GitHub.GistComment'
+ }.GetEnumerator() | ForEach-Object {
+ Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value
+ }
+
+filter Get-GitHubGistComment
+{
+<#
+ .SYNOPSIS
+ Retrieves comments for a specific gist from GitHub.
+
+ .DESCRIPTION
+ Retrieves comments for a specific gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to retrieve the comments for.
+
+ .PARAMETER Comment
+ The ID of the specific comment on the gist that you wish to retrieve.
+
+ .PARAMETER MediaType
+ The format in which the API will return the body of the comment.
+
+ Raw - Return the raw markdown body. Response will include body. This is the default if you do not pass any specific media type.
+ Text - Return a text only representation of the markdown body. Response will include body_text.
+ Html - Return HTML rendered from the body's markdown. Response will include body_html.
+ Full - Return raw, text and HTML representations. Response will include body, body_text, and body_html.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.GistComment
+
+ .EXAMPLE
+ Get-GitHubGistComment -Gist 6cad326836d38bd3a7ae
+
+ Gets all comments on octocat's "hello_world.rb" gist.
+
+ .EXAMPLE
+ Get-GitHubGistComment -Gist 6cad326836d38bd3a7ae -Comment 1507813
+
+ Gets comment 1507813 from octocat's "hello_world.rb" gist.
+#>
+ [CmdletBinding(PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistCommentTypeName})]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [string] $Gist,
+
+ [Parameter(ValueFromPipelineByPropertyName)]
+ [Alias('GistCommentId')]
+ [ValidateNotNullOrEmpty()]
+ [int64] $Comment,
+
+ [ValidateSet('Raw', 'Text', 'Html', 'Full')]
+ [string] $MediaType = 'Full',
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $telemetryProperties = @{}
+
+ $uriFragment = [String]::Empty
+ $description = [String]::Empty
+
+ if ($PSBoundParameters.ContainsKey('Comment'))
+ {
+ $telemetryProperties['SpecifiedComment'] = $true
+
+ $uriFragment = "gists/$Gist/comments/$Comment"
+ $description = "Getting comment $Comment for gist $Gist"
+ }
+ else
+ {
+ $uriFragment = "gists/$Gist/comments"
+ $description = "Getting comments for gist $Gist"
+ }
+
+ $params = @{
+ 'UriFragment' = $uriFragment
+ 'Description' = $description
+ 'AccessToken' = $AccessToken
+ 'AcceptHeader' = (Get-MediaAcceptHeader -MediaType $MediaType -AsJson)
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubGistCommentAdditionalProperties)
+}
+
+filter Remove-GitHubGistComment
+{
+<#
+ .SYNOPSIS
+ Removes/deletes a comment from a gist on GitHub.
+
+ .DESCRIPTION
+ Removes/deletes a comment from a gist on GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to remove the comment from.
+
+ .PARAMETER Comment
+ The ID of the comment to remove from the gist.
+
+ .PARAMETER Force
+ If this switch is specified, you will not be prompted for confirmation of command execution.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567
+
+ Removes the specified comment from octocat's "hello_world.rb" gist
+ (assuming you have permission).
+
+ .EXAMPLE
+ Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567 -Confirm:$false
+
+ Removes the specified comment from octocat's "hello_world.rb" gist
+ (assuming you have permission).
+ Will not prompt for confirmation, as -Confirm:$false was specified.
+
+ .EXAMPLE
+ Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567 -Force
+
+ Removes the specified comment from octocat's "hello_world.rb" gist
+ (assuming you have permission).
+ Will not prompt for confirmation, as -Force was specified.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false,
+ ConfirmImpact="High")]
+ [Alias('Delete-GitHubGist')]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 2)]
+ [Alias('GistCommentId')]
+ [ValidateNotNullOrEmpty()]
+ [int64] $Comment,
+
+ [switch] $Force,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ if ($Force -and (-not $Confirm))
+ {
+ $ConfirmPreference = 'None'
+ }
+
+ if (-not $PSCmdlet.ShouldProcess($Comment, "Delete comment from gist $Gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/comments/$Comment"
+ 'Method' = 'Delete'
+ 'Description' = "Removing comment $Comment from gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return Invoke-GHRestMethod @params
+}
+
+filter New-GitHubGistComment
+{
+<#
+ .SYNOPSIS
+ Creates a new comment on the specified gist from GitHub.
+
+ .DESCRIPTION
+ Creates a new comment on the specified gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to add the comment to.
+
+ .PARAMETER Body
+ The body of the comment that you wish to leave on the gist.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.GistComment
+
+ .EXAMPLE
+ New-GitHubGistComment -Gist 6cad326836d38bd3a7ae -Body 'Hello World'
+
+ Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistCommentTypeName})]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(
+ Mandatory,
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string] $Body,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $hashBody = @{
+ 'body' = $Body
+ }
+
+ if (-not $PSCmdlet.ShouldProcess($Gist, "Create new comment for gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/comments"
+ 'Body' = (ConvertTo-Json -InputObject $hashBody)
+ 'Method' = 'Post'
+ 'Description' = "Creating new comment on gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties)
+}
+
+filter Set-GitHubGistComment
+{
+ <#
+ .SYNOPSIS
+ Edits a comment on the specified gist from GitHub.
+
+ .DESCRIPTION
+ Edits a comment on the specified gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the gist that the comment is on.
+
+ .PARAMETER Comment
+ The ID of the comment that you wish to edit.
+
+ .PARAMETER Body
+ The new text of the comment that you wish to leave on the gist.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.GistComment
+
+ .EXAMPLE
+ New-GitHubGistComment -Gist 6cad326836d38bd3a7ae -Comment 1232456 -Body 'Hello World'
+
+ Updates the body of the comment with ID 1232456 octocat's "hello_world.rb" gist to be
+ "Hello World".
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistCommentTypeName})]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 2)]
+ [Alias('GistCommentId')]
+ [ValidateNotNullOrEmpty()]
+ [int64] $Comment,
+
+ [Parameter(
+ Mandatory,
+ Position = 3)]
+ [ValidateNotNullOrEmpty()]
+ [string] $Body,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $hashBody = @{
+ 'body' = $Body
+ }
+
+ if (-not $PSCmdlet.ShouldProcess($Comment, "Update gist comment on gist $Gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/comments/$Comment"
+ 'Body' = (ConvertTo-Json -InputObject $hashBody)
+ 'Method' = 'Patch'
+ 'Description' = "Creating new comment on gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties)
+}
+
+filter Add-GitHubGistCommentAdditionalProperties
+{
+<#
+ .SYNOPSIS
+ Adds type name and additional properties to ease pipelining to GitHub Gist Comment objects.
+
+ .PARAMETER InputObject
+ The GitHub object to add additional properties to.
+
+ .PARAMETER TypeName
+ The type that should be assigned to the object.
+
+ .PARAMETER GistId
+ The ID of the gist that the comment is for.
+
+ .INPUTS
+ [PSCustomObject]
+
+ .OUTPUTS
+ GitHub.GistComment
+#>
+ [CmdletBinding()]
+ [OutputType({$script:GitHubGisCommentTypeName})]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline)]
+ [AllowNull()]
+ [AllowEmptyCollection()]
+ [PSCustomObject[]] $InputObject,
+
+ [ValidateNotNullOrEmpty()]
+ [string] $TypeName = $script:GitHubGistCommentTypeName
+ )
+
+ foreach ($item in $InputObject)
+ {
+ $item.PSObject.TypeNames.Insert(0, $TypeName)
+
+ if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport))
+ {
+ $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName')
+ if ($item.url -match "^https?://(?:www\.|api\.|)$hostName/gists/([^/]+)/comments/(.+)$")
+ {
+ $gistId = $Matches[1]
+ $commentId = $Matches[2]
+
+ if ($commentId -ne $item.id)
+ {
+ $message = "The gist comment url no longer follows the expected pattern. Please contact the PowerShellForGitHubTeam: $item.url"
+ Write-Log -Message $message -Level Warning
+ }
+ }
+
+ Add-Member -InputObject $item -Name 'GistCommentId' -Value $item.id -MemberType NoteProperty -Force
+ Add-Member -InputObject $item -Name 'GistId' -Value $gistId -MemberType NoteProperty -Force
+
+ if ($null -ne $item.user)
+ {
+ $null = Add-GitHubUserAdditionalProperties -InputObject $item.user
+ }
+ }
+
+ Write-Output $item
+ }
+}
diff --git a/GitHubGists.ps1 b/GitHubGists.ps1
new file mode 100644
index 00000000..d357bc49
--- /dev/null
+++ b/GitHubGists.ps1
@@ -0,0 +1,1884 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+@{
+ GitHubGistTypeName = 'GitHub.Gist'
+ GitHubGistCommitTypeName = 'GitHub.GistCommit'
+ GitHubGistForkTypeName = 'GitHub.GistFork'
+ GitHubGistSummaryTypeName = 'GitHub.GistSummary'
+ }.GetEnumerator() | ForEach-Object {
+ Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value
+ }
+
+filter Get-GitHubGist
+{
+<#
+ .SYNOPSIS
+ Retrieves gist information from GitHub.
+
+ .DESCRIPTION
+ Retrieves gist information from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to retrieve.
+
+ .PARAMETER Sha
+ The specific revision of the gist that you wish to retrieve.
+
+ .PARAMETER Forks
+ Gets the forks of the specified gist.
+
+ .PARAMETER Commits
+ Gets the commits of the specified gist.
+
+ .PARAMETER UserName
+ Gets public gists for the specified user.
+
+ .PARAMETER Path
+ Download the files that are part of the specified gist to this path.
+
+ .PARAMETER Force
+ If downloading files, this will overwrite any files with the same name in the provided path.
+
+ .PARAMETER Current
+ Gets the authenticated user's gists.
+
+ .PARAMETER Starred
+ Gets the authenticated user's starred gists.
+
+ .PARAMETER Public
+ Gets public gists sorted by most recently updated to least recently updated.
+ The results will be limited to the first 3000.
+
+ .PARAMETER Since
+ Only gists updated at or after this time are returned.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.Gist
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Get-GitHubGist -Starred
+
+ Gets all starred gists for the current authenticated user.
+
+ .EXAMPLE
+ Get-GitHubGist -Public -Since ((Get-Date).AddDays(-2))
+
+ Gets all public gists that have been updated within the past two days.
+
+ .EXAMPLE
+ Get-GitHubGist -Gist 6cad326836d38bd3a7ae
+
+ Gets octocat's "hello_world.rb" gist.
+#>
+ [CmdletBinding(
+ DefaultParameterSetName='Current',
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistTypeName})]
+ [OutputType({$script:GitHubGistCommitTypeName})]
+ [OutputType({$script:GitHubGistForkTypeName})]
+ [OutputType({$script:GitHubGistSummaryTypeName})]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ ParameterSetName='Id',
+ Position = 1)]
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ ParameterSetName='Download',
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(ParameterSetName='Id')]
+ [Parameter(ParameterSetName='Download')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Sha,
+
+ [Parameter(ParameterSetName='Id')]
+ [switch] $Forks,
+
+ [Parameter(ParameterSetName='Id')]
+ [switch] $Commits,
+
+ [Parameter(
+ Mandatory,
+ ParameterSetName='User')]
+ [ValidateNotNullOrEmpty()]
+ [string] $UserName,
+
+ [Parameter(
+ Mandatory,
+ ParameterSetName='Download',
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string] $Path,
+
+ [Parameter(ParameterSetName='Download')]
+ [switch] $Force,
+
+ [Parameter(ParameterSetName='Current')]
+ [switch] $Current,
+
+ [Parameter(ParameterSetName='Current')]
+ [switch] $Starred,
+
+ [Parameter(ParameterSetName='Public')]
+ [switch] $Public,
+
+ [Parameter(ParameterSetName='User')]
+ [Parameter(ParameterSetName='Current')]
+ [Parameter(ParameterSetName='Public')]
+ [DateTime] $Since,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $telemetryProperties = @{}
+
+ $uriFragment = [String]::Empty
+ $description = [String]::Empty
+ $outputType = $script:GitHubGistSummaryTypeName
+
+ if ($PSCmdlet.ParameterSetName -in ('Id', 'Download'))
+ {
+ $telemetryProperties['ById'] = $true
+
+ if ($PSBoundParameters.ContainsKey('Sha'))
+ {
+ if ($Forks -or $Commits)
+ {
+ $message = 'Cannot check for forks or commits of a specific SHA. Do not specify SHA if you want to list out forks or commits.'
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $telemetryProperties['SpecifiedSha'] = $true
+
+ $uriFragment = "gists/$Gist/$Sha"
+ $description = "Getting gist $Gist with specified Sha"
+ $outputType = $script:GitHubGistTypeName
+ }
+ elseif ($Forks)
+ {
+ $uriFragment = "gists/$Gist/forks"
+ $description = "Getting forks of gist $Gist"
+ $outputType = $script:GitHubGistForkTypeName
+ }
+ elseif ($Commits)
+ {
+ $uriFragment = "gists/$Gist/commits"
+ $description = "Getting commits of gist $Gist"
+ $outputType = $script:GitHubGistCommitTypeName
+ }
+ else
+ {
+ $uriFragment = "gists/$Gist"
+ $description = "Getting gist $Gist"
+ $outputType = $script:GitHubGistTypeName
+ }
+ }
+ elseif ($PSCmdlet.ParameterSetName -eq 'User')
+ {
+ $telemetryProperties['ByUserName'] = $true
+
+ $uriFragment = "users/$UserName/gists"
+ $description = "Getting public gists for $UserName"
+ $outputType = $script:GitHubGistSummaryTypeName
+ }
+ elseif ($PSCmdlet.ParameterSetName -eq 'Current')
+ {
+ $telemetryProperties['CurrentUser'] = $true
+ $outputType = $script:GitHubGistSummaryTypeName
+
+ if ((Test-GitHubAuthenticationConfigured) -or (-not [String]::IsNullOrEmpty($AccessToken)))
+ {
+ if ($Starred)
+ {
+ $uriFragment = 'gists/starred'
+ $description = 'Getting starred gists for current authenticated user'
+ }
+ else
+ {
+ $uriFragment = 'gists'
+ $description = 'Getting gists for current authenticated user'
+ }
+ }
+ else
+ {
+ if ($Starred)
+ {
+ $message = 'Starred can only be specified for authenticated users. Either call Set-GitHubAuthentication first, or provide a value for the AccessToken parameter.'
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $message = 'Specified -Current, but not currently authenticated. Either call Set-GitHubAuthentication first, or provide a value for the AccessToken parameter.'
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+ }
+ elseif ($PSCmdlet.ParameterSetName -eq 'Public')
+ {
+ $telemetryProperties['Public'] = $true
+ $outputType = $script:GitHubGistSummaryTypeName
+
+ $uriFragment = "gists/public"
+ $description = 'Getting public gists'
+ }
+
+ $getParams = @()
+ $sinceFormattedTime = [String]::Empty
+ if ($null -ne $Since)
+ {
+ $sinceFormattedTime = $Since.ToUniversalTime().ToString('o')
+ $getParams += "since=$sinceFormattedTime"
+ }
+
+ $params = @{
+ 'UriFragment' = $uriFragment + '?' + ($getParams -join '&')
+ 'Description' = $description
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ $result = (Invoke-GHRestMethodMultipleResult @params |
+ Add-GitHubGistAdditionalProperties -TypeName $outputType)
+
+ if ($PSCmdlet.ParameterSetName -eq 'Download')
+ {
+ Save-GitHubGist -GistObject $result -Path $Path -Force:$Force
+ }
+ else
+ {
+ if ($result.truncated -eq $true)
+ {
+ $message = @(
+ 'Response has been truncated. The API will only return the first 3000 gist results',
+ 'the first 300 files within the gist, and the first 1 Mb of an individual',
+ 'file. If the file has been truncated, you can call',
+ '(Invoke-WebRequest -UseBasicParsing -Method Get -Uri ).Content)',
+ 'where is the value of raw_url for the file in question. Be aware that',
+ 'for files larger than 10 Mb, you''ll need to clone the gist via the URL provided',
+ 'by git_pull_url.')
+
+ Write-Log -Message ($message -join ' ') -Level Warning
+ }
+
+ return $result
+ }
+}
+
+function Save-GitHubGist
+{
+<#
+ .SYNOPSIS
+ Downloads the contents of a gist to the specified file path.
+
+ .DESCRIPTION
+ Downloads the contents of a gist to the specified file path.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER GistObject
+ The Gist PSCustomObject
+
+ .PARAMETER Path
+ Download the files that are part of the specified gist to this path.
+
+ .PARAMETER Force
+ If downloading files, this will overwrite any files with the same name in the provided path.
+
+ .NOTES
+ Internal-only helper
+#>
+ [CmdletBinding(PositionalBinding = $false)]
+ param(
+ [Parameter(Mandatory)]
+ [PSCustomObject] $GistObject,
+
+ [Parameter(Mandatory)]
+ [ValidateNotNullOrEmpty()]
+ [string] $Path,
+
+ [switch] $Force
+ )
+
+ # First, check to see if the response is missing files.
+ if ($GistObject.truncated)
+ {
+ $message = @(
+ 'Gist response has been truncated. The API will only return information on',
+ 'the first 300 files within a gist. To download this entire gist,',
+ 'you''ll need to clone it via the URL provided by git_pull_url',
+ "[$($GistObject.git_pull_url)].")
+
+ Write-Log -Message ($message -join ' ') -Level Error
+ throw $message
+ }
+
+ # Then check to see if there are files we won't be able to download
+ $files = $GistObject.files | Get-Member -Type NoteProperty | Select-Object -ExpandProperty Name
+ foreach ($fileName in $files)
+ {
+ if ($GistObject.files.$fileName.truncated -and
+ ($GistObject.files.$fileName.size -gt 10mb))
+ {
+ $message = @(
+ "At least one file ($fileName) in this gist is larger than 10mb.",
+ 'In order to download this gist, you''ll need to clone it via the URL',
+ "provided by git_pull_url [$($GistObject.git_pull_url)].")
+
+ Write-Log -Message ($message -join ' ') -Level Error
+ throw $message
+ }
+ }
+
+ # Finally, we're ready to directly save the non-truncated files,
+ # and download the ones that are between 1 - 10mb.
+ $originalSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol
+ [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12
+ try
+ {
+ $headers = @{}
+ $AccessToken = Get-AccessToken -AccessToken $AccessToken
+ if (-not [String]::IsNullOrEmpty($AccessToken))
+ {
+ $headers['Authorization'] = "token $AccessToken"
+ }
+
+ $Path = Resolve-UnverifiedPath -Path $Path
+ $null = New-Item -Path $Path -ItemType Directory -Force
+ foreach ($fileName in $files)
+ {
+ $filePath = Join-Path -Path $Path -ChildPath $fileName
+ if ((Test-Path -Path $filePath -PathType Leaf) -and (-not $Force))
+ {
+ $message = "File already exists at path [$filePath]. Choose a different path or specify -Force"
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ if ($GistObject.files.$fileName.truncated)
+ {
+ # Disable Progress Bar in function scope during Invoke-WebRequest
+ $ProgressPreference = 'SilentlyContinue'
+
+ $webRequestParams = @{
+ UseBasicParsing = $true
+ Method = 'Get'
+ Headers = $headers
+ Uri = $GistObject.files.$fileName.raw_url
+ OutFile = $filePath
+ }
+
+ Invoke-WebRequest @webRequestParams
+ }
+ else
+ {
+ $stream = New-Object -TypeName System.IO.StreamWriter -ArgumentList ($filePath)
+ try
+ {
+ $stream.Write($GistObject.files.$fileName.content)
+ }
+ finally
+ {
+ $stream.Close()
+ }
+ }
+ }
+ }
+ finally
+ {
+ [Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol
+ }
+}
+
+filter Remove-GitHubGist
+{
+<#
+ .SYNOPSIS
+ Removes/deletes a gist from GitHub.
+
+ .DESCRIPTION
+ Removes/deletes a gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to retrieve.
+
+ .PARAMETER Force
+ If this switch is specified, you will not be prompted for confirmation of command execution.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Remove-GitHubGist -Gist 6cad326836d38bd3a7ae
+
+ Removes octocat's "hello_world.rb" gist (assuming you have permission).
+
+ .EXAMPLE
+ Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Confirm:$false
+
+ Removes octocat's "hello_world.rb" gist (assuming you have permission).
+ Will not prompt for confirmation, as -Confirm:$false was specified.
+
+ .EXAMPLE
+ Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Force
+
+ Removes octocat's "hello_world.rb" gist (assuming you have permission).
+ Will not prompt for confirmation, as -Force was specified.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false,
+ ConfirmImpact = 'High')]
+ [Alias('Delete-GitHubGist')]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [switch] $Force,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ if ($Force -and (-not $Confirm))
+ {
+ $ConfirmPreference = 'None'
+ }
+
+ if (-not $PSCmdlet.ShouldProcess($Gist, "Delete gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist"
+ 'Method' = 'Delete'
+ 'Description' = "Removing gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return Invoke-GHRestMethod @params
+}
+
+filter Copy-GitHubGist
+{
+<#
+ .SYNOPSIS
+ Forks a gist from GitHub.
+
+ .DESCRIPTION
+ Forks a gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to fork.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Copy-GitHubGist -Gist 6cad326836d38bd3a7ae
+
+ Forks octocat's "hello_world.rb" gist.
+
+ .EXAMPLE
+ Fork-GitHubGist -Gist 6cad326836d38bd3a7ae
+
+ Forks octocat's "hello_world.rb" gist. This is using the alias for the command.
+ The result is the same whether you use Copy-GitHubGist or Fork-GitHubGist.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistSummaryTypeName})]
+ [Alias('Fork-GitHubGist')]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ if (-not $PSCmdlet.ShouldProcess($Gist, "Forking gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/forks"
+ 'Method' = 'Post'
+ 'Description' = "Forking gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Invoke-GHRestMethod @params |
+ Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistSummaryTypeName)
+}
+
+filter Set-GitHubGistStar
+{
+<#
+ .SYNOPSIS
+ Changes the starred state of a gist on GitHub for the current authenticated user.
+
+ .DESCRIPTION
+ Changes the starred state of a gist on GitHub for the current authenticated user.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific Gist that you wish to change the starred state for.
+
+ .PARAMETER Star
+ Include this switch to star the gist. Exclude the switch (or use -Star:$false) to
+ remove the star.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Set-GitHubGistStar -Gist 6cad326836d38bd3a7ae -Star
+
+ Stars octocat's "hello_world.rb" gist.
+
+ .EXAMPLE
+ Set-GitHubGistStar -Gist 6cad326836d38bd3a7ae
+
+ Unstars octocat's "hello_world.rb" gist.
+
+ .EXAMPLE
+ Get-GitHubGist -Gist 6cad326836d38bd3a7ae | Set-GitHubGistStar -Star:$false
+
+ Unstars octocat's "hello_world.rb" gist.
+
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [switch] $Star,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+ Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name
+
+ $PSBoundParameters.Remove('Star')
+ if ($Star)
+ {
+ return Add-GitHubGistStar @PSBoundParameters
+ }
+ else
+ {
+ return Remove-GitHubGistStar @PSBoundParameters
+ }
+}
+
+filter Add-GitHubGistStar
+{
+<#
+ .SYNOPSIS
+ Star a gist from GitHub.
+
+ .DESCRIPTION
+ Star a gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific Gist that you wish to star.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Add-GitHubGistStar -Gist 6cad326836d38bd3a7ae
+
+ Stars octocat's "hello_world.rb" gist.
+
+ .EXAMPLE
+ Star-GitHubGist -Gist 6cad326836d38bd3a7ae
+
+ Stars octocat's "hello_world.rb" gist. This is using the alias for the command.
+ The result is the same whether you use Add-GitHubGistStar or Star-GitHubGist.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [Alias('Star-GitHubGist')]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ if (-not $PSCmdlet.ShouldProcess($Gist, "Starring gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/star"
+ 'Method' = 'Put'
+ 'Description' = "Starring gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return Invoke-GHRestMethod @params
+}
+
+filter Remove-GitHubGistStar
+{
+<#
+ .SYNOPSIS
+ Unstar a gist from GitHub.
+
+ .DESCRIPTION
+ Unstar a gist from GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to unstar.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .EXAMPLE
+ Remove-GitHubGistStar -Gist 6cad326836d38bd3a7ae
+
+ Unstars octocat's "hello_world.rb" gist.
+
+ .EXAMPLE
+ Unstar-GitHubGist -Gist 6cad326836d38bd3a7ae
+
+ Unstars octocat's "hello_world.rb" gist. This is using the alias for the command.
+ The result is the same whether you use Remove-GitHubGistStar or Unstar-GitHubGist.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [Alias('Unstar-GitHubGist')]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ if (-not $PSCmdlet.ShouldProcess($Gist, "Unstarring gist"))
+ {
+ return
+ }
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/star"
+ 'Method' = 'Delete'
+ 'Description' = "Unstarring gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return Invoke-GHRestMethod @params
+}
+
+filter Test-GitHubGistStar
+{
+<#
+ .SYNOPSIS
+ Checks if a gist from GitHub is starred.
+
+ .DESCRIPTION
+ Checks if a gist from GitHub is starred.
+ Will return $false if it isn't starred, as well as if it couldn't be checked
+ (due to permissions or non-existence).
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID of the specific gist that you wish to check.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ Boolean indicating if the gist was both found and determined to be starred.
+
+ .EXAMPLE
+ Test-GitHubGistStar -Gist 6cad326836d38bd3a7ae
+
+ Returns $true if the gist is starred, or $false if isn't starred or couldn't be checked
+ (due to permissions or non-existence).
+#>
+ [CmdletBinding(PositionalBinding = $false)]
+ [OutputType([bool])]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $telemetryProperties = @{}
+ $params = @{
+ 'UriFragment' = "gists/$Gist/star"
+ 'Method' = 'Get'
+ 'Description' = "Checking if gist $Gist is starred"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'ExtendedResult' = $true
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ try
+ {
+ $response = Invoke-GHRestMethod @params
+ return $response.StatusCode -eq 204
+ }
+ catch
+ {
+ return $false
+ }
+}
+
+filter New-GitHubGist
+{
+<#
+ .SYNOPSIS
+ Creates a new gist on GitHub.
+
+ .DESCRIPTION
+ Creates a new gist on GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER File
+ An array of filepaths that should be part of this gist.
+ Use this when you have multiple files that should be part of a gist, or when you simply
+ want to reference an existing file on disk.
+
+ .PARAMETER FileName
+ The name of the file that Content should be stored in within the newly created gist.
+
+ .PARAMETER Content
+ The content of a single file that should be part of the gist.
+
+ .PARAMETER Description
+ A descriptive name for this gist.
+
+ .PARAMETER Public
+ When specified, the gist will be public and available for anyone to see.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ String - Filename(s) of file(s) that should be the content of the gist.
+
+ .OUTPUTS
+ GitHub.GitDetail
+
+ .EXAMPLE
+ New-GitHubGist -FileName 'sample.txt' -Content 'Body of my file.' -Description 'This is my gist!' -Public
+
+ Creates a new public gist with a single file named 'sample.txt' that has the body of "Body of my file."
+
+ .EXAMPLE
+ New-GitHubGist -File 'c:\files\foo.txt' -Description 'This is my gist!'
+
+ Creates a new private gist with a single file named 'foo.txt'. Will populate it with the
+ content of the file at c:\files\foo.txt.
+
+ .EXAMPLE
+ New-GitHubGist -File ('c:\files\foo.txt', 'c:\other\bar.txt', 'c:\octocat.ps1') -Description 'This is my gist!'
+
+ Creates a new private gist with a three files named 'foo.txt', 'bar.txt' and 'octocat.ps1'.
+ Each will be populated with the content from the file on disk at the specified location.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ DefaultParameterSetName='FileRef',
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistTypeName})]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline,
+ ParameterSetName='FileRef',
+ Position = 1)]
+ [ValidateNotNullOrEmpty()]
+ [string[]] $File,
+
+ [Parameter(
+ Mandatory,
+ ParameterSetName='Content',
+ Position = 1)]
+ [ValidateNotNullOrEmpty()]
+ [string] $FileName,
+
+ [Parameter(
+ Mandatory,
+ ParameterSetName='Content',
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string] $Content,
+
+ [string] $Description,
+
+ [switch] $Public,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ begin
+ {
+ $files = @{}
+ }
+
+ process
+ {
+ foreach ($path in $File)
+ {
+ $path = Resolve-UnverifiedPath -Path $path
+ if (-not (Test-Path -Path $path -PathType Leaf))
+ {
+ $message = "Specified file [$path] could not be found or was inaccessible."
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $content = [System.IO.File]::ReadAllText($path)
+ $fileName = (Get-Item -Path $path).Name
+
+ if ($files.ContainsKey($fileName))
+ {
+ $message = "You have specified more than one file with the same name [$fileName]. gists don't have a concept of directory structures, so please ensure each file has a unique name."
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $files[$fileName] = @{ 'content' = $Content }
+ }
+ }
+
+ end
+ {
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $telemetryProperties = @{}
+
+ if ($PSCmdlet.ParameterSetName -eq 'Content')
+ {
+ $files[$FileName] = @{ 'content' = $Content }
+ }
+
+ if (($files.Keys.StartsWith('gistfile') | Where-Object { $_ -eq $true }).Count -gt 0)
+ {
+ $message = "Don't name your files starting with 'gistfile'. This is the format of the automatic naming scheme that Gist uses internally."
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $hashBody = @{
+ 'description' = $Description
+ 'public' = $Public.ToBool()
+ 'files' = $files
+ }
+
+ if (-not $PSCmdlet.ShouldProcess('Create new gist'))
+ {
+ return
+ }
+
+ $params = @{
+ 'UriFragment' = "gists"
+ 'Body' = (ConvertTo-Json -InputObject $hashBody)
+ 'Method' = 'Post'
+ 'Description' = "Creating a new gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Invoke-GHRestMethod @params |
+ Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistTypeName)
+ }
+}
+
+filter Set-GitHubGist
+{
+<#
+ .SYNOPSIS
+ Updates a gist on GitHub.
+
+ .DESCRIPTION
+ Updates a gist on GitHub.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID for the gist to update.
+
+ .PARAMETER Update
+ A hashtable of files to update in the gist.
+ The key should be the name of the file in the gist as it exists right now.
+ The value should be another hashtable with the following optional key/value pairs:
+ fileName - Specify a new name here if you want to rename the file.
+ filePath - Specify a path to a file on disk if you wish to update the contents of the
+ file in the gist with the contents of the specified file.
+ Should not be specified if you use 'content' (below)
+ content - Directly specify the raw content that the file in the gist should be updated with.
+ Should not be used if you use 'filePath' (above).
+
+ .PARAMETER Delete
+ A list of filenames that should be removed from this gist.
+
+ .PARAMETER Description
+ New description for this gist.
+
+ .PARAMETER Force
+ If this switch is specified, you will not be prompted for confirmation of command execution.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.GistDetail
+
+ .EXAMPLE
+ Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Description 'This is my newer description'
+
+ Updates the description for the specified gist.
+
+ .EXAMPLE
+ Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Force
+
+ Deletes the 'hello_world.rb' file from the specified gist without prompting for confirmation.
+
+ .EXAMPLE
+ Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Description 'This is my newer description'
+
+ Deletes the 'hello_world.rb' file from the specified gist and updates the description.
+
+ .EXAMPLE
+ Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }}
+
+ Renames the 'hello_world.rb' file in the specified gist to be 'hello_universe.rb'.
+
+ .EXAMPLE
+ Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }}
+
+ Renames the 'hello_world.rb' file in the specified gist to be 'hello_universe.rb'.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ DefaultParameterSetName='Content',
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistTypeName})]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [hashtable] $Update,
+
+ [string[]] $Delete,
+
+ [string] $Description,
+
+ [switch] $Force,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+
+ $telemetryProperties = @{}
+
+ $files = @{}
+
+ $shouldProcessMessage = 'Update gist'
+
+ # Mark the files that should be deleted.
+ if ($Delete.Count -gt 0)
+ {
+ $ConfirmPreference = 'Low'
+ $shouldProcessMessage = 'Update gist (and remove files)'
+
+ foreach ($toDelete in $Delete)
+ {
+ $files[$toDelete] = $null
+ }
+ }
+
+ # Then figure out which ones need content updates and/or file renames
+ if ($null -ne $Update)
+ {
+ foreach ($toUpdate in $Update.GetEnumerator())
+ {
+ $currentFileName = $toUpdate.Key
+
+ $providedContent = $toUpdate.Value.Content
+ $providedFileName = $toUpdate.Value.FileName
+ $providedFilePath = $toUpdate.Value.FilePath
+
+ if (-not [String]::IsNullOrWhiteSpace($providedContent))
+ {
+ $files[$currentFileName] = @{ 'content' = $providedContent }
+ }
+
+ if (-not [String]::IsNullOrWhiteSpace($providedFilePath))
+ {
+ if (-not [String]::IsNullOrWhiteSpace($providedContent))
+ {
+ $message = "When updating a file [$currentFileName], you cannot provide both a path to a file [$providedFilePath] and the raw content."
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $providedFilePath = Resolve-Path -Path $providedFilePath
+ if (-not (Test-Path -Path $providedFilePath -PathType Leaf))
+ {
+ $message = "Specified file [$providedFilePath] could not be found or was inaccessible."
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $newContent = [System.IO.File]::ReadAllText($providedFilePath)
+ $files[$currentFileName] = @{ 'content' = $newContent }
+ }
+
+ # The user has chosen to rename the file.
+ if (-not [String]::IsNullOrWhiteSpace($providedFileName))
+ {
+ $files[$currentFileName] = @{ 'filename' = $providedFileName }
+ }
+ }
+ }
+
+ $hashBody = @{}
+ if (-not [String]::IsNullOrWhiteSpace($Description)) { $hashBody['description'] = $Description }
+ if ($files.Keys.count -gt 0) { $hashBody['files'] = $files }
+
+ if ($Force -and (-not $Confirm))
+ {
+ $ConfirmPreference = 'None'
+ }
+
+ if (-not $PSCmdlet.ShouldProcess($Gist, $shouldProcessMessage))
+ {
+ return
+ }
+
+ $ConfirmPreference = 'None'
+ $params = @{
+ 'UriFragment' = "gists/$Gist"
+ 'Body' = (ConvertTo-Json -InputObject $hashBody)
+ 'Method' = 'Patch'
+ 'Description' = "Updating gist $Gist"
+ 'AccessToken' = $AccessToken
+ 'TelemetryEventName' = $MyInvocation.MyCommand.Name
+ 'TelemetryProperties' = $telemetryProperties
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ try
+ {
+ return (Invoke-GHRestMethod @params |
+ Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistTypeName)
+ }
+ catch
+ {
+ if ($_.Exception.Message -like '*(422)*')
+ {
+ $message = 'This error can happen if you try to delete a file that doesn''t exist. Be aware that casing matters. ''A.txt'' is not the same as ''a.txt''.'
+ Write-Log -Message $message -Level Warning
+ }
+
+ throw
+ }
+}
+
+function Set-GitHubGistFile
+{
+<#
+ .SYNOPSIS
+ Updates content of file(s) in an existing gist on GitHub,
+ or adds them if they aren't already part of the gist.
+
+ .DESCRIPTION
+ Updates content of file(s) in an existing gist on GitHub,
+ or adds them if they aren't already part of the gist.
+
+ This is a helper function built on top of Set-GitHubGist.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID for the gist to update.
+
+ .PARAMETER File
+ An array of filepaths that should be part of this gist.
+ Use this when you have multiple files that should be part of a gist, or when you simply
+ want to reference an existing file on disk.
+
+ .PARAMETER FileName
+ The name of the file that Content should be stored in within the newly created gist.
+
+ .PARAMETER Content
+ The content of a single file that should be part of the gist.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.Gist
+
+ .EXAMPLE
+ Set-GitHubGistFile -Gist 1234567 -Content 'Body of my file.' -FileName 'sample.txt'
+
+ Adds a file named 'sample.txt' that has the body of "Body of my file." to the existing
+ specified gist, or updates the contents of 'sample.txt' in the gist if is already there.
+
+ .EXAMPLE
+ Set-GitHubGistFile -Gist 1234567 -File 'c:\files\foo.txt'
+
+ Adds the file 'foo.txt' to the existing specified gist, or updates its content if it
+ is already there.
+
+ .EXAMPLE
+ Set-GitHubGistFile -Gist 1234567 -File ('c:\files\foo.txt', 'c:\other\bar.txt', 'c:\octocat.ps1')
+
+ Adds all three files to the existing specified gist, or updates the contents of the files
+ in the gist if they are already there.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ DefaultParameterSetName='Content',
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistTypeName})]
+ [Alias('Add-GitHubGistFile')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline,
+ ParameterSetName='FileRef',
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string[]] $File,
+
+ [Parameter(
+ Mandatory,
+ ParameterSetName='Content',
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string] $FileName,
+
+ [Parameter(
+ Mandatory,
+ ParameterSetName='Content',
+ Position = 3)]
+ [ValidateNotNullOrEmpty()]
+ [string] $Content,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ begin
+ {
+ $files = @{}
+ }
+
+ process
+ {
+ foreach ($path in $File)
+ {
+ $path = Resolve-UnverifiedPath -Path $path
+ if (-not (Test-Path -Path $path -PathType Leaf))
+ {
+ $message = "Specified file [$path] could not be found or was inaccessible."
+ Write-Log -Message $message -Level Error
+ throw $message
+ }
+
+ $fileName = (Get-Item -Path $path).Name
+ $files[$fileName] = @{ 'filePath' = $path }
+ }
+ }
+
+ end
+ {
+ Write-InvocationLog -Invocation $MyInvocation
+ Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name
+
+ if ($PSCmdlet.ParameterSetName -eq 'Content')
+ {
+ $files[$FileName] = @{ 'content' = $Content }
+ }
+
+ $params = @{
+ 'Gist' = $Gist
+ 'Update' = $files
+ 'AccessToken' = $AccessToken
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Set-GitHubGist @params)
+ }
+}
+
+function Remove-GitHubGistFile
+{
+<#
+ .SYNOPSIS
+ Removes one or more files from an existing gist on GitHub.
+
+ .DESCRIPTION
+ Removes one or more files from an existing gist on GitHub.
+
+ This is a helper function built on top of Set-GitHubGist.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID for the gist to update.
+
+ .PARAMETER FileName
+ An array of filenames (no paths, just names) to remove from the gist.
+
+ .PARAMETER Force
+ If this switch is specified, you will not be prompted for confirmation of command execution.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.Gist
+
+ .EXAMPLE
+ Remove-GitHubGistFile -Gist 1234567 -FileName ('foo.txt')
+
+ Removes the file 'foo.txt' from the specified gist.
+
+ .EXAMPLE
+ Remove-GitHubGistFile -Gist 1234567 -FileName ('foo.txt') -Force
+
+ Removes the file 'foo.txt' from the specified gist without prompting for confirmation.
+
+ .EXAMPLE
+ @('foo.txt', 'bar.txt') | Remove-GitHubGistFile -Gist 1234567
+
+ Removes the files 'foo.txt' and 'bar.txt' from the specified gist.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistTypeName})]
+ [Alias('Delete-GitHubGistFile')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline,
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string[]] $FileName,
+
+ [switch] $Force,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ begin
+ {
+ $files = @()
+ }
+
+ process
+ {
+ foreach ($name in $FileName)
+ {
+ $files += $name
+ }
+ }
+
+ end
+ {
+ Write-InvocationLog -Invocation $MyInvocation
+ Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name
+
+ $params = @{
+ 'Gist' = $Gist
+ 'Delete' = $files
+ 'Force' = $Force
+ 'Confirm' = ($Confirm -eq $true)
+ 'AccessToken' = $AccessToken
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Set-GitHubGist @params)
+ }
+}
+
+filter Rename-GitHubGistFile
+{
+<#
+ .SYNOPSIS
+ Renames a file in a gist on GitHub.
+
+ .DESCRIPTION
+ Renames a file in a gist on GitHub.
+
+ This is a helper function built on top of Set-GitHubGist.
+
+ The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
+
+ .PARAMETER Gist
+ The ID for the gist to update.
+
+ .PARAMETER FileName
+ The current file in the gist to be renamed.
+
+ .PARAMETER NewName
+ The new name of the file for the gist.
+
+ .PARAMETER AccessToken
+ If provided, this will be used as the AccessToken for authentication with the
+ REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
+
+ .PARAMETER NoStatus
+ If this switch is specified, long-running commands will run on the main thread
+ with no commandline status update. When not specified, those commands run in
+ the background, enabling the command prompt to provide status information.
+ If not supplied here, the DefaultNoStatus configuration property value will be used.
+
+ .INPUTS
+ GitHub.Gist
+ GitHub.GistComment
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+
+ .OUTPUTS
+ GitHub.Gist
+
+ .EXAMPLE
+ Rename-GitHubGistFile -Gist 1234567 -FileName 'foo.txt' -NewName 'bar.txt'
+
+ Renames the file 'foo.txt' to 'bar.txt' in the specified gist.
+#>
+ [CmdletBinding(
+ SupportsShouldProcess,
+ PositionalBinding = $false)]
+ [OutputType({$script:GitHubGistTypeName})]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipelineByPropertyName,
+ Position = 1)]
+ [Alias('GistId')]
+ [ValidateNotNullOrEmpty()]
+ [string] $Gist,
+
+ [Parameter(
+ Mandatory,
+ Position = 2)]
+ [ValidateNotNullOrEmpty()]
+ [string] $FileName,
+
+ [Parameter(
+ Mandatory,
+ Position = 3)]
+ [ValidateNotNullOrEmpty()]
+ [string] $NewName,
+
+ [string] $AccessToken,
+
+ [switch] $NoStatus
+ )
+
+ Write-InvocationLog -Invocation $MyInvocation
+ Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name
+
+ $params = @{
+ 'Gist' = $Gist
+ 'Update' = @{$FileName = @{ 'fileName' = $NewName }}
+ 'AccessToken' = $AccessToken
+ 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus)
+ }
+
+ return (Set-GitHubGist @params)
+}
+
+filter Add-GitHubGistAdditionalProperties
+{
+<#
+ .SYNOPSIS
+ Adds type name and additional properties to ease pipelining to GitHub Gist objects.
+
+ .PARAMETER InputObject
+ The GitHub object to add additional properties to.
+
+ .PARAMETER TypeName
+ The type that should be assigned to the object.
+
+ .INPUTS
+ [PSCustomObject]
+
+ .OUTPUTS
+ GitHub.Gist
+ GitHub.GistCommit
+ GitHub.GistFork
+ GitHub.GistSummary
+#>
+ [CmdletBinding()]
+ [OutputType({$script:GitHubGistTypeName})]
+ [OutputType({$script:GitHubGistFormTypeName})]
+ [OutputType({$script:GitHubGistSummaryTypeName})]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline)]
+ [AllowNull()]
+ [AllowEmptyCollection()]
+ [PSCustomObject[]] $InputObject,
+
+ [ValidateNotNullOrEmpty()]
+ [string] $TypeName = $script:GitHubGistSummaryTypeName
+ )
+
+ if ($TypeName -eq $script:GitHubGistCommitTypeName)
+ {
+ return Add-GitHubGistCommitAdditionalProperties -InputObject $InputObject
+ }
+ elseif ($TypeName -eq $script:GitHubGistForkTypeName)
+ {
+ return Add-GitHubGistForkAdditionalProperties -InputObject $InputObject
+ }
+
+ foreach ($item in $InputObject)
+ {
+ $item.PSObject.TypeNames.Insert(0, $TypeName)
+
+ if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport))
+ {
+ Add-Member -InputObject $item -Name 'GistId' -Value $item.id -MemberType NoteProperty -Force
+
+ @('user', 'owner') |
+ ForEach-Object {
+ if ($null -ne $item.$_)
+ {
+ $null = Add-GitHubUserAdditionalProperties -InputObject $item.$_
+ }
+ }
+
+ if ($null -ne $item.forks)
+ {
+ $item.forks = Add-GitHubGistForkAdditionalProperties -InputObject $item.forks
+ }
+
+ if ($null -ne $item.history)
+ {
+ $item.history = Add-GitHubGistCommitAdditionalProperties -InputObject $item.history
+ }
+ }
+
+ Write-Output $item
+ }
+}
+
+filter Add-GitHubGistCommitAdditionalProperties
+{
+<#
+ .SYNOPSIS
+ Adds type name and additional properties to ease pipelining to GitHub GistCommit objects.
+
+ .PARAMETER InputObject
+ The GitHub object to add additional properties to.
+
+ .PARAMETER TypeName
+ The type that should be assigned to the object.
+
+ .INPUTS
+ [PSCustomObject]
+
+ .OUTPUTS
+ GitHub.GistCommit
+#>
+ [CmdletBinding()]
+ [OutputType({$script:GitHubGistCommitTypeName})]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline)]
+ [AllowNull()]
+ [AllowEmptyCollection()]
+ [PSCustomObject[]] $InputObject,
+
+ [ValidateNotNullOrEmpty()]
+ [string] $TypeName = $script:GitHubGistCommitTypeName
+ )
+
+ foreach ($item in $InputObject)
+ {
+ $item.PSObject.TypeNames.Insert(0, $TypeName)
+
+ if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport))
+ {
+ $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName')
+ if ($item.url -match "^https?://(?:www\.|api\.|)$hostName/gists/([^/]+)/(.+)$")
+ {
+ $id = $Matches[1]
+ $sha = $Matches[2]
+
+ if ($sha -ne $item.version)
+ {
+ $message = "The gist commit url no longer follows the expected pattern. Please contact the PowerShellForGitHubTeam: $item.uri"
+ Write-Log -Message $message -Level Warning
+ }
+ }
+
+ Add-Member -InputObject $item -Name 'GistId' -Value $id -MemberType NoteProperty -Force
+ Add-Member -InputObject $item -Name 'Sha' -Value $item.version -MemberType NoteProperty -Force
+
+ $null = Add-GitHubUserAdditionalProperties -InputObject $item.user
+ }
+
+ Write-Output $item
+ }
+}
+
+filter Add-GitHubGistForkAdditionalProperties
+{
+<#
+ .SYNOPSIS
+ Adds type name and additional properties to ease pipelining to GitHub Gist Fork objects.
+
+ .PARAMETER InputObject
+ The GitHub object to add additional properties to.
+
+ .PARAMETER TypeName
+ The type that should be assigned to the object.
+
+ .INPUTS
+ [PSCustomObject]
+
+ .OUTPUTS
+ GitHub.GistFork
+#>
+ [CmdletBinding()]
+ [OutputType({$script:GitHubGistForkTypeName})]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")]
+ param(
+ [Parameter(
+ Mandatory,
+ ValueFromPipeline)]
+ [AllowNull()]
+ [AllowEmptyCollection()]
+ [PSCustomObject[]] $InputObject,
+
+ [ValidateNotNullOrEmpty()]
+ [string] $TypeName = $script:GitHubGistForkTypeName
+ )
+
+ foreach ($item in $InputObject)
+ {
+ $item.PSObject.TypeNames.Insert(0, $TypeName)
+
+ if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport))
+ {
+ Add-Member -InputObject $item -Name 'GistId' -Value $item.id -MemberType NoteProperty -Force
+
+ # See here for why we need to work with both 'user' _and_ 'owner':
+ # https://github.community/t/gist-api-v3-documentation-incorrect-for-forks/122545
+ @('user', 'owner') |
+ ForEach-Object {
+ if ($null -ne $item.$_)
+ {
+ $null = Add-GitHubUserAdditionalProperties -InputObject $item.$_
+ }
+ }
+ }
+
+ Write-Output $item
+ }
+}
\ No newline at end of file
diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1
index 3063585b..5cbc5e48 100644
--- a/PowerShellForGitHub.psd1
+++ b/PowerShellForGitHub.psd1
@@ -15,6 +15,8 @@
# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = @(
+ 'Formatters/GitHubGistComments.Format.ps1xml',
+ 'Formatters/GitHubGists.Format.ps1xml',
'Formatters/GitHubReleases.Format.ps1xml'
'Formatters/GitHubRepositories.Format.ps1xml'
)
@@ -32,6 +34,8 @@
'GitHubCore.ps1',
'GitHubContents.ps1',
'GitHubEvents.ps1',
+ 'GitHubGistComments.ps1',
+ 'GitHubGists.ps1',
'GitHubIssueComments.ps1',
'GitHubIssues.ps1',
'GitHubLabels.ps1',
@@ -59,9 +63,11 @@
FunctionsToExport = @(
'Add-GitHubAssignee',
'Add-GitHubIssueLabel',
+ 'Add-GitHubGistStar',
'Backup-GitHubConfiguration',
'Clear-GitHubAuthentication',
'ConvertFrom-GitHubMarkdown',
+ 'Copy-GitHubGist',
'Disable-GitHubRepositorySecurityFix',
'Disable-GitHubRepositoryVulnerabilityAlert',
'Enable-GitHubRepositorySecurityFix',
@@ -73,6 +79,8 @@
'Get-GitHubContent',
'Get-GitHubEmoji',
'Get-GitHubEvent',
+ 'Get-GitHubGist',
+ 'Get-GitHubGistComment',
'Get-GitHubGitIgnore',
'Get-GitHubIssue',
'Get-GitHubIssueComment',
@@ -115,6 +123,8 @@
'Move-GitHubProjectCard',
'Move-GitHubProjectColumn',
'Move-GitHubRepositoryOwnership',
+ 'New-GitHubGist',
+ 'New-GitHubGistComment',
'New-GitHubIssue',
'New-GitHubIssueComment',
'New-GitHubLabel',
@@ -130,6 +140,11 @@
'New-GitHubRepositoryBranch',
'New-GitHubRepositoryFork',
'Remove-GitHubAssignee',
+ 'Remove-GitHubComment',
+ 'Remove-GitHubGist',
+ 'Remove-GitHubGistComment',
+ 'Remove-GitHubGistFile',
+ 'Remove-GitHubGistStar',
'Remove-GitHubIssueComment',
'Remove-GitHubIssueLabel',
'Remove-GitHubLabel',
@@ -142,12 +157,17 @@
'Remove-GitHubReleaseAsset',
'Remove-GitHubRepository',
'Remove-GitHubRepositoryBranch'
+ 'Rename-GitHubGistFile',
'Rename-GitHubRepository',
'Reset-GitHubConfiguration',
'Restore-GitHubConfiguration',
'Set-GitHubAuthentication',
'Set-GitHubConfiguration',
'Set-GitHubContent',
+ 'Set-GitHubGist',
+ 'Set-GitHubGistComment',
+ 'Set-GitHubGistFile',
+ 'Set-GitHubGistStar',
'Set-GitHubIssue',
'Set-GitHubIssueComment',
'Set-GitHubIssueLabel',
@@ -165,15 +185,20 @@
'Split-GitHubUri',
'Test-GitHubAssignee',
'Test-GitHubAuthenticationConfigured',
+ 'Test-GitHubGistStar',
'Test-GitHubOrganizationMember',
'Test-GitHubRepositoryVulnerabilityAlert',
'Unlock-GitHubIssue'
)
AliasesToExport = @(
+ 'Add-GitHubGistFile',
'Delete-GitHubAsset',
'Delete-GitHubBranch',
'Delete-GitHubComment',
+ 'Delete-GitHubGist',
+ 'Delete-GitHubGistComment',
+ 'Delete-GitHubGistFile',
'Delete-GitHubIssueComment',
'Delete-GitHubLabel',
'Delete-GitHubMilestone',
@@ -185,6 +210,7 @@
'Delete-GitHubReleaseAsset',
'Delete-GitHubRepository',
'Delete-GitHubRepositoryBranch',
+ 'Fork-GitHubGist',
'Get-GitHubAsset',
'Get-GitHubBranch',
'Get-GitHubComment',
@@ -197,7 +223,9 @@
'Remove-GitHubComment',
'Set-GitHubAsset',
'Set-GitHubComment',
+ 'Star-GitHubGist',
'Transfer-GitHubRepositoryOwnership'
+ 'Unstar-GitHubGist'
'Update-GitHubIssue',
'Update-GitHubLabel',
'Update-GitHubCurrentUser',
diff --git a/Tests/GitHubGistComments.tests.ps1 b/Tests/GitHubGistComments.tests.ps1
new file mode 100644
index 00000000..ab14b510
--- /dev/null
+++ b/Tests/GitHubGistComments.tests.ps1
@@ -0,0 +1,335 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+<#
+.Synopsis
+ Tests for GitHubGistCommentss.ps1 module
+#>
+
+[CmdletBinding()]
+[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '',
+ Justification='Suppress false positives in Pester code blocks')]
+param()
+
+# This is common test code setup logic for all Pester test files
+$moduleRootPath = Split-Path -Path $PSScriptRoot -Parent
+. (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1')
+
+try
+{
+ Describe 'Get-GitHubGistComment' {
+ BeforeAll {
+ $body = 'Comment body'
+ }
+
+ Context 'By parameters' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ $body = 'Comment body'
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Raw')
+ It 'Should have no comments so far' {
+ $comments.Count | Should -Be 0
+ }
+
+ $firstComment = New-GitHubGistComment -Gist $gist.id -Body $body
+ $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Text')
+ It 'Should have one comments so far' {
+ $comments.Count | Should -Be 1
+ $comments[0].id | Should -Be $firstComment.id
+ $comments[0].body | Should -BeNullOrEmpty
+ $comments[0].body_html | Should -BeNullOrEmpty
+ $comments[0].body_text | Should -Not -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comments[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comments[0].GistCommentId | Should -Be $comments[0].id
+ $comments[0].GistId | Should -Be $gist.id
+ $comments[0].user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $null = New-GitHubGistComment -Gist $gist.id -Body $body
+ $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Html')
+ It 'Should have one comments so far' {
+ $comments.Count | Should -Be 2
+ foreach ($comment in $comments)
+ {
+ $comment.body | Should -BeNullOrEmpty
+ $comment.body_html | Should -Not -BeNullOrEmpty
+ $comment.body_text | Should -BeNullOrEmpty
+ }
+ }
+
+ It 'Should have the expected type and additional properties' {
+ foreach ($comment in $comments)
+ {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ $comment = Get-GitHubGistComment -Gist $gist.id -Comment $firstComment.id -MediaType 'Html'
+ It 'Should retrieve the specific comment' {
+ $comment.id | Should -Be $firstComment.id
+ $comment.body | Should -BeNullOrEmpty
+ $comment.body_html | Should -Not -BeNullOrEmpty
+ $comment.body_text | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ Context 'Gist on the pipeline' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ $body = 'Comment body'
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Text')
+ It 'Should have no comments so far' {
+ $comments.Count | Should -Be 0
+ }
+
+ $firstComment = $gist | New-GitHubGistComment -Body $body
+ $comments = @($gist | Get-GitHubGistComment -MediaType 'Raw')
+ It 'Should have one comments so far' {
+ $comments.Count | Should -Be 1
+ $comments[0].id | Should -Be $firstComment.id
+ $comments[0].body | Should -Not -BeNullOrEmpty
+ $comments[0].body_html | Should -BeNullOrEmpty
+ $comments[0].body_text | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comments[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comments[0].GistCommentId | Should -Be $comments[0].id
+ $comments[0].GistId | Should -Be $gist.id
+ $comments[0].user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $null = $gist | New-GitHubGistComment -Body $body
+ $comments = @($gist | Get-GitHubGistComment -MediaType 'Full')
+ It 'Should have one comments so far' {
+ $comments.Count | Should -Be 2
+ foreach ($comment in $comments)
+ {
+ $comment.body | Should -Not -BeNullOrEmpty
+ $comment.body_html | Should -Not -BeNullOrEmpty
+ $comment.body_text | Should -Not -BeNullOrEmpty
+ }
+ }
+
+ It 'Should have the expected type and additional properties' {
+ foreach ($comment in $comments)
+ {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ $comment = Get-GitHubGistComment -Gist $gist.id -Comment $firstComment.id -MediaType 'Html'
+ It 'Should retrieve the specific comment' {
+ $comment.id | Should -Be $firstComment.id
+ $comment.body | Should -BeNullOrEmpty
+ $comment.body_html | Should -Not -BeNullOrEmpty
+ $comment.body_text | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $comment = $firstComment | Get-GitHubGistComment -MediaType 'Html'
+ It 'Should retrieve the specific comment with the comment on the pipeline' {
+ $comment.id | Should -Be $firstComment.id
+ $comment.body | Should -BeNullOrEmpty
+ $comment.body_html | Should -Not -BeNullOrEmpty
+ $comment.body_text | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+ }
+
+ Describe 'New-GitHubGistComment' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ $body = 'Comment body'
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ Context 'By parameters' {
+ $comment = New-GitHubGistComment -Gist $gist.id -Body $body
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $body
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ Context 'Gist on the pipeline' {
+ $comment = $gist | New-GitHubGistComment -Body $body
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $body
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+ }
+
+ Describe 'New-GitHubGistComment' {
+ BeforeAll {
+ $gist = New-GitHubGist -Filename 'sample.txt' -Content 'Sample text'
+ $body = 'Comment body'
+ $updatedBody = 'Updated comment body'
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ Context 'By parameters' {
+ $comment = New-GitHubGistComment -Gist $gist.id -Body $body
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $body
+ }
+
+ $comment = Set-GitHubGistComment -Gist $gist.id -Comment $comment.id -Body $updatedBody
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $updatedBody
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ Context 'Gist on the pipeline' {
+ $comment = $gist | New-GitHubGistComment -Body $body
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $body
+ }
+
+ $comment = $gist | Set-GitHubGistComment -Comment $comment.id -Body $updatedBody
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $updatedBody
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ Context 'Gist Comment on the pipeline' {
+ $comment = $gist | New-GitHubGistComment -Body $body
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $body
+ }
+
+ $comment = $comment | Set-GitHubGistComment -Body $updatedBody
+ It 'Should have the expected result' {
+ $comment.body | Should -Be $updatedBody
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment'
+ $comment.GistCommentId | Should -Be $comment.id
+ $comment.GistId | Should -Be $gist.id
+ $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+ }
+
+ Describe 'Remove-GitHubGistComment' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ $body = 'Comment body'
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ Context 'By parameters' {
+ $comment = New-GitHubGistComment -Gist $gist.id -Body $body
+
+ Remove-GitHubGistComment -Gist $gist.id -Comment $comment.id -Force
+ It 'Should be gone' {
+ { Get-GitHubGistComment -Gist $gist.id -Comment $comment.id } | Should -Throw
+ }
+ }
+
+ Context 'Gist on the pipeline' {
+ $comment = $gist | New-GitHubGistComment -Body $body
+
+ $gist | Remove-GitHubGistComment -Comment $comment.id -Force
+ It 'Should be gone' {
+ { $gist | Get-GitHubGistComment -Comment $comment.id } | Should -Throw
+ }
+ }
+
+ Context 'Gist Comment on the pipeline' {
+ $comment = $gist | New-GitHubGistComment -Body $body
+
+ $comment | Remove-GitHubGistComment -Force
+ It 'Should be gone' {
+ { $comment | Get-GitHubGistComment } | Should -Throw
+ }
+ }
+ }
+}
+finally
+{
+ if (Test-Path -Path $script:originalConfigFile -PathType Leaf)
+ {
+ # Restore the user's configuration to its pre-test state
+ Restore-GitHubConfiguration -Path $script:originalConfigFile
+ $script:originalConfigFile = $null
+ }
+}
diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1
new file mode 100644
index 00000000..67e06ccf
--- /dev/null
+++ b/Tests/GitHubGists.tests.ps1
@@ -0,0 +1,1193 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+<#
+.Synopsis
+ Tests for GitHubGists.ps1 module
+#>
+
+[CmdletBinding()]
+[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '',
+ Justification='Suppress false positives in Pester code blocks')]
+param()
+
+# This is common test code setup logic for all Pester test files
+$moduleRootPath = Split-Path -Path $PSScriptRoot -Parent
+. (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1')
+
+filter New-LargeFile
+{
+<#
+ .SYNOPSIS
+ Creates a large dummy file with random conntent
+
+ .DESCRIPTION
+ Creates a large dummy file with random conntent
+ Credits for the random content creation logic goes to Robert Robelo
+
+ .PARAMETER Path
+ The full path to the file to create.
+
+ .PARAMETER SizeMB
+ The size of the random file to be genrated. Default is one MB
+
+ .PARAMETER Type
+ The type of file should be created.
+
+ .PARAMETER Force
+ Will allow this to overwrite the target file if it already exists.
+
+ .EXAMPLE
+ New-LargeFile -Path C:\Temp\LF\bigfile.txt -SizeMB 10
+#>
+
+ [CmdletBinding(SupportsShouldProcess)]
+ param(
+ [Parameter(ValueFromPipeline)]
+ [String] $Path,
+
+ [ValidateRange(1, 5120)]
+ [UInt16] $SizeMB = 1,
+
+ [ValidateSet('Text', 'Binary')]
+ [string] $Type = 'Text',
+
+ [switch] $Force
+ )
+
+ $tempFile = New-TemporaryFile
+
+ if ($Type -eq 'Text')
+ {
+ $streamWriter = New-Object -TypeName IO.StreamWriter -ArgumentList ($tempFile)
+ try
+ {
+ # get a 64 element Char[]; I added the - and \n to have 64 chars
+ [char[]]$chars = 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789-\n'
+ 1..$SizeMB | ForEach-Object {
+ # get 1MB of chars from 4 256KB strings
+ 1..4 | ForEach-Object {
+ $randomizedChars = $chars | Get-Random -Count $chars.Count
+
+ # repeat random string 4096 times to get a 256KB string
+ $output = (-join $randomizedChars) * 4kb
+
+ # write 256KB string to file
+ $streamWriter.Write($output)
+
+ # release resources
+ Clear-Variable -Name @('randomizedChars', 'output')
+ }
+ }
+ }
+ catch
+ {
+ Remove-File -Path $tempFile -ErrorAction SilentlyContinue
+ }
+ finally
+ {
+ $streamWriter.Close()
+ $streamWriter.Dispose()
+
+ # Force the immediate garbage collection of allocated resources
+ [GC]::Collect()
+ }
+ }
+ else
+ {
+ $content = New-Object -TypeName Byte[] -ArgumentList ($SizeMB * 1mb)
+ (New-Object -TypeName Random).NextBytes($content)
+ [IO.File]::WriteAllBytes($tempFile, $content)
+ }
+
+ try
+ {
+ if ($PSBoundParameters.ContainsKey('Path'))
+ {
+ return (Move-Item -Path $tempFile -Destination $Path -Force:$Force)
+ }
+ else
+ {
+ return (Get-Item -Path $tempFile)
+ }
+ }
+ catch
+ {
+ Remove-File -Path $tempFile -ErrorAction SilentlyContinue
+ }
+}
+
+try
+{
+ Describe 'Get-GitHubGist' {
+ Context 'Specific Gist' {
+ $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh
+ $gist = Get-GitHubGist -Gist $id
+ It 'Should be the expected gist' {
+ $gist.id | Should -Be $id
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ $gist.history[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit'
+ $gist.forks[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistFork'
+ }
+
+ $gist = $gist | Get-GitHubGist
+ It 'Should be the expected gist with the gist on the pipeline' {
+ $gist.id | Should -Be $id
+ }
+ }
+
+ Context 'Commits and specific Gist with Sha' {
+ $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh
+
+ $gist = Get-GitHubGist -Gist $id
+ $commits = Get-GitHubGist -Gist $gist.id -Commits
+
+ It 'Should have multiple commits' {
+ $commits.Count | Should -BeGreaterThan 1
+ }
+
+ It 'Should have the expected type and additional properties' {
+ foreach ($commit in $commits)
+ {
+ $commit.PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit'
+ $commit.GistId | Should -Be $gist.id
+ $commit.Sha | Should -Be $commit.version
+ $commit.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ $oldestSha = $commits | Sort-Object -Property 'committed_at' | Select-Object -First 1
+
+ $firstGistCommit = Get-GitHubGist -Gist $gist.id -Sha $oldestSha.version
+ It 'Should be the expected commit' {
+ $firstGistCommit.created_at | Should -Be $oldestSha.committed_at
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $firstGistCommit.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $firstGistCommit.GistId | Should -Be $firstGistCommit.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ $gist.history[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit'
+ $gist.forks[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistFork'
+ }
+
+ It 'Should fail if we specify Sha _and_ Commits' {
+ { Get-GitHubGist -Gist $gist.id -Commits -Sha $oldestSha.version } | Should -Throw
+ }
+
+ It 'Should fail if we specify Sha _and_ Forks' {
+ { Get-GitHubGist -Gist $gist.id -Forks -Sha $oldestSha.version } | Should -Throw
+ }
+
+ $firstGistCommit = $gist | Get-GitHubGist -Sha $oldestSha.version
+ It 'Should be the expected gist commit with the gist on the pipeline' {
+ $firstGistCommit.created_at | Should -Be $oldestSha.committed_at
+ }
+
+ $firstGistCommit = $firstGistCommit | Get-GitHubGist
+ It 'Should be the expected gist commit with the gist commit on the pipeline' {
+ $firstGistCommit.created_at | Should -Be $oldestSha.committed_at
+ }
+ }
+
+ Context 'Forks' {
+ $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh
+
+ $gist = Get-GitHubGist -Gist $id
+ $forks = Get-GitHubGist -Gist $gist.id -Forks
+
+ It 'Should have multiple forks' {
+ $forks.Count | Should -BeGreaterThan 1
+ }
+
+ It 'Should have the expected type and additional properties' {
+ foreach ($fork in $forks)
+ {
+ $fork.PSObject.TypeNames[0] | Should -Be 'GitHub.GistFork'
+ $fork.GistId | Should -Be $fork.id
+ $fork.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ $forks = $gist | Get-GitHubGist -Forks
+
+ It 'Should have multiple forks when gist is on the pipeline' {
+ $forks.Count | Should -BeGreaterThan 1
+ }
+ }
+
+ Context 'All gists for a specific user' {
+ $username = 'octocat'
+ $gists = Get-GitHubGist -UserName $username
+
+ It 'Should have multiple gists' {
+ $gists.Count | Should -BeGreaterThan 1
+ }
+
+ It 'Should have the expected type and additional properties' {
+ foreach ($gist in $gists)
+ {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ $since = (Get-Date -Date '01/01/2016')
+ $sinceGists = Get-GitHubGist -UserName $username -Since $since
+ It 'Should have fewer results with using the since parameter' {
+ $sinceGists.Count | Should -BeGreaterThan 0
+ $sinceGists.Count | Should -BeLessThan $gists.Count
+ }
+ }
+
+ Context 'All gists for the current authenticated user' {
+ $gist = New-GitHubGist -Filename 'sample.txt' -Content 'Sample text'
+ $gists = @(Get-GitHubGist)
+ It 'Should at least one gist including the one just created' {
+ $gists.Count | Should -BeGreaterOrEqual 1
+ $gists.id | Should -Contain $gist.id
+ }
+
+ It 'Should have the expected type and additional properties' {
+ foreach ($gist in $gists)
+ {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+ }
+
+ It 'Should be removed' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'All gists for the current authenticated user, but not authenticated' {
+ # This would just be testing that an exception is thrown.
+ # There's no easy way to cover unauthenticated sessions in the UT's,
+ # so we'll just accept the lower code coverage here.
+ }
+
+ Context 'All starred gists for the current authenticated user' {
+ $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh
+ Add-GitHubGistStar -Gist $id
+
+ $gists = @(Get-GitHubGist -Starred)
+ It 'Should include the one we just starred' {
+ $gists.Count | Should -BeGreaterOrEqual 1
+ $gists.id | Should -Contain $id
+ }
+
+ Remove-GitHubGistStar -Gist $id
+ }
+
+ Context 'All starred gists for the current authenticated user, but not authenticated' {
+ # This would just be testing that an exception is thrown.
+ # There's no easy way to cover unauthenticated sessions in the UT's,
+ # so we'll just accept the lower code coverage here.
+ }
+
+ Context 'All public gists' {
+ # This would require 100 queries, taking over 2 minutes.
+ # Given the limited additional value that we'd get from this additional test relative
+ # to the time it would take to execute, we'll just accept the lower code coverage here.
+ }
+ }
+
+ Describe 'Get-GitHubGist/Download' {
+ BeforeAll {
+ # To get access to New-TemporaryDirectory
+ $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent
+ . (Join-Path -Path $moduleRootPath -ChildPath 'Helpers.ps1')
+ $tempPath = New-TemporaryDirectory
+ }
+
+ AfterAll {
+ if (Get-Variable -Name tempPath -ErrorAction SilentlyContinue)
+ {
+ Remove-Item -Path $tempPath -Recurse -ErrorAction SilentlyContinue -Force
+ }
+ }
+
+ Context 'Download gist content' {
+ BeforeAll {
+ $tempFile = New-TemporaryFile
+ $fileA = "$($tempFile.FullName).ps1"
+ Move-Item -Path $tempFile -Destination $fileA
+ $fileAName = (Get-Item -Path $fileA).Name
+ $fileAContent = 'fileA content'
+ Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8
+
+ $tempFile = New-TemporaryFile
+ $fileB = "$($tempFile.FullName).txt"
+ Move-Item -Path $tempFile -Destination $fileB
+ $fileBName = (Get-Item -Path $fileB).Name
+ $fileBContent = 'fileB content'
+ Out-File -FilePath $fileB -InputObject $fileBContent -Encoding utf8
+
+ $tempFile = New-LargeFile -SizeMB 1
+ $twoMegFile = "$($tempFile.FullName).bin"
+ Move-Item -Path $tempFile -Destination $twoMegFile
+ $twoMegFileName = (Get-Item -Path $twoMegFile).Name
+
+ $gist = @($fileA, $fileB, $twoMegFile) | New-GitHubGist
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ @($fileA, $fileB, $twoMegFile) |
+ Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ It 'Should have no files at the download path' {
+ @(Get-ChildItem -Path $tempPath).Count | Should -Be 0
+ }
+
+ Get-GitHubGist -Gist $gist.id -Path $tempPath
+ It 'Should download all of the files' {
+ @(Get-ChildItem -Path $tempPath).Count | Should -Be 3
+ [System.IO.File]::ReadAllText($fileA).Trim() |
+ Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileAName)).Trim())
+ [System.IO.File]::ReadAllText($fileB).Trim() |
+ Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileBName)).Trim())
+ (Get-FileHash -Path $twoMegFile).Hash |
+ Should -Be (Get-FileHash -Path (Join-Path -Path $tempPath -ChildPath $twoMegFileName)).Hash
+ }
+
+ $gist | Get-GitHubGist -Path $tempPath -Force
+ It 'Should download all of the files with the gist on the pipeline and -Force' {
+ @(Get-ChildItem -Path $tempPath).Count | Should -Be 3
+ [System.IO.File]::ReadAllText($fileA).Trim() |
+ Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileAName)).Trim())
+ [System.IO.File]::ReadAllText($fileB).Trim() |
+ Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileBName)).Trim())
+ (Get-FileHash -Path $twoMegFile).Hash |
+ Should -Be (Get-FileHash -Path (Join-Path -Path $tempPath -ChildPath $twoMegFileName)).Hash
+ }
+ }
+
+ Context 'More than 300 files' {
+ BeforeAll {
+ $files = @()
+ 1..301 | ForEach-Object {
+ $tempFile = New-TemporaryFile
+ $file = "$($tempFile.FullName)-$_.ps1"
+ Move-Item -Path $tempFile -Destination $file
+ $fileContent = "file-$_ content"
+ Out-File -FilePath $file -InputObject $fileContent -Encoding utf8
+ $files += $file
+ }
+ }
+
+ AfterAll {
+ $files | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ # May want to consider skipping this test.
+ # It works just fine, but takes 26 second to execute.
+ # (May not be worth it for the moderate improvement to code coverage.)
+ It 'Should throw an exception because there are too many files' {
+ $gist = $files | New-GitHubGist
+ { $gist | Get-GitHubGist -Path $tempPath -Force } | Should -Throw
+ $gist | Remove-GitHubGist -Force
+ }
+
+ }
+
+ Context 'Download gist content' {
+ BeforeAll {
+ $tempFile = New-LargeFile -SizeMB 10
+ $tenMegFile = "$($tempFile.FullName).bin"
+ Move-Item -Path $tempFile -Destination $tenMegFile
+ $tenMegFileName = (Get-Item -Path $tenMegFile).Name
+ }
+
+ AfterAll {
+ @($tenMegFile) |
+ Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ # May want to consider skipping this test.
+ # It works just fine, but takes 26 second to execute.
+ # (May not be worth it for the moderate improvement to code coverage.)
+ It 'Should throw an exception because the file is too large to download' {
+ $gist = $tenMegFile | New-GitHubGist
+ { $gist | Get-GitHubGist -Path $tempPath -Force } | Should -Throw
+ $gist | Remove-GitHubGist -Force
+ }
+ }
+ }
+
+ Describe 'Remove-GitHubGist' {
+ Context 'With parameters' {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ It 'Should be there' {
+ { Get-GitHubGist -Gist $gist.id } | Should -Not -Throw
+ }
+
+ It 'Should remove the gist successfully' {
+ { Remove-GitHubGist -Gist $gist.id -Force } | Should -Not -Throw
+ }
+
+ It 'Should be removed' {
+ { Get-GitHubGist -Gist $gist.id } | Should -Throw
+ }
+ }
+
+ Context 'With the gist on the pipeline' {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ It 'Should be there' {
+ { $gist | Get-GitHubGist } | Should -Not -Throw
+ }
+
+ It 'Should remove the gist successfully' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+
+ It 'Should be removed' {
+ { $gist | Get-GitHubGist } | Should -Throw
+ }
+ }
+ }
+
+ Describe 'Copy-GitHubGist' {
+ BeforeAll {
+ $originalGist = Get-GitHubGist -Gist '1169852' # octocat/test.cs
+ }
+
+ Context 'By parameters' {
+ $gist = Copy-GitHubGist -Gist $originalGist.id
+ It 'Should have been forked' {
+ $gist.files.Count | Should -Be $originalGist.files.Count
+ foreach ($file in $gist.files)
+ {
+ $originalFile = $originalGist.files |
+ Where-Object { $_.filename -eq $file.filename }
+ $file.filename | Should -Be $originalFile.filename
+ $file.size | Should -Be $originalFile.size
+ }
+ }
+
+ It 'Should have the expected additional type and properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should be removed' {
+ { Remove-GitHubGist -Gist $gist.id -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'Gist on the pipeline' {
+ $gist = $originalGist | Copy-GitHubGist
+ It 'Should have been forked' {
+ $gist.files.Count | Should -Be $originalGist.files.Count
+ foreach ($file in $gist.files)
+ {
+ $originalFile = $originalGist.files |
+ Where-Object { $_.filename -eq $file.filename }
+ $file.filename | Should -Be $originalFile.filename
+ $file.size | Should -Be $originalFile.size
+ }
+ }
+
+ It 'Should have the expected additional type and properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should be removed' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+ }
+
+ Describe 'Add/Remove/Set/Test-GitHubGistStar' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text'
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ Context 'With parameters' {
+ $starred = Test-GitHubGistStar -Gist $gist.id
+ It 'Should not be starred yet' {
+ $starred | Should -BeFalse
+ }
+
+ Add-GitHubGistStar -Gist $gist.id
+ $starred = Test-GitHubGistStar -Gist $gist.id
+ It 'Should now be starred' {
+ $starred | Should -BeTrue
+ }
+
+ Remove-GitHubGistStar -Gist $gist.id
+ $starred = Test-GitHubGistStar -Gist $gist.id
+ It 'Should no longer be starred' {
+ $starred | Should -BeFalse
+ }
+
+ Set-GitHubGistStar -Gist $gist.id -Star
+ $starred = Test-GitHubGistStar -Gist $gist.id
+ It 'Should now be starred' {
+ $starred | Should -BeTrue
+ }
+
+ Set-GitHubGistStar -Gist $gist.id
+ $starred = Test-GitHubGistStar -Gist $gist.id
+ It 'Should no longer be starred' {
+ $starred | Should -BeFalse
+ }
+ }
+
+ Context 'With the gist on the pipeline' {
+ $starred = $gist | Test-GitHubGistStar
+ It 'Should not be starred yet' {
+ $starred | Should -BeFalse
+ }
+
+ $gist | Add-GitHubGistStar
+ $starred = $gist | Test-GitHubGistStar
+ It 'Should now be starred' {
+ $starred | Should -BeTrue
+ }
+
+ $gist | Remove-GitHubGistStar
+ $starred = $gist | Test-GitHubGistStar
+ It 'Should no longer be starred' {
+ $starred | Should -BeFalse
+ }
+
+ $gist | Set-GitHubGistStar -Star
+ $starred = $gist | Test-GitHubGistStar
+ It 'Should now be starred' {
+ $starred | Should -BeTrue
+ }
+
+ $gist | Set-GitHubGistStar
+ $starred = $gist | Test-GitHubGistStar
+ It 'Should no longer be starred' {
+ $starred | Should -BeFalse
+ }
+ }
+ }
+
+ Describe 'New-GitHubGist' {
+ Context 'By content' {
+ BeforeAll {
+ $content = 'This is my content'
+ $filename = 'sample.txt'
+ $description = 'my description'
+ }
+
+ $gist = New-GitHubGist -FileName $filename -Content $content -Public
+ It 'Should have the expected result' {
+ $gist.public | Should -BeTrue
+ $gist.description | Should -BeNullOrEmpty
+ $gist.files.$filename.content | Should -Be $content
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should be removed' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+
+ $gist = New-GitHubGist -FileName $filename -Content $content -Description $description -Public:$false
+ It 'Should have the expected result' {
+ $gist.public | Should -BeFalse
+ $gist.description | Should -Be $description
+ $gist.files.$filename.content | Should -Be $content
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should error if file starts with "gistfile"' {
+ { New-GitHubGist -FileName 'gistfile1' -Content $content } | Should -Throw
+ }
+
+ It 'Should be removed' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'By files' {
+ BeforeAll {
+ $tempFile = New-TemporaryFile
+ $fileA = "$($tempFile.FullName).ps1"
+ Move-Item -Path $tempFile -Destination $fileA
+ $fileAName = (Get-Item -Path $fileA).Name
+ $fileAContent = 'fileA content'
+ Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8
+
+ $tempFile = New-TemporaryFile
+ $fileB = "$($tempFile.FullName).txt"
+ Move-Item -Path $tempFile -Destination $fileB
+ $fileBName = (Get-Item -Path $fileB).Name
+ $fileBContent = 'fileB content'
+ Out-File -FilePath $fileB -InputObject $fileBContent -Encoding utf8
+
+ $description = 'my description'
+ }
+
+ AfterAll {
+ @($fileA, $fileB) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ $gist = New-GitHubGist -File @($fileA, $fileB) -Public
+ It 'Should have the expected result' {
+ $gist.public | Should -BeTrue
+ $gist.description | Should -BeNullOrEmpty
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent
+ $gist.files.$fileBName.content.Trim() | Should -Be $fileBContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should be removed' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+
+ $gist = New-GitHubGist -File @($fileA, $fileB) -Description $description -Public:$false
+ It 'Should have the expected result' {
+ $gist.public | Should -BeFalse
+ $gist.description | Should -Be $description
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent
+ $gist.files.$fileBName.content.Trim() | Should -Be $fileBContent
+ }
+
+ It 'Should be removed' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+
+ $gist = @($fileA, $fileB) | New-GitHubGist -Description $description -Public:$false
+ It 'Should have the expected result with the files on the pipeline' {
+ $gist.public | Should -BeFalse
+ $gist.description | Should -Be $description
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent
+ $gist.files.$fileBName.content.Trim() | Should -Be $fileBContent
+ }
+ }
+ }
+
+ Describe 'Set-GitHubGist' {
+ BeforeAll {
+ $fileAName = 'foo.txt'
+ $fileAContent = 'foo content'
+ $fileAUpdatedContent = 'foo updated content'
+ $fileANewName = 'gamma.txt'
+
+ $fileBName = 'bar.txt'
+ $fileBContent = 'bar content'
+ $fileBUpdatedContent = 'bar updated content'
+
+ $fileCName = 'alpha.txt'
+ $fileCContent = 'alpha content'
+ $fileCUpdatedContent = 'alpha updated content'
+ $fileCNewName = 'gamma.txt'
+
+ $tempFile = New-TemporaryFile
+ $fileD = "$($tempFile.FullName).txt"
+ Move-Item -Path $tempFile -Destination $fileD
+ $fileDName = (Get-Item -Path $fileD).Name
+ $fileDContent = 'fileD content'
+ Out-File -FilePath $fileD -InputObject $fileDContent -Encoding utf8
+ $fileDUpdatedContent = 'fileD updated content'
+
+ $description = 'my description'
+ $updatedDescription = 'updated description'
+ }
+
+ AfterAll {
+ @($fileD) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ Context 'With parameters' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName $fileAName -Content $fileAContent -Description $description
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $fileBName -Content $fileBContent
+ It 'Should be in the expected, original state' {
+ $gist.description | Should -Be $description
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$fileAName.content | Should -Be $fileAContent
+ $gist.files.$fileBName.content | Should -Be $fileBContent
+ }
+
+ $setParams = @{
+ Gist = $gist.id
+ Description = $updatedDescription
+ Delete = @($fileBName)
+ Update = @{
+ $fileAName = @{
+ fileName = $fileANewName
+ content = $fileAUpdatedContent
+ }
+ $fileCName = @{ content = $fileCContent }
+ $fileDName = @{ filePath = $fileD }
+ }
+ }
+
+ $gist = Set-GitHubGist @setParams -Force
+ It 'Should have been properly updated' {
+ $gist.description | Should -Be $updatedDescription
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 3
+ $gist.files.$fileAName | Should -BeNullOrEmpty
+ $gist.files.$fileANewName.content | Should -Be $fileAContent
+ $gist.files.$fileBName | Should -BeNullOrEmpty
+ $gist.files.$fileCName.content | Should -Be $fileCContent
+ $gist.files.$fileDName.content.Trim() | Should -Be $fileDContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $setParams = @{
+ Gist = $gist.id
+ Update = @{
+ $fileDName = @{
+ content = 'updated content'
+ filePath = $fileD
+ }
+ }
+ }
+
+ It 'Should throw if updating a file with both a filePath and content' {
+ { $gist = Set-GitHubGist @setParams } | Should -Throw
+ }
+ }
+
+ Context 'With the gist on the pipeline' {
+ BeforeAll {
+ $gist = New-GitHubGist -FileName $fileAName -Content $fileAContent -Description $description
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $fileBName -Content $fileBContent
+ It 'Should be in the expected, original state' {
+ $gist.description | Should -Be $description
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$fileAName.content | Should -Be $fileAContent
+ $gist.files.$fileBName.content | Should -Be $fileBContent
+ }
+
+ $setParams = @{
+ Description = $updatedDescription
+ Delete = @($fileBName)
+ Update = @{
+ $fileAName = @{
+ fileName = $fileANewName
+ content = $fileAUpdatedContent
+ }
+ $fileCName = @{ content = $fileCContent }
+ $fileDName = @{ filePath = $fileD }
+ }
+ }
+
+ $gist = $gist | Set-GitHubGist @setParams -Confirm:$false
+ It 'Should have been properly updated' {
+ $gist.description | Should -Be $updatedDescription
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 3
+ $gist.files.$fileAName | Should -BeNullOrEmpty
+ $gist.files.$fileANewName.content | Should -Be $fileAContent
+ $gist.files.$fileBName | Should -BeNullOrEmpty
+ $gist.files.$fileCName.content | Should -Be $fileCContent
+ $gist.files.$fileDName.content.Trim() | Should -Be $fileDContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $setParams = @{
+ Update = @{
+ $fileDName = @{
+ content = 'updated content'
+ filePath = $fileD
+ }
+ }
+ }
+
+ It 'Should throw if updating a file with both a filePath and content' {
+ { $gist = $gist | Set-GitHubGist @setParams } | Should -Throw
+ }
+ }
+ }
+
+ Describe 'Set-GitHubGistFile' {
+ BeforeAll {
+ $origFileName = 'foo.txt'
+ $origContent = 'original content'
+ $updatedOrigContent = 'updated content'
+
+ $newFileName = 'bar.txt'
+ $newContent = 'new content'
+
+ $gist = New-GitHubGist -FileName $origFileName -Content $origContent
+ }
+
+ AfterAll {
+ $gist | Remove-GitHubGist -Force
+ }
+
+ Context 'By content with parameters' {
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $updatedOrigContent
+ It 'Should have the expected result' {
+ $gist.files.$origFileName.content | Should -Be $updatedOrigContent
+ $gist.files.$newFileName | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $newFileName -Content $newContent
+ It 'Should have the expected result' {
+ $gist.files.$origFileName.content | Should -Be $updatedOrigContent
+ $gist.files.$newFileName.content | Should -Be $newContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent
+ It 'Should remove the new file' {
+ { $gist | Remove-GitHubGistFile -FileName $newFileName -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'By content with the gist on the pipeline' {
+ $gist = $gist | Set-GitHubGistFile -FileName $origFileName -Content $updatedOrigContent
+ It 'Should have the expected result' {
+ $gist.files.$origFileName.content | Should -Be $updatedOrigContent
+ $gist.files.$newFileName | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = $gist | Set-GitHubGistFile -FileName $newFileName -Content $newContent
+ It 'Should have the expected result' {
+ $gist.files.$origFileName.content | Should -Be $updatedOrigContent
+ $gist.files.$newFileName.content | Should -Be $newContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent
+ It 'Should remove the new file' {
+ { $gist | Remove-GitHubGistFile -FileName $newFileName -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'By files with parameters' {
+ BeforeAll {
+ $tempFile = New-TemporaryFile
+ $fileA = "$($tempFile.FullName).txt"
+ Move-Item -Path $tempFile -Destination $fileA
+ $fileAName = (Get-Item -Path $fileA).Name
+ $fileAContent = 'fileA content'
+ Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8
+ $fileAUpdatedContent = 'fileA content updated'
+ }
+
+ AfterAll {
+ @($fileA) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -File $fileA
+ It 'Should have the expected result' {
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$origFileName.content | Should -Be $origContent
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ Out-File -FilePath $fileA -InputObject $fileAUpdatedContent -Encoding utf8
+ $gist = Set-GitHubGistFile -Gist $gist.id -File $fileA
+ It 'Should have the expected result' {
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$origFileName.content | Should -Be $origContent
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAUpdatedContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent
+ It 'Should remove the new file' {
+ { $gist | Remove-GitHubGistFile -FileName $fileAName -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'By files with the gist on the pipeline' {
+ BeforeAll {
+ $tempFile = New-TemporaryFile
+ $fileA = "$($tempFile.FullName).txt"
+ Move-Item -Path $tempFile -Destination $fileA
+ $fileAName = (Get-Item -Path $fileA).Name
+ $fileAContent = 'fileA content'
+ Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8
+ $fileAUpdatedContent = 'fileA content updated'
+ }
+
+ AfterAll {
+ @($fileA) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ $gist = $gist | Set-GitHubGistFile -File $fileA
+ It 'Should have the expected result' {
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$origFileName.content | Should -Be $origContent
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ Out-File -FilePath $fileA -InputObject $fileAUpdatedContent -Encoding utf8
+ $gist = $gist | Set-GitHubGistFile -File $fileA
+ It 'Should have the expected result' {
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$origFileName.content | Should -Be $origContent
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAUpdatedContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent
+ It 'Should remove the new file' {
+ { $gist | Remove-GitHubGistFile -FileName $fileAName -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'By files with the file on the pipeline' {
+ BeforeAll {
+ $tempFile = New-TemporaryFile
+ $fileA = "$($tempFile.FullName).txt"
+ Move-Item -Path $tempFile -Destination $fileA
+ $fileAName = (Get-Item -Path $fileA).Name
+ $fileAContent = 'fileA content'
+ Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8
+ $fileAUpdatedContent = 'fileA content updated'
+ }
+
+ AfterAll {
+ @($fileA) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null
+ }
+
+ $gist = $fileA | Set-GitHubGistFile -Gist $gist.id
+ It 'Should have the expected result' {
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$origFileName.content | Should -Be $origContent
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ Out-File -FilePath $fileA -InputObject $fileAUpdatedContent -Encoding utf8
+ $gist = $fileA | Set-GitHubGistFile -Gist $gist.id
+ It 'Should have the expected result' {
+ ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2
+ $gist.files.$origFileName.content | Should -Be $origContent
+ $gist.files.$fileAName.content.Trim() | Should -Be $fileAUpdatedContent
+ }
+
+ It 'Should have the expected type and additional properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent
+ It 'Should remove the new file' {
+ { $gist | Remove-GitHubGistFile -FileName $fileAName -Force } | Should -Not -Throw
+ }
+ }
+ }
+
+ Describe 'Rename-GitHubGistFile' {
+ BeforeAll {
+ $originalName = 'foo.txt'
+ $newName = 'bar.txt'
+ $content = 'sample content'
+ }
+
+ Context 'With parameters' {
+ $gist = New-GitHubGist -FileName $originalName -Content $content
+ It 'Should have the expected file' {
+ $gist.files.$originalName.content | Should -Be $content
+ $gist.files.$newName | Should -BeNullOrEmpty
+ }
+
+ $gist = Rename-GitHubGistFile -Gist $gist.id -FileName $originalName -NewName $newName
+ It 'Should have been renamed' {
+ $gist.files.$originalName | Should -BeNullOrEmpty
+ $gist.files.$newName.content | Should -Be $content
+ }
+
+ It 'Should have the expected additional type and properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should successfully remove the gist' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'With the gist on the pipeline' {
+ $gist = New-GitHubGist -FileName $originalName -Content $content
+ It 'Should have the expected file' {
+ $gist.files.$originalName.content | Should -Be $content
+ $gist.files.$newName | Should -BeNullOrEmpty
+ }
+
+ $gist = $gist | Rename-GitHubGistFile -FileName $originalName -NewName $newName
+ It 'Should have been renamed' {
+ $gist.files.$originalName | Should -BeNullOrEmpty
+ $gist.files.$newName.content | Should -Be $content
+ }
+
+ It 'Should have the expected additional type and properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should successfully remove the gist' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+ }
+
+ Describe 'Remove-GitHubGistFile' {
+ BeforeAll {
+ $fileName = 'sample.txt'
+ $content = 'sample'
+ }
+
+ Context 'With parameters' {
+ $gist = New-GitHubGist -FileName $fileName -Content $content
+ It 'Should have the expected file' {
+ $gist.files.$fileName | Should -Not -BeNullOrEmpty
+ }
+
+ $gist = Remove-GitHubGistFile -Gist $gist.id -FileName $fileName -Force
+ It 'Should have been removed' {
+ $gist.files.$fileName | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected additional type and properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should successfully remove the gist' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+
+ Context 'With the gist on the pipeline' {
+ $gist = New-GitHubGist -FileName $fileName -Content $content
+ It 'Should have the expected file' {
+ $gist.files.$fileName | Should -Not -BeNullOrEmpty
+ }
+
+ $gist = $gist | Remove-GitHubGistFile -FileName $fileName -Confirm:$false
+ It 'Should have been removed' {
+ $gist.files.$fileName | Should -BeNullOrEmpty
+ }
+
+ It 'Should have the expected additional type and properties' {
+ $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist'
+ $gist.GistId | Should -Be $gist.id
+ $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User'
+ }
+
+ It 'Should successfully remove the gist' {
+ { $gist | Remove-GitHubGist -Force } | Should -Not -Throw
+ }
+ }
+ }
+}
+finally
+{
+ if (Test-Path -Path $script:originalConfigFile -PathType Leaf)
+ {
+ # Restore the user's configuration to its pre-test state
+ Restore-GitHubConfiguration -Path $script:originalConfigFile
+ $script:originalConfigFile = $null
+ }
+}
diff --git a/USAGE.md b/USAGE.md
index 8e93a1c5..456c0186 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -97,6 +97,18 @@
* [Create a release asset](#create-a-release-asset)
* [Update a release asset](#update-a-release-asset)
* [Remove a release asset](#remove-a-release-asset)
+ * [Gists](#gists)
+ * [Getting gists](#getting-gists)
+ * [Download a gist](#download-a-gist)
+ * [Fork a gist](#fork-a-gist)
+ * [Creating a gist](#creating-a-gist)
+ * [Removing a gist](#removing-a-gist)
+ * [Updating a gist](#updating-a-gist)
+ * [Starring a gist](#starring-a-gist)
+ * [Getting gist comments](#getting-gist-comments)
+ * [Adding a gist comment](#adding-a-gist-comment)
+ * [Changing a gist comment](#changing-a-gist-comment)
+ * [Removing a gist comment](#removing-a-gist-comment)
* [Advanced](#advanced)
* [Migrating blog comments to GitHub issues](#migrating-blog-comments-to-github-issues)
@@ -869,6 +881,169 @@ or with pipelining...
```powershell
$asset | Remove-GitHubReleaseAsset -force
+
+----------
+
+### Gists
+
+#### Getting gists
+```powershell
+# There are many options here:
+
+# 1. Getting all gists for the current authenticated user:
+Get-GitHubGist
+
+# 1b. Getting all gists for the current authenticated user that were updated in the past 6 days.
+Get-GitHubGist -Since ((Get-Date).AddDays(-6))
+
+# 2. Get all starred gists for the current authenticated user
+Get-GitHubGist -Starred
+
+# 3. Get all public gists for a specific user
+Get-GitHubGist -UserName 'octocat'
+
+# 4. Get all public gists (well, the first 3000):
+Get-GitHubGist -Public
+
+# 5. Get a specific gist
+Get-GitHubGist -Gist '6cad326836d38bd3a7ae'
+
+# 5a. List all commits for a specific gist
+Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Commits
+
+# 5b. Get a gist at a specific commit (Sha)
+Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Sha 'de5b9b59d1f28206e8d646c7c8025e9809d0ed73'
+
+# 5c. Get all of the forks for a gist
+Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Forks
+```
+
+#### Download a gist
+```powershell
+Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Path 'c:\users\octocat\downloads\gist\'
+```
+
+#### Fork a gist
+```powershell
+Fork-GitHubGist -Gist '6cad326836d38bd3a7ae'
+```
+
+#### Creating a gist
+```powershell
+# You can create a gist by specifying a single file's content in-line...
+New-GitHubGist -FileName 'foo.txt' -Content 'foo content'
+
+# or by providing one or more files that should be part of the gist
+New-GitHubGist -File @('c:\files\foo.txt', 'c:\files\bar.txt')
+@('c:\files\foo.txt', 'c:\files\bar.txt') | New-GitHubGist
+```
+
+#### Removing a gist
+```powershell
+Remove-GitHubGist -Gist '6cad326836d38bd3a7ae'
+```
+
+#### Updating a gist
+```powershell
+$gist = New-GitHubGist -FileName 'foo.txt' -Content 'content'
+
+# The main method to use is Set-GitHubGist, however it is quite complicated.
+$params = @{
+ Description = 'new description' # modifies the description of the gist
+ Update = @{
+ 'foo.txt' = @{
+ fileName = 'alpha.txt' # Will rename foo.txt -> alpha.txt
+ content = 'updated content' # and will also update its content
+ }
+ 'bar.txt' = @{
+ filePath = 'c:\files\bar.txt' # Will upload the content of bar.txt to the gist.
+ }
+ }
+ Delete = @('bar.txt')
+ Force = $true # avoid confirmation prompting due to the deletion
+}
+
+Set-GitHubGist -Gist $gist.id @params
+
+# Therefore, you can use simpler helper methods to accomplish atomic tasks
+Set-GistHubGistFile -Gist $gist.id -FileName 'foo.txt' -Content 'updated content'
+
+# This will update the text in the existing file 'foo.txt' and add the file 'bar.txt'
+$gist | Set-GitHubGistFile -File ('c:\files\foo.txt', 'c:\files\bar.txt')
+
+Rename-GistHubGistFile -Gist $gist.id -FileName 'foo.txt' -NewName 'bar.txt'
+
+$gist | Remove-GitHubGistFile -FileName 'bar.txt' -Force
+
+```
+
+#### Starring a gist
+```powershell
+$gistId = '6cad326836d38bd3a7ae'
+
+# All of these options will star the same gist
+Star-GitHubGist -Gist $gistId
+Add-GitHubGistStar -Gist $gistId
+Set-GitHubGistStar -Gist $gistId -Star
+Get-GitHubGist -Gist $gistId | Star-GitHubGist
+
+# All of these options will unstar the same gist
+Unstar-GitHubGist -Gist $gistId
+Remove-GitHubGistStar -Gist $gistId
+Set-GitHubGistStar -Gist $gistId
+Set-GitHubGistStar -Gist $gistId -Star:$false
+Get-GitHubGist -Gist $gistId | Unstar-GitHubGist
+
+# All of these options will tell you if you have starred a gist
+Test-GitHubGistStar -Gist $gistId
+Get-GitHubGist -Gist $gistId | Test-GitHubGistStar
+```
+
+#### Getting gist comments
+```powershell
+$gistId = '6cad326836d38bd3a7ae'
+$commentId = 1507813
+
+# You can get all comments for a gist with any of these options:
+Get-GitHubGistComment -Gist $gistId
+Get-GitHubGist -Gist $gistId | Get-GitHubGistComment
+
+# You can retrieve an individual comment like this:
+Get-GitHubGistComment -Gist $gistId -Comment $commentId
+```
+
+#### Adding a gist comment
+```powershell
+$gistId = '6cad326836d38bd3a7ae'
+
+New-GitHubGistComment -Gist $gistId -Body 'Hello World'
+
+# or with the pipeline
+Get-GitHubGist -Gist $gistId | New-GitHubGistComment -Body 'Hello World'
+```
+
+#### Changing a gist comment
+```powershell
+$gistId = '6cad326836d38bd3a7ae'
+$commentId = 1507813
+
+Set-GitHubGistComment -Gist $gistId -Comment $commentId -Body 'Updated comment'
+
+# or with the pipeline
+Get-GitHubGist -Gist $gistId -Comment $commentId | Set-GitHubGistComment -Body 'Updated comment'
+```
+
+#### Removing a gist comment
+```powershell
+$gistId = '6cad326836d38bd3a7ae'
+$commentId = 1507813
+
+# If you don't specify -Force, it will prompt for confirmation before it will delete the comment
+
+Remove-GitHubGistComment -Gist $gistId -Comment $commentId -Force
+
+# or with the pipeline
+Get-GitHubGist -Gist $gistId -Comment $commentId | Remove-GitHubGistComment -Force
```
----------