Private/Repository/Get-CgrRepositoryDefaultBranchTree.ps1
|
function Get-CgrRepositoryDefaultBranchTree { [CmdletBinding()] param( [Parameter(Mandatory)] [psobject] $Repository ) if ([string]::IsNullOrWhiteSpace([string] $Repository.DefaultBranch)) { $message = "Repository '$($Repository.FullName)' has no default branch whose tree can be inspected." $exception = [System.InvalidOperationException]::new($message) $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, 'RepositoryDefaultBranchMissing', [System.Management.Automation.ErrorCategory]::InvalidData, $Repository.FullName ) $PSCmdlet.ThrowTerminatingError($errorRecord) } $tempPath = Join-Path ([System.IO.Path]::GetTempPath()) "copy-github-repo-tree-$([guid]::NewGuid().ToString('N'))" try { $cloneResult = Invoke-CgrGitCommand ` -HostName $Repository.HostName ` -ArgumentList @('clone', '--depth', '1', '--branch', $Repository.DefaultBranch, $Repository.CloneUrl, $tempPath) ` -Environment @{ GIT_LFS_SKIP_SMUDGE = '1' } if ($cloneResult.ExitCode -ne 0) { $message = "Git failed to clone '$($Repository.FullName)' while reading its default-branch tree. $($cloneResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'RepositoryTreeCloneFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $Repository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } $commitResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $tempPath, 'rev-parse', 'HEAD') if ($commitResult.ExitCode -ne 0 -or @($commitResult.Output).Count -eq 0) { $message = "Git failed to resolve the default-branch commit for '$($Repository.FullName)'. $($commitResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'RepositoryCommitResolutionFailed', [System.Management.Automation.ErrorCategory]::InvalidData, $Repository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } $treeResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $tempPath, 'rev-parse', 'HEAD^{tree}') if ($treeResult.ExitCode -ne 0 -or @($treeResult.Output).Count -eq 0) { $message = "Git failed to resolve the default-branch tree for '$($Repository.FullName)'. $($treeResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'RepositoryTreeResolutionFailed', [System.Management.Automation.ErrorCategory]::InvalidData, $Repository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } $pointerFiles = @() $gitLfsObjectsAvailable = $true $attributeFiles = if ([System.IO.Directory]::Exists($tempPath)) { @([System.IO.Directory]::EnumerateFiles($tempPath, '.gitattributes', [System.IO.SearchOption]::AllDirectories) | Where-Object { $_ -notmatch '[\\/]\.git[\\/]' }) } else { @() } $usesGitLfs = $false foreach ($attributeFile in $attributeFiles) { foreach ($line in [System.IO.File]::ReadAllLines($attributeFile)) { $trimmedLine = $line.Trim() if (-not $trimmedLine.StartsWith('#') -and $trimmedLine -match '(^|\s)filter=lfs(\s|$)') { $usesGitLfs = $true break } } if ($usesGitLfs) { break } } if ($usesGitLfs) { $gitLfsVersionResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('lfs', 'version') if ($gitLfsVersionResult.ExitCode -ne 0) { $message = "Source repository '$($Repository.FullName)' uses Git LFS, but Git LFS is unavailable while capturing the approved Snapshot source state." $exception = [System.InvalidOperationException]::new($message) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'GitLfsRequiredForSnapshotPlanning', [System.Management.Automation.ErrorCategory]::ResourceUnavailable, 'git-lfs') $PSCmdlet.ThrowTerminatingError($errorRecord) } $listResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $tempPath, 'lfs', 'ls-files', '--name-only') if ($listResult.ExitCode -ne 0) { $message = "Git LFS failed to enumerate Snapshot pointer files for '$($Repository.FullName)'. $($listResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'SnapshotPlanningGitLfsEnumerationFailed', [System.Management.Automation.ErrorCategory]::InvalidData, $Repository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } $pointerFiles = @($listResult.Output | ForEach-Object { $_.ToString() } | Sort-Object) if ($pointerFiles.Count -gt 0) { $fetchResult = Invoke-CgrGitCommand -HostName $Repository.HostName -ArgumentList @('-C', $tempPath, 'lfs', 'fetch', 'origin', $Repository.DefaultBranch) $gitLfsObjectsAvailable = $fetchResult.ExitCode -eq 0 if (-not $gitLfsObjectsAvailable) { $message = "Git LFS objects referenced by the approved Snapshot source state for '$($Repository.FullName)' could not be fetched. $($fetchResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'SnapshotPlanningGitLfsFetchFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $Repository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } } } $workspaceBytes = 0L if ([System.IO.Directory]::Exists($tempPath)) { $measuredWorkspaceBytes = (Get-ChildItem -LiteralPath $tempPath -File -Recurse -Force | Measure-Object -Property Length -Sum).Sum if ($null -ne $measuredWorkspaceBytes) { $workspaceBytes = [long] $measuredWorkspaceBytes } } return [pscustomobject] @{ PSTypeName = 'CopyGitHubRepo.RepositoryTreeIdentity' Repository = $Repository.FullName BranchName = $Repository.DefaultBranch CommitSha = [string] @($commitResult.Output)[0] TreeSha = [string] @($treeResult.Output)[0] GitLfsObjectsAvailable = $gitLfsObjectsAvailable GitLfsPointerFiles = $pointerFiles PlanningWorkspaceBytes = [long] $workspaceBytes } } finally { Remove-Item -LiteralPath $tempPath -Recurse -Force -ErrorAction SilentlyContinue } } |