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