Types/OpenPackage.Source/Tar.ps1
|
<# .SYNOPSIS Gets a tarfile as a package .DESCRIPTION Gets a tarfile as an open package. #> param( # The path to a tarfile. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $TarFile, # A list of file wildcards to include. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Include, # A list of file wildcards to exclude. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Exclude, # The base path within the package. # Content should be added beneath this base path. [string] $BasePath = '/', # A content type map. # This maps extensions and URIs to a content type. [Collections.IDictionary] $TypeMap = $( ([PSCustomObject]@{PSTypeName='OpenPackage.ContentTypeMap'}).TypeMap ), # The compression option. [IO.Packaging.CompressionOption] [Alias('CompressionLevel')] $CompressionOption = 'Superfast', # If set, will force the redownload of various resources and remove existing files or directories [switch] $Force, # If set, will include hidden files and folders, except for files beneath `.git` [Alias('IncludeDotFiles')] [switch] $IncludeHidden, # If set, will include the `.git` directory contents if found. [switch] $IncludeGit, # If set, will include any content found in `/node_modules`. [Alias('IncludeNodeModules')] [switch] $IncludeNodeModule ) $namedParameters = [Ordered]@{} foreach ($key in $MyInvocation.MyCommand.Parameters.Keys) { $var = $ExecutionContext.SessionState.PSVariable.Get($key) if ($var) { $namedParameters[$key] = $var.value } } $namedParameters.Remove('TarFile') # Put tar files into their own subdirectory foreach ($resolvedItem in Get-Item -Path $TarFile) { # First lets peek at the magic bytes that might give us a clue $peekMagicBytes = Get-Content -AsByteStream -LiteralPath $resolvedItem.FullName -First 5 $myAppData = if ($env:OpenPackagePath) { # Get our first OpenPackage package path @($env:OpenPackagePath -split $( if ($IsLinux -or $IsMacOS) { ':' } else { ';' } ))[0] } else { $pwd } $tarDestination = Join-Path $myAppData 'tar' if (-not (Test-Path $tarDestination)) { $newDir = New-Item -ItemType Directory -Path $tarDestination -Force if (-not $newDir) { return } } # and each destination in its own subdirectory $thisTarDestination = Join-Path $tarDestination ($resolvedItem.Name -replace '\.gz$' -replace '\.tar$') if (-not (Test-Path $thisTarDestination)) { $newDir = New-Item -ItemType Directory -Path $thisTarDestination -Force if (-not $newDir) { return } } $tarFormat = if ( $peekMagicBytes[0] -as [char] -eq '.' -and $peekMagicBytes[1] -as [char] -eq '/' ) { # classic tarfile without gzipping 'tar' } elseif ($peekMagicBytes -and $peekMagicBytes[0] -eq 31 -and $peekMagicBytes[1] -eq 139 -and $peekMagicBytes[2] -eq 8 ) { # gzipped tarball 'tar.gz' } else { Write-Error "$($resolvedItem.Name) does not appear to be a .tar or .tar.gz file" continue } # If the engine supports tarfiles if ('Formats.Tar.TarFile' -as [Type]) { # read the file as a stream $openFile = [IO.File]::OpenRead($resolvedItem.FullName) if ($tarFormat -eq 'tar.gz') { # and read that as a decompressed gzip stream $gzipStream = [IO.Compression.GZipStream]::new($openFile, [IO.Compression.CompressionMode]'Decompress') if (-not $gzipStream) { $openFile.Close() } [Formats.Tar.TarFile]::ExtractToDirectory($gzipStream, $thisTarDestination, $true) # Track if it worked $worked = $? # and close up $gzipStream.Close() $null = $gzipStream.DisposeAsync() $openFile.Close() $null = $openFile.DisposeAsync() } else { [Formats.Tar.TarFile]::ExtractToDirectory($openFile, $thisTarDestination, $true) $worked = $? $openFile.Close() $null = $openFile.DisposeAsync() } # If it worked if ($worked) { # pack that directory Get-Item -LiteralPath "$thisTarDestination" | Get-OpenPackage @namedParameters } } elseif ($( $tarApp = $ExecutionContext.SessionState.InvokeCommand.GetCommand('tar', 'Application') $tarApp )) { # Alternatively, if the tar application installed, we can use that $null = & $tarApp -xvf $resolvedItem.FullName -C "$thisTarDestination" if ($?) { # and then pack the directory Get-Item -LiteralPath "$thisTarDestination" | Get-OpenPackage @namedParameters } } else { # If neither of those paths work, write a warning. Write-Warning "$($resolvedItem.FullName) is a tar gz, but Formats.Tar.TarFile is not loaded and `tar` app does not exist" } } |