mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-14 05:39:11 +00:00
Add New-TemporaryDirectory cmdlet (#27549)
Co-authored-by: Justin Chung <124807742+jshigetomi@users.noreply.github.com>
This commit is contained in:
1 parent
174a75396c
commit
f83ccddf80
5 files changed
+226
-2
No files matched your search
+113
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.IO;
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// The implementation of the "New-TemporaryDirectory" cmdlet.
|
||||
/// </summary>
|
||||
[Cmdlet(VerbsCommon.New, "TemporaryDirectory", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Low, HelpUri = "https://go.microsoft.com/fwlink/?LinkId=2097032")]
|
||||
[OutputType(typeof(System.IO.DirectoryInfo))]
|
||||
public class NewTemporaryDirectoryCommand : Cmdlet
|
||||
{
|
||||
private const string NewTemporaryDirectoryInvalidPrefix = "NewTemporaryDirectoryInvalidPrefix";
|
||||
private const string NewTemporaryDirectoryWriteError = "NewTemporaryDirectoryWriteError";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional prefix for the temporary directory name.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[ValidateNotNullOrEmpty]
|
||||
public string Prefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a temporary directory.
|
||||
/// </summary>
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
string tempPath = Path.GetTempPath();
|
||||
|
||||
if (!string.IsNullOrEmpty(Prefix) && IsInvalidPrefix(Prefix))
|
||||
{
|
||||
ThrowTerminatingError(
|
||||
CreateErrorRecord(
|
||||
new System.ArgumentException("The prefix contains invalid characters.", nameof(Prefix)),
|
||||
NewTemporaryDirectoryInvalidPrefix,
|
||||
ErrorCategory.InvalidArgument,
|
||||
Prefix));
|
||||
return;
|
||||
}
|
||||
|
||||
string targetDescription = string.IsNullOrEmpty(Prefix)
|
||||
? $"temporary directory under '{tempPath}'"
|
||||
: $"temporary directory under '{tempPath}' with prefix '{Prefix}'";
|
||||
|
||||
if (!ShouldProcess(targetDescription, "Create temporary directory"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DirectoryInfo createdDirectory = string.IsNullOrEmpty(Prefix)
|
||||
? Directory.CreateTempSubdirectory()
|
||||
: Directory.CreateTempSubdirectory(Prefix);
|
||||
|
||||
WriteObject(createdDirectory);
|
||||
}
|
||||
catch (IOException ioException)
|
||||
{
|
||||
ThrowTerminatingError(
|
||||
CreateErrorRecord(
|
||||
ioException,
|
||||
NewTemporaryDirectoryWriteError,
|
||||
ErrorCategory.WriteError,
|
||||
targetDescription));
|
||||
}
|
||||
catch (System.UnauthorizedAccessException unauthorizedAccessException)
|
||||
{
|
||||
ThrowTerminatingError(
|
||||
CreateErrorRecord(
|
||||
unauthorizedAccessException,
|
||||
NewTemporaryDirectoryWriteError,
|
||||
ErrorCategory.PermissionDenied,
|
||||
targetDescription));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsInvalidPrefix(string prefix)
|
||||
{
|
||||
if (prefix.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (char prefixCharacter in prefix)
|
||||
{
|
||||
if (prefixCharacter is '/' or '\\' || char.IsControl(prefixCharacter))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return prefix.Equals(".", System.StringComparison.Ordinal)
|
||||
|| prefix.Equals("..", System.StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static ErrorRecord CreateErrorRecord(
|
||||
System.Exception exception,
|
||||
string errorId,
|
||||
ErrorCategory category,
|
||||
object targetObject)
|
||||
{
|
||||
return new ErrorRecord(
|
||||
exception,
|
||||
errorId,
|
||||
category,
|
||||
targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ CmdletsToExport = @(
|
||||
'Get-PSBreakpoint', 'Remove-PSBreakpoint', 'Set-PSBreakpoint', 'Get-PSCallStack', 'Export-PSSession',
|
||||
'Import-PSSession', 'Get-Random', 'Get-SecureRandom', 'Invoke-RestMethod', 'Debug-Runspace', 'Get-Runspace',
|
||||
'Disable-RunspaceDebug', 'Enable-RunspaceDebug', 'Get-RunspaceDebug', 'Start-Sleep', 'Join-String',
|
||||
'Out-String', 'Select-String', 'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryFile', 'New-TimeSpan',
|
||||
'Out-String', 'Select-String', 'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryDirectory', 'New-TemporaryFile', 'New-TimeSpan',
|
||||
'Get-TraceSource', 'Set-TraceSource', 'Add-Type', 'Get-TypeData', 'Remove-TypeData', 'Update-TypeData',
|
||||
'Get-UICulture', 'Get-Unique', 'Get-Uptime', 'Clear-Variable', 'Get-Variable', 'New-Variable',
|
||||
'Remove-Variable', 'Set-Variable', 'Get-Verb', 'Write-Verbose', 'Write-Warning', 'Invoke-WebRequest',
|
||||
|
||||
@@ -20,7 +20,7 @@ CmdletsToExport = @(
|
||||
'Remove-PSBreakpoint', 'Set-PSBreakpoint', 'Get-PSCallStack', 'Export-PSSession', 'Import-PSSession', 'Get-Random', 'Get-SecureRandom'
|
||||
'Invoke-RestMethod', 'Debug-Runspace', 'Get-Runspace', 'Disable-RunspaceDebug', 'Enable-RunspaceDebug',
|
||||
'Get-RunspaceDebug', 'ConvertFrom-SddlString', 'Start-Sleep', 'Join-String', 'Out-String', 'Select-String',
|
||||
'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryFile', 'New-TimeSpan', 'Get-TraceSource', 'Set-TraceSource',
|
||||
'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryDirectory', 'New-TemporaryFile', 'New-TimeSpan', 'Get-TraceSource', 'Set-TraceSource',
|
||||
'Add-Type', 'Get-TypeData', 'Remove-TypeData', 'Update-TypeData', 'Get-UICulture', 'Get-Unique', 'Get-Uptime',
|
||||
'Clear-Variable', 'Get-Variable', 'New-Variable', 'Remove-Variable', 'Set-Variable', 'Get-Verb', 'Write-Verbose',
|
||||
'Write-Warning', 'Invoke-WebRequest', 'Format-Wide', 'ConvertTo-Xml', 'Select-Xml', 'Get-Error', 'Update-List',
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe "New-TemporaryDirectory" -Tags "CI" {
|
||||
BeforeEach {
|
||||
$tempDirectory = $null
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
if ($tempDirectory -and (Test-Path -LiteralPath $tempDirectory.FullName)) {
|
||||
Remove-Item -LiteralPath $tempDirectory.FullName -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
It "creates a new temporary directory" {
|
||||
$tempDirectory = New-TemporaryDirectory
|
||||
|
||||
$tempDirectory | Should -Exist
|
||||
$tempDirectory | Should -BeOfType System.IO.DirectoryInfo
|
||||
$tempDirectory.FullName | Should -BeLikeExactly "$([System.IO.Path]::GetTempPath())*"
|
||||
(Get-Item -LiteralPath $tempDirectory.FullName).PSIsContainer | Should -BeTrue
|
||||
}
|
||||
|
||||
It "creates unique temporary directories" {
|
||||
$tempDirectory = New-TemporaryDirectory
|
||||
$secondTempDirectory = New-TemporaryDirectory
|
||||
|
||||
try {
|
||||
$secondTempDirectory.FullName | Should -Not -BeExactly $tempDirectory.FullName
|
||||
$secondTempDirectory | Should -Exist
|
||||
$secondTempDirectory | Should -BeOfType System.IO.DirectoryInfo
|
||||
}
|
||||
finally {
|
||||
if ($secondTempDirectory -and (Test-Path -LiteralPath $secondTempDirectory.FullName)) {
|
||||
Remove-Item -LiteralPath $secondTempDirectory.FullName -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
It "with WhatIf does not create a directory" {
|
||||
New-TemporaryDirectory -WhatIf | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "with WhatIf and Prefix does not create a directory" {
|
||||
New-TemporaryDirectory -Prefix "Test_" -WhatIf | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "with WhatIf and Prefix reports a descriptive target" {
|
||||
$prefix = "Test_"
|
||||
$rawTarget = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), $prefix)
|
||||
$whatIfOutput = & "$PSHOME/pwsh" -NoProfile -CommandWithArgs 'param($prefix) New-TemporaryDirectory -Prefix $prefix -WhatIf' $prefix 2>&1 | Out-String
|
||||
|
||||
$whatIfOutput | Should -Not -Match ([regex]::Escape("`"$rawTarget`""))
|
||||
$whatIfOutput | Should -Match ([regex]::Escape("with prefix '$prefix'"))
|
||||
}
|
||||
|
||||
It "rejects special relative path Prefix '<Prefix>'" -TestCases @(
|
||||
@{ Prefix = "." }
|
||||
@{ Prefix = ".." }
|
||||
) {
|
||||
param($Prefix)
|
||||
|
||||
{ New-TemporaryDirectory -Prefix $Prefix -ErrorAction Stop } | Should -Throw -ErrorId "NewTemporaryDirectoryInvalidPrefix,Microsoft.PowerShell.Commands.NewTemporaryDirectoryCommand"
|
||||
}
|
||||
|
||||
It "rejects separator-like Prefix '<Prefix>'" -TestCases @(
|
||||
@{ Prefix = "path/name" }
|
||||
@{ Prefix = "path\name" }
|
||||
@{ Prefix = "../name" }
|
||||
@{ Prefix = "..\name" }
|
||||
) {
|
||||
param($Prefix)
|
||||
|
||||
{ New-TemporaryDirectory -Prefix $Prefix -ErrorAction Stop } | Should -Throw -ErrorId "NewTemporaryDirectoryInvalidPrefix,Microsoft.PowerShell.Commands.NewTemporaryDirectoryCommand"
|
||||
}
|
||||
|
||||
It "rejects Prefix with control character '<CharacterCode>'" -TestCases @(
|
||||
@{ CharacterCode = 10 }
|
||||
@{ CharacterCode = 13 }
|
||||
@{ CharacterCode = 9 }
|
||||
@{ CharacterCode = 27 }
|
||||
) {
|
||||
param($CharacterCode)
|
||||
|
||||
$Prefix = "bad$([char]$CharacterCode)name"
|
||||
{ New-TemporaryDirectory -Prefix $Prefix -ErrorAction Stop } | Should -Throw -ErrorId "NewTemporaryDirectoryInvalidPrefix,Microsoft.PowerShell.Commands.NewTemporaryDirectoryCommand"
|
||||
}
|
||||
|
||||
It "has an OutputType of System.IO.DirectoryInfo" {
|
||||
(Get-Command New-TemporaryDirectory).OutputType.Name | Should -Contain "System.IO.DirectoryInfo"
|
||||
}
|
||||
|
||||
It "creates a directory with custom prefix" {
|
||||
$prefix = "MyApp"
|
||||
$tempDirectory = New-TemporaryDirectory -Prefix $prefix
|
||||
|
||||
$tempDirectory | Should -Exist
|
||||
$tempDirectory | Should -BeOfType System.IO.DirectoryInfo
|
||||
$tempDirectory.Name | Should -BeLike "$prefix*"
|
||||
}
|
||||
|
||||
It "rejects Prefix with invalid file name characters" {
|
||||
$invalidChars = [System.IO.Path]::GetInvalidFileNameChars()
|
||||
|
||||
if ($invalidChars.Count -gt 0) {
|
||||
$badPrefix = "bad$($invalidChars[0])prefix"
|
||||
{ New-TemporaryDirectory -Prefix $badPrefix -ErrorAction Stop } | Should -Throw -ErrorId "NewTemporaryDirectoryInvalidPrefix,Microsoft.PowerShell.Commands.NewTemporaryDirectoryCommand"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -401,6 +401,7 @@ Describe "Verify aliases and cmdlets" -Tags "CI" {
|
||||
"Cmdlet", "New-PSSessionOption", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "New-PSTransportOption", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "New-Service", "", $($FullCLR -or $CoreWindows ), "", "", "Medium"
|
||||
"Cmdlet", "New-TemporaryDirectory", "", $( $CoreWindows -or $CoreUnix), "", "", "Low"
|
||||
"Cmdlet", "New-TemporaryFile", "", $( $CoreWindows -or $CoreUnix), "", "", "Low"
|
||||
"Cmdlet", "New-TimeSpan", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "New-Variable", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "Low"
|
||||
|
||||
Reference in new issue
Block a user