Skip to content

Instantly share code, notes, and snippets.

@tsmarvin
Last active November 10, 2023 03:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsmarvin/c28208e85409e914c7009c336d123a71 to your computer and use it in GitHub Desktop.
Save tsmarvin/c28208e85409e914c7009c336d123a71 to your computer and use it in GitHub Desktop.
TM-PSGitHubGistManagement

TM-PSGitHubGistManagement Module

Introduction

TM-PSGitHubGistManagement is a PowerShell module that provides GitHub Gist-related utility functions. It allows you to download a script hosted in a gist, as well as allowing you to update it again from that gist later.

This module is part of a suite of tools designed to improve and streamline the PowerShell commandline and scripting experience.
Check out the rest of the modules by visiting my page on the PowerShell Gallery.

Features

  • Get-GistScript: Retrieves scripts from a Gist.
  • Update-GistScript: Updates the content of a Gist script.
  • Start-BackgroundGistScriptUpdate: Initiates a background process to update a Gist script.

Requirements

Installation

Install TM-PSGitHubGistManagement from the PowerShell Gallery:

Install-Module TM-PSGitHubGistManagement -Scope CurrentUser -Repository PSGallery

For manual installation, download the module files and place them in a "TM-PSGitHubGistManagement" folder in your PowerShell modules directory ($Env:PSModulePath).

MIT License
Copyright (c) 2023 Taylor Marvin
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.
@{
# Script module or binary module file associated with this manifest.
RootModule = 'TM-PSGitHubGistManagement.psm1'
# Version number of this module.
ModuleVersion = '0.0.6'
# Supported PSEditions
CompatiblePSEditions = @('Desktop','Core')
# ID used to uniquely identify this module
GUID = '429cacf0-6b52-4e7c-a86a-ddbb7fae4b88'
# Author of this module
Author = 'Taylor Marvin'
# Company or vendor of this module
CompanyName = 'N/A'
# Copyright statement for this module
Copyright = 'Taylor Marvin (2023)'
# Description of the functionality provided by this module
Description = 'Provides github "gist" related utility functions.'
# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @(@{ModuleName='TM-ValidationUtility'; ModuleVersion='0.0.4'; GUID='1f1eebe8-7a0b-49ae-901e-c877f090a7fc'})
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @(
'Get-GistScript',
'Update-GistScript',
'Start-BackgroundGistScriptUpdate'
)
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('Profile', 'GitHub', 'Gist')
# A URL to the license for this module.
LicenseUri = 'https://gist.github.com/tsmarvin/c28208e85409e914c7009c336d123a71#file-license'
# A URL to the main website for this project.
ProjectUri = 'https://gist.github.com/tsmarvin/c28208e85409e914c7009c336d123a71'
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
RequireLicenseAcceptance = $false
}
}
}
using namespace System
using namespace System.IO
using namespace System.Management.Automation
function Get-GistScript {
<#
.SYNOPSIS
Downloads the contents of a specified GitHub Gist file.
.PARAMETER GistUri
The GitHub Gist URL.
.PARAMETER FileName
The file to select from within the Gist.
#>
[CmdletBinding()]
[OutputType([Void])]
param (
[Parameter(Mandatory)]
[Validation.ValidateGistUriFormatAttribute()]
[string]$GistUri,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]$FileName
)
if ($GistUri -match '/(?<guid>[a-zA-Z0-9]{32})$') {
$GistUri = "https://api.github.com/gists/$($matches.guid)"
}
$gist = Invoke-RestMethod $gistUri -ErrorAction Stop
return $gist.Files.$FileName.Content
}
function Update-GistScript {
<#
.SYNOPSIS
Updates a local script file with the content of a GitHub Gist.
.DESCRIPTION
Compares the local script version number to the version in the remote Gist, and updates the local script
if the Gist version is newer.
.PARAMETER Path
Local script file path
.PARAMETER ScriptPath
Full path of the local script file (Alias: FullName)
.OUTPUTS
Returns a boolean value indicating whether the local Gist script has been updated.
#>
[CmdletBinding()]
[OutputType([Boolean])]
param (
[Parameter(
Mandatory,
ValueFromPipeline,
ValueFromPipelineByPropertyName,
ParameterSetName = 'FileInfo',
Position = 0
)]
[Validation.ValidatePathExists('File')]
[FileInfo]$Path,
[Alias('FullName')]
[Parameter(
Mandatory,
ValueFromPipeline,
ParameterSetName = 'String',
ValueFromPipelineByPropertyName,
Position = 0
)]
[Validation.ValidatePathExists('File')]
[string]$ScriptPath
)
begin {
$projectUriRegEx = '\.PROJECTURI\r?\n\s*(?<ProjectUri>https?:.*)'
$versionRegEx = '\.VERSION\r?\n\s*(?<Version>\d+\.\d+\.\d+)'
$FilePath = switch ($PSCmdlet.ParameterSetName) {
'String' { $ScriptPath }
'FileInfo' { $Path.FullName }
}
$FileName = [Path]::GetFileName($FilePath)
}
process {
[string]$BadVerNum = '0.0.0'
[string]$ScriptContent = [IO.File]::ReadAllText($FilePath)
[version]$currentVersion = if ($ScriptContent -match $versionRegEx) { $matches.Version } else { $BadVerNum }
[string]$projectUri = [string]::Empty
if ($ScriptContent -match $projectUriRegEx) { $projectUri = $matches.ProjectUri.Trim() }
if ($projectUri -ne [string]::Empty) {
try {
$gistScript = Get-GistScript -GistUri $projectUri -FileName $FileName
[version]$gistVersion = if ($gistScript -match $versionRegEx) { $matches.Version } else { $BadVerNum }
if ($gistVersion -gt $currentVersion) {
Microsoft.PowerShell.Utility\Write-Host (
"Updating '$FileName' from v$currentVersion to v$gistVersion."
)
Set-Content -Path $FilePath -Value $gistScript
return $true
} elseif ($gistVersion -eq $BadVerNum) {
Microsoft.PowerShell.Utility\Write-Warning (
"Unsuccessful gist version parse. v$gistVersion in '$FilePath' is invalid."
)
} elseif ($gistVersion -lt $currentVersion) {
Microsoft.PowerShell.Utility\Write-Host (
"Local copy of '$FileName' is v$currentVersion which is newer than the gist (v$gistVersion). " +
"Don't forget to update the gist when you're done editing!"
)
}
} catch {
Microsoft.PowerShell.Utility\Write-Warning "Failed to update gist. Error: $($_.Exception.Message)"
}
} else {
Microsoft.PowerShell.Utility\Write-Warning (
"'$FilePath' does not contain the required ProjectUri, or it is in an invalid format."
)
}
return $false
}
}
function Start-BackgroundGistScriptUpdate {
<#
.SYNOPSIS
Starts a background job to update the specified Gist script.
.DESCRIPTION
Initiates a background job to update a PowerShell script from the GitHub Gist URL mentioned in the PROJECTURI field
of the ScriptFileInfo header.
.PARAMETER LocalScriptPath
Specifies the path to the local Gist script that needs to be updated.
.NOTES
This function requires internet access to reach the gist URL.
#>
[CmdletBinding()]
[OutputType([System.Management.Automation.Job])]
param (
[Parameter(Mandatory)]
[Validation.ValidatePathExists('File')]
[string]$LocalScriptPath
)
# Get the file item from the local script path
$ScriptPath = Get-Item -Path $LocalScriptPath -ErrorAction Stop
# Create parameters for the job or thread that will be started
$UpdateGistJobParams = [hashtable]@{
Name = "Update Gist Script - $($ScriptPath.Name)"
ArgumentList = @($ScriptPath.FullName)
ScriptBlock = {
param ($LocalScriptPath)
. ([ScriptBlock]::Create('using module TM-ValidationUtility'))
Import-Module -Name TM-PSGitHubGistManagement
# Call the Update-GistScript function if the local script path is valid
Update-GistScript -ScriptPath $LocalScriptPath | Out-Null # Ignore the boolean return
}
}
# Create the job or thread depending on the PowerShell edition
$Job = if ($PSVersionTable.PSEdition -eq 'Desktop') {
Start-Job @UpdateGistJobParams
} else {
Start-ThreadJob @UpdateGistJobParams
}
return $Job
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment