Skip to content

Commit f1c2964

Browse files
Copilotalerickson
andcommitted
Add Reset-PSResourceRepository cmdlet and tests
Co-authored-by: alerickson <[email protected]>
1 parent 50ab17d commit f1c2964

File tree

3 files changed

+250
-1
lines changed

3 files changed

+250
-1
lines changed

src/code/RepositorySettings.cs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public static void CheckRepositoryStore()
7272
}
7373
catch (Exception e)
7474
{
75-
throw new PSInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Repository store may be corrupted, file reading failed with error: {0}.", e.Message));
75+
throw new PSInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Repository store may be corrupted, file reading failed with error: {0}. Run 'Reset-PSResourceRepository' to reset the repository store to its default state.", e.Message));
7676
}
7777
}
7878

@@ -845,6 +845,55 @@ public static List<PSRepositoryInfo> Read(string[] repoNames, out string[] error
845845
return reposToReturn.ToList();
846846
}
847847

848+
/// <summary>
849+
/// Resets the repository store by deleting the existing file and creating a new one with PSGallery
850+
/// Returns: PSRepositoryInfo for the newly registered PSGallery
851+
/// </summary>
852+
public static PSRepositoryInfo ResetRepositoryStore()
853+
{
854+
// Delete the existing repository file if it exists
855+
if (File.Exists(FullRepositoryPath))
856+
{
857+
try
858+
{
859+
File.Delete(FullRepositoryPath);
860+
}
861+
catch (Exception e)
862+
{
863+
throw new PSInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Failed to delete repository store file with error: {0}.", e.Message));
864+
}
865+
}
866+
867+
// Ensure directory exists
868+
if (!Directory.Exists(RepositoryPath))
869+
{
870+
try
871+
{
872+
Directory.CreateDirectory(RepositoryPath);
873+
}
874+
catch (Exception e)
875+
{
876+
throw new PSInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Failed to create repository directory with error: {0}.", e.Message));
877+
}
878+
}
879+
880+
// Create a new repository store file
881+
try
882+
{
883+
XDocument newRepoXML = new XDocument(
884+
new XElement("configuration"));
885+
newRepoXML.Save(FullRepositoryPath);
886+
}
887+
catch (Exception e)
888+
{
889+
throw new PSInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Repository store creation failed with error: {0}.", e.Message));
890+
}
891+
892+
// Add PSGallery to the newly created store
893+
Uri psGalleryUri = new Uri(PSGalleryRepoUri);
894+
return Add(PSGalleryRepoName, psGalleryUri, DefaultPriority, DefaultTrusted, repoCredentialInfo: null, repoCredentialProvider: CredentialProviderType.None, APIVersion.V2, force: false);
895+
}
896+
848897
#endregion
849898

850899
#region Private methods
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.PowerShell.PSResourceGet.UtilClasses;
5+
using System;
6+
using System.Management.Automation;
7+
8+
namespace Microsoft.PowerShell.PSResourceGet.Cmdlets
9+
{
10+
/// <summary>
11+
/// The Reset-PSResourceRepository cmdlet creates a fresh repository store by deleting
12+
/// the existing PSResourceRepository.xml file and creating a new one with only PSGallery registered.
13+
/// This is useful when the repository store becomes corrupted.
14+
/// </summary>
15+
[Cmdlet(VerbsCommon.Reset,
16+
"PSResourceRepository",
17+
SupportsShouldProcess = true,
18+
ConfirmImpact = ConfirmImpact.High)]
19+
[OutputType(typeof(PSRepositoryInfo))]
20+
public sealed class ResetPSResourceRepository : PSCmdlet
21+
{
22+
#region Parameters
23+
24+
/// <summary>
25+
/// When specified, displays the PSGallery repository that was registered.
26+
/// </summary>
27+
[Parameter]
28+
public SwitchParameter PassThru { get; set; }
29+
30+
#endregion
31+
32+
#region Method overrides
33+
34+
protected override void ProcessRecord()
35+
{
36+
string repositoryStorePath = System.IO.Path.Combine(
37+
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
38+
"PSResourceGet",
39+
"PSResourceRepository.xml");
40+
41+
string actionMessage = $"Reset repository store at '{repositoryStorePath}'. This will delete all registered repositories and register only PSGallery.";
42+
43+
if (!ShouldProcess(repositoryStorePath, actionMessage))
44+
{
45+
return;
46+
}
47+
48+
try
49+
{
50+
WriteVerbose("Resetting repository store");
51+
PSRepositoryInfo psGallery = RepositorySettings.ResetRepositoryStore();
52+
WriteVerbose($"Repository store has been reset. PSGallery registered at: {repositoryStorePath}");
53+
54+
if (PassThru)
55+
{
56+
WriteObject(psGallery);
57+
}
58+
}
59+
catch (Exception e)
60+
{
61+
ThrowTerminatingError(new ErrorRecord(
62+
new PSInvalidOperationException($"Failed to reset repository store: {e.Message}", e),
63+
"ResetRepositoryStoreFailed",
64+
ErrorCategory.InvalidOperation,
65+
this));
66+
}
67+
}
68+
69+
#endregion
70+
}
71+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
$modPath = "$psscriptroot/../PSGetTestUtils.psm1"
5+
Write-Verbose -Verbose -Message "PSGetTestUtils path: $modPath"
6+
Import-Module $modPath -Force -Verbose
7+
8+
Describe "Test Reset-PSResourceRepository" -tags 'CI' {
9+
BeforeEach {
10+
$PSGalleryName = Get-PSGalleryName
11+
$PSGalleryUri = Get-PSGalleryLocation
12+
Get-NewPSResourceRepositoryFile
13+
$tmpDir1Path = Join-Path -Path $TestDrive -ChildPath "tmpDir1"
14+
$tmpDir2Path = Join-Path -Path $TestDrive -ChildPath "tmpDir2"
15+
$tmpDirPaths = @($tmpDir1Path, $tmpDir2Path)
16+
Get-NewTestDirs($tmpDirPaths)
17+
}
18+
AfterEach {
19+
Get-RevertPSResourceRepositoryFile
20+
$tmpDir1Path = Join-Path -Path $TestDrive -ChildPath "tmpDir1"
21+
$tmpDir2Path = Join-Path -Path $TestDrive -ChildPath "tmpDir2"
22+
$tmpDirPaths = @($tmpDir1Path, $tmpDir2Path)
23+
Get-RemoveTestDirs($tmpDirPaths)
24+
}
25+
26+
It "reset repository store with multiple repositories registered" {
27+
# Register multiple repositories
28+
Register-PSResourceRepository -Name "testRepository1" -Uri $tmpDir1Path
29+
Register-PSResourceRepository -Name "testRepository2" -Uri $tmpDir2Path
30+
31+
# Verify multiple repositories exist
32+
$repos = Get-PSResourceRepository
33+
$repos.Count | Should -BeGreaterThan 2
34+
35+
# Reset repository store
36+
Reset-PSResourceRepository -Confirm:$false
37+
38+
# Verify only PSGallery exists
39+
$repos = Get-PSResourceRepository
40+
$repos.Count | Should -Be 1
41+
$repos.Name | Should -Be $PSGalleryName
42+
$repos.Uri | Should -Be $PSGalleryUri
43+
$repos.Priority | Should -Be 50
44+
$repos.Trusted | Should -Be $false
45+
}
46+
47+
It "reset repository store when only PSGallery is registered" {
48+
# Reset repository store
49+
Reset-PSResourceRepository -Confirm:$false
50+
51+
# Verify only PSGallery exists
52+
$repos = Get-PSResourceRepository
53+
$repos.Count | Should -Be 1
54+
$repos.Name | Should -Be $PSGalleryName
55+
}
56+
57+
It "reset repository store with -PassThru returns PSGallery" {
58+
# Register a test repository
59+
Register-PSResourceRepository -Name "testRepository1" -Uri $tmpDir1Path
60+
61+
# Reset repository store with PassThru
62+
$result = Reset-PSResourceRepository -Confirm:$false -PassThru
63+
64+
# Verify PassThru returns PSGallery
65+
$result.Name | Should -Be $PSGalleryName
66+
$result.Uri | Should -Be $PSGalleryUri
67+
$result.Priority | Should -Be 50
68+
$result.Trusted | Should -Be $false
69+
70+
# Verify only PSGallery exists
71+
$repos = Get-PSResourceRepository
72+
$repos.Count | Should -Be 1
73+
}
74+
75+
It "reset repository store respects -WhatIf" {
76+
# Register test repositories
77+
Register-PSResourceRepository -Name "testRepository1" -Uri $tmpDir1Path
78+
Register-PSResourceRepository -Name "testRepository2" -Uri $tmpDir2Path
79+
80+
# Get count before reset
81+
$reposBefore = Get-PSResourceRepository
82+
$countBefore = $reposBefore.Count
83+
84+
# Reset with WhatIf
85+
Reset-PSResourceRepository -WhatIf
86+
87+
# Verify repositories still exist (WhatIf should not make changes)
88+
$reposAfter = Get-PSResourceRepository
89+
$reposAfter.Count | Should -Be $countBefore
90+
$reposAfter.Name | Should -Contain "testRepository1"
91+
$reposAfter.Name | Should -Contain "testRepository2"
92+
}
93+
94+
It "reset repository store when PSGallery was unregistered" {
95+
# Unregister PSGallery
96+
Unregister-PSResourceRepository -Name $PSGalleryName
97+
98+
# Verify PSGallery is not registered
99+
$repos = Get-PSResourceRepository -ErrorAction SilentlyContinue
100+
$repos.Name | Should -Not -Contain $PSGalleryName
101+
102+
# Reset repository store
103+
Reset-PSResourceRepository -Confirm:$false
104+
105+
# Verify PSGallery is back
106+
$repos = Get-PSResourceRepository
107+
$repos.Count | Should -Be 1
108+
$repos.Name | Should -Be $PSGalleryName
109+
}
110+
111+
It "reset repository store with custom PSGallery settings" {
112+
# Unregister default PSGallery and register with custom settings
113+
Unregister-PSResourceRepository -Name $PSGalleryName
114+
Register-PSResourceRepository -PSGallery -Priority 10 -Trusted
115+
116+
# Verify custom settings
117+
$repo = Get-PSResourceRepository -Name $PSGalleryName
118+
$repo.Priority | Should -Be 10
119+
$repo.Trusted | Should -Be $true
120+
121+
# Reset repository store
122+
Reset-PSResourceRepository -Confirm:$false
123+
124+
# Verify PSGallery is reset to default settings
125+
$repo = Get-PSResourceRepository -Name $PSGalleryName
126+
$repo.Priority | Should -Be 50
127+
$repo.Trusted | Should -Be $false
128+
}
129+
}

0 commit comments

Comments
 (0)