Types/OpenPackage.Source/Zip.ps1
|
<# .SYNOPSIS Gets a zipfile as a package .DESCRIPTION Gets a zipfile as an open package. #> param( # The path to a tarfile. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $ZipFile, # A list of file wildcards to include. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Include, # A list of file wildcards to exclude. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Exclude, # 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 $namedParameters.Keys) { $var = $ExecutionContext.SessionState.PSVariable.Get($key) if ($var) { $namedParameters[$key] = $var.value } } $namedParameters.Remove('ZipFile') # Put tar files into their own subdirectory foreach ($resolvedItem in Get-Item -Path $ZipFile) { # By reading the file with Get-Content -AsByteStream, we avoid locking the file # (or the file being locked by another process) $peekMagicBytes = Get-Content -AsByteStream -LiteralPath $resolvedItem.FullName -First 5 if ($peekMagicBytes[0,1] -as 'char[]' -join '' -ne 'PK') { return } $packageBytes = Get-Content -LiteralPath $resolvedItem.FullName -AsByteStream -Raw # Create a memory stream from the byte array $memoryStream = [IO.MemoryStream]::new($packageBytes) # and open the package from the memory stream $currentPackage = [IO.Packaging.Package]::Open($memoryStream, "Open", "ReadWrite") # If that did not work, return. if (-not $currentPackage) { return } $packageParts = @($currentPackage.GetParts()) # If we could open the file but not see the parts, it's a normal zip if (-not $packageParts) { # Close the package and the stream and try Expand-Archive. $currentPackage.Close() $memoryStream.Close() # To make things work, we want to extract to a folder and reload # it's important that the folder name matches the file name, without the extension $folderName = $resolvedItem.Name -replace '\.[^\.]+?$' $myAppData = if ($env:OpenPackagePath) { # Get our first OpenPackage package path @($env:OpenPackagePath -split $( if ($IsLinux -or $IsMacOS) { ':' } else { ';' } ))[0] } else { $pwd } $folderPath = Join-Path $myAppData $folderName # If the folder path did not exist if (-not (Test-Path $folderPath)) { # create it $newDirectory = New-Item -ItemType Directory -Path $folderPath if (-not $newDirectory) { return } } # If the folder already exists, and we are not using force if ((Test-Path $folderPath)) { if (-not $Force) { Write-Error "$FolderPath exists, use -Force" return } # remove the current folder, so that no errant files show up in the package. Remove-Item -Path $folderPath -Recurse -Force } # If that worked, expand the archive to this path (giving us a fresh copy) Expand-Archive -LiteralPath $resolvedItem.FullName -DestinationPath $folderPath if ($?) { # and call ourself return Get-OpenPackage -FilePath $folderPath @namedParameters } else { return } } $currentPackage = $currentPackage | Add-Member NoteProperty FilePath $filePath -Force -PassThru | Add-Member NoteProperty MemoryStream $memoryStream -Force -PassThru # If there is no identifier, set it to the file name if (-not $currentPackage.PackageProperties.Identifier) { $currentPackage.PackageProperties.Identifier = $resolvedItem.Name } $currentPackage } |