From 3cdf0a6610861540c0353c80eb6239745ca8e531 Mon Sep 17 00:00:00 2001 From: Raymond LaRose Date: Fri, 25 Apr 2025 14:07:34 -0400 Subject: [PATCH 1/5] Add LoadVariables and Force switches to Get-GiteaConfiguration; implement Get-GiteaLFSFile for LFS file retrieval --- PS-GiteaUtilities/PS-GiteaUtilities.psm1 | 133 ++++++++++++++++++++++- 1 file changed, 130 insertions(+), 3 deletions(-) diff --git a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 index 8226903..6747365 100644 --- a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 +++ b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 @@ -31,12 +31,42 @@ Function Set-GiteaConfiguration { Function Get-GiteaConfiguration { [CmdletBinding()] - param() + param( + [switch]$LoadVariables, + [switch]$Force + ) $configPath = Join-Path -Path $env:USERPROFILE -ChildPath ".giteautils\config.xml" if (Test-Path -Path $configPath) { - return Import-Clixml -Path $configPath + $config = Import-Clixml -Path $configPath + + # If LoadVariables switch is used, set each config value as a variable in the global scope + if ($LoadVariables) { + foreach ($key in $config.Keys) { + # Check if variable exists in global scope + $variableExists = $false + try { + $existingVar = Get-Variable -Name $key -Scope Global -ErrorAction Stop + $variableExists = $true + } + catch { + $variableExists = $false + } + + # Set variable if it doesn't exist or if Force is used + if (-not $variableExists -or $Force) { + Write-Verbose "Loading configuration variable: $key = $($config[$key])" + Set-Variable -Name $key -Value $config[$key] -Scope Global + Write-Host "Created global variable: `$$key" -ForegroundColor Green + } + else { + Write-Verbose "Skipping existing variable: $key (use -Force to override)" + } + } + } + + return $config } else { Write-Warning "Gitea configuration not found. Use Set-GiteaConfiguration to set up." @@ -275,6 +305,103 @@ Function Get-GiteaLFSConfiguration { } } +function Get-GiteaLFSFile { + [CmdletBinding()] + param( + [string]$giteaURL, + [Parameter(ValueFromPipelineByPropertyName)] + [string]$repoOwner, + [Parameter(ValueFromPipelineByPropertyName)] + [string]$repoName, + [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Alias('FullName')] + [string[]]$Path, + [Parameter(ValueFromPipelineByPropertyName)] + [string]$branch = "main", + [string]$token + ) + + begin { + # Initialize results array + $results = @() + + # Use configuration if parameters aren't provided + if (-not $PSBoundParameters.ContainsKey('giteaURL') -or + -not $PSBoundParameters.ContainsKey('repoOwner') -or + -not $PSBoundParameters.ContainsKey('repoName') -or + -not $PSBoundParameters.ContainsKey('branch') -or + -not $PSBoundParameters.ContainsKey('token')) { + + $config = Get-GiteaConfiguration + if ($config) { + if (-not $PSBoundParameters.ContainsKey('giteaURL')) { $giteaURL = $config.giteaURL } + if (-not $PSBoundParameters.ContainsKey('repoOwner')) { $repoOwner = $config.defaultOwner } + if (-not $PSBoundParameters.ContainsKey('repoName')) { $repoName = $config.defaultRepo } + if (-not $PSBoundParameters.ContainsKey('branch')) { $branch = $config.defaultBranch } + if (-not $PSBoundParameters.ContainsKey('token')) { $token = $config.token } + } + } + + # Validate that we have all required parameters + $missingParams = @() + if (-not $giteaURL) { $missingParams += "giteaURL" } + if (-not $repoOwner) { $missingParams += "repoOwner" } + if (-not $repoName) { $missingParams += "repoName" } + if (-not $token) { $missingParams += "token" } + + if ($missingParams.Count -gt 0) { + throw "Missing required parameters: $($missingParams -join ', '). Either provide them directly or set them with Set-GiteaConfiguration." + } + + Write-Verbose "Parameters:" + Write-Verbose "giteaURL: $giteaURL" + Write-Verbose "repoOwner: $repoOwner" + Write-Verbose "repoName: $repoName" + Write-Verbose "Path: $Path" + Write-Verbose "token: $token" + + $headers = @{ + "Authorization" = "token $token" + "Accept" = "application/json" + } + } + + process { + $paths = $path + foreach ($path in $paths) { + Write-Verbose "Processing path: $path" + # Normalize the path format - replace backslashes with forward slashes and trim trailing slashes + $normalizedPath = $path -replace '\\', '/' -replace '/$', '' + $encodedPath = [System.Uri]::EscapeDataString($normalizedPath) + Write-Verbose "Normalized path: $normalizedPath" + Write-Verbose "Encoded path: $encodedPath" + $url = "$giteaURL" + $url += "/api/v1/repos" + $url += "/$repoOwner" + $url += "/$repoName" + $url += "/media" + # Only add the path component if it's not empty + if (-not [string]::IsNullOrWhiteSpace($normalizedPath)) { + $url += "/$encodedPath" + } + $url += "?ref=$branch" + Write-Verbose "URL: $url" + + try { + $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -ResponseHeadersVariable ResponseHeaders - + } + catch { + + } + } + } + + end { + return $ResponseHeaders + } + +} + Function Invoke-GiteaFileDownload { <# .SYNOPSIS @@ -823,4 +950,4 @@ Function Get-GiteaChildItem { } } -Export-ModuleMember -Function Set-GiteaConfiguration, Get-GiteaConfiguration, Get-GiteaFileContent, Invoke-GiteaFileDownload, Get-GiteaChildItem \ No newline at end of file +Export-ModuleMember -Function Set-GiteaConfiguration, Get-GiteaConfiguration, Get-GiteaFileContent, Invoke-GiteaFileDownload, Get-GiteaChildItem, Get-GiteaLFSFile \ No newline at end of file From 0c40d07bcd208a7ca9e72696482914b071b7fb49 Mon Sep 17 00:00:00 2001 From: Raymond LaRose Date: Fri, 25 Apr 2025 14:25:13 -0400 Subject: [PATCH 2/5] Remove Get-GiteaLFSFile function to streamline codebase; enhance clarity and maintainability. --- PS-GiteaUtilities/PS-GiteaUtilities.psm1 | 97 ------------------------ 1 file changed, 97 deletions(-) diff --git a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 index 6747365..a518878 100644 --- a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 +++ b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 @@ -305,103 +305,6 @@ Function Get-GiteaLFSConfiguration { } } -function Get-GiteaLFSFile { - [CmdletBinding()] - param( - [string]$giteaURL, - [Parameter(ValueFromPipelineByPropertyName)] - [string]$repoOwner, - [Parameter(ValueFromPipelineByPropertyName)] - [string]$repoName, - [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] - [Alias('FullName')] - [string[]]$Path, - [Parameter(ValueFromPipelineByPropertyName)] - [string]$branch = "main", - [string]$token - ) - - begin { - # Initialize results array - $results = @() - - # Use configuration if parameters aren't provided - if (-not $PSBoundParameters.ContainsKey('giteaURL') -or - -not $PSBoundParameters.ContainsKey('repoOwner') -or - -not $PSBoundParameters.ContainsKey('repoName') -or - -not $PSBoundParameters.ContainsKey('branch') -or - -not $PSBoundParameters.ContainsKey('token')) { - - $config = Get-GiteaConfiguration - if ($config) { - if (-not $PSBoundParameters.ContainsKey('giteaURL')) { $giteaURL = $config.giteaURL } - if (-not $PSBoundParameters.ContainsKey('repoOwner')) { $repoOwner = $config.defaultOwner } - if (-not $PSBoundParameters.ContainsKey('repoName')) { $repoName = $config.defaultRepo } - if (-not $PSBoundParameters.ContainsKey('branch')) { $branch = $config.defaultBranch } - if (-not $PSBoundParameters.ContainsKey('token')) { $token = $config.token } - } - } - - # Validate that we have all required parameters - $missingParams = @() - if (-not $giteaURL) { $missingParams += "giteaURL" } - if (-not $repoOwner) { $missingParams += "repoOwner" } - if (-not $repoName) { $missingParams += "repoName" } - if (-not $token) { $missingParams += "token" } - - if ($missingParams.Count -gt 0) { - throw "Missing required parameters: $($missingParams -join ', '). Either provide them directly or set them with Set-GiteaConfiguration." - } - - Write-Verbose "Parameters:" - Write-Verbose "giteaURL: $giteaURL" - Write-Verbose "repoOwner: $repoOwner" - Write-Verbose "repoName: $repoName" - Write-Verbose "Path: $Path" - Write-Verbose "token: $token" - - $headers = @{ - "Authorization" = "token $token" - "Accept" = "application/json" - } - } - - process { - $paths = $path - foreach ($path in $paths) { - Write-Verbose "Processing path: $path" - # Normalize the path format - replace backslashes with forward slashes and trim trailing slashes - $normalizedPath = $path -replace '\\', '/' -replace '/$', '' - $encodedPath = [System.Uri]::EscapeDataString($normalizedPath) - Write-Verbose "Normalized path: $normalizedPath" - Write-Verbose "Encoded path: $encodedPath" - $url = "$giteaURL" - $url += "/api/v1/repos" - $url += "/$repoOwner" - $url += "/$repoName" - $url += "/media" - # Only add the path component if it's not empty - if (-not [string]::IsNullOrWhiteSpace($normalizedPath)) { - $url += "/$encodedPath" - } - $url += "?ref=$branch" - Write-Verbose "URL: $url" - - try { - $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -ResponseHeadersVariable ResponseHeaders - - } - catch { - - } - } - } - - end { - return $ResponseHeaders - } - -} - Function Invoke-GiteaFileDownload { <# .SYNOPSIS From dfb34f240b4844a0bc66ab915739434733a39478 Mon Sep 17 00:00:00 2001 From: Raymond LaRose Date: Fri, 25 Apr 2025 15:03:33 -0400 Subject: [PATCH 3/5] Refactor verbose logging to debug level for token information; enhance Get-GiteaChildItem to handle LFS pointer details and update download URLs. --- PS-GiteaUtilities/PS-GiteaUtilities.psm1 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 index a518878..77cf0b3 100644 --- a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 +++ b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 @@ -169,7 +169,7 @@ Function Get-GiteaFileContent { Write-Verbose "repoOwner: $repoOwner" Write-Verbose "repoName: $repoName" Write-Verbose "branch: $branch" - Write-Verbose "token: $token" + Write-Debug "Token: $token" Write-Verbose "decode: $decode" $headers = @{ @@ -279,7 +279,7 @@ Function Get-GiteaLFSConfiguration { Write-Verbose "giteaURL: $giteaURL" Write-Verbose "repoOwner: $repoOwner" Write-Verbose "repoName: $repoName" - Write-Verbose "token: $token" + Write-Debug "Token: $token" $filePath = ".gitattributes" @@ -389,7 +389,7 @@ Function Invoke-GiteaFileDownload { } Write-Verbose "Parameters:" - Write-Verbose "token: $token (length: $(if($token){$token.Length}else{0}))" + Write-Debug "Token: $token (length: $(if($token){$token.Length}else{0}))" Write-Verbose "PreserveRelativePath: $PreserveRelativePath" # Create a WebClient to be reused @@ -645,7 +645,7 @@ Function Get-GiteaChildItem { Write-Verbose "repoOwner: $repoOwner" Write-Verbose "repoName: $repoName" Write-Verbose "Path: $Path" - Write-Verbose "token: $token" + Write-Debug "Token: $token" Write-Verbose "File: $File" $headers = @{ @@ -698,6 +698,15 @@ Function Get-GiteaChildItem { } if ($isLFS) { $item.type = "lfs" + # Save the original download URL for LFS pointers to be used to populate the size and sha fields + $GitLFSPointerURL = $item.download_url + # Use the Gitea API to get the LFS pointer details + $lfsPointerResponse = Invoke-RestMethod -Uri $GitLFSPointerURL -Method Get -Headers $headers -ErrorAction Stop + Write-Debug "LFS Pointer Response: $($lfsPointerResponse | ConvertTo-Json -Depth 1 -Compress)" + # Update the item with the LFS pointer details + $item.size = $lfsPointerResponse.size + $item.sha = $lfsPointerResponse.sha + # 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)" } From 8e1a5f187ae0656db6001b0fb9cb69d790794929 Mon Sep 17 00:00:00 2001 From: Raymond LaRose Date: Fri, 25 Apr 2025 15:44:37 -0400 Subject: [PATCH 4/5] Enhance Get-GiteaChildItem to retrieve and parse LFS pointer details for size and SHA; update download URL for LFS files. --- PS-GiteaUtilities/PS-GiteaUtilities.psm1 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 index 77cf0b3..d094e22 100644 --- a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 +++ b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 @@ -701,11 +701,17 @@ Function Get-GiteaChildItem { # Save the original download URL for LFS pointers to be used to populate the size and sha fields $GitLFSPointerURL = $item.download_url # Use the Gitea API to get the LFS pointer details - $lfsPointerResponse = Invoke-RestMethod -Uri $GitLFSPointerURL -Method Get -Headers $headers -ErrorAction Stop - Write-Debug "LFS Pointer Response: $($lfsPointerResponse | ConvertTo-Json -Depth 1 -Compress)" - # Update the item with the LFS pointer details - $item.size = $lfsPointerResponse.size - $item.sha = $lfsPointerResponse.sha + # For LFS files, we need to get the pointer file and parse it for details + $lfsPointerContent = Invoke-RestMethod -Uri $GitLFSPointerURL -Method Get -Headers $headers -ErrorAction Stop + Write-Debug "LFS Pointer Content: $($lfsPointerContent)" + + # Parse the LFS pointer to extract size and SHA + if ($lfsPointerContent -match 'oid sha256:([a-f0-9]+)') { + $item.sha = $matches[1] + } + if ($lfsPointerContent -match 'size (\d+)') { + $item.size = [long]$matches[1] + } # 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)" } From 9cdcfeddff9d754f83027b1d268dd0ef73f66b4c Mon Sep 17 00:00:00 2001 From: Raymond LaRose Date: Fri, 25 Apr 2025 16:10:52 -0400 Subject: [PATCH 5/5] Refactor Get-GiteaChildItem to improve LFS handling; extract size and SHA from LFS pointers. Remove excess entries in returned object. --- PS-GiteaUtilities/PS-GiteaUtilities.psm1 | 38 +++++++++++++----------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 index d094e22..1447807 100644 --- a/PS-GiteaUtilities/PS-GiteaUtilities.psm1 +++ b/PS-GiteaUtilities/PS-GiteaUtilities.psm1 @@ -717,17 +717,12 @@ Function Get-GiteaChildItem { } $itemObj = [PSCustomObject]@{ - filePath = $item.path - Path = $item.path - repoOwner = $repoOwner - repoName = $repoName - giteaURL = $giteaURL - downloadURL = $item.download_url - branch = $branch - type = $item.type name = $item.name + Path = $item.path + type = $item.type size = $item.size sha = $item.sha + downloadURL = $item.download_url Success = $true Error = $null Level = 0 @@ -786,21 +781,31 @@ Function Get-GiteaChildItem { } if ($isLFS) { $subItem.type = "lfs" + # Save the original download URL for LFS pointers to be used to populate the size and sha fields + $GitLFSPointerURL = $subItem.download_url + # Use the Gitea API to get the LFS pointer details + # For LFS files, we need to get the pointer file and parse it for details + $lfsPointerContent = Invoke-RestMethod -Uri $GitLFSPointerURL -Method Get -Headers $headers -ErrorAction Stop + Write-Debug "LFS Pointer Content: $($lfsPointerContent)" + + # Parse the LFS pointer to extract size and SHA + if ($lfsPointerContent -match 'oid sha256:([a-f0-9]+)') { + $subItem.sha = $matches[1] + } + if ($lfsPointerContent -match 'size (\d+)') { + $subItem.size = [long]$matches[1] + } + # Set the download URL to the media endpoint for LFS files to download the actual file $subItem.download_url = "$giteaURL/api/v1/repos/$repoOwner/$repoName/media/$($subItem.path)" } $subItemObj = [PSCustomObject]@{ - filePath = $subItem.path - Path = $subItem.path - repoOwner = $repoOwner - repoName = $repoName - giteaURL = $giteaURL - downloadURL = $subItem.download_url - branch = $branch - type = $subItem.type name = $subItem.name + Path = $subItem.path + type = $subItem.type size = $subItem.size sha = $subItem.sha + downloadURL = $subItem.download_url Success = $true Error = $null Level = $currentLevel @@ -838,7 +843,6 @@ Function Get-GiteaChildItem { Write-Error "Failed to retrieve '$normalizedPath' from Gitea: $($_.Exception.Message)`n$($errorDetails | ConvertTo-Json -Depth 1 -Compress)" $results += [PSCustomObject]@{ - filePath = $normalizedPath Path = $normalizedPath repoOwner = $repoOwner repoName = $repoName