19 Commits
1.3.0 ... main

Author SHA1 Message Date
ae0d450e2e Refactor Invoke-GiteaFileDownload to replace URL encoded characters in file output path. Remove redundant unescaping of file name. 2025-05-28 14:42:56 -04:00
08bf6a709c Bump module version to 1.5.4 and update Invoke-GiteaFileDownload to handle URL encoded characters in file names. Update pester tests to account for changes.
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 32s
2025-05-27 14:32:35 -04:00
b6a46b38bd Revert module version to 1.5.3 in the module manifest
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 33s
2025-05-27 14:23:10 -04:00
3f66adb4ca Bump module version to 1.5.5 and update Invoke-GiteaFileDownload to ensure URL encoded characters in the file name are properly replaced. 2025-05-27 14:22:51 -04:00
d647600568 Update Get-GiteaFileContent tests to use 'Result' for status reporting instead of 'Success'
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 32s
2025-05-27 13:27:38 -04:00
ed8f3ab02e Update pester tests
Some checks failed
Publish Powershell Module to Gitea Repository / test (push) Failing after 10s
Publish Powershell Module to Gitea Repository / deploy (push) Has been skipped
2025-05-27 13:23:37 -04:00
67d69c52e9 Bump module version to 1.5.0 and update Invoke-GiteaFileDownload and Get-GiteaChildItem functions to use 'Result' instead of 'Success' for status reporting, and add OverwriteByHash parameter for conditional file overwriting.
Some checks failed
Publish Powershell Module to Gitea Repository / test (push) Failing after 10s
Publish Powershell Module to Gitea Repository / deploy (push) Has been skipped
2025-05-27 13:14:28 -04:00
ed9ba80938 Bump module version to 1.4.5 and enhance Invoke-GiteaFileDownload to replace URL encoded characters in the file name
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 9s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 31s
2025-05-27 12:50:01 -04:00
edb1501f40 Bump module version to 1.4.4 and enhance Invoke-GiteaFileDownload to handle LFS file downloads with type inference and properly format file path based on API URL
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 31s
2025-05-27 12:38:58 -04:00
5854940f75 Bump module version to 1.4.3 and update download URL in Get-GiteaChildItem function to allow for getting LFS files from other branches
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 32s
2025-05-27 12:11:54 -04:00
02f83e6633 Bump module version to 1.4.2 and update exported functions in the module manifest
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 33s
2025-05-27 11:52:31 -04:00
d4c7aa5a92 Bump module version to 1.4.1 in the module manifest 2025-05-27 11:41:09 -04:00
15381257e5 Exclude "Tests" directory when retrieving module name for publishing
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 10s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 34s
2025-05-27 11:35:41 -04:00
1c09d40253 Resolve -preserverelativepath issue in invoke-giteafiledownload, update pester tests, and bump module version to 1.4.0
Some checks failed
Publish Powershell Module to Gitea Repository / deploy (push) Has been cancelled
Publish Powershell Module to Gitea Repository / test (push) Has been cancelled
2025-05-27 11:31:00 -04:00
1d0c8b43bc Update module path in test files for consistency 2025-05-27 08:19:53 -04:00
445fa8a429 Move tests to root 2025-05-27 08:16:01 -04:00
dd47a1b7e2 Bump module version to 1.3.1 in the module manifest.
All checks were successful
Publish Powershell Module to Gitea Repository / test (push) Successful in 9s
Publish Powershell Module to Gitea Repository / deploy (push) Successful in 32s
2025-04-30 15:23:44 -04:00
c65cde9fbc Refactor path handling for cross-platform compatibility and update configuration directory path 2025-04-30 15:20:52 -04:00
c18f68bc46 Remove unnecessary blank line in Pester test execution step 2025-04-30 15:05:05 -04:00
9 changed files with 213 additions and 114 deletions

View File

@@ -20,7 +20,6 @@ jobs:
- name: Run pester tests and verify all tests pass - name: Run pester tests and verify all tests pass
shell: pwsh shell: pwsh
run: | run: |
Write-Host "Changing to repository directory: ${{ github.workspace }}" Write-Host "Changing to repository directory: ${{ github.workspace }}"
Set-Location -Path ${{ github.workspace }} Set-Location -Path ${{ github.workspace }}
Write-Host "Running Pester tests" Write-Host "Running Pester tests"
@@ -73,7 +72,7 @@ jobs:
Set-Location -Path ${{ github.workspace }} Set-Location -Path ${{ github.workspace }}
$moduleVersion = git describe --tags $moduleVersion = git describe --tags
Write-Host "Module version: $moduleVersion" Write-Host "Module version: $moduleVersion"
$module = get-childItem -path . -Directory -Exclude ".*" | Select-Object -ExpandProperty Name $module = get-childItem -path . -Directory -Exclude (".*", "Tests") | Select-Object -ExpandProperty Name
Write-Host "Publishing module $module to Gitea" Write-Host "Publishing module $module to Gitea"
Publish-Module -Path $module -Repository 'GiteaPublic' -NuGetApiKey "${{ secrets.PACKAGES_TOKEN }}" Publish-Module -Path $module -Repository 'GiteaPublic' -NuGetApiKey "${{ secrets.PACKAGES_TOKEN }}"
Write-Host "Module $module published to Gitea" Write-Host "Module $module published to Gitea"

View File

@@ -12,7 +12,7 @@
RootModule = 'PS-GiteaUtilities.psm1' RootModule = 'PS-GiteaUtilities.psm1'
# Version number of this module. # Version number of this module.
ModuleVersion = '1.3.0' ModuleVersion = '1.5.4'
# Supported PSEditions # Supported PSEditions
# CompatiblePSEditions = @() # CompatiblePSEditions = @()
@@ -69,7 +69,7 @@ PowerShellVersion = '5.1'
# NestedModules = @() # NestedModules = @()
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'Set-GiteaConfiguration', 'Get-GiteaConfiguration', 'Get-GiteaFileContent', 'Invoke-GiteaFileDownload', 'Get-GiteaChildItem' FunctionsToExport = 'Set-GiteaConfiguration', 'Get-GiteaConfiguration', 'Get-GiteaFileContent', 'Invoke-GiteaFileDownload', 'Get-GiteaChildItem', 'Get-GiteaReleases'
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = '*' CmdletsToExport = '*'

View File

@@ -11,7 +11,7 @@ Function Set-GiteaConfiguration {
) )
# Create configuration directory if it doesn't exist # Create configuration directory if it doesn't exist
$configDir = Join-Path -Path $env:USERPROFILE -ChildPath ".giteautils" $configDir = Join-Path -Path $HOME -ChildPath ".giteautils"
if (-not (Test-Path -Path $configDir)) { if (-not (Test-Path -Path $configDir)) {
New-Item -Path $configDir -ItemType Directory | Out-Null New-Item -Path $configDir -ItemType Directory | Out-Null
} }
@@ -36,7 +36,7 @@ Function Get-GiteaConfiguration {
[switch]$Force [switch]$Force
) )
$configPath = Join-Path -Path $env:USERPROFILE -ChildPath ".giteautils\config.xml" $configPath = Join-Path -Path $HOME -ChildPath ".giteautils/config.xml"
if (Test-Path -Path $configPath) { if (Test-Path -Path $configPath) {
$config = Import-Clixml -Path $configPath $config = Import-Clixml -Path $configPath
@@ -180,6 +180,8 @@ Function Get-GiteaFileContent {
process { process {
foreach ($file in $filePath) { foreach ($file in $filePath) {
# Normalize path separators for cross-platform compatibility
$file = $file -replace '\\', '/'
Write-Verbose "Processing file: $file" Write-Verbose "Processing file: $file"
$encodedFile = [System.Uri]::EscapeDataString($file) $encodedFile = [System.Uri]::EscapeDataString($file)
Write-Verbose "Encoded file: $encodedFile" Write-Verbose "Encoded file: $encodedFile"
@@ -191,7 +193,6 @@ Function Get-GiteaFileContent {
$url += "/$encodedFile" $url += "/$encodedFile"
$url += "?ref=$branch" $url += "?ref=$branch"
Write-Verbose "URL: $url" Write-Verbose "URL: $url"
try { try {
$fileContent = Invoke-RestMethod -Uri $url -Method Get -Headers $headers $fileContent = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
@@ -206,7 +207,7 @@ Function Get-GiteaFileContent {
Content = $content Content = $content
Size = $fileContent.size Size = $fileContent.size
SHA = $fileContent.sha SHA = $fileContent.sha
Success = $true Result = 'Success'
Error = $null Error = $null
} }
} }
@@ -217,7 +218,7 @@ Function Get-GiteaFileContent {
Content = $null Content = $null
Size = $null Size = $null
SHA = $null SHA = $null
Success = $false Result = 'Failure'
Error = $_.Exception.Message Error = $_.Exception.Message
} }
} }
@@ -323,27 +324,40 @@ Function Invoke-GiteaFileDownload {
A personal access token for the Gitea server. A personal access token for the Gitea server.
.PARAMETER outputPath .PARAMETER outputPath
The path where the downloaded file should be saved. If not specified, the file will be saved in the current directory using the filename from the URL. The path where the downloaded file should be saved. If not specified, the file will be saved in the current directory with its original name from the download URL.
If using PreserveRelativePath, outputPath is treated as the base directory to append the relative path to.
.PARAMETER force .PARAMETER outputName
A switch parameter to force overwriting of an existing file at the output path. The name of the file to save the downloaded content as. If not specified, the file will be saved with its original name from the download URL.
Cannot be used with PreserveRelativePath.
.PARAMETER PreserveRelativePath .PARAMETER PreserveRelativePath
A switch parameter to preserve the relative path structure from the repository. 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 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. If used with outputPath, treats the outputPath as the base directory to append the relative path to.
Cannot be used with outputName.
.PARAMETER OverwriteByHash
A switch parameter to overwrite the file if it exists based on its hash.
.PARAMETER force
A switch parameter to force overwriting of an existing file at the output path.
.PARAMETER type .PARAMETER type
The type of the item to download (file, dir, lfs). This parameter is typically used with pipeline input from Get-GiteaChildItem. 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. Directories will be skipped with a verbose message.
.PARAMETER sha
The SHA of the file to download. This parameter is typically used with pipeline input from Get-GiteaChildItem.
Can be combined with OverwriteByHash to overwrite an existing file if the hashes do not match.
.EXAMPLE .EXAMPLE
# Example 1: Download a file to the current directory # Example 1: Download a file to the current directory
Invoke-GiteaFileDownload -downloadURL "https://gitea.example.com/api/v1/repos/owner/repo/raw/path/to/file.txt" -token "your_token" Invoke-GiteaFileDownload -downloadURL "https://gitea.example.com/api/v1/repos/owner/repo/raw/path/to/file.txt" -token "your_token"
.EXAMPLE .EXAMPLE
# Example 2: Download a file to a specific location with force overwrite # Example 2: Download a file to a specific location with force overwrite
Invoke-GiteaFileDownload -downloadURL "https://gitea.example.com/api/v1/repos/owner/repo/raw/path/to/file.txt" -token "your_token" -outputPath "C:\Downloads\file.txt" -force Invoke-GiteaFileDownload -downloadURL "https://gitea.example.com/api/v1/repos/owner/repo/raw/path/to/file.txt" -token "your_token" -outputPath "C:\Downloads\" -outputName "file.txt" -force
.EXAMPLE .EXAMPLE
# Example 3: Download files in pipeline from Get-GiteaChildItem # Example 3: Download files in pipeline from Get-GiteaChildItem
@@ -365,12 +379,15 @@ Function Invoke-GiteaFileDownload {
[string]$token, [string]$token,
[Parameter(ValueFromPipelineByPropertyName)] [Parameter(ValueFromPipelineByPropertyName)]
[string]$outputPath, [string]$outputPath,
[Parameter(ValueFromPipelineByPropertyName)]
[string]$outputName,
[switch]$PreserveRelativePath,
[switch]$OverwriteByHash,
[switch]$force, [switch]$force,
[Parameter(ValueFromPipelineByPropertyName)] [Parameter(ValueFromPipelineByPropertyName)]
[string]$filePath, [string]$type,
[switch]$PreserveRelativePath,
[Parameter(ValueFromPipelineByPropertyName)] [Parameter(ValueFromPipelineByPropertyName)]
[string]$type [string]$sha
) )
begin { begin {
@@ -392,25 +409,33 @@ Function Invoke-GiteaFileDownload {
Write-Debug "Token: $token (length: $(if($token){$token.Length}else{0}))" Write-Debug "Token: $token (length: $(if($token){$token.Length}else{0}))"
Write-Verbose "PreserveRelativePath: $PreserveRelativePath" Write-Verbose "PreserveRelativePath: $PreserveRelativePath"
# Ensure PreserveRelativePath is not used with outputName
if ($PreserveRelativePath -and $PSBoundParameters.ContainsKey('outputName')) {
throw "The -PreserveRelativePath switch cannot be used with the -outputName parameter. Use -outputPath instead."
}
# Create a WebClient to be reused # Create a WebClient to be reused
$webClient = New-Object System.Net.WebClient $webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("Authorization", "token $token") $webClient.Headers.Add("Authorization", "token $token")
} }
process { process {
Write-Verbose "File path: $filePath" # If type is not provided, check for any hints for cases such as LFS where a type can be inferred and special handling is needed
If($downloadURL -match "/api/v1/repos/[^/]+/[^/]+/media/") {
$type = "lfs"
}
Write-Verbose "Type: $type" Write-Verbose "Type: $type"
# Handle the type parameter
# Skip directories and provide a verbose message # Skip directories and provide a verbose message
if ($type -eq "dir") { if ($type -eq "dir") {
Write-Verbose "Skipping directory: $filePath" Write-Verbose "Skipping directory"
return [PSCustomObject]@{ return [PSCustomObject]@{
Path = $filePath
SourceURL = $downloadURL SourceURL = $downloadURL
FilePath = $filePath
Type = $type Type = $type
Success = $true Result = 'Skipped'
Error = "Skipped - item is a directory" Error = $null
Timestamp = Get-Date Timestamp = Get-Date
FileSize = $null FileSize = $null
} }
@@ -418,104 +443,144 @@ Function Invoke-GiteaFileDownload {
# Handle invalid entry types # Handle invalid entry types
if ([string]::IsNullOrEmpty($type) -and [string]::IsNullOrEmpty($downloadURL)) { if ([string]::IsNullOrEmpty($type) -and [string]::IsNullOrEmpty($downloadURL)) {
$errorMsg = "Invalid item type or missing download URL for path: $filePath" $errorMsg = "Invalid item type or missing download URL for path"
Write-Error $errorMsg Write-Error $errorMsg
return [PSCustomObject]@{ return [PSCustomObject]@{
Path = $filePath
SourceURL = $downloadURL SourceURL = $downloadURL
FilePath = $filePath
Type = $type Type = $type
Success = $false Result = 'Failure'
Error = $errorMsg Error = $errorMsg
Timestamp = Get-Date Timestamp = Get-Date
FileSize = $null FileSize = $null
} }
} }
Write-Verbose "Processing download URL: $downloadURL"
# Set the output path based on parameters # Parse the download URL to extract the file path and file name
$currentOutputPath = ""
# Get the file name from the download URL or file path # Separate the URL into its components: Gitea URL, Repo Owner, Repo Name, branch, file path, and file name
$outputFileName = $downloadURL.Substring($downloadURL.LastIndexOf("/") + 1) $uri = New-Object System.Uri($downloadURL)
# Clean the file name by removing any query string parameters and HTML encoded characters $pathSegments = $uri.AbsolutePath.Trim('/').Split('/')
$outputFileName = [System.Uri]::UnescapeDataString($outputFileName.Split("?")[0]) If($type -eq "lfs") {
# Everything after the media segment is considered the file path with the last segment being the file name
if ($PreserveRelativePath -and $filePath) { $branchIndex = [Array]::IndexOf($pathSegments, "media") + 1
# If PreserveRelativePath is used, set up the directory structure $DownloadFilePath = $pathSegments[$branchIndex..($pathSegments.Length - 2)] -join '/'
Write-Verbose "Preserving relative path structure for: $filePath" $DownloadFileName = $pathSegments[-1]
}
if ($outputPath) { Else {
# If outputPath is specified, use it as the base directory # Everything after the branch + 1 segment is considered the file path with the last segment being the file name
$baseDir = $outputPath $branchIndex = [Array]::IndexOf($pathSegments, "branch") + 2
Write-Verbose "Using base directory: $baseDir" $DownloadFilePath = $pathSegments[$branchIndex..($pathSegments.Length - 2)] -join '/'
# Replace any URL encoded characters in the file name
# Combine the base directory with the file path $DownloadFileName = $pathSegments[-1]
$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"
} }
if ($PreserveRelativePath -and $outputPath) {
# If PreserveRelativePath is used, set up the directory structure
Write-Verbose "Preserving relative path structure for: $DownloadFileName"
$baseDir = $outputPath
Write-Verbose "Using base directory: $baseDir"
# Combine the base directory with the file path
$fileOutputPath = Join-Path -Path $baseDir -ChildPath $DownloadFilePath
# Combine with the file name
$fileOutputPath = Join-Path -Path $fileOutputPath -ChildPath $DownloadFileName
}
elseif($PreserveRelativePath) {
# If no outputPath is specified, use the current directory as base and the file name from the download URL
$fileOutputPath = Join-Path -Path (Get-Location) -ChildPath $DownloadFilePath
# Combine with the file name
$fileOutputPath = Join-Path -Path $fileOutputPath -ChildPath $DownloadFileName
}
elseif ($outputPath -and $outputName) {
# If both outputPath and outputName are specified, use outputPath as the base directory with the file name specified by outputName
$fileOutputPath = Join-Path -Path $outputPath -ChildPath $outputName
}
elseif ($outputPath) {
# If outputPath is specified, use it as the base directory with the file name from the download URL
$fileOutputPath = Join-Path -Path $outputPath -ChildPath $DownloadFileName
}
elseif($outputName) {
# If only outputName is specified, use the current directory with the specified outputName
$fileOutputPath = Join-Path -Path (Get-Location) -ChildPath $outputName
}
else {
# Fallback to current directory with the file name from the download URL
$fileOutputPath = Join-Path -Path (Get-Location) -ChildPath $DownloadFileName
}
# Normalize path separators
$fileOutputPath = $fileOutputPath.Replace("/", [System.IO.Path]::DirectorySeparatorChar)
# Replace any URL encoded characters in the file output path
$fileOutputPath = [System.Uri]::UnescapeDataString($fileOutputPath)
Write-Verbose "Output path: $fileOutputPath"
$result = [PSCustomObject]@{ $result = [PSCustomObject]@{
Path = $currentOutputPath Path = $fileOutputPath
SourceURL = $downloadURL SourceURL = $downloadURL
FilePath = $filePath Type = "file"
Type = $type Result = $null
Success = $false
Error = $null Error = $null
Timestamp = Get-Date Timestamp = Get-Date
FileSize = $null FileSize = $null
} }
if((Test-Path -Path $currentOutputPath -PathType Leaf) -and (-not $force)) { if((Test-Path -Path $fileOutputPath -PathType Leaf) -and (-not $force)) {
$errorMsg = "The file '$currentOutputPath' already exists. Use the -Force switch to overwrite the file." # Check if OverwriteByHash is set
Write-Error $errorMsg if ($OverwriteByHash) {
$result.Error = $errorMsg Write-Verbose "OverwriteByHash is set; checking file hash for existing file: $fileOutputPath"
return $result $existingFileHash = (Get-FileHash -Path $fileOutputPath -Algorithm SHA256).Hash
$downloadFileHash = $sha
if ($existingFileHash -eq $downloadFileHash) {
Write-Host "The file '$fileOutputPath' already exists and hashes match. Skipping download."
$result.Result = 'Skipped'
return $result
}
else {
Write-Host "The file '$fileOutputPath' already exists but hashes do not match and OverwriteByHash is set; overwriting file."
}
}
else {
$result.Result = 'Skipped'
$errorMsg = "The file '$fileOutputPath' already exists. Use the -Force switch to overwrite the file."
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 $fileOutputPath -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" Write-Verbose "Creating directory structure: $directory"
New-Item -Path $directory -ItemType Directory -Force | Out-Null New-Item -Path $directory -ItemType Directory -Force | Out-Null
} }
# Download the file # Download the file
Write-Verbose "Downloading from $downloadURL to $currentOutputPath" Write-Verbose "Downloading from $downloadURL to $fileOutputPath"
# Use synchronous download # Use synchronous download
$webClient.DownloadFile($downloadURL, $currentOutputPath) $webClient.DownloadFile($downloadURL, $fileOutputPath)
Write-Verbose "File downloaded successfully to $currentOutputPath" Write-Verbose "File downloaded successfully to $fileOutputPath"
# Get file info for the result object # Get file info for the result object
if (Test-Path -Path $currentOutputPath -PathType Leaf) { if (Test-Path -Path $fileOutputPath -PathType Leaf) {
$fileInfo = Get-Item -Path $currentOutputPath $fileInfo = Get-Item -Path $fileOutputPath
$result.FileSize = $fileInfo.Length $result.FileSize = $fileInfo.Length
} }
$result.Success = $true $result.Result = 'Success'
return $result return $result
} }
catch { catch {
$result.Result = 'Failure'
$errorMsg = "Failed to download file from Gitea: $_" $errorMsg = "Failed to download file from Gitea: $_"
Write-Error $errorMsg Write-Error $errorMsg
$result.Error = $errorMsg $result.Error = $errorMsg
@@ -664,11 +729,10 @@ Function Get-GiteaChildItem {
$paths = $path $paths = $path
foreach ($path in $paths) { foreach ($path in $paths) {
Write-Verbose "Processing path: $path" Write-Verbose "Processing path: $path"
# Normalize the path format - replace backslashes with forward slashes and trim trailing slashes # Normalize path separators for cross-platform compatibility
$normalizedPath = $path -replace '\\', '/' -replace '/$', '' $normalizedPath = $path -replace '\\', '/' -replace '/$', ''
$encodedPath = [System.Uri]::EscapeDataString($normalizedPath)
Write-Verbose "Normalized path: $normalizedPath" Write-Verbose "Normalized path: $normalizedPath"
Write-Verbose "Encoded path: $encodedPath" $encodedPath = [System.Uri]::EscapeDataString($normalizedPath)
$url = "$giteaURL" $url = "$giteaURL"
$url += "/api/v1/repos" $url += "/api/v1/repos"
$url += "/$repoOwner" $url += "/$repoOwner"
@@ -713,7 +777,7 @@ Function Get-GiteaChildItem {
$item.size = [long]$matches[1] $item.size = [long]$matches[1]
} }
# Set the download URL to the media endpoint for LFS files to download the actual file # Set the download URL to the media endpoint for LFS files to download the actual file
$item.download_url = "$giteaURL/api/v1/repos/$repoOwner/$repoName/media/$($item.path)" $item.download_url = "$giteaURL/api/v1/repos/$repoOwner/$repoName/media/$($item.path)?ref=$branch"
} }
$itemObj = [PSCustomObject]@{ $itemObj = [PSCustomObject]@{
@@ -723,7 +787,7 @@ Function Get-GiteaChildItem {
size = $item.size size = $item.size
sha = $item.sha sha = $item.sha
downloadURL = $item.download_url downloadURL = $item.download_url
Success = $true Result = 'Success'
Error = $null Error = $null
Level = 0 Level = 0
} }
@@ -806,7 +870,7 @@ Function Get-GiteaChildItem {
size = $subItem.size size = $subItem.size
sha = $subItem.sha sha = $subItem.sha
downloadURL = $subItem.download_url downloadURL = $subItem.download_url
Success = $true Result = 'Success'
Error = $null Error = $null
Level = $currentLevel Level = $currentLevel
} }
@@ -853,7 +917,7 @@ Function Get-GiteaChildItem {
size = $null size = $null
sha = $null sha = $null
downloadURL = $null downloadURL = $null
Success = $false Result = 'Failure'
Error = $_.Exception.Message Error = $_.Exception.Message
Level = 0 Level = 0
} }
@@ -1010,4 +1074,4 @@ function Get-GiteaReleases {
} }
} }
Export-ModuleMember -Function Set-GiteaConfiguration, Get-GiteaConfiguration, Get-GiteaFileContent, Invoke-GiteaFileDownload, Get-GiteaChildItem, Get-GiteaLFSFile, Get-GiteaReleases # Export-ModuleMember -Function Set-GiteaConfiguration, Get-GiteaConfiguration, Get-GiteaFileContent, Invoke-GiteaFileDownload, Get-GiteaChildItem, Get-GiteaReleases

View File

@@ -1,7 +1,7 @@
# Get-GiteaChildItem.Tests.ps1 # Get-GiteaChildItem.Tests.ps1
# Import the module under test # Import the module under test
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities.psm1' $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities\PS-GiteaUtilities.psm1'
Import-Module -Name $modulePath -Force Import-Module -Name $modulePath -Force
Describe 'Get-GiteaChildItem' { Describe 'Get-GiteaChildItem' {

View File

@@ -1,7 +1,7 @@
# Get-GiteaConfiguration.Tests.ps1 # Get-GiteaConfiguration.Tests.ps1
# Import the module under test # Import the module under test
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities.psm1' $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities\PS-GiteaUtilities.psm1'
Import-Module -Name $modulePath -Force Import-Module -Name $modulePath -Force
Describe 'Get-GiteaConfiguration' { Describe 'Get-GiteaConfiguration' {

View File

@@ -1,7 +1,7 @@
# Get-GiteaFileContent.Tests.ps1 # Get-GiteaFileContent.Tests.ps1
# Import the module under test # Import the module under test
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities.psm1' $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities\PS-GiteaUtilities.psm1'
Import-Module -Name $modulePath -Force Import-Module -Name $modulePath -Force
Describe 'Get-GiteaFileContent' { Describe 'Get-GiteaFileContent' {
@@ -21,7 +21,7 @@ Describe 'Get-GiteaFileContent' {
$result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'README.md' -token 'abc123' $result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'README.md' -token 'abc123'
$result | Should -Not -BeNullOrEmpty $result | Should -Not -BeNullOrEmpty
$result.Success | Should -Be $true $result.Result | Should -Be 'Success'
$result.Content | Should -Be ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('Hello World'))) $result.Content | Should -Be ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('Hello World')))
} }
@@ -29,7 +29,7 @@ Describe 'Get-GiteaFileContent' {
$result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'README.md' -token 'abc123' -decode $result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'README.md' -token 'abc123' -decode
$result | Should -Not -BeNullOrEmpty $result | Should -Not -BeNullOrEmpty
$result.Success | Should -Be $true $result.Result | Should -Be 'Success'
$result.Content | Should -Be 'Hello World' $result.Content | Should -Be 'Hello World'
} }
} }
@@ -73,7 +73,7 @@ Describe 'Get-GiteaFileContent' {
It 'Should capture error and mark result as unsuccessful' { It 'Should capture error and mark result as unsuccessful' {
$result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'badfile.ps1' -token 'abc123' $result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'badfile.ps1' -token 'abc123'
$result.Success | Should -Be $false $result.Result | Should -Be 'Failure'
$result.Error | Should -Match 'API call failed' $result.Error | Should -Match 'API call failed'
} }
} }
@@ -103,7 +103,7 @@ Describe 'Get-GiteaFileContent' {
$result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'testfile.txt' -token 'abc123' $result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'testfile.txt' -token 'abc123'
$result | Should -Not -BeNullOrEmpty $result | Should -Not -BeNullOrEmpty
$result.Success | Should -Be $true $result.Result | Should -Be 'Success'
$result.Content | Should -Be ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('Hello from API!'))) $result.Content | Should -Be ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('Hello from API!')))
} }
@@ -111,7 +111,7 @@ Describe 'Get-GiteaFileContent' {
$result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'testfile.txt' -token 'abc123' -decode $result = Get-GiteaFileContent -repoOwner 'user' -repoName 'repo' -filePath 'testfile.txt' -token 'abc123' -decode
$result | Should -Not -BeNullOrEmpty $result | Should -Not -BeNullOrEmpty
$result.Success | Should -Be $true $result.Result | Should -Be 'Success'
$result.Content | Should -Be 'Hello from API!' $result.Content | Should -Be 'Hello from API!'
} }
} }

View File

@@ -1,7 +1,7 @@
# Get-GiteaReleases.Tests.ps1 # Get-GiteaReleases.Tests.ps1
# Import the module # Import the module
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities.psm1' $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities\PS-GiteaUtilities.psm1'
Import-Module -Name $modulePath -Force Import-Module -Name $modulePath -Force
Describe 'Get-GiteaReleases' { Describe 'Get-GiteaReleases' {

View File

@@ -1,7 +1,7 @@
# Invoke-GiteaFileDownload.Tests.ps1 # Invoke-GiteaFileDownload.Tests.ps1
# Import the module under test # Import the module under test
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities.psm1' $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities\PS-GiteaUtilities.psm1'
Import-Module -Name $modulePath -Force Import-Module -Name $modulePath -Force
Describe 'Invoke-GiteaFileDownload' { Describe 'Invoke-GiteaFileDownload' {
@@ -13,7 +13,7 @@ Describe 'Invoke-GiteaFileDownload' {
} }
# Correct webClient Mock: headers, download, dispose # Correct webClient Mock: headers, download, dispose
Mock -CommandName New-Object -ModuleName PS-GiteaUtilities -MockWith { Mock -CommandName New-Object -ModuleName PS-GiteaUtilities -ParameterFilter { $TypeName -eq 'System.Net.WebClient' } -MockWith {
$headers = New-Object System.Net.WebHeaderCollection $headers = New-Object System.Net.WebHeaderCollection
# Create a real object # Create a real object
@@ -46,30 +46,67 @@ Describe 'Invoke-GiteaFileDownload' {
Context 'When all parameters are valid' { Context 'When all parameters are valid' {
It 'Should download a file successfully' { It 'Should download a file successfully' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/raw/path/to/file.txt' -token 'abc123' $result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/file.txt' -token 'abc123'
$result | Should -Not -BeNullOrEmpty $result | Should -Not -BeNullOrEmpty
$result.Success | Should -Be $true $result.Result | Should -Be 'Success'
$result.Path | Should -Match 'file\.txt$' $result.Path | Should -Match 'file\.txt$'
} }
} }
Context 'When preserving relative paths' { Context 'When specifying an outputPath' {
It 'Should create a path based on filePath with PreserveRelativePath' { It 'Should create a path based on outputPath' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/raw/path/to/file.txt' ` $result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/file.txt' `
-filePath 'docs/manual/file.txt' -PreserveRelativePath -token 'abc123' -outputPath 'docs/manual/' -token 'abc123'
$result.Path | Should -Match 'docs[\\/]+manual[\\/]+file\.txt$' $result.Path | Should -Match 'docs[\\/]+manual[\\/]+file\.txt$'
$result.Success | Should -Be $true $result.Result | Should -Be 'Success'
}
}
Context 'When specifying an outputName' {
It 'Should download file and name it based on outputName' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/file.txt' `
-outputName 'newfile.txt' -token 'abc123'
$result.Path | Should -Match 'newfile\.txt$'
$result.Result | Should -Be 'Success'
}
}
Context 'When specifying an outputName and outputPath' {
It 'Should download file and name it based on outputName' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/file.txt' `
-outputPath 'docs/manual/' -outputName 'newfile.txt' -token 'abc123'
$result.Path | Should -Match 'docs[\\/]+manual[\\/]+newfile\.txt$'
$result.Result | Should -Be 'Success'
}
}
Context 'When using -PreserveRelativePath' {
It 'Should preserve the relative path structure' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/file.txt' `
-PreserveRelativePath -token 'abc123'
$result.Path | Should -Match 'path[\\/]+to[\\/]+file\.txt$'
$result.Result | Should -Be 'Success'
}
It 'Should ensure the outputPath does not contain any URL encoding' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/Client%20Files/Certificates/file name.txt' `
-PreserveRelativePath -token 'abc123'
$result.Path | Should -Match 'Client[ ]Files[\\/]+Certificates[\\/]+file name\.txt$'
$result.Result | Should -Be 'Success'
} }
} }
Context 'When skipping directories' { Context 'When skipping directories' {
It 'Should skip items with type = dir' { It 'Should skip items with type = dir' {
$result = Invoke-GiteaFileDownload -filePath 'docs/' -type 'dir' -token 'abc123' $result = Invoke-GiteaFileDownload -outputPath 'docs/' -type 'dir' -token 'abc123'
$result.Success | Should -Be $true $result.Result | Should -Be 'Skipped'
$result.Error | Should -Match 'Skipped'
} }
} }
@@ -84,16 +121,15 @@ Describe 'Invoke-GiteaFileDownload' {
} }
It 'Should not overwrite existing file without Force' { It 'Should not overwrite existing file without Force' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/raw/path/to/existingfile.txt' -token 'abc123' $result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/existingfile.txt' -token 'abc123'
$result.Success | Should -Be $false $result.Result | Should -Be 'Skipped'
$result.Error | Should -Match 'already exists'
} }
} }
Context 'When download fails' { Context 'When download fails' {
BeforeEach { BeforeEach {
Mock -CommandName New-Object -ModuleName PS-GiteaUtilities -MockWith { Mock -CommandName New-Object -ModuleName PS-GiteaUtilities -ParameterFilter { $TypeName -eq 'System.Net.WebClient' } -MockWith {
$headers = New-Object System.Net.WebHeaderCollection $headers = New-Object System.Net.WebHeaderCollection
$webClient = New-Object PSObject $webClient = New-Object PSObject
@@ -113,9 +149,9 @@ Describe 'Invoke-GiteaFileDownload' {
} }
It 'Should capture error and mark download as failed' { It 'Should capture error and mark download as failed' {
$result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/raw/path/to/badfile.txt' -token 'abc123' $result = Invoke-GiteaFileDownload -downloadURL 'https://gitea.example.com/test/example/raw/branch/dev/path/to/badfile.txt' -token 'abc123'
$result.Success | Should -Be $false $result.Result | Should -Be 'Failure'
$result.Error | Should -Match 'Failed to download' $result.Error | Should -Match 'Failed to download'
} }
} }

View File

@@ -4,7 +4,7 @@ Describe 'Set-GiteaConfiguration' {
BeforeAll { BeforeAll {
# Import the module dynamically # Import the module dynamically
$modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities.psm1' $modulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\PS-GiteaUtilities\PS-GiteaUtilities.psm1'
Import-Module -Name $modulePath -Force Import-Module -Name $modulePath -Force
} }