Public/Save-GitHubModule.ps1
<# .Synopsis Downloads a module from GitHub to the specificed location. .Description Downloads the source code of a module stored on GitHub to the specified path. .Parameter Repository The repository to download from (e.g. "AnterisPowershell/Core"). .Parameter Version The version of the module to download. .Parameter Path The path to download the module to. .Example Save-GitHubModule -Name "AnterisPowershell/Core" -Version "v0.1.0" -Path "$(Get-Location)/vendor" #> function Save-GitHubModule { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string] $Repository, [string] $Version = 'main', [Parameter(Mandatory=$true)] $Path ) Process { $gitHubModule = Find-GitHubModule $Repository $Version; Write-Verbose "Module has been found at $($gitHubModule.Download)."; # Create a temporary directory to download this module to. $tempDir = Join-Path -path ([System.IO.Path]::GetTempPath()) -childpath ([System.Guid]::NewGuid()); $tempFile = Join-Path -path $($tempDir) -childpath "$($gitHubModule.Name).zip"; $null = New-Item -ItemType Directory -Path $tempDir -Force # Download the file. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; try { Invoke-WebRequest $gitHubModule.Download -OutFile $tempFile; } catch { throw("We were unable to download the file from $($gitHubModule.Download)!"); } # Extract the zip archive to the temp directory. $fileHash = $(Get-FileHash -Path $tempFile).hash; $unzippedDir = Join-Path -Path $tempDir -ChildPath $fileHash; Expand-Archive -Path $tempFile -DestinationPath $unzippedDir -Force; # Reset the unzipped dir context to the sub-directory created when expanding. $unzippedDir = (Get-ChildItem $unzippedDir)[-1]; # Setup the destination environment. $Path = Join-Path -Path $Path -ChildPath $gitHubModule.Name; # Set the unzipped directory to the context of a sub-folder if nested. $module = Get-ChildItem $unzippedDir -Filter "*.psm1" -File -Recurse; if ($module) { $unzippedDir = $module.Directory.FullName; } # If there is a version included in the manifest, place the source within # a sub-directory with that version number. $manifest = Get-ChildItem $unzippedDir -Filter "*.psd1" -File -Recurse if ($manifest) { $moduleVersion = (Get-Content -Raw $manifest.FullName | Invoke-Expression).ModuleVersion; $Path = Join-Path -Path $Path -ChildPath $moduleVersion; } # Copy the source code. $null = New-Item -ItemType Directory -Path $Path -Force; # Now copy all the contents of the zip archive to this path. Write-Verbose -Message "Copying contents of $($unzippedDir) to $($Path)."; $null = Copy-Item "$($unzippedDir)\*" $Path -Force -Recurse # Finally cleanup our mess. Write-Verbose -Message "Removing $($tempDir)."; $null = Remove-Item $tempDir -Recurse -Force; } } |