mao
4/28/2016 - 3:41 PM

Powershell Gist management CMDlets

Powershell Gist management CMDlets

<?xml version="1.0" encoding="utf-8" ?>
<Types>
  <Type>
    <Name>posh-gist.gist</Name>
    <Members>
      <MemberSet>
        <Name>PSStandardMembers</Name>
        <Members>
          <PropertySet>
            <Name>DefaultDisplayPropertySet</Name>
            <ReferencedProperties>
              <Name>id</Name>
              <Name>public</Name>
              <Name>created</Name>
              <Name>updated</Name>
              <Name>description</Name>
              <Name>ownerlogin</Name>
            </ReferencedProperties>
          </PropertySet>
        </Members>
      </MemberSet>
      <ScriptProperty>
        <Name>created</Name>
        <GetScriptBlock>
          Get-Date -Date $this.created_at
        </GetScriptBlock>
      </ScriptProperty>
      <ScriptProperty>
        <Name>updated</Name>
        <GetScriptBlock>
          Get-Date -Date $this.updated_at
        </GetScriptBlock>
      </ScriptProperty>
      <ScriptProperty>
        <Name>ownerlogin</Name>
        <GetScriptBlock>
          $this.owner.login
        </GetScriptBlock>
      </ScriptProperty>
    </Members>
  </Type>
  <Type>
    <Name>posh-gist.gistcommit</Name>
    <Members>
      <MemberSet>
        <Name>PSStandardMembers</Name>
        <Members>
          <PropertySet>
            <Name>DefaultDisplayPropertySet</Name>
            <ReferencedProperties>
              <Name>userlogin</Name>
              <Name>committed</Name>
              <Name>change_status</Name>
            </ReferencedProperties>
          </PropertySet>
        </Members>
      </MemberSet>
      <ScriptProperty>
        <Name>committed</Name>
        <GetScriptBlock>
          Get-Date -Date $this.committed_at
        </GetScriptBlock>
      </ScriptProperty>
      <ScriptProperty>
        <Name>userlogin</Name>
        <GetScriptBlock>
          $this.user.login
        </GetScriptBlock>
      </ScriptProperty>
    </Members>
  </Type>
</Types>
param([switch]$NoVersionWarn = $false)

if (Get-Module posh-gist) { return }

Push-Location $psScriptRoot
. .\posh-gist.ps1
Pop-Location

Export-ModuleMember `
    -Function @(
        'Get-Gist',
        'New-Gist',
        'Remove-Gist',
        'Update-Gist',
        'Get-GistCommits',
        'Get-GistStar'
)
@{
    RootModule = 'posh-gist.psm1'
    ModuleVersion = '0.4'
    GUID = 'f9039736-02a7-45e7-97da-6551b2ce8e89'
    Author = 'Xavier Plantefeve'
    Copyright = '(c) 2016 Xavier Plantefeve'
    Description = 'Gist management CMDlets'
    PowerShellVersion = '3.0'
    TypesToProcess = 'posh-gist.types.ps1xml'
    FormatsToProcess = 'posh-gist.Format.ps1xml'
    FunctionsToExport = @(
        'Get-Gist',
        'New-Gist',
        'Remove-Gist',
        'Update-Gist',
        'Get-GistCommits',
        'Get-GistStar'
    )
    FileList = @(
        'install.ps1',
        'posh-gist.md',
        'posh-gist.ps1',
        'posh-gist.psd1',
        'posh-gist.psm1',
        'posh-gist.types.ps1xml',
        'posh-gist.Format.ps1xml',
        'LICENSE.txt'
    )

    PrivateData = @{
        PSData = @{
            LicenseUri = 'https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f#LICENSE.txt'
            ProjectUri = 'https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f'
        } # End of PSData hashtable
    } # End of PrivateData hashtable
}


Function Get-CredentialBasic {
    <#
    .Synopsis
       Outputs BASIC credentials.
    .INPUTS
       PSCredential
    .OUTPUTS
       string
    .NOTES
       The accepted credentials is either your Github username/password pair, or, preferably,
       your username and a token created at https://github.com/settings/tokens

       The PSCredential object has to be decoded as Github breaks RFC2617 and never sends the
       needed HTTP code. See https://developer.github.com/v3/auth/#basic-authentication
    .COMPONENT
       poshgist
    .LINK
       https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding()]
    Param (
        # Credentials. See notes.
        [Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)]
        [Alias('Cred')]
        [PSCredential]$Credential
    )
    
    $BasicString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password)
    $UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BasicString)
    $auth = '{0}:{1}' -f $Credential.UserName,$UnsecurePassword
    $bytes = [System.Text.Encoding]::ASCII.GetBytes($auth)
    $base64 = [System.Convert]::ToBase64String($bytes)
    Return 'Basic {0}' -f $base64
}

Function Get-Gist {
    <#
    .Synopsis
       Retrieves Github gists
    .DESCRIPTION
       Retrieves gists, either public ones or for the current user.
       Optionally writes the files contained in the gist to the disk.
    .EXAMPLE
       Get-Gist
       Retrieves the most recent public gists.
    .EXAMPLE
       Get-Gist -Credential ( Get-Credential )
       Retrieves the current users gists.
    .EXAMPLE
       Get-Gist -User johndoe -Since 2016-03-03
       Retrieves johndoe's gist updated after the given date.
    .EXAMPLE
       Get-Gist -Credential $cred -Starred
       Retrieves gists starred by the current user.
    .EXAMPLE
       Get-Gist -Id 5e85af5998abf08f2d86c9aef968ef9f -Forks
       Retrieves the forks of a specific gist.
    .EXAMPLE
       Get-Gist -User johndoe | select -First 1 | Get-Gist -File * -Destination out
       Retrieves johndoe's last gist and outputs the files in the 'out' folder.
    .INPUTS
       System.String
       You can pipe strings that contains gists Ids.

       posh-gist.gist
       You can pipe the custom object posh-gist.gist (type output by the poshgist CMDlets)
    .OUTPUTS
       posh-gist.gist
       Get-Gists outputs a custom object type that contains all information pertaining to a gist.

       The CMDlet returns $false when an error occured.
    .NOTES
       The accepted credentials is either your Github username/password pair, or, preferably,
       your username and a token created at https://github.com/settings/tokens
    .COMPONENT
       poshgist
    .LINK
       https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding(DefaultParameterSetName='User')]
    Param (
        # To retrieves the gists of the selected user.
        [Parameter(ParameterSetName='User')]
        [string[]]$User,
        # Limits the gists to the ones updated after the given date.
        [Parameter(ParameterSetName='User')]
        [string]$Since,
        # Retrieves gists by Id. 
        [Parameter(ParameterSetName='Id',ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0,Mandatory=$true)]
        [Parameter(ParameterSetName='Forks',Mandatory=$true)]
        [string[]]$Id,
        # To retrieves a specific revision of the gist.
        [Parameter(ParameterSetName='Id')]
        [string]$Sha,
        # Select files from the gist to be written to disk.
        # Wildcard permitted (IE. '*.txt' to get all text files) 
        [Parameter(ParameterSetName='Id')]
        [string[]]$File,
        # Folder to write the files to. Will be created if needed. Defaults to current folder.
        [Parameter(ParameterSetName='Id')]
        [string]$Destination,
        # Overwrites files if they already exist.
        [Parameter(ParameterSetName='Id')]
        [switch]$Force,
        # To retrieves the forks of a specific gist.
        [Parameter(ParameterSetName='Forks',Mandatory=$true)]
        [switch]$Forks,
        # To retrieves the last public gists.
        [Parameter(ParameterSetName='Public')]
        [switch]$Public,
        # To retrieves the gists starred by the current user.
        [Parameter(ParameterSetName='Starred')]
        [switch]$Starred,
        # Credentials. See notes.
        [Alias('Cred')]
        [PSCredential]$Credential
        #FIXME
        #[int[]]$Page
    )
    Begin {
        $headers = @{}
        If ( $Credential ) {
            $headers.Authorization = Get-CredentialBasic -Credential $Credential
        }
        $parameters = @()
        If ( $Since ) {
            $parameters += 'since={0}' -f ( Get-Date -Date $Since -Format s )
        }
        if ($parameters.count) { $reqparameters = '?' + ( $parameters -join '&' ) }
        If ( $Destination -and ( -not $File ) ) { $File = '*' }
    }
    Process {
        If ( $Public ) {
            $URI = 'https://api.github.com/gists/public'
        } elseIf ( $Starred ) {
            $URI = 'https://api.github.com/gists/starred'
        } elseIf ( $Forks ) {
            $URI = 'https://api.github.com/gists/{0}/forks' -f $Id
        } elseIf ( $Id ) {
            $URI = 'https://api.github.com/gists/{0}' -f $Id
            If ( $Sha ) {
                $URI += '/' + $Sha
            }
        } ElseIf ( $User ) {
            $URI = 'https://api.github.com/users/{0}/gists' -f $User
        } Else {
            $URI = 'https://api.github.com/gists'
        }
        
        Try {
            $WebRequest = Invoke-WebRequest -Headers $headers -Uri ( $URI + $reqparameters ) -Method Get
            $gists = ConvertFrom-Json -InputObject $WebRequest.content
            foreach ($gist in $gists) 
            {
                $gist.PSTypeNames.Insert(0,'posh-gist.gist')
            }

            $outfiles = @()
            foreach ( $filename in $File ) {
                If ( $filename -notmatch '[*?]' ) {
                    $outfiles += $filename
                } Else {
                    $regexp = [Regex]::Escape($filename) -replace '\\\*','.*' -replace '\\\?','.'
                    $outfiles += $gist.files.psobject.Properties | ? name -Match $regexp | select -ExpandProperty name
                }
            }
            foreach ( $OutFile in ( $outfiles | select -Unique ) ) {
                If ( $gist.files."$OutFile" ) {
                    $DestinationPath = Join-Path -Path $Destination -ChildPath $OutFile
                    If ( ( Test-Path -Path $DestinationPath ) -and ( -not $Force ) ) {
                        Throw '{0} already exists. Use -Force to overwrite' -f $DestinationPath
                    } Else {
                        If ( $gist.file."$OutFile".truncated ) {
                            $content = Invoke-WebRequest -Uri $tg.files.'poshgist.ps1'.raw_url | select -ExpandProperty content
                        } Else {
                            $content = $gist.files."$OutFile".content
                        }
                        If ( -not ( Test-Path -Path $Destination ) ) { $null = New-Item -Path $Destination -ItemType directory }
                        Out-File -FilePath $DestinationPath -InputObject $content -Force
                        # Trade-off. Getting the real timestamp of every file would require analysing history
                        (Get-Item -Path $DestinationPath).LastWriteTime = $gist.updated_at
                    }
                } Else {
                    Throw '{0} was not found in the gist.' -f $OutFile
                }
            }
            Return $gists
        }
        Catch {
            Write-Host -Object $_.Exception.Message
            Return $false
        }
    }
}

Function New-Gist {
    <#
    .Synopsis
       Creates a Github gist
    .DESCRIPTION
       Creates a gist by including files, or by forking an existing one.
    .EXAMPLE
       New-Gist -file poshgist.*,readme.txt -Description 'Gist management CMDlets' -Public
       Creates a gist containing the selected files.
    .EXAMPLE
       New-Gist -Fork 5e85af5998abf08f2d86c9aef968ef9f
       Forks a gist. Forks are always public.
    .INPUTS
       None.
       You cannot pipe anything to New-Gist.
    .OUTPUTS
       posh-gist.gist
       New-Gists outputs a custom object type that contains all information pertaining to the new gist.
       
       The CMDlet returns $false when an error occured.
    .NOTES
       The accepted credentials is either your Github username/password pair, or, preferably,
       your username and a token created at https://github.com/settings/tokens
    .COMPONENT
       poshgist
    .LINK
       https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding()]
    Param (
        # Files to include in the gist. Wildcard are permitted.
        [Parameter(ParameterSetName='New',Mandatory=$true,ValueFromPipeline=$true,Position=0)]
        [Parameter(ParameterSetName='Anonymous',Mandatory=$true)]
        [string[]]$Path,
        # Description of the gist.
        [Parameter(ParameterSetName='New')]
        [Parameter(ParameterSetName='Anonymous')]
        [string]$Description,
        # Creates a public gist. The default option is a secret one.
        [Parameter(ParameterSetName='New')]
        [Parameter(ParameterSetName='Anonymous')]
        [switch]$Public,
        # Creates an anonymous gist.
        [Parameter(ParameterSetName='Anonymous',Mandatory=$true)]
        [switch]$Anonymous,
        # The id of the gist to fork.
        [Parameter(ParameterSetName='Fork',Mandatory=$true)]
        [string]$Fork,
        # Credentials. See notes.
        [Alias('Cred')]
        [Parameter(ParameterSetName='Fork')]
        [Parameter(ParameterSetName='New',Mandatory=$true)]
        [PSCredential]$Credential
    )
    Begin {
        $Body = @{}
        $Files = @{}
        If ( $Description ) { $Body.description = $Description }
        If ( $Public ) { $Body.public = $true }
        If ( $Credential ) {
            $headers = @{ Authorization = Get-CredentialBasic -Credential $Credential }
        }
    }
    Process {
        If ( -not $Fork ) {
            $FileList = Get-Item -Path $Path
            foreach ( $File in $FileList ) { $Files[$File.Name] = @{content=( Get-Content $File -Encoding UTF8 | Out-String )} }
        }
    }
    End {
        If ( $Fork ) {
            Try {
                $Uri = 'https://api.github.com/gists/92fa6e65eacf26219022/forks'
                $RawReq = Invoke-WebRequest -Headers $headers -Uri $Uri -Method Post
                $Req = ConvertFrom-Json -InputObject $RawReq
                $Req.PSTypeNames.Insert(0,'posh-gist.gist')
                Return $Req
            }
            Catch {
                Write-Host -Object $_.Exception.Message
                Return $false
            }
        } Else {
            Try {
                $Body.files = $Files
                $json = ConvertTo-Json -InputObject $Body
                $json = [System.Text.Encoding]::UTF8.GetBytes($json)
                $RawReq = Invoke-WebRequest -Headers $headers -Uri https://api.github.com/gists -Method Post -Body $json
                $Req = ConvertFrom-Json -InputObject $RawReq
                $Req.PSTypeNames.Insert(0,'posh-gist.gist')
                Return $Req
            }
            Catch {
                Write-Host -Object $_.Exception.Message
                Return $false
            }
        }
    }
}

Function Remove-Gist {
    <#
    .Synopsis
       Deletes a Github gist
    .DESCRIPTION
       Deletes a gist by ID. You must be authenticated.
    .EXAMPLE
       Remove-Gist -Id <gist id> -Credential ( Get-Credential )
       Deletes the gist.
    .INPUTS
       None.
       You cannot pipe anything to New-Gist.
    .OUTPUTS
        Boolean
        Remove-Gists returns true if the gist was deleted. False otherwise.
    .NOTES
        The accepted credentials is either your Github username/password pair, or, preferably,
        your username and a token created at https://github.com/settings/tokens
    .COMPONENT
        poshgist
    .LINK
        https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding()]
    Param (
        # Id of the gist to delete.
        [Parameter(ParameterSetName='Id',ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0)]
        [string[]]$Id,
        # Credential. Mandatory, as you can only delete your own gists.
        [Parameter(Mandatory=$true)]
        [Alias('Cred')]
        [PSCredential]$Credential
    )
    Begin {
        If ( $Credential ) {
            $headers = @{ Authorization = Get-CredentialBasic -Credential $Credential }
        }
    }
    Process {
        Try {
            $Uri = 'https://api.github.com/gists/{0}' -f $Id
            Invoke-WebRequest -Headers $headers -Uri $Uri -Method Delete
            Return $true
        }
        Catch {
            Write-Host -Object $_.Exception.Message
            Return $false
        }
    }
}

Function Update-Gist {
    <#
    .Synopsis
       Updates a Github gist
    .DESCRIPTION
       Updates a gist by adding, removing, updating or renoming files.
    .EXAMPLE
       Update-Gist -id 5e85af5998abf08f2d86c9aef968ef9f -Update poshgist.ps1 -Add poshgist.md
       Updates poshgist.ps1 in the gist, and adds poshgist.md
    .EXAMPLE
       Update-Gist -id 5e85af5998abf08f2d86c9aef968ef9f -Remove *.txt
       Removes text files from the gist.
    .EXAMPLE
       Update-Gist -id 5e85af5998abf08f2d86c9aef968ef9f -Rename readme.txt -Destination readme.md
       Renames the file in the gist.
    .EXAMPLE
       Update-Gist -id 5e85af5998abf08f2d86c9aef968ef9f -Description 'My oh so very nice gist'
       Adds or changes the gist's description
    .EXAMPLE
       Update-Gist -id 5e85af5998abf08f2d86c9aef968ef9f -Star
       Stars a gist. Go on, try it.
    .INPUTS
       System.String
       You can pipe strings that contains gists Ids.

       posh-gist.gist
       You can pipe the custom object posh-gist.gist (type output by the poshgist CMDlets)
    .OUTPUTS
       posh-gist.gist
       New-Gists outputs a custom object type that contains all information pertaining to the updated gist.
       
       The CMDlet returns $false when an error occured.
    .NOTES
       The accepted credentials is either your Github username/password pair, or, preferably,
       your username and a token created at https://github.com/settings/tokens
    .COMPONENT
       poshgist
    .LINK
       https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding()]
    Param (
        # Id of the gists to update
        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0)]
        [string[]]$Id,
        # Description of the gist
        [Parameter(ParameterSetName='Update')]
        [string]$Description,
        # File(s) to add to the gist
        [Parameter(ParameterSetName='Update')]
        [string[]]$Add,
        # File(s) to update in the gist
        [Parameter(ParameterSetName='Update')]
        [string[]]$Update,
        # File(s) to remove from the gist
        [Parameter(ParameterSetName='Update')]
        [string[]]$Remove,
        # File(s) to rename in the gist
        [Parameter(ParameterSetName='Update')]
        [string[]]$Rename,
        # New name(s) for the file(s) in the gist
        [Parameter(ParameterSetName='Update')]
        [string[]]$Destination,
        # Stars a gist. Can belong to another user.
        [Parameter(ParameterSetName='Star')]
        [switch]$Star,
        # Unstars a gist. Can belongs to another user.
        [Parameter(ParameterSetName='Unstar')]
        [switch]$Unstar,
        [Parameter(Mandatory=$true)]
        # Credential. Mandatory, as you can only modify your own gists, and stars are per account.
        [Alias('Cred')]
        [PSCredential]$Credential
    )
    Begin {
        $headers = @{}
        If ( $Credential ) {
            $headers.Authorization = Get-CredentialBasic -Credential $Credential
        }
        $Files = @{}
    }
    Process {
        If ( $Star ) {
            Try {
                $Uri = 'https://api.github.com/gists/{0}/star' -f $Id
                $headers.'Content-Length' = 0
                Invoke-WebRequest -Headers $headers -Uri $Uri -Method Put
                Return $true
            }
            Catch {
                Write-Host -Object $_.Exception.Message
                Return $false
            }
        } Elseif ( $Unstar ) {
            Try {
                $Uri = 'https://api.github.com/gists/{0}/star' -f $Id
                Invoke-WebRequest -Headers $headers -Uri $Uri -Method Delete
                Return $true
            }
            Catch {
                Write-Host -Object $_.Exception.Message
                Return $false
            }
        } Else {
            $Body = @{}
            If ( $Description ) { $Body.description = $Description }
            If ( $Add ) {
                $FileList = Get-Item -Path $Add
                foreach ( $File in $FileList ) { $Files[$File.Name] = @{content=( Get-Content $File -Encoding UTF8 | Out-String )} }
            }
            If ( $Update ) {
                $FileList = Get-Item -Path $Update
                foreach ( $File in $FileList ) { $Files[$File.Name] = @{content=( Get-Content $File -Encoding UTF8 | Out-String )} }
            }
            If ( $Remove ) {
                foreach ( $filename in $Remove ) {
                    $Files[$filename] = $null
                }
            }
            If ( $Rename ) {
                If ( $Rename.count -eq $Destination.count ) {
                    foreach ( $i in ( 0..($Rename.Count -1) ) ) {
                        $Files[$Rename[$i]] = @{filename=$Destination[$i]}
                    }
                } Else {
                    Throw '-Rename and -Destination must include the same number of elements.'
                }
            }
            If ( $Files.count -ne 0 ) { $Body.files = $Files }

            # $Body
            # ConvertTo-Json $Body

            Try {
                $Uri = 'https://api.github.com/gists/{0}' -f $Id
                $json = ConvertTo-Json -InputObject $Body
                $json = [System.Text.Encoding]::UTF8.GetBytes($json)
                $RawReq = Invoke-WebRequest -Headers $headers -Uri $Uri -Method Patch -Body $json
                $Req = ConvertFrom-Json -InputObject $RawReq
                $Req.PSTypeNames.Insert(0,'posh-gist.gist')
                Return $Req
            }
            Catch {
                Write-Host -Object $_.Exception.Message
                Return $false
            }
        }
    }
}

Function Get-GistCommits {
    <#
    .Synopsis
       Retrieves a Github gist history
    .DESCRIPTION
       Retrieves a list of commits for a gist.
    .EXAMPLE
       Get-GistCommits -Id 5e85af5998abf08f2d86c9aef968ef9f
       Retrieves the commits history of a specific gist.
    .INPUTS
       System.String
       You can pipe strings that contains gists Ids.

       posh-gist.gist
       You can pipe the custom object posh-gist.gist (type output by the poshgist CMDlets)
    .OUTPUTS
       posh-gist.gistcommit
       Get-GistsCommits outputs a custom object type that contains all information pertaining to commits.

       The CMDlet returns $false when an error occured.
    .NOTES
       Commits get their own CMDlets because it has a different output format.
    .COMPONENT
       poshgist
    .LINK
       https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding()]
    Param (
        # Id of the gists to history of.
        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0,Mandatory=$true)]
        [string]$Id
    )

    $Uri = 'https://api.github.com/gists/{0}/commits' -f $Id
    Try {
        $Req = Invoke-WebRequest -Uri $Uri
        $Commits = ConvertFrom-Json -InputObject $Req.content
        foreach ($commit in $Commits) 
            {
                $commit.PSTypeNames.Insert(0,'posh-gist.gistcommit')
            }
        Return $Commits

    }
    Catch {
        Write-Host -Object $_.Exception.Message
        Return $false
    }
}

Function Get-GistStar {
    <#
    .Synopsis
       Retrieves a Github gist starred status
    .DESCRIPTION
       Retrieves a gist's the starred status for the current user.
    .EXAMPLE
       Get-GistStar -Id 5e85af5998abf08f2d86c9aef968ef9f -Credential $cred
       Check whether you starred the gist or not.
    .INPUTS
       System.String
       You can pipe a string that contains the gist Id.

       posh-gist.gist
       You can pipe the custom object posh-gist.gist (type output by the poshgist CMDlets)
    .OUTPUTS
       Boolean
       Get-GistStar outputs $true if the gist is starred. $false otherwise.
    .NOTES
       The accepted credentials is either your Github username/password pair, or, preferably,
       your username and a token created at https://github.com/settings/tokens
    .COMPONENT
       poshgist
    .LINK
       https://gist.github.com/XPlantefeve/5e85af5998abf08f2d86c9aef968ef9f
    #>
    [CmdletBinding()]
    Param (
        # Id of the gist to history of.
        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0,Mandatory=$true)]
        [string]$Id,
        # Credentials. Mandatory as stars are a per-user thing.
        [Parameter(Mandatory=$true)]
        [Alias('Cred')]
        [PSCredential]$Credential
    )

    $headers = @{}
    $headers.Authorization = Get-CredentialBasic -Credential $Credential
    $Uri = 'https://api.github.com/gists/{0}/star' -f $Id
    Try {
        $Req = Invoke-WebRequest -Uri $Uri -Headers $headers
        Return $true
    }
    Catch {
        Return $false
    }
}

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
  <ViewDefinitions>
        <View>
            <Name>posh-gist.gist</Name>
            <ViewSelectedBy>
                <TypeName>posh-gist.gist</TypeName>
            </ViewSelectedBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Width>33</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
		    <Label>Owner login</Label>
                        <Width>16</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>6</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>20</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>20</Width>
                    </TableColumnHeader>
                    <TableColumnHeader />
                </TableHeaders>
                <TableRowEntries>
                    <TableRowEntry>
                        <TableColumnItems>
                            <TableColumnItem>
                                <PropertyName>Id</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>ownerlogin</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>Public</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>Created</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>Updated</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>Description</PropertyName>
                            </TableColumnItem>
                        </TableColumnItems>
                    </TableRowEntry>
                </TableRowEntries>
            </TableControl>
        </View>
    </ViewDefinitions>
</Configuration>
[CmdletBinding()]
Param (
    [switch]$Force
)

#Requires -Version 3

Push-Location -Path $PSScriptRoot
$Manifest = Invoke-Expression -Command ( Get-Content -Path *.psd1 | Out-String )
$ModuleName = $Manifest.RootModule -replace '\.psm1$',''

if ( Get-Module $ModuleName -ListAvailable ) {
    $InstalledVersion = Get-Module $ModuleName -ListAvailable | Select -ExpandProperty Version
} Else {
    $InstalledVersion = 0
}

$ShouldUpdate = ( $Force -or $Manifest.ModuleVersion -gt $InstalledVersion )

If ( -not $ShouldUpdate ) { Pop-Location ; Return 'The {0} module is already installed' -f $ModuleName }

If ( Get-Module -Name $ModuleName ) { Remove-Module -Name $ModuleName }

$ProfilePath = Split-Path -Path $profile
$ModulesPath = Join-Path -Path $ProfilePath -ChildPath 'Modules'
$InstallPath = Join-Path -Path $ModulesPath -ChildPath $ModuleName

If ( Test-Path -Path $InstallPath ) { Remove-Item -Path $InstallPath -Recurse }

Try {
    If ( $InstallPath -ne $PSScriptRoot ) {
        $null = New-Item -Path $InstallPath -ItemType Directory
        foreach ( $file in $Manifest.FileList ) {
            $FullFilePath =  Join-Path -Path $PSScriptRoot -ChildPath $file
            Copy-Item -Path $FullFilePath -Destination $InstallPath
        }
        Out-Default -InputObject ( 'The {0} module has been installed.' -f $ModuleName )
    }
}
Catch {
    Out-Default -InputObject 'There has been a problem installing the {0} module.' -f $ModuleName
    Pop-Location
}

Pop-Location

PoshGist

PoshGist is a set of Powershell CMDlets that manipulate Github gists.

The current CMDlets are:

  • Get-Gist
  • New-Gist
  • Remove-Gist
  • Update-Gist
  • Get-GistCommits
  • Get-GistStar

All but the last two directly act on Gists and evetually outputs Gists information. Get-Gist can optionally output a Gist's files to disk.

It's not meant to be perfect: I wrote those in a few hours as a matter of practicing my PS skills and there are to be sure lots of ways to break things. Still, the basic functionality works.

Example use

This Gist was created with the following command:

New-Gist -Path poshgist.* -Description 'Powershell Gist management CMDlets'

The fifth revision has been made with the following command:

Update-Gist -id 5e85af5998abf08f2d86c9aef968ef9f -Update poshgist.ps1 -Add poshgist.md -Remove poshgist.txt

Help is on its way.

MIT License

Copyright (c) 2016 Xavier Plantefeve

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.