Add PreserveRelativePath and type parameters to Invoke-GiteaFileDownload; enhance Get-GiteaChildItem with File switch for filtering

This commit is contained in:
2025-04-24 16:34:18 -04:00
parent d8dfb1d1fe
commit fb2a87ed84

View File

@@ -297,6 +297,15 @@ Function Invoke-GiteaFileDownload {
.PARAMETER force .PARAMETER force
A switch parameter to force overwriting of an existing file at the output path. A switch parameter to force overwriting of an existing file at the output path.
.PARAMETER PreserveRelativePath
A switch parameter to preserve the relative path structure from the repository.
If used without specifying an outputPath, creates the directory structure in the current location.
If used with outputPath, treats the outputPath as the base directory to append the relative path to.
.PARAMETER type
The type of the item to download (file, dir, lfs). This parameter is typically used with pipeline input from Get-GiteaChildItem.
Directories will be skipped with a verbose message.
.EXAMPLE .EXAMPLE
# Example 1: Download a file to the current directory # Example 1: Download a file to the current directory
@@ -309,16 +318,29 @@ Function Invoke-GiteaFileDownload {
.EXAMPLE .EXAMPLE
# Example 3: Download files in pipeline from Get-GiteaChildItem # Example 3: Download files in pipeline from Get-GiteaChildItem
Get-GiteaChildItem -path "docs" | Where-Object { $_.type -eq 'file' } | Invoke-GiteaFileDownload Get-GiteaChildItem -path "docs" | Where-Object { $_.type -eq 'file' } | Invoke-GiteaFileDownload
.EXAMPLE
# Example 4: Download files preserving their relative paths
Get-GiteaChildItem -path "docs" -Recurse | Where-Object { $_.type -eq 'file' } | Invoke-GiteaFileDownload -PreserveRelativePath
.EXAMPLE
# Example 5: Download files preserving their relative paths with a base output directory
Get-GiteaChildItem -path "docs" -Recurse | Where-Object { $_.type -eq 'file' } | Invoke-GiteaFileDownload -PreserveRelativePath -outputPath "C:\Downloads"
#> #>
[cmdletbinding()] [cmdletbinding()]
param( param(
[Parameter(Mandatory, ValueFromPipelineByPropertyName)] [Parameter(ValueFromPipelineByPropertyName)]
[string]$downloadURL, [string]$downloadURL,
[string]$token, [string]$token,
[Parameter(ValueFromPipelineByPropertyName)] [Parameter(ValueFromPipelineByPropertyName)]
[string]$outputPath, [string]$outputPath,
[switch]$force [switch]$force,
[Parameter(ValueFromPipelineByPropertyName)]
[string]$filePath,
[switch]$PreserveRelativePath,
[Parameter(ValueFromPipelineByPropertyName)]
[string]$type
) )
begin { begin {
@@ -338,6 +360,7 @@ Function Invoke-GiteaFileDownload {
Write-Verbose "Parameters:" Write-Verbose "Parameters:"
Write-Verbose "token: $token (length: $(if($token){$token.Length}else{0}))" Write-Verbose "token: $token (length: $(if($token){$token.Length}else{0}))"
Write-Verbose "PreserveRelativePath: $PreserveRelativePath"
# Create a WebClient to be reused # Create a WebClient to be reused
$webClient = New-Object System.Net.WebClient $webClient = New-Object System.Net.WebClient
@@ -345,31 +368,103 @@ Function Invoke-GiteaFileDownload {
} }
process { process {
Write-Verbose "File path: $filePath"
Write-Verbose "Type: $type"
# Skip directories and provide a verbose message
if ($type -eq "dir") {
Write-Verbose "Skipping directory: $filePath"
return [PSCustomObject]@{
Path = $filePath
SourceURL = $downloadURL
FilePath = $filePath
Type = $type
Success = $true
Error = "Skipped - item is a directory"
Timestamp = Get-Date
FileSize = $null
}
}
# Handle invalid entry types
if ([string]::IsNullOrEmpty($type) -and [string]::IsNullOrEmpty($downloadURL)) {
$errorMsg = "Invalid item type or missing download URL for path: $filePath"
Write-Error $errorMsg
return [PSCustomObject]@{
Path = $filePath
SourceURL = $downloadURL
FilePath = $filePath
Type = $type
Success = $false
Error = $errorMsg
Timestamp = Get-Date
FileSize = $null
}
}
Write-Verbose "Processing download URL: $downloadURL" Write-Verbose "Processing download URL: $downloadURL"
# If the output path is not specified, use the current directory and the file name from the download URL # Set the output path based on parameters
$currentOutputPath = $outputPath $currentOutputPath = ""
if (-not $currentOutputPath) {
# Get the file name from the download URL # Get the file name from the download URL or file path
$outputFileName = $downloadURL.Substring($downloadURL.LastIndexOf("/") + 1) $outputFileName = $downloadURL.Substring($downloadURL.LastIndexOf("/") + 1)
# Clean the file name by removing any query string parameters and HTML encoded characters # Clean the file name by removing any query string parameters and HTML encoded characters
$outputFileName = [System.Uri]::UnescapeDataString($outputFileName.Split("?")[0]) $outputFileName = [System.Uri]::UnescapeDataString($outputFileName.Split("?")[0])
if ($PreserveRelativePath -and $filePath) {
# If PreserveRelativePath is used, set up the directory structure
Write-Verbose "Preserving relative path structure for: $filePath"
# Append the outputFileName to the current location if ($outputPath) {
$currentOutputPath = Join-Path -Path (Get-Location) -ChildPath $outputFileName # If outputPath is specified, use it as the base directory
$baseDir = $outputPath
Write-Verbose "Using base directory: $baseDir"
# Combine the base directory with the file path
$currentOutputPath = Join-Path -Path $baseDir -ChildPath $filePath
} else {
# If no outputPath is specified, use the current directory as base
$currentOutputPath = Join-Path -Path (Get-Location) -ChildPath $filePath
}
# Normalize path separators
$currentOutputPath = $currentOutputPath.Replace("/", [System.IO.Path]::DirectorySeparatorChar)
Write-Verbose "Output path with preserved structure: $currentOutputPath"
} else {
# Standard path handling (unchanged from original)
if ($outputPath) {
$currentOutputPath = $outputPath
} else {
# Append the outputFileName to the current location
$currentOutputPath = Join-Path -Path (Get-Location) -ChildPath $outputFileName
}
Write-Verbose "Output path: $currentOutputPath"
} }
Write-Verbose "Output path: $currentOutputPath" $result = [PSCustomObject]@{
Path = $currentOutputPath
SourceURL = $downloadURL
FilePath = $filePath
Type = $type
Success = $false
Error = $null
Timestamp = Get-Date
FileSize = $null
}
if((Test-Path -Path $currentOutputPath -PathType Leaf) -and (-not $force)) { if((Test-Path -Path $currentOutputPath -PathType Leaf) -and (-not $force)) {
Write-Error "The file '$currentOutputPath' already exists. Use the -Force switch to overwrite the file." $errorMsg = "The file '$currentOutputPath' already exists. Use the -Force switch to overwrite the file."
return $false Write-Error $errorMsg
$result.Error = $errorMsg
return $result
} }
try { try {
# Create the directory structure if it doesn't exist # Create the directory structure if it doesn't exist
$directory = Split-Path -Path $currentOutputPath -Parent $directory = Split-Path -Path $currentOutputPath -Parent
if (-not (Test-Path -Path $directory -PathType Container) -and $directory) { if (-not (Test-Path -Path $directory -PathType Container) -and $directory) {
Write-Verbose "Creating directory structure: $directory"
New-Item -Path $directory -ItemType Directory -Force | Out-Null New-Item -Path $directory -ItemType Directory -Force | Out-Null
} }
@@ -380,11 +475,21 @@ Function Invoke-GiteaFileDownload {
$webClient.DownloadFile($downloadURL, $currentOutputPath) $webClient.DownloadFile($downloadURL, $currentOutputPath)
Write-Verbose "File downloaded successfully to $currentOutputPath" Write-Verbose "File downloaded successfully to $currentOutputPath"
return $true
# Get file info for the result object
if (Test-Path -Path $currentOutputPath -PathType Leaf) {
$fileInfo = Get-Item -Path $currentOutputPath
$result.FileSize = $fileInfo.Length
}
$result.Success = $true
return $result
} }
catch { catch {
Write-Error "Failed to download file from Gitea: $_" $errorMsg = "Failed to download file from Gitea: $_"
return $false Write-Error $errorMsg
$result.Error = $errorMsg
return $result
} }
} }
@@ -428,6 +533,9 @@ Function Get-GiteaChildItem {
.PARAMETER Depth .PARAMETER Depth
Specifies the number of subdirectory levels to include in the recursion. Default is unlimited if Recurse is specified. Specifies the number of subdirectory levels to include in the recursion. Default is unlimited if Recurse is specified.
.PARAMETER File
Returns only files, omitting directories from the results.
.EXAMPLE .EXAMPLE
# List items in the root directory of a repository # List items in the root directory of a repository
@@ -446,6 +554,10 @@ Function Get-GiteaChildItem {
.EXAMPLE .EXAMPLE
# List items with a maximum depth of 2 subdirectories # List items with a maximum depth of 2 subdirectories
Get-GiteaChildItem -repoOwner "owner" -repoName "repo" -Path "src" -Recurse -Depth 2 -token "your_token" Get-GiteaChildItem -repoOwner "owner" -repoName "repo" -Path "src" -Recurse -Depth 2 -token "your_token"
.EXAMPLE
# List only files (no directories) in a repository
Get-GiteaChildItem -repoOwner "owner" -repoName "repo" -Path "src" -File -token "your_token"
#> #>
[CmdletBinding()] [CmdletBinding()]
@@ -462,7 +574,8 @@ Function Get-GiteaChildItem {
[string]$branch = "main", [string]$branch = "main",
[string]$token, [string]$token,
[switch]$Recurse, [switch]$Recurse,
[int]$Depth [int]$Depth,
[switch]$File
) )
begin { begin {
@@ -503,6 +616,7 @@ Function Get-GiteaChildItem {
Write-Verbose "repoName: $repoName" Write-Verbose "repoName: $repoName"
Write-Verbose "Path: $Path" Write-Verbose "Path: $Path"
Write-Verbose "token: $token" Write-Verbose "token: $token"
Write-Verbose "File: $File"
$headers = @{ $headers = @{
"Authorization" = "token $token" "Authorization" = "token $token"
@@ -699,6 +813,12 @@ Function Get-GiteaChildItem {
} }
end { end {
# Filter out directories if -File switch is specified
if ($File) {
Write-Verbose "Filtering results to include only files"
$results = $results | Where-Object { $_.type -ne 'dir' }
}
return $results return $results
} }
} }