NoGit.psm1
#Region '.\Private\Get-NoGitHubRepoRecursiveContents.ps1' -1 function Get-NoGitHubRepoRecursiveContents { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Url, [string] $RelativePath = '', [Parameter(Mandatory)] [hashtable] $Headers, [Parameter(Mandatory)] [string] $TargetDir, [Parameter(Mandatory)] [string] $Branch ) try { $items = Invoke-RestMethod -Uri $Url -Headers $Headers -ErrorAction Stop -Verbose:$false $count = @($items).Count Write-Verbose "Fetching: $Url ($count item(s))" } catch { Write-Error "Error fetching contents from: $Url - $($_.Exception.Message)" $script:FailCount++ return } foreach ($item in $items) { $ItemPath = if ($RelativePath) { "$RelativePath\$($item.name)" } else { $item.name } if ($item.type -eq 'file') { $DownloadUrl = $item.download_url $OutputPath = Join-Path -Path $TargetDir -ChildPath $ItemPath $OutputDir = Split-Path -Path $OutputPath -Parent try { if (-not (Test-Path -Path $OutputDir)) { New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null } Invoke-WebRequest -Uri $DownloadUrl -Headers $Headers -OutFile $OutputPath -ErrorAction Stop -Verbose:$false Write-Verbose "Downloaded: $ItemPath" $script:SuccessCount++ } catch { Write-Error "Failed: $ItemPath - $($_.Exception.Message)" $script:FailCount++ } } elseif ($item.type -eq 'dir') { $UrlForItem = if ($item.url -like '*?ref=*') { $item.url } else { "$($item.url)?ref=$Branch" } $childParams = @{ Url = $UrlForItem RelativePath = $ItemPath Headers = $Headers TargetDir = $TargetDir Branch = $Branch } Get-NoGitHubRepoRecursiveContents @childParams } } } #EndRegion '.\Private\Get-NoGitHubRepoRecursiveContents.ps1' 72 #Region '.\Public\Get-NoGitHubRepoContents.ps1' -1 function Get-NoGitHubRepoContents { <# .SYNOPSIS Recursively downloads the contents of a GitHub repository to a local directory using the GitHub REST API. .DESCRIPTION Get-NoGitHubRepoContents uses a personal access token (PAT) to authenticate against GitHub and retrieve all files and folders from a given repository. The content is downloaded recursively and saved to a local folder. .EXAMPLE Get-NoGitHubRepoContents -Token 'abc' -Owner 'kevinblumenfeld' -Repo 'PS7' -TargetDir 'C:\Temp\PS7' #> [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Token, [Parameter(Mandatory)] [string] $Owner, [Parameter(Mandatory)] [string] $Repo, [string] $Branch = 'main', [Parameter(Mandatory)] [string] $TargetDir ) $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $headers = @{ Authorization = "token $Token" 'User-Agent' = $Owner } if (-not (Test-Path -Path $TargetDir)) { try { New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null Write-Verbose "Created directory: $TargetDir" } catch { Write-Error ("Failed to create directory: $TargetDir - {0}" -f $_.Exception.Message) return } } $script:SuccessCount = 0 $script:FailCount = 0 $ApiUrl = "https://api.github.com/repos/$Owner/$Repo/contents" $initialParams = @{ Url = "${ApiUrl}?ref=${Branch}" Headers = $headers TargetDir = $TargetDir Branch = $Branch } Get-NoGitHubRepoRecursiveContents @initialParams $stopwatch.Stop() $elapsed = $stopwatch.Elapsed $formattedTime = '{0:D2}:{1:D2}:{2:D2}' -f $elapsed.Hours, $elapsed.Minutes, $elapsed.Seconds Write-Verbose "--- Summary for $Owner/$Repo ---" Write-Verbose ("Success : {0}" -f $script:SuccessCount) Write-Verbose ("Fail : {0}" -f $script:FailCount) Write-Verbose ("OutputDir : {0}" -f $TargetDir) Write-Verbose ("Elapsed : {0}" -f $formattedTime) } #EndRegion '.\Public\Get-NoGitHubRepoContents.ps1' 78 #Region '.\Public\Get-NoGitHubRepoTreeContents.ps1' -1 function Get-NoGitHubRepoTreeContents { <# .SYNOPSIS Downloads files from a GitHub repository using the Git Trees API. .DESCRIPTION Uses the Git Trees API to recursively traverse a repository tree and download all blob (file) entries to a local directory. Handles SHA resolution, recursive trees, blob retrieval, and writes file contents to disk. Skips directories and submodules. .PARAMETER Token The GitHub Personal Access Token (PAT). .PARAMETER Owner The repository owner (user or organization). .PARAMETER Repo The name of the repository. .PARAMETER Branch The branch to download (default: main). .PARAMETER TargetDir Directory to save the files to. .EXAMPLE Get-NoGitHubRepoTreeContents -Token 'abc' -Owner 'octocat' -Repo 'Hello-World' -TargetDir './repo' #> [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Token, [Parameter(Mandatory)] [string] $Owner, [Parameter(Mandatory)] [string] $Repo, [Parameter()] [string] $Branch = 'main', [Parameter(Mandatory)] [string] $TargetDir ) $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $headers = @{ Authorization = "token $Token" 'User-Agent' = 'NoGit' Accept = 'application/vnd.github+json' } if (-not (Test-Path -Path $TargetDir)) { New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null } # Step 1: Get commit SHA from branch reference $refUrl = "https://api.github.com/repos/$Owner/$Repo/git/refs/heads/$Branch" try { $refResponse = Invoke-RestMethod -Uri $refUrl -Headers $headers $commitUrl = $refResponse.object.url } catch { Write-Error "Failed to resolve branch '$Branch'. Verify that it exists." return } # Step 2: Get commit object to find tree SHA $commitResponse = Invoke-RestMethod -Uri $commitUrl -Headers $headers $treeSha = $commitResponse.tree.sha # Step 3: Get tree recursively $treeUrl = "https://api.github.com/repos/$Owner/$Repo/git/trees/${treeSha}?recursive=1" $treeResponse = Invoke-RestMethod -Uri $treeUrl -Headers $headers if ($treeResponse.truncated -eq $true) { Write-Warning "Tree listing was truncated. Not all files may be downloaded." } $script:SuccessCount = 0 $script:FailCount = 0 foreach ($entry in $treeResponse.tree) { if ($entry.type -ne 'blob') { continue } $outputPath = Join-Path -Path $TargetDir -ChildPath $entry.path $outputDir = Split-Path -Path $outputPath -Parent if (-not (Test-Path -Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null } try { $blobUrl = "https://api.github.com/repos/$Owner/$Repo/git/blobs/$($entry.sha)" $blobHeaders = $headers.Clone() $blobHeaders['Accept'] = 'application/vnd.github.v3.raw' Invoke-WebRequest -Uri $blobUrl -Headers $blobHeaders -OutFile $outputPath -Verbose:$false Write-Verbose "Downloaded: $($entry.path)" $script:SuccessCount++ } catch { Write-Error "Failed to download: $($entry.path) - $_" $script:FailCount++ } } $stopwatch.Stop() $elapsed = $stopwatch.Elapsed $formattedTime = '{0:D2}:{1:D2}:{2:D2}' -f $elapsed.Hours, $elapsed.Minutes, $elapsed.Seconds Write-Verbose "--- Summary for $Owner/$Repo ---" Write-Verbose ("Success : {0}" -f $script:SuccessCount) Write-Verbose ("Fail : {0}" -f $script:FailCount) Write-Verbose ("OutputDir : {0}" -f $TargetDir) Write-Verbose ("Elapsed : {0}" -f $formattedTime) } #EndRegion '.\Public\Get-NoGitHubRepoTreeContents.ps1' 129 |