PSDependScripts/FileDownload.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
<# .SYNOPSIS Download a file .DESCRIPTION Download a file Relevant Dependency metadata: DependencyName (Key): The key for this dependency is used as the URL. This can be overridden by 'Source' Name: Optional file name for the downloaded file. Defaults to parsing filename from the URL Target: The folder to download this file to. If a full path to a new file is used, this overrides any other file name. Source: Optional override for URL AddToPath: If specified, prepend the target's parent container to PATH .PARAMETER PSDependAction Test or Install the module. Defaults to Install Test: Return true or false on whether the dependency is in place Install: Install the dependency .EXAMPLE sqllite_dll = @{ DependencyType = 'FileDownload' Source = 'https://github.com/RamblingCookieMonster/PSSQLite/blob/master/PSSQLite/x64/System.Data.SQLite.dll?raw=true' Target = 'C:\temp' } # Downloads System.Data.SQLite.dll to C:\temp .EXAMPLE 'https://github.com/RamblingCookieMonster/PSSQLite/blob/master/PSSQLite/x64/System.Data.SQLite.dll?raw=true' = @{ DependencyType = 'FileDownload' Target = 'C:\temp\sqlite.dll' } # Downloads System.Data.SQLite.dll to C:\temp\sqlite.dll #> [cmdletbinding()] param( [PSTypeName('PSDepend.Dependency')] [psobject[]] $Dependency, [ValidateSet('Test', 'Install')] [string[]]$PSDependAction = @('Install') ) function Parse-URLForFile { [cmdletbinding()] param($URL) # This will need work. Assume leaf is file. If CGI exists in leaf, assume it is after the file $FileName = $URL.split('/')[-1] if($FileName -match '\?') { $FileName.split('?')[0] } else { $FileName } Write-Verbose "Parsed file name [$FileName] from `$URL" } # Extract data from Dependency $DependencyName = $Dependency.DependencyName $Name = $Dependency.Name $Target = $Dependency.Target $Source = $Dependency.Source # Pick the URL if($Source) { $URL = $Source } else { $URL = $DependencyName } Write-Verbose "Using URL: $URL" # Act on target path.... $ToInstall = $False # Anti pattern $TargetParent = Split-Path $Target -Parent $PathToAdd = $Target if( (Test-Path $TargetParent) -and -not (Test-Path $Target)) { # They gave us a full path, don't parse the file name, use this! $Path = $Target $ToInstall = $True Write-Verbose "Found parent [$TargetParent], not target [$Target], assuming this is target file path" } elseif(Test-Path $Target -PathType Leaf) { # File exists. We should download to temp spot, compare hashes, take action as appropriate. # For now, skip the file. Write-Verbose "Skipping existing file [$Target]" if($PSDependAction -contains 'Test') { return $True } $PathToAdd = Split-Path $Target -Parent } elseif(-not (Test-Path $Target)) { # They gave us something that doesn't look like a new container for a new or existing file. Wat? Write-Error "Could not find target path [$Target]" if($PSDependAction -contains 'Test') { return $False } } else { Write-Verbose "[$Target] is a container, creating path to file" # We have a target container, now find the name If($Name) { # explicit name $FileName = $Name } else { $FileName = Parse-URLForFile -URL $URL } $Path = Join-Path $Target $FileName if(Test-Path $Path -PathType Leaf) { Write-Verbose "Skipping existing file [$Path]" if($PSDependAction -contains 'Test') { return $True } } else { $ToInstall = $True } } Write-Verbose "Using [$Path] as `$Target" #No dependency found, return false if we're testing alone... if( $PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1) { return $False } Write-Verbose "Downloading [$URL] to [$Path]" if($PSDependAction -contains 'Install' -and $ToInstall) { # Future considerations: # Should we check for existing? And if we find it, still download file, and compare sha256 hash, replace if it does not match? # We should consider credentials at some point, but PSD1 does not lend itself to securely storing passwords Get-WebFile -URL $URL -Path $Path } if($Dependency.AddToPath) { Write-Verbose "Setting PATH to`n$($PathToAdd, $env:PATH -join ';' | Out-String)" Add-ToItemCollection -Reference Env:\Path -Item $PathToAdd } |