Bendev.Assets.Management.psm1
enum CopyMode{ Default = 0 # The asset will be copied only if it has no sub-assets Copy = 1 # The asset will be copied regardless of not having sub-assets Skip = 2 # The asset will not be copied regardless of having sub-assets } class TransformExecutionArgs{ [string]$AssetPath [string]$TransformPath [string]$ImagePath TransformExecutionArgs([string]$assetPath, [string]$transformPath, [string]$imagePath){ $this.AssetPath = $assetPath; $this.TransformPath = $transformPath; $this.ImagePath = $imagePath; } } class Transform { [String]$TargetPath; [void] Execute([TransformExecutionArgs]$data){ Write-Host "No transformation performed" } Transform (){ } } class Asset { [String]$SourcePath; [Transform[]]$Transforms; [Asset[]]$Assets; [String]$TargetPath; [CopyMode]$CopyMode = [CopyMode]::Default; static [Asset[]]ParseArray([Array] $objs){ $newAssets = New-Object "System.Collections.Generic.List[Asset]" $objs | ForEach-Object{ [Asset]$newObj = $null; $obj = $_; if ($obj -is [string]){ $newObj = [Asset]::Parse([string]$obj); $newAssets.Add($newObj); }elseif($obj -is [PsObject]){ $newObj = [Asset]::Parse([PsObject]$obj); $newAssets.Add($newObj); }else{ throw [System.NotSupportedException] "Not supported object type" } } return $newAssets.ToArray(); } static [Asset]Parse([String] $obj){ [Asset]$newObj = [Asset]::New($obj, [string]$null); return $newObj; } static [Asset]Parse([PsObject] $obj){ [Asset]$newObj = $null; $trfms = New-Object "System.Collections.Generic.List[Transform]" if ($obj.Transforms){ $obj.Transforms | ForEach-Object { $transformDef= $_; $type = 'Transform'; if ($transformDef.Type){ $type = $transformDef.Type; if($transformDef -is [System.Collections.IDictionary]){ $transformDef.Remove("Type"); } } [Object[]]$args = $null if ($transformDef.ConstructorArgs){ $args = $transformDef.ConstructorArgs; if($transformDef -is [System.Collections.IDictionary]){ $transformDef.Remove("ConstructorArgs") } } [System.Collections.IDictionary]$props = $null; if ($transformDef.Properties){ $props = $transformDef.Properties; if($transformDef -is [System.Collections.IDictionary]){ $transformDef.Remove("Properties"); } }else{ if($transformDef -is [System.Collections.IDictionary]){ $props = $transformDef; }else{ $props = [System.Collections.Generic.Dictionary[String, Object]]::new(); $transformDef.PSObject.Properties | ForEach-Object { $prp = $_; switch($prp.name){ Type{} ConstructorArgs{} Properties{} default{ $props.Add($prp.name, $prp.value); } } } } } [Transform]$transform = [Transform](New-Object -TypeName $type -ArgumentList $args -Property $props); $trfms.Add($transform); } } [Asset[]]$subAssets= $null if ($obj.Assets){ $subAssets = [Asset]::ParseArray($obj.Assets); } [String]$tPath = $null; if($obj.TargetPath){ $tPath = $obj.TargetPath } [CopyMode]$tmpCopyMode = [CopyMode]::Default; if ($obj.CopyMode){ $tmpCopyMode = $obj.CopyMode; } $newObj = [Asset]::New($obj.SourcePath, $trfms.ToArray(), $subAssets, $tPath, $tmpCopyMode); return $newObj; } [string]ToString(){ return $this.SourcePath } Asset ([String]$sourcePath, [String]$targetPath){ $this.SourcePath = $sourcePath; $this.TargetPath = $targetPath; } Asset ([String]$sourcePath, [Transform[]]$transforms, [Asset[]]$assets, [String]$targetPath, [CopyMode]$copyMode){ $this.SourcePath = $sourcePath $this.Transforms = $transforms $this.Assets = $assets $this.TargetPath = $targetPath; $this.CopyMode = $copyMode; } } class PowerShellScriptTransform: Transform{ [String]$PSScript; [PSObject]$AdditionalParameters; [void] Execute([TransformExecutionArgs]$data){ $assetPath = $data.AssetPath; $transformPath = $data.TransformPath; if ($this.TargetPath){ if ([System.IO.Path]::IsPathRooted($this.TargetPath)){ $transformPath = $this.TargetPath }else{ $transformPath = (Join-Path $transformPath $this.TargetPath) } } $scriptPath = (Join-Path $data.ImagePath $this.PSScript) $data.AssetPath = $transformPath; $data.TransformPath = $transformPath; Write-Host "Transforming the JSON file '$assetPath' into '$transformPath' using '$scriptPath'" -ForegroundColor Green $exp = "&`"$scriptPath`" -SourcePath `"$assetPath`" -TargetPath `"$transformPath`"" # Additional parameters can be passed from the JSON file as follows: # "AdditionalParameters": {"Param1":"aaa", "Param2":"bbb"} if($this.AdditionalParameters){ $this.AdditionalParameters.PSObject.Properties | ForEach-Object { $prp = $_; $exp = "{0} -{1} `"{2}`"" -f $exp, $prp.Name, $prp.Value } } #Write-Host $exp Invoke-Expression $exp #$assetItem = Get-Item -Path $assetPath; #Copy-Item $assetItem -Destination $transformPath Write-Host "Transformed JSON file '$assetPath' into '$transformPath'" -ForegroundColor Green } PowerShellScriptTransform () : base (){ } } class UnzipTransform: Transform{ [void] Execute([TransformExecutionArgs]$data){ $assetPath = $data.AssetPath; $transformPath = $data.TransformPath; if ($this.TargetPath){ if ([System.IO.Path]::IsPathRooted($this.TargetPath)){ $transformPath = $this.TargetPath }else{ $transformPath = (Join-Path $transformPath $this.TargetPath) } } $data.AssetPath = $transformPath; $data.TransformPath = $transformPath; if (!(Test-Path -Path $transformPath)) { Expand-Archive -Path $assetPath -DestinationPath $transformPath; Write-Host "Unzipped $assetPath into $transformPath" -ForegroundColor Green }else{ Write-Host "Not need to unzip asset $assetPath. Destination '$transformPath' already exists" -ForegroundColor Green } } UnzipTransform () : base (){ } } class DotNetUnzipTransform: Transform{ [Boolean]$Overwrite = $false; [void] Execute([TransformExecutionArgs]$data){ $assetPath = $data.AssetPath; $transformPath = $data.TransformPath; if ($this.TargetPath){ if ([System.IO.Path]::IsPathRooted($this.TargetPath)){ $transformPath = $this.TargetPath }else{ $transformPath = (Join-Path $transformPath $this.TargetPath) } } $data.AssetPath = $transformPath; $data.TransformPath = $transformPath; Invoke-EnsureDirectoryExists $transformPath Get-ChildItem -Path $assetPath | ForEach-Object { $zipPath = $_.FullName $maxPathSize = 260 try { $stream = New-Object IO.FileStream($zipPath, [System.IO.FileMode]::Open) $zip = New-Object IO.Compression.ZipArchive($stream, [System.IO.Compression.ZipArchiveMode]::Read) #[System.IO.Compression.ZipFileExtensions]::ExtractToDirectory($zip, $transformPath) <# #> $zip.Entries | Foreach-Object { if ($_.FullName.EndsWith('/')){ Invoke-EnsureDirectoryExists (Join-Path $transformPath $_.FullName); }else{ $filePath = (Join-Path $transformPath $_.FullName) $parentDirectory = [System.IO.Path]::GetDirectoryName($filePath) if ($filePath.Length -gt $maxPathSize){ Write-Host "Too long Path ($filePath.Length): $filePath" -ForegroundColor Red }else{ Invoke-EnsureDirectoryExists $parentDirectory; #Write-Host "Decompressing: $filePath" #[IO.Compression.ZipFileExtensions]::ExtractToFile($_, $filePath , $this.Overwrite) if ( (-Not $this.Overwrite) -And (Test-Path $filePath)){ Write-Host "Already Exists: $filePath" }else{ Write-Host "Overwriting: $filePath" [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $filePath , $true) } } } } } finally { if ($zip -ne $null) { $zip.Dispose() } if ($stream -ne $null) { $stream.Dispose() } } } } DotNetUnzipTransform () : base (){ } } function Invoke-ProcessAssets{ param( [Parameter(Mandatory = $true)] [Asset[]]$Assets, [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_ -PathType 'Container'})] [String]$AssetsSourcePath, [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_ -PathType 'Container'})] [String]$TargetPath, [Parameter(Mandatory = $false)] [ValidateScript( {[String]::IsNullOrWhiteSpace($AssetsTransformPath) -or (Test-Path $_ -PathType 'Container')})] [String]$AssetsTransformPath, [Parameter(Mandatory = $false)] [ValidateScript( {Test-Path $_ -PathType 'Container'})] [string]$PSTransformationsSourcePath ) if ([String]::IsNullOrWhiteSpace($AssetsTransformPath)){ $AssetsTransformPath = $AssetsSourcePath; } $Assets | ForEach-Object { $assetMetadata = $_; $assetPath = Join-Path $AssetsSourcePath $assetMetadata.SourcePath; $transformArgs = [TransformExecutionArgs]::new($assetPath, $AssetsTransformPath, $PSTransformationsSourcePath) if($assetMetadata.Transforms){ $assetMetadata.Transforms | ForEach-Object{ $transform = $_; #if ($transform){ $transform.Execute(($transformArgs));} $transform.Execute(($transformArgs)); $assetPath = $transformArgs.AssetPath;# The asset path may have changed in the transform } } if ($assetMetadata.Assets){ Invoke-ProcessAssets $assetMetadata.Assets $transformArgs.AssetPath $TargetPath $transformArgs.TransformPath $PSTransformationsSourcePath } [Boolean]$shouldCopy = (($assetMetadata.CopyMode -eq [CopyMode]::Copy) -Or (-Not $assetMetadata.Assets)); if($shouldCopy){ $assetItem = Get-Item -Path $assetPath; if ($assetMetadata.TargetPath){ $destinationFolder = Join-Path $TargetPath $assetMetadata.TargetPath }else{ $destinationFolder = $TargetPath } #Copy-Item $assetItem -Destination $newTargetPath -Verbose:$VerbosePreference -Recurse -Force #$destinationFolder = $newTargetPath.Replace($newTargetPath.Split("\")[-1],"") if (!(Test-Path -path $destinationFolder)) { New-Item $destinationFolder -Type Directory } $newTargetPath = Join-Path $destinationFolder $assetItem.Path Write-Host "Copying '$assetPath' to '$newTargetPath'" Copy-Item $assetPath $newTargetPath -Verbose:$VerbosePreference -Recurse -Force } } } |