Private/Git/Copy-CgrGitLfsObject.ps1
|
function Copy-CgrGitLfsObject { [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSUseShouldProcessForStateChangingFunctions', '', Justification = 'The public Copy-GitHubRepository command performs the ShouldProcess check before calling this migration boundary.' )] [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $SourcePath, [Parameter(Mandatory)] [psobject] $SourceRepository, [Parameter(Mandatory)] [psobject] $DestinationRepository, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $BranchName ) $attributeFiles = if ([System.IO.Directory]::Exists($SourcePath)) { @([System.IO.Directory]::EnumerateFiles($SourcePath, '.gitattributes', [System.IO.SearchOption]::AllDirectories) | Where-Object { $_ -notmatch '[\\/]\.git[\\/]' }) } else { @() } $hasGitLfsFilter = $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|$)') { $hasGitLfsFilter = $true break } } if ($hasGitLfsFilter) { break } } if (-not $hasGitLfsFilter) { return [pscustomobject] @{ PSTypeName = 'CopyGitHubRepo.GitLfsCopyResult' UsesGitLfs = $false PointerFiles = @() ObjectsCopied = $false IsSuccessful = $true } } $gitLfsVersionResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('lfs', 'version') if ($gitLfsVersionResult.ExitCode -ne 0) { $message = "Source repository '$($SourceRepository.FullName)' uses Git LFS, but Git LFS is not available. Install Git LFS before retrying so the referenced objects can be copied safely." $exception = [System.InvalidOperationException]::new($message) $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, 'GitLfsRequired', [System.Management.Automation.ErrorCategory]::ResourceUnavailable, 'git-lfs' ) $PSCmdlet.ThrowTerminatingError($errorRecord) } $listResult = Invoke-CgrNativeCommand ` -FilePath 'git' ` -ArgumentList @('-C', $SourcePath, 'lfs', 'ls-files', '--name-only') if ($listResult.ExitCode -ne 0) { $message = "Git LFS failed while listing tracked files in '$($SourceRepository.FullName)'. $($listResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, 'GitLfsPointerDetectionFailed', [System.Management.Automation.ErrorCategory]::InvalidData, $SourceRepository.FullName ) $PSCmdlet.ThrowTerminatingError($errorRecord) } $pointerFiles = @($listResult.Output | ForEach-Object { $_.ToString() }) if ($pointerFiles.Count -eq 0) { return [pscustomobject] @{ PSTypeName = 'CopyGitHubRepo.GitLfsCopyResult' UsesGitLfs = $false PointerFiles = @() ObjectsCopied = $false IsSuccessful = $true } } $fetchResult = Invoke-CgrGitCommand ` -HostName $SourceRepository.HostName ` -ArgumentList @('-C', $SourcePath, 'lfs', 'fetch', 'origin', $BranchName) if ($fetchResult.ExitCode -ne 0) { $message = "Git LFS failed to fetch objects from '$($SourceRepository.FullName)'. $($fetchResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, 'SourceGitLfsFetchFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $SourceRepository.FullName ) $PSCmdlet.ThrowTerminatingError($errorRecord) } $remoteName = 'cgr-destination' $addRemoteResult = Invoke-CgrNativeCommand ` -FilePath 'git' ` -ArgumentList @('-C', $SourcePath, 'remote', 'add', $remoteName, $DestinationRepository.CloneUrl) if ($addRemoteResult.ExitCode -ne 0) { $message = "Git failed to configure the destination remote for Git LFS migration. $($addRemoteResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, 'DestinationGitLfsRemoteConfigurationFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $DestinationRepository.FullName ) $PSCmdlet.ThrowTerminatingError($errorRecord) } try { $pushResult = Invoke-CgrGitCommand ` -HostName $DestinationRepository.HostName ` -ArgumentList @('-C', $SourcePath, 'lfs', 'push', '--all', $remoteName, $BranchName) if ($pushResult.ExitCode -ne 0) { $message = "Git LFS failed to push objects to '$($DestinationRepository.FullName)'. $($pushResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, 'DestinationGitLfsPushFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $DestinationRepository.FullName ) $PSCmdlet.ThrowTerminatingError($errorRecord) } } finally { Invoke-CgrNativeCommand ` -FilePath 'git' ` -ArgumentList @('-C', $SourcePath, 'remote', 'remove', $remoteName) | Out-Null } [pscustomobject] @{ PSTypeName = 'CopyGitHubRepo.GitLfsCopyResult' UsesGitLfs = $true PointerFiles = $pointerFiles ObjectsCopied = $true IsSuccessful = $true } } |