Skip to content

Commit 41dbb56

Browse files
authored
Add -SkipDependencyCheck to cmdlets. (#550)
* Add -SkipDependencyCheck to install/save/update cmdlets * Change -Force to -SkipDependencyCheck * Fix tests
1 parent b9f7acd commit 41dbb56

8 files changed

+93
-42
lines changed

src/code/InstallHelper.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public void InstallPackages(
7979
string specifiedPath,
8080
bool asNupkg,
8181
bool includeXML,
82+
bool skipDependencyCheck,
8283
List<string> pathsToInstallPkg)
8384
{
8485
_cmdletPassedIn.WriteVerbose(string.Format("Parameters passed in >>> Name: '{0}'; Version: '{1}'; Prerelease: '{2}'; Repository: '{3}'; " +
@@ -123,7 +124,12 @@ public void InstallPackages(
123124
}
124125

125126
// Go through the repositories and see which is the first repository to have the pkg version available
126-
ProcessRepositories(names, repository, _trustRepository, _credential);
127+
ProcessRepositories(
128+
packageNames: names,
129+
repository: repository,
130+
trustRepository: _trustRepository,
131+
credential: _credential,
132+
skipDependencyCheck: skipDependencyCheck);
127133
}
128134

129135
#endregion
@@ -135,7 +141,8 @@ private void ProcessRepositories(
135141
string[] packageNames,
136142
string[] repository,
137143
bool trustRepository,
138-
PSCredential credential)
144+
PSCredential credential,
145+
bool skipDependencyCheck)
139146
{
140147
var listOfRepositories = RepositorySettings.Read(repository, out string[] _);
141148
List<string> pckgNamesToInstall = packageNames.ToList();
@@ -185,7 +192,7 @@ private void ProcessRepositories(
185192
tag: null,
186193
repository: new string[] { repoName },
187194
credential: credential,
188-
includeDependencies: true);
195+
includeDependencies: !skipDependencyCheck);
189196

190197
if (!pkgsFromRepoToInstall.Any())
191198
{

src/code/InstallPSResource.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets
1515
/// The Install-PSResource cmdlet installs a resource.
1616
/// It returns nothing.
1717
/// </summary>
18-
1918
[Cmdlet(VerbsLifecycle.Install, "PSResource", DefaultParameterSetName = "NameParameterSet", SupportsShouldProcess = true)]
2019
public sealed
2120
class InstallPSResource : PSCmdlet
@@ -106,6 +105,13 @@ class InstallPSResource : PSCmdlet
106105
[ValidateNotNullOrEmpty]
107106
public PSResourceInfo InputObject { get; set; }
108107

108+
/// <summary>
109+
/// Skips the check for resource dependencies, so that only found resources are installed,
110+
/// and not any resources the found resource depends on.
111+
/// </summary>
112+
[Parameter]
113+
public SwitchParameter SkipDependencyCheck { get; set; }
114+
109115
#endregion
110116

111117
#region Members
@@ -250,6 +256,7 @@ private void ProcessInstallHelper(string[] pkgNames, bool pkgPrerelease, string[
250256
specifiedPath: null,
251257
asNupkg: false,
252258
includeXML: true,
259+
skipDependencyCheck: SkipDependencyCheck,
253260
pathsToInstallPkg: _pathsToInstallPkg);
254261
}
255262

src/code/SavePSResource.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ public string Path
123123
[ValidateNotNullOrEmpty]
124124
public PSResourceInfo InputObject { get; set; }
125125

126+
/// <summary>
127+
/// Skips the check for resource dependencies, so that only found resources are saved,
128+
/// and not any resources the found resource depends on.
129+
/// </summary>
130+
[Parameter]
131+
public SwitchParameter SkipDependencyCheck { get; set; }
132+
126133
#endregion
127134

128135
#region Method overrides
@@ -243,7 +250,8 @@ private void ProcessSaveHelper(string[] pkgNames, bool pkgPrerelease, string[] p
243250
noClobber: false,
244251
specifiedPath: _path,
245252
asNupkg: false,
246-
includeXML: false,
253+
includeXML: false,
254+
skipDependencyCheck: SkipDependencyCheck,
247255
pathsToInstallPkg: new List<string> { _path } );
248256
}
249257

src/code/UninstallPSResource.cs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ public sealed class UninstallPSResource : PSCmdlet
4343
public PSResourceInfo InputObject { get; set; }
4444

4545
/// <summary>
46+
/// Skips check to see if other resources are dependent on the resource being uninstalled.
4647
/// </summary>
47-
[Parameter(ParameterSetName = NameParameterSet)]
48-
[Parameter(ParameterSetName = InputObjectParameterSet)]
49-
public SwitchParameter Force { get; set; }
48+
[Parameter]
49+
public SwitchParameter SkipDependencyCheck { get; set; }
5050

5151
#endregion
5252

@@ -212,9 +212,9 @@ private bool UninstallModuleHelper(string pkgPath, string pkgName, out ErrorReco
212212
errRecord = null;
213213
var successfullyUninstalledPkg = false;
214214

215-
// if -Force is not specified and the pkg is a dependency for another package,
215+
// if -SkipDependencyCheck is not specified and the pkg is a dependency for another package,
216216
// an error will be written and we return false
217-
if (!Force && CheckIfDependency(pkgName, out errRecord))
217+
if (!SkipDependencyCheck && CheckIfDependency(pkgName, out errRecord))
218218
{
219219
return false;
220220
}
@@ -301,9 +301,8 @@ private bool UninstallScriptHelper(string pkgPath, string pkgName, out ErrorReco
301301
return successfullyUninstalledPkg;
302302
}
303303

304-
private bool CheckIfDependency(string pkgName, out ErrorRecord errRecord)
304+
private bool CheckIfDependency(string pkgName, out ErrorRecord errorRecord)
305305
{
306-
errRecord = null;
307306
// this is a primitive implementation
308307
// TODO: implement a dependencies database for querying dependency info
309308
// cannot uninstall a module if another module is dependent on it
@@ -317,29 +316,34 @@ private bool CheckIfDependency(string pkgName, out ErrorRecord errRecord)
317316
// RequiredModules is collection of PSModuleInfo objects that need to be iterated through to see if any of them are the pkg we're trying to uninstall
318317
// If we anything from the final call gets returned, there is a dependency on this pkg.
319318
IEnumerable<PSObject> pkgsWithRequiredModules = new List<PSObject>();
319+
errorRecord = null;
320320
try
321321
{
322322
pkgsWithRequiredModules = results.Where(
323-
p => ((ReadOnlyCollection<PSModuleInfo>)p.Properties["RequiredModules"].Value).Where(
323+
pkg => ((ReadOnlyCollection<PSModuleInfo>)pkg.Properties["RequiredModules"].Value).Where(
324324
rm => rm.Name.Equals(pkgName, StringComparison.InvariantCultureIgnoreCase)).Any());
325325
}
326326
catch (Exception e)
327327
{
328-
var exMessage = String.Format("Error checking if resource is a dependency: {0}. If you would still like to uninstall, rerun the command with -Force", e.Message);
329-
var ex = new ArgumentException(exMessage);
330-
var DependencyCheckError = new ErrorRecord(ex, "DependencyCheckError", ErrorCategory.OperationStopped, null);
331-
errRecord = DependencyCheckError;
328+
errorRecord = new ErrorRecord(
329+
new PSInvalidOperationException(
330+
$"Error checking if resource is a dependency: {e.Message}."),
331+
"UninstallPSResourceDependencyCheckError",
332+
ErrorCategory.InvalidOperation,
333+
null);
332334
}
333335

334336
if (pkgsWithRequiredModules.Any())
335337
{
336338
var uniquePkgNames = pkgsWithRequiredModules.Select(p => p.Properties["Name"].Value).Distinct().ToArray();
337339
var strUniquePkgNames = string.Join(",", uniquePkgNames);
338340

339-
var exMessage = String.Format("Cannot uninstall '{0}', the following package(s) take a dependency on this package: {1}. If you would still like to uninstall, rerun the command with -Force", pkgName, strUniquePkgNames);
340-
var ex = new ArgumentException(exMessage);
341-
var PackageIsaDependency = new ErrorRecord(ex, "PackageIsaDependency", ErrorCategory.OperationStopped, null);
342-
errRecord = PackageIsaDependency;
341+
errorRecord = new ErrorRecord(
342+
new PSInvalidOperationException(
343+
$"Cannot uninstall '{pkgName}'. The following package(s) take a dependency on this package: {strUniquePkgNames}. If you would still like to uninstall, rerun the command with -SkipDependencyCheck"),
344+
"UninstallPSResourcePackageIsaDependency",
345+
ErrorCategory.InvalidOperation,
346+
null);
343347

344348
return true;
345349
}

src/code/UpdatePSResource.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ public sealed class UpdatePSResource : PSCmdlet
9797
[Parameter]
9898
public SwitchParameter Force { get; set; }
9999

100+
/// <summary>
101+
/// Skips the check for resource dependencies, so that only found resources are updated,
102+
/// and not any resources the found resource depends on.
103+
/// </summary>
104+
[Parameter]
105+
public SwitchParameter SkipDependencyCheck { get; set; }
106+
100107
#endregion
101108

102109
#region Override Methods
@@ -166,6 +173,7 @@ protected override void ProcessRecord()
166173
specifiedPath: null,
167174
asNupkg: false,
168175
includeXML: true,
176+
skipDependencyCheck: SkipDependencyCheck,
169177
pathsToInstallPkg: _pathsToInstallPkg);
170178
}
171179

@@ -253,7 +261,7 @@ private string[] ProcessPackageNames(
253261
tag: null,
254262
repository: Repository,
255263
credential: Credential,
256-
includeDependencies: false))
264+
includeDependencies: !SkipDependencyCheck))
257265
{
258266
if (!repositoryPackages.ContainsKey(foundResource.Name))
259267
{

test/InstallPSResource.Tests.ps1

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Describe 'Test Install-PSResource for Module' {
1717
AfterEach {
1818
Uninstall-PSResource "TestModule", "TestModule99", "myTestModule", "myTestModule2", "testModulePrerelease",
1919
"testModuleWithlicense","PSGetTestModule", "PSGetTestDependency1", "TestFindModule","ClobberTestModule1",
20-
"ClobberTestModule2" -Force -ErrorAction SilentlyContinue
20+
"ClobberTestModule2" -SkipDependencyCheck -ErrorAction SilentlyContinue
2121
}
2222

2323
AfterAll {
@@ -103,22 +103,22 @@ Describe 'Test Install-PSResource for Module' {
103103
}
104104

105105
It "Install resource when given Name, Version '*', should install the latest version" {
106-
$pkg = Install-PSResource -Name "TestModule" -Version "*" -Repository $TestGalleryName
106+
Install-PSResource -Name "TestModule" -Version "*" -Repository $TestGalleryName
107107
$pkg = Get-Module "TestModule" -ListAvailable
108108
$pkg.Name | Should -Be "TestModule"
109109
$pkg.Version | Should -Be "1.3.0"
110110
}
111111

112112
It "Install resource with latest (including prerelease) version given Prerelease parameter" {
113-
$pkg = Install-PSResource -Name "TestModulePrerelease" -Prerelease -Repository $TestGalleryName
113+
Install-PSResource -Name "TestModulePrerelease" -Prerelease -Repository $TestGalleryName
114114
$pkg = Get-Module "TestModulePrerelease" -ListAvailable
115115
$pkg.Name | Should -Be "TestModulePrerelease"
116116
$pkg.Version | Should -Be "0.0.1"
117117
$pkg.PrivateData.PSData.Prerelease | Should -Be "preview"
118118
}
119119

120120
It "Install a module with a dependency" {
121-
$pkg = Install-PSResource -Name "PSGetTestModule" -Prerelease -Repository $TestGalleryName
121+
Install-PSResource -Name "PSGetTestModule" -Prerelease -Repository $TestGalleryName
122122
$pkg = Get-Module "PSGetTestModule" -ListAvailable
123123
$pkg.Name | Should -Be "PSGetTestModule"
124124
$pkg.Version | Should -Be "2.0.2"
@@ -129,6 +129,17 @@ Describe 'Test Install-PSResource for Module' {
129129
$pkg.Version | Should -Be "1.0.0"
130130
}
131131

132+
It "Install a module with a dependency and skip installing the dependency" {
133+
Install-PSResource -Name "PSGetTestModule" -Prerelease -Repository $TestGalleryName -SkipDependencyCheck
134+
$pkg = Get-Module "PSGetTestModule" -ListAvailable
135+
$pkg.Name | Should -Be "PSGetTestModule"
136+
$pkg.Version | Should -Be "2.0.2"
137+
$pkg.PrivateData.PSData.Prerelease | Should -Be "-alpha1"
138+
139+
$pkg = Get-Module "PSGetTestDependency1" -ListAvailable
140+
$pkg | Should -BeNullOrEmpty
141+
}
142+
132143
It "Install resource via InputObject by piping from Find-PSresource" {
133144
Find-PSResource -Name "TestModule" -Repository $TestGalleryName | Install-PSResource
134145
$pkg = Get-Module "TestModule" -ListAvailable
@@ -309,7 +320,7 @@ Describe 'Test Install-PSResource for interactive and root user scenarios' {
309320
}
310321
311322
AfterEach {
312-
Uninstall-PSResource "TestModule", "testModuleWithlicense" -Force -ErrorAction SilentlyContinue
323+
Uninstall-PSResource "TestModule", "testModuleWithlicense" -SkipDependencyCheck -ErrorAction SilentlyContinue
313324
}
314325
315326
AfterAll {

test/SavePSResource.Tests.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ Describe 'Test Save-PSResource for PSResources' {
129129
(Get-ChildItem $pkgDirs[1].FullName).Count | Should -Be 1
130130
}
131131

132+
It "Save a module with a dependency and skip saving the dependency" {
133+
Save-PSResource -Name "PSGetTestModule" -Prerelease -Repository $TestGalleryName -Path $SaveDir -SkipDependencyCheck
134+
$pkgDirs = Get-ChildItem -Path $SaveDir | Where-Object { $_.Name -eq "PSGetTestModule" -or $_.Name -eq "PSGetTestDependency1" }
135+
$pkgDirs.Count | Should -Be 1
136+
(Get-ChildItem $pkgDirs[0].FullName).Count | Should -Be 1
137+
}
138+
132139
It "Save resource via InputObject by piping from Find-PSresource" {
133140
Find-PSResource -Name "TestModule" -Repository $TestGalleryName | Save-PSResource -Path $SaveDir
134141
$pkgDir = Get-ChildItem -Path $SaveDir | Where-Object Name -eq "TestModule"

test/UninstallPSResource.Tests.ps1

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Describe 'Test Uninstall-PSResource for Modules' {
1111
$testModuleName = "test_module"
1212
$testScriptName = "test_script"
1313
Get-NewPSResourceRepositoryFile
14-
$res = Uninstall-PSResource -name ContosoServer -Version "*"
14+
Uninstall-PSResource -name ContosoServer -Version "*"
1515
}
1616
BeforeEach{
1717
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue
@@ -21,7 +21,7 @@ Describe 'Test Uninstall-PSResource for Modules' {
2121
}
2222

2323
It "Uninstall a specific module by name" {
24-
$res = Uninstall-PSResource -name ContosoServer
24+
Uninstall-PSResource -name ContosoServer
2525
Get-Module ContosoServer -ListAvailable | Should -Be $null
2626
}
2727

@@ -38,28 +38,28 @@ Describe 'Test Uninstall-PSResource for Modules' {
3838
It "Uninstall a list of modules by name" {
3939
$null = Install-PSResource BaseTestPackage -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue
4040

41-
$res = Uninstall-PSResource -Name BaseTestPackage, ContosoServer
41+
Uninstall-PSResource -Name BaseTestPackage, ContosoServer
4242
Get-Module ContosoServer, BaseTestPackage -ListAvailable | Should -be $null
4343
}
4444

4545
It "Uninstall a specific script by name" {
4646
$null = Install-PSResource Test-RPC -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue
4747

48-
$pkg = Uninstall-PSResource -name Test-RPC
48+
Uninstall-PSResource -name Test-RPC
4949
}
5050

5151
It "Uninstall a list of scripts by name" {
5252
$null = Install-PSResource adsql, airoute -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue
5353

54-
$pkg = Uninstall-PSResource -Name adsql, airoute
54+
Uninstall-PSResource -Name adsql, airoute
5555
}
5656

5757
It "Uninstall a module when given name and specifying all versions" {
5858
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "1.0.0" -TrustRepository -WarningAction SilentlyContinue
5959
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "1.5.0" -TrustRepository -WarningAction SilentlyContinue
6060
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "2.0.0" -TrustRepository -WarningAction SilentlyContinue
6161

62-
$res = Uninstall-PSResource -Name ContosoServer -version "*"
62+
Uninstall-PSResource -Name ContosoServer -version "*"
6363
$pkgs = Get-Module ContosoServer -ListAvailable
6464
$pkgs.Version | Should -Not -Contain "1.0.0"
6565
$pkgs.Version | Should -Not -Contain "1.5.0"
@@ -72,7 +72,7 @@ Describe 'Test Uninstall-PSResource for Modules' {
7272
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "1.5.0" -TrustRepository -WarningAction SilentlyContinue
7373
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "2.0.0" -TrustRepository -WarningAction SilentlyContinue
7474

75-
$res = Uninstall-PSResource -Name ContosoServer
75+
Uninstall-PSResource -Name ContosoServer
7676
$pkgs = Get-Module ContosoServer -ListAvailable
7777
$pkgs.Version | Should -Not -Contain "1.0.0"
7878
$pkgs.Version | Should -Not -Contain "1.5.0"
@@ -85,7 +85,7 @@ Describe 'Test Uninstall-PSResource for Modules' {
8585
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "1.5.0" -TrustRepository -WarningAction SilentlyContinue
8686
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "2.0.0" -TrustRepository -WarningAction SilentlyContinue
8787

88-
$res = Uninstall-PSResource -Name "ContosoServer" -Version "1.0.0"
88+
Uninstall-PSResource -Name "ContosoServer" -Version "1.0.0"
8989
$pkgs = Get-Module ContosoServer -ListAvailable
9090
$pkgs.Version | Should -Not -Contain "1.0.0"
9191
}
@@ -106,7 +106,7 @@ Describe 'Test Uninstall-PSResource for Modules' {
106106
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "1.5.0" -TrustRepository -WarningAction SilentlyContinue
107107
$null = Install-PSResource ContosoServer -Repository $TestGalleryName -Version "2.0.0" -TrustRepository -WarningAction SilentlyContinue
108108

109-
$res = Uninstall-PSResource -Name ContosoServer -Version $Version
109+
Uninstall-PSResource -Name ContosoServer -Version $Version
110110
$pkgs = Get-Module ContosoServer -ListAvailable
111111
$pkgs.Version | Should -Not -Contain $Version
112112
}
@@ -169,8 +169,7 @@ Describe 'Test Uninstall-PSResource for Modules' {
169169
}
170170

171171
It "Uninstall module using -WhatIf, should not uninstall the module" {
172-
$res = Uninstall-PSResource -Name "ContosoServer" -WhatIf
173-
172+
Uninstall-PSResource -Name "ContosoServer" -WhatIf
174173
$pkg = Get-Module ContosoServer -ListAvailable
175174
$pkg.Version | Should -Be "2.5"
176175
}
@@ -183,16 +182,16 @@ Describe 'Test Uninstall-PSResource for Modules' {
183182
$pkg = Get-Module "RequiredModule1" -ListAvailable
184183
$pkg | Should -Not -Be $null
185184

186-
$ev | Should -Be "Cannot uninstall 'RequiredModule1', the following package(s) take a dependency on this package: test_module. If you would still like to uninstall, rerun the command with -Force"
185+
$ev.FullyQualifiedErrorId | Should -BeExactly 'UninstallPSResourcePackageIsaDependency,Microsoft.PowerShell.PowerShellGet.Cmdlets.UninstallPSResource'
187186
}
188187

189-
It "Uninstall module that is a dependency for another module using -Force" {
188+
It "Uninstall module that is a dependency for another module using -SkipDependencyCheck" {
190189
$null = Install-PSResource "test_module" -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue
191190

192-
$res = Uninstall-PSResource -Name "RequiredModule1" -Force
191+
Uninstall-PSResource -Name "RequiredModule1" -SkipDependencyCheck
193192

194193
$pkg = Get-Module "RequiredModule1" -ListAvailable
195-
$pkg | Should -Be $null
194+
$pkg | Should -BeNullOrEmpty
196195
}
197196

198197
It "Uninstall PSResourceInfo object piped in" {

0 commit comments

Comments
 (0)