-
Notifications
You must be signed in to change notification settings - Fork 102
Add Reset-PSResourceRepository cmdlet to recover from corrupted repository store #1895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
10
commits into
master
Choose a base branch
from
copilot/add-reset-functionality-to-repository-store
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
dad9e47
Initial plan
Copilot cfa7758
Add Reset-PSResourceRepository cmdlet and Reset method to RepositoryS…
Copilot d7a00df
Add Reset-PSResourceRepository to CmdletsToExport in module manifest
Copilot a2c0ca2
Use Utils.MoveFiles instead of File.Copy in Reset method
Copilot 357437e
Add cleanup error handling in Reset method instead of ignoring except…
Copilot 35882de
Add exception handling for LoadXDocument validation in Reset method
Copilot a20f9ad
Add error handling for temp file cleanup in validation failure path
Copilot a97ba29
Update src/code/ResetPSResourceRepository.cs
anamnavi 10a67db
Update src/code/RepositorySettings.cs
alerickson b6b3bc9
Update src/code/ResetPSResourceRepository.cs
alerickson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using Microsoft.PowerShell.PSResourceGet.UtilClasses; | ||
| using System; | ||
| using System.Management.Automation; | ||
|
|
||
| namespace Microsoft.PowerShell.PSResourceGet.Cmdlets | ||
| { | ||
| /// <summary> | ||
| /// The Reset-PSResourceRepository cmdlet resets the repository store by creating a new PSRepositories.xml file. | ||
| /// This is useful when the repository store becomes corrupted. | ||
| /// It will create a new repository store with only the PSGallery repository registered. | ||
| /// </summary> | ||
| [Cmdlet(VerbsCommon.Reset, | ||
| "PSResourceRepository", | ||
| SupportsShouldProcess = true, | ||
| ConfirmImpact = ConfirmImpact.High)] | ||
| [OutputType(typeof(PSRepositoryInfo))] | ||
| public sealed class ResetPSResourceRepository : PSCmdlet | ||
| { | ||
| #region Parameters | ||
|
|
||
| /// <summary> | ||
| /// When specified, displays the PSGallery repository that was registered after reset | ||
| /// </summary> | ||
| [Parameter] | ||
| public SwitchParameter PassThru { get; set; } | ||
|
|
||
| #endregion | ||
|
|
||
| #region Methods | ||
|
|
||
| protected override void ProcessRecord() | ||
| { | ||
| string repositoryStorePath = System.IO.Path.Combine( | ||
| Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), | ||
| "PSResourceGet", | ||
| "PSResourceRepository.xml"); | ||
|
|
||
| WriteVerbose($"Resetting repository store at: {repositoryStorePath}"); | ||
|
|
||
| if (!ShouldProcess(repositoryStorePath, "Reset repository store and create new PSRepositories.xml file with PSGallery registered")) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| PSRepositoryInfo psGalleryRepo = RepositorySettings.Reset(this, out string errorMsg); | ||
alerickson marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if (!string.IsNullOrEmpty(errorMsg)) | ||
| { | ||
| WriteError(new ErrorRecord( | ||
| new PSInvalidOperationException(errorMsg), | ||
| "ErrorResettingRepositoryStore", | ||
| ErrorCategory.InvalidOperation, | ||
| this)); | ||
| return; | ||
| } | ||
|
|
||
| WriteVerbose("Repository store reset successfully. PSGallery has been registered."); | ||
|
|
||
| if (PassThru && psGalleryRepo != null) | ||
anamnavi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| WriteObject(psGalleryRepo); | ||
| } | ||
| } | ||
|
|
||
| #endregion | ||
| } | ||
| } | ||
149 changes: 149 additions & 0 deletions
149
test/ResourceRepositoryTests/ResetPSResourceRepository.Tests.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| $modPath = "$psscriptroot/../PSGetTestUtils.psm1" | ||
| Write-Verbose -Verbose -Message "PSGetTestUtils path: $modPath" | ||
| Import-Module $modPath -Force -Verbose | ||
|
|
||
| Describe "Test Reset-PSResourceRepository" -tags 'CI' { | ||
| BeforeEach { | ||
| $PSGalleryName = Get-PSGalleryName | ||
| $PSGalleryUri = Get-PSGalleryLocation | ||
| Get-NewPSResourceRepositoryFile | ||
| } | ||
|
|
||
| AfterEach { | ||
| Get-RevertPSResourceRepositoryFile | ||
| } | ||
|
|
||
| It "Reset repository store without PassThru parameter" { | ||
| # Arrange: Add a test repository | ||
| $TestRepoName = "testRepository" | ||
| $tmpDirPath = Join-Path -Path $TestDrive -ChildPath "tmpDir1" | ||
| New-Item -ItemType Directory -Path $tmpDirPath -Force | Out-Null | ||
| Register-PSResourceRepository -Name $TestRepoName -Uri $tmpDirPath | ||
|
|
||
| # Verify repository was added | ||
| $repos = Get-PSResourceRepository | ||
| $repos.Count | Should -BeGreaterThan 1 | ||
|
|
||
| # Act: Reset repository store | ||
| Reset-PSResourceRepository -Confirm:$false | ||
|
|
||
| # Assert: Only PSGallery should exist | ||
| $repos = Get-PSResourceRepository | ||
| $repos.Count | Should -Be 1 | ||
| $repos.Name | Should -Be $PSGalleryName | ||
| $repos.Uri | Should -Be $PSGalleryUri | ||
| } | ||
|
|
||
| It "Reset repository store with PassThru parameter returns PSGallery" { | ||
| # Arrange: Add a test repository | ||
| $TestRepoName = "testRepository" | ||
| $tmpDirPath = Join-Path -Path $TestDrive -ChildPath "tmpDir1" | ||
| New-Item -ItemType Directory -Path $tmpDirPath -Force | Out-Null | ||
| Register-PSResourceRepository -Name $TestRepoName -Uri $tmpDirPath | ||
|
|
||
| # Act: Reset repository store with PassThru | ||
| $result = Reset-PSResourceRepository -Confirm:$false -PassThru | ||
|
|
||
| # Assert: Result should be PSGallery repository info | ||
| $result | Should -Not -BeNullOrEmpty | ||
| $result.Name | Should -Be $PSGalleryName | ||
| $result.Uri | Should -Be $PSGalleryUri | ||
| $result.Trusted | Should -Be $false | ||
| $result.Priority | Should -Be 50 | ||
|
|
||
| # Verify only PSGallery exists | ||
| $repos = Get-PSResourceRepository | ||
| $repos.Count | Should -Be 1 | ||
| } | ||
|
|
||
| It "Reset repository store should support -WhatIf" { | ||
| # Arrange: Add a test repository | ||
| $TestRepoName = "testRepository" | ||
| $tmpDirPath = Join-Path -Path $TestDrive -ChildPath "tmpDir1" | ||
| New-Item -ItemType Directory -Path $tmpDirPath -Force | Out-Null | ||
| Register-PSResourceRepository -Name $TestRepoName -Uri $tmpDirPath | ||
|
|
||
| # Capture repository count before WhatIf | ||
| $reposBefore = Get-PSResourceRepository | ||
| $countBefore = $reposBefore.Count | ||
|
|
||
| # Act: Run with WhatIf | ||
| Reset-PSResourceRepository -WhatIf | ||
|
|
||
| # Assert: Repositories should not have changed | ||
| $reposAfter = Get-PSResourceRepository | ||
| $reposAfter.Count | Should -Be $countBefore | ||
| } | ||
|
|
||
| It "Reset repository store when corrupted should succeed" { | ||
| # Arrange: Corrupt the repository file | ||
| $powerShellGetPath = Join-Path -Path ([Environment]::GetFolderPath([System.Environment+SpecialFolder]::LocalApplicationData)) -ChildPath "PSResourceGet" | ||
| $repoFilePath = Join-Path -Path $powerShellGetPath -ChildPath "PSResourceRepository.xml" | ||
|
|
||
| # Write invalid XML to corrupt the file | ||
| "This is not valid XML" | Set-Content -Path $repoFilePath -Force | ||
|
|
||
| # Act: Reset the repository store | ||
| $result = Reset-PSResourceRepository -Confirm:$false -PassThru | ||
|
|
||
| # Assert: Should successfully reset and return PSGallery | ||
| $result | Should -Not -BeNullOrEmpty | ||
| $result.Name | Should -Be $PSGalleryName | ||
|
|
||
| # Verify we can now read repositories | ||
| $repos = Get-PSResourceRepository | ||
| $repos.Count | Should -Be 1 | ||
| $repos.Name | Should -Be $PSGalleryName | ||
| } | ||
|
|
||
| It "Reset repository store when file doesn't exist should succeed" { | ||
| # Arrange: Delete the repository file | ||
| $powerShellGetPath = Join-Path -Path ([Environment]::GetFolderPath([System.Environment+SpecialFolder]::LocalApplicationData)) -ChildPath "PSResourceGet" | ||
| $repoFilePath = Join-Path -Path $powerShellGetPath -ChildPath "PSResourceRepository.xml" | ||
|
|
||
| if (Test-Path -Path $repoFilePath) { | ||
| Remove-Item -Path $repoFilePath -Force | ||
| } | ||
|
|
||
| # Act: Reset the repository store | ||
| $result = Reset-PSResourceRepository -Confirm:$false -PassThru | ||
|
|
||
| # Assert: Should successfully reset and return PSGallery | ||
| $result | Should -Not -BeNullOrEmpty | ||
| $result.Name | Should -Be $PSGalleryName | ||
|
|
||
| # Verify PSGallery is registered | ||
| $repos = Get-PSResourceRepository | ||
| $repos.Count | Should -Be 1 | ||
| $repos.Name | Should -Be $PSGalleryName | ||
| } | ||
|
|
||
| It "Reset repository store with multiple repositories should only keep PSGallery" { | ||
| # Arrange: Register multiple repositories | ||
| $tmpDir1Path = Join-Path -Path $TestDrive -ChildPath "tmpDir1" | ||
| $tmpDir2Path = Join-Path -Path $TestDrive -ChildPath "tmpDir2" | ||
| $tmpDir3Path = Join-Path -Path $TestDrive -ChildPath "tmpDir3" | ||
| New-Item -ItemType Directory -Path $tmpDir1Path -Force | Out-Null | ||
| New-Item -ItemType Directory -Path $tmpDir2Path -Force | Out-Null | ||
| New-Item -ItemType Directory -Path $tmpDir3Path -Force | Out-Null | ||
|
|
||
| Register-PSResourceRepository -Name "testRepo1" -Uri $tmpDir1Path | ||
| Register-PSResourceRepository -Name "testRepo2" -Uri $tmpDir2Path | ||
| Register-PSResourceRepository -Name "testRepo3" -Uri $tmpDir3Path | ||
|
|
||
| # Verify multiple repositories exist | ||
| $reposBefore = Get-PSResourceRepository | ||
| $reposBefore.Count | Should -BeGreaterThan 1 | ||
|
|
||
| # Act: Reset repository store | ||
| Reset-PSResourceRepository -Confirm:$false | ||
|
|
||
| # Assert: Only PSGallery should remain | ||
| $reposAfter = Get-PSResourceRepository | ||
| $reposAfter.Count | Should -Be 1 | ||
| $reposAfter.Name | Should -Be $PSGalleryName | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.