PSDeployScripts/FileSystem.ps1
<# .SYNOPSIS Deploy using Robocopy or Copy-Item for folder and file deployments, respectively. .DESCRIPTION Deploy using Robocopy or Copy-Item for folder and file deployments, respectively. Runs in the current session (i.e. as the current user) .PARAMETER Deployment Deployment to run .PARAMETER Mirror If specified and the source is a folder, we effectively call robocopy /MIR (Can remove folders/files...) .PARAMETER IncludeOlder If specified and the source is a folder, we effectively call robocopy without /XO (Exclude Older Files) #> [cmdletbinding()] param ( [ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PSDeploy.Deployment' })] [psobject[]]$Deployment, [switch]$Mirror, [switch]$IncludeOlder ) Write-Verbose "Starting local deployment with $($Deployment.count) sources" #Local Deployment. Duplicate code. Sigh. foreach($Map in $Deployment) { if($Map.SourceExists) { $Targets = $Map.Targets foreach($Target in $Targets) { if($Map.SourceType -eq 'Directory') { if($null -ne (Get-Command -Name Robocopy -ErrorAction SilentlyContinue)){ if($Map.DeploymentOptions.includeolder -eq 'True' -or $IncludeOlder) { [string[]]$Arguments = "/E" } else { [string[]]$Arguments = "/XO" $Arguments += "/E" } if($Map.DeploymentOptions.mirror -eq 'True' -or $Mirror) { [string[]]$Arguments = "/E" $Arguments += "/PURGE" } # Resolve PSDrives. $Target = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Target) Write-Verbose "Invoking ROBOCOPY.exe $($Map.Source) $Target $Arguments" Invoke-Robocopy -Path $Map.Source -Destination $Target -ArgumentList $Arguments } #TODO: If the platform is Unix, try to use rsync to perform this action # elseif(($PSVersionTable.Platform -eq 'Unix') -and ($null -ne (Get-Command -Name 'rsync' -ErrorAction SilentlyContinue))){} else{ #PowerShell Fall Back # Write-Warning -Message 'Robocopy or rsync could not be found. Falling back to basic PowerShell based file copy' Write-Warning -Message 'Robocopy could not be found. Falling back to basic PowerShell based file copy' Try { if(($Map.DeploymentOptions.mirror -eq 'True' -or $Mirror) -and (Test-Path -PathType Container -Path $Target)){ Get-ChildItem -Path $Target -Force | Remove-Item -Force -Recurse } if(!(Test-Path -PathType Container -Path $Target)){ New-Item -ItemType Directory -Path $Target -Force } Get-ChildItem -Path $Map.Source | Copy-Item -Destination $Target -Recurse } catch{ $PSCmdlet.ThrowTerminatingError($_) } } } else { $SourceHash = ( Get-Hash $Map.Source ).SHA256 $TargetHash = ( Get-Hash $Target -ErrorAction SilentlyContinue -WarningAction SilentlyContinue ).SHA256 if($SourceHash -ne $TargetHash) { Write-Verbose "Deploying file '$($Map.Source)' to '$Target'" Try { Copy-Item -Path $Map.Source -Destination $Target -Force } Catch [System.IO.IOException],[System.IO.DirectoryNotFoundException] { $NewDir = $Target if ($NewDir[-1] -ne '\') { $NewDir = Split-Path -Path $NewDir } $null = New-Item -ItemType Directory -Path $NewDir Copy-Item -Path $Map.Source -Destination $Target -Force } } else { Write-Verbose "Skipping deployment with matching hash: '$($Map.Source)' = '$Target')" } } } } } |