зеркало из https://github.com/microsoft/PSRule.git
This commit is contained in:
Родитель
56a21369f9
Коммит
6c21b047ab
|
@ -29,6 +29,15 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers
|
|||
|
||||
What's changed since pre-release v3.0.0-B0267:
|
||||
|
||||
- New features:
|
||||
- Allow CLI upgrade command to upgrade a single module by @BernieWhite.
|
||||
[#2551](https://github.com/microsoft/PSRule/issues/2551)
|
||||
- A single or specific modules can be upgraded by name when using `module upgrade`.
|
||||
- By default, all modules are upgraded.
|
||||
- Allow CLI to install pre-release modules by @BernieWhite.
|
||||
[#2550](https://github.com/microsoft/PSRule/issues/2550)
|
||||
- Add and upgrade pre-release modules with `--prerelease`.
|
||||
- Pre-release modules will be restored from the lock file with `module restore`.
|
||||
- General improvements:
|
||||
- **Breaking change**: Empty version comparison only accepts stable versions by default by @BernieWhite.
|
||||
[#2557](https://github.com/microsoft/PSRule/issues/2557)
|
||||
|
|
|
@ -67,6 +67,9 @@ Optional parameters:
|
|||
- `--version` - Specifies a specific version of the module to add.
|
||||
By default, the latest stable version of the module is added.
|
||||
Any required version constraints set by the `Requires` option are taken into consideration.
|
||||
- `--prerelease` - Accept pre-release versions in addition to stable module versions.
|
||||
By default, pre-release versions are not included.
|
||||
A pre-release version may also be accepted when `Requires` includes pre-releases.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -80,6 +83,12 @@ For example, a specific version of the module is added:
|
|||
ps-rule module add PSRule.Rules.Azure --version 1.32.1
|
||||
```
|
||||
|
||||
For example, include pre-release versions added:
|
||||
|
||||
```bash title="PSRule CLI command-line"
|
||||
ps-rule module add PSRule.Rules.Azure --prerelease
|
||||
```
|
||||
|
||||
## `module remove`
|
||||
|
||||
Remove one or more modules from the lock file.
|
||||
|
@ -112,7 +121,13 @@ ps-rule module restore --force
|
|||
|
||||
## `module upgrade`
|
||||
|
||||
Upgrade to the latest versions any modules within the lock file.
|
||||
Upgrade to the latest versions for all or a specific module within the lock file.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
- `--prerelease` - Accept pre-release versions in addition to stable module versions.
|
||||
By default, pre-release versions are not included.
|
||||
A pre-release version may also be accepted when `Requires` includes pre-releases.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -120,6 +135,12 @@ For example:
|
|||
ps-rule module upgrade
|
||||
```
|
||||
|
||||
For example, upgrade a specific module and include pre-release versions:
|
||||
|
||||
```bash title="PSRule CLI command-line"
|
||||
ps-rule module upgrade PSRule.Rules.Azure --prerelease
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
For more information on the module lock file, see [Lock file](../lockfile.md).
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
"type": "string",
|
||||
"title": "Module version",
|
||||
"description": "The version of the module to use."
|
||||
},
|
||||
"includePrerelease": {
|
||||
"type": "boolean",
|
||||
"title": "Include prerelease",
|
||||
"description": "Accept pre-release versions in addition to stable module versions."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
@ -17,7 +17,6 @@ using PSRule.Pipeline.Dependencies;
|
|||
using SemanticVersion = PSRule.Data.SemanticVersion;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Common;
|
||||
using PSRule.Pipeline;
|
||||
|
||||
namespace PSRule.CommandLine.Commands;
|
||||
|
||||
|
@ -51,7 +50,7 @@ public sealed class ModuleCommand
|
|||
var requires = clientContext.Option.Requires.ToDictionary();
|
||||
var file = LockFile.Read(null);
|
||||
|
||||
using var pwsh = PowerShell.Create();
|
||||
using var pwsh = CreatePowerShell();
|
||||
|
||||
// Restore from the lock file.
|
||||
foreach (var kv in file.Modules)
|
||||
|
@ -70,9 +69,11 @@ public sealed class ModuleCommand
|
|||
|
||||
var idealVersion = await FindVersionAsync(module, null, targetVersion, null, cancellationToken);
|
||||
if (idealVersion != null)
|
||||
await InstallVersionAsync(clientContext, module, idealVersion.ToString(), cancellationToken);
|
||||
{
|
||||
installedVersion = await InstallVersionAsync(clientContext, module, idealVersion, cancellationToken);
|
||||
}
|
||||
|
||||
if (pwsh.HadErrors || (idealVersion == null && installedVersion == null))
|
||||
if (pwsh.HadErrors || idealVersion == null || installedVersion == null)
|
||||
{
|
||||
exitCode = ERROR_MODULE_FAILED_TO_INSTALL;
|
||||
clientContext.LogError(Messages.Error_501, module, targetVersion);
|
||||
|
@ -109,7 +110,7 @@ public sealed class ModuleCommand
|
|||
var idealVersion = await FindVersionAsync(includeModule, moduleConstraint, null, null, cancellationToken);
|
||||
if (idealVersion != null)
|
||||
{
|
||||
await InstallVersionAsync(clientContext, includeModule, idealVersion.ToString(), cancellationToken);
|
||||
await InstallVersionAsync(clientContext, includeModule, idealVersion, cancellationToken);
|
||||
}
|
||||
else if (idealVersion == null)
|
||||
{
|
||||
|
@ -143,8 +144,7 @@ public sealed class ModuleCommand
|
|||
var exitCode = 0;
|
||||
var requires = clientContext.Option.Requires.ToDictionary();
|
||||
var file = !operationOptions.Force ? LockFile.Read(null) : new LockFile();
|
||||
|
||||
using var pwsh = PowerShell.Create();
|
||||
using var pwsh = CreatePowerShell();
|
||||
|
||||
// Add for any included modules.
|
||||
if (clientContext.Option?.Include?.Module != null && clientContext.Option.Include.Module.Length > 0)
|
||||
|
@ -197,8 +197,7 @@ public sealed class ModuleCommand
|
|||
var exitCode = 0;
|
||||
var requires = clientContext.Option.Requires.ToDictionary();
|
||||
var file = LockFile.Read(null);
|
||||
|
||||
var pwsh = PowerShell.Create();
|
||||
var pwsh = CreatePowerShell();
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
|
@ -218,13 +217,13 @@ public sealed class ModuleCommand
|
|||
var requires = clientContext.Option.Requires.ToDictionary();
|
||||
var file = LockFile.Read(null);
|
||||
|
||||
using var pwsh = PowerShell.Create();
|
||||
using var pwsh = CreatePowerShell();
|
||||
foreach (var module in operationOptions.Module)
|
||||
{
|
||||
if (!file.Modules.TryGetValue(module, out var item) || operationOptions.Force)
|
||||
{
|
||||
// Get a constraint if set from options.
|
||||
var moduleConstraint = requires.TryGetValue(module, out var c) ? c : ModuleConstraint.Any(module, includePrerelease: false);
|
||||
var moduleConstraint = requires.TryGetValue(module, out var c) ? c : ModuleConstraint.Any(module, includePrerelease: operationOptions.Prerelease);
|
||||
|
||||
// Get target version if specified in command-line.
|
||||
var targetVersion = !string.IsNullOrEmpty(operationOptions.Version) && SemanticVersion.TryParseVersion(operationOptions.Version, out var v) && v != null ? v : null;
|
||||
|
@ -250,7 +249,8 @@ public sealed class ModuleCommand
|
|||
clientContext.LogVerbose(Messages.UsingModule, module, idealVersion.ToString());
|
||||
item = new LockEntry
|
||||
{
|
||||
Version = idealVersion
|
||||
Version = idealVersion,
|
||||
IncludePrerelease = operationOptions.Prerelease && !idealVersion.Stable ? true : null,
|
||||
};
|
||||
file.Modules[module] = item;
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ public sealed class ModuleCommand
|
|||
|
||||
var file = LockFile.Read(null);
|
||||
|
||||
using var pwsh = PowerShell.Create();
|
||||
using var pwsh = CreatePowerShell();
|
||||
foreach (var module in operationOptions.Module)
|
||||
{
|
||||
if (file.Modules.TryGetValue(module, out var constraint))
|
||||
|
@ -311,12 +311,13 @@ public sealed class ModuleCommand
|
|||
var exitCode = 0;
|
||||
var requires = clientContext.Option.Requires.ToDictionary();
|
||||
var file = LockFile.Read(null);
|
||||
var filteredModules = operationOptions.Module != null && operationOptions.Module.Length > 0 ? new HashSet<string>(operationOptions.Module, StringComparer.OrdinalIgnoreCase) : null;
|
||||
|
||||
using var pwsh = PowerShell.Create();
|
||||
foreach (var kv in file.Modules)
|
||||
using var pwsh = CreatePowerShell();
|
||||
foreach (var kv in file.Modules.Where(m => filteredModules == null || filteredModules.Contains(m.Key)))
|
||||
{
|
||||
// Get a constraint if set from options.
|
||||
var moduleConstraint = requires.TryGetValue(kv.Key, out var c) ? c : ModuleConstraint.Any(kv.Key, includePrerelease: false);
|
||||
var moduleConstraint = requires.TryGetValue(kv.Key, out var c) ? c : ModuleConstraint.Any(kv.Key, includePrerelease: kv.Value.IncludePrerelease ?? operationOptions.Prerelease);
|
||||
|
||||
// Find the ideal version.
|
||||
var idealVersion = await FindVersionAsync(kv.Key, moduleConstraint, null, null, cancellationToken);
|
||||
|
@ -332,6 +333,7 @@ public sealed class ModuleCommand
|
|||
clientContext.LogVerbose(Messages.UsingModule, kv.Key, idealVersion.ToString());
|
||||
|
||||
kv.Value.Version = idealVersion;
|
||||
kv.Value.IncludePrerelease = (kv.Value.IncludePrerelease.GetValueOrDefault(false) || operationOptions.Prerelease) && !idealVersion.Stable ? true : null;
|
||||
file.Modules[kv.Key] = kv.Value;
|
||||
}
|
||||
|
||||
|
@ -461,24 +463,26 @@ public sealed class ModuleCommand
|
|||
return result;
|
||||
}
|
||||
|
||||
private static async Task InstallVersionAsync([DisallowNull] ClientContext context, [DisallowNull] string name, [DisallowNull] string version, CancellationToken cancellationToken)
|
||||
private static async Task<SemanticVersion.Version?> InstallVersionAsync([DisallowNull] ClientContext context, [DisallowNull] string name, [DisallowNull] SemanticVersion.Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
context.LogVerbose(Messages.RestoringModule, name, version);
|
||||
|
||||
var cache = new SourceCacheContext();
|
||||
var logger = new NullLogger();
|
||||
var resource = await GetSourceRepositoryAsync();
|
||||
var stringVersion = version.ToString();
|
||||
|
||||
var packageVersion = new NuGetVersion(version);
|
||||
var packageVersion = new NuGetVersion(stringVersion);
|
||||
using var packageStream = new MemoryStream();
|
||||
|
||||
await resource.CopyNupkgToStreamAsync(
|
||||
if (!await resource.CopyNupkgToStreamAsync(
|
||||
name,
|
||||
packageVersion,
|
||||
packageStream,
|
||||
cache,
|
||||
logger,
|
||||
cancellationToken);
|
||||
cancellationToken))
|
||||
return null;
|
||||
|
||||
using var packageReader = new PackageArchiveReader(packageStream);
|
||||
var nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken);
|
||||
|
@ -489,6 +493,7 @@ public sealed class ModuleCommand
|
|||
if (Directory.Exists(modulePath))
|
||||
Directory.Delete(modulePath, true);
|
||||
|
||||
var count = 0;
|
||||
var files = packageReader.GetFiles();
|
||||
packageReader.CopyFiles(modulePath, files, (name, targetPath, s) =>
|
||||
{
|
||||
|
@ -496,10 +501,18 @@ public sealed class ModuleCommand
|
|||
return null;
|
||||
|
||||
s.CopyToFile(targetPath);
|
||||
count++;
|
||||
|
||||
return targetPath;
|
||||
|
||||
}, logger, cancellationToken);
|
||||
|
||||
// Check module path exists.
|
||||
if (!Directory.Exists(modulePath))
|
||||
return null;
|
||||
|
||||
context.LogVerbose("Module saved to: {0} -- {1}", name, modulePath);
|
||||
return count > 0 ? version : null;
|
||||
}
|
||||
|
||||
private static async Task<FindPackageByIdResource> GetSourceRepositoryAsync()
|
||||
|
@ -509,9 +522,9 @@ public sealed class ModuleCommand
|
|||
return await repository.GetResourceAsync<FindPackageByIdResource>();
|
||||
}
|
||||
|
||||
private static string GetModulePath(ClientContext context, string name, string version)
|
||||
private static string GetModulePath(ClientContext context, string name, [DisallowNull] SemanticVersion.Version version)
|
||||
{
|
||||
return Path.Combine(context.CachePath, MODULES_PATH, name, version);
|
||||
return Path.Combine(context.CachePath, MODULES_PATH, name, version.ToShortString());
|
||||
}
|
||||
|
||||
private static bool ShouldIgnorePackageFile(string name)
|
||||
|
@ -520,5 +533,10 @@ public sealed class ModuleCommand
|
|||
string.Equals(name, "_rels/.rels", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static PowerShell CreatePowerShell()
|
||||
{
|
||||
return PowerShell.Create();
|
||||
}
|
||||
|
||||
#endregion Helper methods
|
||||
}
|
||||
|
|
|
@ -4,32 +4,37 @@
|
|||
namespace PSRule.CommandLine.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Options for the module command.
|
||||
/// </summary>
|
||||
public sealed class ModuleOptions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// A specific path to use for the operation.
|
||||
/// </summary>
|
||||
public string[]? Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// The name of any specified modules.
|
||||
/// </summary>
|
||||
public string[]? Module { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Determines if the module is overridden if it already exists.
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// The target module version.
|
||||
/// </summary>
|
||||
public string? Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Determines if verification that the module exists is skipped.
|
||||
/// </summary>
|
||||
public bool SkipVerification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Accept pre-release versions in addition to stable module versions.
|
||||
/// </summary>
|
||||
public bool Prerelease { get; set; }
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ internal sealed class ClientBuilder
|
|||
private readonly Option<string> _Module_Add_Version;
|
||||
private readonly Option<bool> _Module_Add_Force;
|
||||
private readonly Option<bool> _Module_Add_SkipVerification;
|
||||
private readonly Option<bool> _Module_Prerelease;
|
||||
private readonly Option<string[]> _Global_Path;
|
||||
private readonly Option<DirectoryInfo> _Run_OutputPath;
|
||||
private readonly Option<string> _Run_OutputFormat;
|
||||
|
@ -43,70 +44,74 @@ internal sealed class ClientBuilder
|
|||
|
||||
// Global options.
|
||||
_Global_Option = new Option<string>(
|
||||
new string[] { "--option" },
|
||||
["--option"],
|
||||
getDefaultValue: () => "ps-rule.yaml",
|
||||
description: CmdStrings.Global_Option_Description
|
||||
);
|
||||
_Global_Verbose = new Option<bool>(
|
||||
new string[] { "--verbose" },
|
||||
["--verbose"],
|
||||
description: CmdStrings.Global_Verbose_Description
|
||||
);
|
||||
_Global_Debug = new Option<bool>(
|
||||
new string[] { "--debug" },
|
||||
["--debug"],
|
||||
description: CmdStrings.Global_Debug_Description
|
||||
);
|
||||
_Global_Path = new Option<string[]>(
|
||||
new string[] { "-p", "--path" },
|
||||
["-p", "--path"],
|
||||
description: CmdStrings.Global_Path_Description
|
||||
);
|
||||
|
||||
// Options for the run command.
|
||||
_Run_OutputPath = new Option<DirectoryInfo>(
|
||||
new string[] { "--output-path" },
|
||||
["--output-path"],
|
||||
description: CmdStrings.Run_OutputPath_Description
|
||||
);
|
||||
_Run_OutputFormat = new Option<string>(
|
||||
new string[] { "-o", "--output" },
|
||||
["-o", "--output"],
|
||||
description: CmdStrings.Run_OutputFormat_Description
|
||||
);
|
||||
_Run_InputPath = new Option<string[]>(
|
||||
new string[] { "-f", "--input-path" },
|
||||
["-f", "--input-path"],
|
||||
description: CmdStrings.Run_InputPath_Description
|
||||
);
|
||||
_Run_Module = new Option<string[]>(
|
||||
new string[] { "-m", "--module" },
|
||||
["-m", "--module"],
|
||||
description: CmdStrings.Run_Module_Description
|
||||
);
|
||||
_Run_Baseline = new Option<string>(
|
||||
new string[] { "--baseline" },
|
||||
["--baseline"],
|
||||
description: CmdStrings.Run_Baseline_Description
|
||||
);
|
||||
_Run_Outcome = new Option<string[]>(
|
||||
new string[] { "--outcome" },
|
||||
["--outcome"],
|
||||
description: CmdStrings.Run_Outcome_Description
|
||||
).FromAmong("Pass", "Fail", "Error", "Processed", "Problem");
|
||||
_Run_Outcome.Arity = ArgumentArity.ZeroOrMore;
|
||||
|
||||
// Options for the module command.
|
||||
_Module_Init_Force = new Option<bool>(
|
||||
new string[] { ARG_FORCE },
|
||||
[ARG_FORCE],
|
||||
description: CmdStrings.Module_Init_Force_Description
|
||||
);
|
||||
_Module_Add_Version = new Option<string>
|
||||
(
|
||||
new string[] { "--version" },
|
||||
["--version"],
|
||||
description: CmdStrings.Module_Add_Version_Description
|
||||
);
|
||||
_Module_Add_Force = new Option<bool>(
|
||||
new string[] { ARG_FORCE },
|
||||
[ARG_FORCE],
|
||||
description: CmdStrings.Module_Add_Force_Description
|
||||
);
|
||||
_Module_Add_SkipVerification = new Option<bool>(
|
||||
new string[] { "--skip-verification" },
|
||||
["--skip-verification"],
|
||||
description: CmdStrings.Module_Add_SkipVerification_Description
|
||||
);
|
||||
_Module_Prerelease = new Option<bool>(
|
||||
["--prerelease"],
|
||||
description: CmdStrings.Module_Prerelease_Description
|
||||
);
|
||||
_Module_Restore_Force = new Option<bool>(
|
||||
new string[] { ARG_FORCE },
|
||||
[ARG_FORCE],
|
||||
description: CmdStrings.Module_Restore_Force_Description
|
||||
);
|
||||
|
||||
|
@ -165,12 +170,12 @@ internal sealed class ClientBuilder
|
|||
{
|
||||
var cmd = new Command("module", CmdStrings.Module_Description);
|
||||
|
||||
var moduleArg = new Argument<string[]>
|
||||
var requiredModuleArg = new Argument<string[]>
|
||||
(
|
||||
"module",
|
||||
CmdStrings.Module_Module_Description
|
||||
CmdStrings.Module_RequiredModule_Description
|
||||
);
|
||||
moduleArg.Arity = ArgumentArity.OneOrMore;
|
||||
requiredModuleArg.Arity = ArgumentArity.OneOrMore;
|
||||
|
||||
// Init
|
||||
var init = new Command
|
||||
|
@ -219,19 +224,21 @@ internal sealed class ClientBuilder
|
|||
"add",
|
||||
CmdStrings.Module_Add_Description
|
||||
);
|
||||
add.AddArgument(moduleArg);
|
||||
add.AddArgument(requiredModuleArg);
|
||||
add.AddOption(_Module_Add_Version);
|
||||
add.AddOption(_Module_Add_Force);
|
||||
add.AddOption(_Module_Add_SkipVerification);
|
||||
add.AddOption(_Module_Prerelease);
|
||||
add.SetHandler(async (invocation) =>
|
||||
{
|
||||
var option = new ModuleOptions
|
||||
{
|
||||
Path = invocation.ParseResult.GetValueForOption(_Global_Path),
|
||||
Module = invocation.ParseResult.GetValueForArgument(moduleArg),
|
||||
Module = invocation.ParseResult.GetValueForArgument(requiredModuleArg),
|
||||
Version = invocation.ParseResult.GetValueForOption(_Module_Add_Version),
|
||||
Force = invocation.ParseResult.GetValueForOption(_Module_Add_Force),
|
||||
SkipVerification = invocation.ParseResult.GetValueForOption(_Module_Add_SkipVerification),
|
||||
Prerelease = invocation.ParseResult.GetValueForOption(_Module_Prerelease),
|
||||
};
|
||||
|
||||
var client = GetClientContext(invocation);
|
||||
|
@ -244,13 +251,13 @@ internal sealed class ClientBuilder
|
|||
"remove",
|
||||
CmdStrings.Module_Remove_Description
|
||||
);
|
||||
remove.AddArgument(moduleArg);
|
||||
remove.AddArgument(requiredModuleArg);
|
||||
remove.SetHandler(async (invocation) =>
|
||||
{
|
||||
var option = new ModuleOptions
|
||||
{
|
||||
Path = invocation.ParseResult.GetValueForOption(_Global_Path),
|
||||
Module = invocation.ParseResult.GetValueForArgument(moduleArg),
|
||||
Module = invocation.ParseResult.GetValueForArgument(requiredModuleArg),
|
||||
};
|
||||
|
||||
var client = GetClientContext(invocation);
|
||||
|
@ -263,11 +270,21 @@ internal sealed class ClientBuilder
|
|||
"upgrade",
|
||||
CmdStrings.Module_Upgrade_Description
|
||||
);
|
||||
var optionalModuleArg = new Argument<string[]>
|
||||
(
|
||||
"module",
|
||||
CmdStrings.Module_OptionalModule_Description
|
||||
);
|
||||
optionalModuleArg.Arity = ArgumentArity.ZeroOrMore;
|
||||
upgrade.AddArgument(optionalModuleArg);
|
||||
upgrade.AddOption(_Module_Prerelease);
|
||||
upgrade.SetHandler(async (invocation) =>
|
||||
{
|
||||
var option = new ModuleOptions
|
||||
{
|
||||
Path = invocation.ParseResult.GetValueForOption(_Global_Path),
|
||||
Module = invocation.ParseResult.GetValueForArgument(requiredModuleArg),
|
||||
Prerelease = invocation.ParseResult.GetValueForOption(_Module_Prerelease),
|
||||
};
|
||||
|
||||
var client = GetClientContext(invocation);
|
||||
|
|
|
@ -178,11 +178,20 @@ namespace PSRule.Tool.Resources {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The name of one or more modules..
|
||||
/// Looks up a localized string similar to Optionally specifies one or more modules to apply to..
|
||||
/// </summary>
|
||||
internal static string Module_Module_Description {
|
||||
internal static string Module_OptionalModule_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Module_Module_Description", resourceCulture);
|
||||
return ResourceManager.GetString("Module_OptionalModule_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Accept pre-release versions in addition to stable module versions..
|
||||
/// </summary>
|
||||
internal static string Module_Prerelease_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Module_Prerelease_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +204,15 @@ namespace PSRule.Tool.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The name of one or more modules..
|
||||
/// </summary>
|
||||
internal static string Module_RequiredModule_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Module_RequiredModule_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Restore from the module lock file and configured options..
|
||||
/// </summary>
|
||||
|
|
|
@ -141,9 +141,12 @@
|
|||
<data name="Module_Description" xml:space="preserve">
|
||||
<value>Manage or restore modules tracked by the module lock file and configured options.</value>
|
||||
</data>
|
||||
<data name="Module_Module_Description" xml:space="preserve">
|
||||
<data name="Module_RequiredModule_Description" xml:space="preserve">
|
||||
<value>The name of one or more modules.</value>
|
||||
</data>
|
||||
<data name="Module_OptionalModule_Description" xml:space="preserve">
|
||||
<value>Optionally specifies one or more modules to apply to.</value>
|
||||
</data>
|
||||
<data name="Module_Remove_Description" xml:space="preserve">
|
||||
<value>Remove one or more modules from the lock file.</value>
|
||||
</data>
|
||||
|
@ -192,4 +195,7 @@
|
|||
<data name="Run_OutputPath_Description" xml:space="preserve">
|
||||
<value>Specifies a path to write results to.</value>
|
||||
</data>
|
||||
<data name="Module_Prerelease_Description" xml:space="preserve">
|
||||
<value>Accept pre-release versions in addition to stable module versions.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -346,7 +346,8 @@ public static class SemanticVersion
|
|||
[DebuggerDisplay("{_VersionString}")]
|
||||
public sealed class Version : IComparable<Version>, IEquatable<Version>
|
||||
{
|
||||
private readonly string _VersionString;
|
||||
private string? _VersionString;
|
||||
private string? _ShortVersionString;
|
||||
|
||||
/// <summary>
|
||||
/// The major part of the version.
|
||||
|
@ -380,8 +381,6 @@ public static class SemanticVersion
|
|||
Patch = patch;
|
||||
Prerelease = prerelease;
|
||||
Build = build;
|
||||
|
||||
_VersionString = GetVersionString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -397,10 +396,20 @@ public static class SemanticVersion
|
|||
return TryParseVersion(value, out version);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>
|
||||
/// Get the version as a string.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return _VersionString;
|
||||
return _VersionString ??= GetVersionString(simple: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version as a string returning only the major.minor.patch part of the version.
|
||||
/// </summary>
|
||||
public string ToShortString()
|
||||
{
|
||||
return _ShortVersionString ??= GetVersionString(simple: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -480,10 +489,14 @@ public static class SemanticVersion
|
|||
return Prerelease != other.Prerelease ? PR.Compare(Prerelease, other.Prerelease) : 0;
|
||||
}
|
||||
|
||||
private string GetVersionString()
|
||||
/// <summary>
|
||||
/// Returns a version string.
|
||||
/// </summary>
|
||||
/// <param name="simple">When <c>true</c>, only return the major.minor.patch version.</param>
|
||||
private string GetVersionString(bool simple = false)
|
||||
{
|
||||
var count = 5 + (Prerelease != null && !Prerelease.Stable ? 2 : 0) + (Build != null && Build.Length > 0 ? 2 : 0);
|
||||
var parts = new object[count];
|
||||
var size = 5 + (!simple && Prerelease != null && !Prerelease.Stable ? 2 : 0) + (!simple && Build != null && Build.Length > 0 ? 2 : 0);
|
||||
var parts = new object[size];
|
||||
|
||||
parts[0] = Major;
|
||||
parts[1] = DOT;
|
||||
|
@ -491,19 +504,21 @@ public static class SemanticVersion
|
|||
parts[3] = DOT;
|
||||
parts[4] = Patch;
|
||||
|
||||
var next = 5;
|
||||
if (Prerelease != null && !Prerelease.Stable)
|
||||
if (size > 5)
|
||||
{
|
||||
parts[next++] = DASH;
|
||||
parts[next++] = Prerelease.Value;
|
||||
}
|
||||
var next = 5;
|
||||
if (Prerelease != null && !Prerelease.Stable)
|
||||
{
|
||||
parts[next++] = DASH;
|
||||
parts[next++] = Prerelease.Value;
|
||||
}
|
||||
|
||||
if (Build != null && Build.Length > 0)
|
||||
{
|
||||
parts[next++] = PLUS;
|
||||
parts[next++] = Build;
|
||||
if (Build != null && Build.Length > 0)
|
||||
{
|
||||
parts[next++] = PLUS;
|
||||
parts[next++] = Build;
|
||||
}
|
||||
}
|
||||
|
||||
return string.Concat(parts);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,3 +6,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: InternalsVisibleTo("Microsoft.PSRule.Core")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.PSRule.Tool")]
|
||||
[assembly: InternalsVisibleTo("PSRule.Tests")]
|
||||
[assembly: InternalsVisibleTo("PSRule.Types.Tests")]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
using PSRule.Data;
|
||||
|
||||
|
@ -16,4 +17,10 @@ public sealed class LockEntry
|
|||
/// </summary>
|
||||
[JsonProperty("version", NullValueHandling = NullValueHandling.Include)]
|
||||
public SemanticVersion.Version Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Accept pre-release versions in addition to stable module versions.
|
||||
/// </summary>
|
||||
[DefaultValue(null), JsonProperty("includePrerelease", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? IncludePrerelease { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using PSRule.Data;
|
||||
|
||||
namespace PSRule.CommandLine;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for <see cref="ModuleConstraint"/>.
|
||||
/// </summary>
|
||||
public sealed class ModuleConstraintTests
|
||||
{
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.PowerShell;
|
||||
using PSRule.Data;
|
||||
|
||||
namespace PSRule;
|
||||
namespace PSRule.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for semantic version comparison.
|
||||
|
@ -18,20 +15,20 @@ public sealed class SemanticVersionTests
|
|||
public void Version()
|
||||
{
|
||||
Assert.True(SemanticVersion.TryParseVersion("1.2.3-alpha.3+7223b39", out var actual1));
|
||||
Assert.Equal(1, actual1.Major);
|
||||
Assert.Equal(1, actual1!.Major);
|
||||
Assert.Equal(2, actual1.Minor);
|
||||
Assert.Equal(3, actual1.Patch);
|
||||
Assert.Equal("alpha.3", actual1.Prerelease.Value);
|
||||
Assert.Equal("7223b39", actual1.Build);
|
||||
|
||||
Assert.True(SemanticVersion.TryParseVersion("v1.2.3-alpha.3", out var actual2));
|
||||
Assert.Equal(1, actual2.Major);
|
||||
Assert.Equal(1, actual2!.Major);
|
||||
Assert.Equal(2, actual2.Minor);
|
||||
Assert.Equal(3, actual2.Patch);
|
||||
Assert.Equal("alpha.3", actual2.Prerelease.Value);
|
||||
|
||||
Assert.True(SemanticVersion.TryParseVersion("v1.2.3+7223b39", out var actual3));
|
||||
Assert.Equal(1, actual3.Major);
|
||||
Assert.Equal(1, actual3!.Major);
|
||||
Assert.Equal(2, actual3.Minor);
|
||||
Assert.Equal(3, actual3.Patch);
|
||||
Assert.Equal("7223b39", actual3.Build);
|
||||
|
@ -48,11 +45,11 @@ public sealed class SemanticVersionTests
|
|||
Assert.True(SemanticVersion.TryParseVersion("10.0.0", out var actual3));
|
||||
Assert.True(SemanticVersion.TryParseVersion("1.0.2", out var actual4));
|
||||
|
||||
Assert.True(actual1.CompareTo(actual1) == 0);
|
||||
Assert.Equal(0, actual1!.CompareTo(actual1));
|
||||
Assert.True(actual1.CompareTo(actual2) < 0);
|
||||
Assert.True(actual1.CompareTo(actual3) < 0);
|
||||
Assert.True(actual1.CompareTo(actual4) < 0);
|
||||
Assert.True(actual2.CompareTo(actual2) == 0);
|
||||
Assert.Equal(0, actual2!.CompareTo(actual2));
|
||||
Assert.True(actual2.CompareTo(actual1) > 0);
|
||||
Assert.True(actual2.CompareTo(actual3) < 0);
|
||||
Assert.True(actual2.CompareTo(actual4) > 0);
|
||||
|
@ -205,7 +202,7 @@ public sealed class SemanticVersionTests
|
|||
var actual7 = new SemanticVersion.PR("beta.11");
|
||||
var actual8 = new SemanticVersion.PR("rc.1");
|
||||
|
||||
Assert.True(actual1.CompareTo(actual1) == 0);
|
||||
Assert.Equal(0, actual1.CompareTo(actual1));
|
||||
Assert.True(actual1.CompareTo(actual2) > 0);
|
||||
Assert.True(actual1.CompareTo(actual6) > 0);
|
||||
Assert.True(actual2.CompareTo(actual3) < 0);
|
||||
|
@ -226,6 +223,17 @@ public sealed class SemanticVersionTests
|
|||
public void ToString_WhenValid_ShouldReturnString(string version)
|
||||
{
|
||||
Assert.True(SemanticVersion.TryParseVersion(version, out var actual));
|
||||
Assert.Equal(version, actual.ToString());
|
||||
Assert.Equal(version, actual!.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.2.3")]
|
||||
[InlineData("1.2.3-alpha.3+7223b39")]
|
||||
[InlineData("3.4.5-alpha.9")]
|
||||
[InlineData("3.4.5+7223b39")]
|
||||
public void ToShortString_WhenValid_ShouldReturnString(string version)
|
||||
{
|
||||
Assert.True(SemanticVersion.TryParseVersion(version, out var actual));
|
||||
Assert.Equal(string.Join(".", actual!.Major, actual.Minor, actual.Patch), actual!.ToShortString());
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче