Fix Rename-Item -Path with wildcard char (#7398)

This commit is contained in:
kwkam 2018-11-10 03:08:26 +08:00 committed by Aditya Patwardhan
parent 4118fd2829
commit caad7ed471
4 changed files with 124 additions and 12 deletions

View file

@ -3519,22 +3519,87 @@ namespace Microsoft.PowerShell.Commands
#region Command code #region Command code
private Collection<PathInfo> GetResolvedPaths(string path)
{
Collection<PathInfo> results = null;
try
{
results = SessionState.Path.GetResolvedPSPathFromPSPath(path, CmdletProviderContext);
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
}
return results;
}
/// <summary> /// <summary>
/// Moves the specified item to the specified destination /// Moves the specified item to the specified destination
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecord()
{
if (SuppressWildcardExpansion)
{
RenameItem(Path, literalPath: true);
return;
}
Collection<PathInfo> resolvedPaths = GetResolvedPaths(Path);
if (resolvedPaths == null)
{
return;
}
if (resolvedPaths.Count == 1)
{
RenameItem(resolvedPaths[0].Path, literalPath: true);
}
else
{
RenameItem(WildcardPattern.Unescape(Path), literalPath: true);
}
}
private void RenameItem(string path, bool literalPath = false)
{ {
CmdletProviderContext currentContext = CmdletProviderContext; CmdletProviderContext currentContext = CmdletProviderContext;
currentContext.SuppressWildcardExpansion = literalPath;
try try
{ {
if (!InvokeProvider.Item.Exists(Path, currentContext)) if (!InvokeProvider.Item.Exists(path, currentContext))
{ {
PSInvalidOperationException invalidOperation = PSInvalidOperationException invalidOperation =
(PSInvalidOperationException) (PSInvalidOperationException)
PSTraceSource.NewInvalidOperationException( PSTraceSource.NewInvalidOperationException(
NavigationResources.RenameItemDoesntExist, NavigationResources.RenameItemDoesntExist,
Path); path);
WriteError( WriteError(
new ErrorRecord( new ErrorRecord(
@ -3580,7 +3645,7 @@ namespace Microsoft.PowerShell.Commands
bool isCurrentLocationOrAncestor = false; bool isCurrentLocationOrAncestor = false;
try try
{ {
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(_path, currentContext); isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(path, currentContext);
} }
catch (PSNotSupportedException notSupported) catch (PSNotSupportedException notSupported)
{ {
@ -3621,7 +3686,7 @@ namespace Microsoft.PowerShell.Commands
(PSInvalidOperationException) (PSInvalidOperationException)
PSTraceSource.NewInvalidOperationException( PSTraceSource.NewInvalidOperationException(
NavigationResources.RenamedItemInUse, NavigationResources.RenamedItemInUse,
Path); path);
WriteError( WriteError(
new ErrorRecord( new ErrorRecord(
@ -3635,12 +3700,12 @@ namespace Microsoft.PowerShell.Commands
currentContext.PassThru = PassThru; currentContext.PassThru = PassThru;
tracer.WriteLine("Rename {0} to {1}", Path, NewName); tracer.WriteLine("Rename {0} to {1}", path, NewName);
try try
{ {
// Now do the rename // Now do the rename
InvokeProvider.Item.Rename(Path, NewName, currentContext); InvokeProvider.Item.Rename(path, NewName, currentContext);
} }
catch (PSNotSupportedException notSupported) catch (PSNotSupportedException notSupported)
{ {
@ -3674,7 +3739,7 @@ namespace Microsoft.PowerShell.Commands
pathNotFound)); pathNotFound));
return; return;
} }
} // ProcessRecord }
#endregion Command code #endregion Command code
} // RenameItemCommand } // RenameItemCommand

View file

@ -433,7 +433,13 @@ namespace System.Management.Automation
s_pathResolutionTracer.WriteLine("Path is DRIVE-QUALIFIED"); s_pathResolutionTracer.WriteLine("Path is DRIVE-QUALIFIED");
string relativePath = GetDriveRootRelativePathFromPSPath(path, context, true, out drive, out providerInstance); string relativePath =
GetDriveRootRelativePathFromPSPath(
path,
context,
!context.SuppressWildcardExpansion,
out drive,
out providerInstance);
Dbg.Diagnostics.Assert( Dbg.Diagnostics.Assert(
drive != null, drive != null,

View file

@ -104,7 +104,7 @@ Describe "Basic Function Provider Tests" -Tags "CI" {
} }
It "Fails to rename not existing function" { It "Fails to rename not existing function" {
{ Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand" { Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "PathNotFound,Microsoft.PowerShell.Commands.RenameItemCommand"
} }
It "Fails to rename function which is Constant" { It "Fails to rename function which is Constant" {
@ -113,8 +113,8 @@ Describe "Basic Function Provider Tests" -Tags "CI" {
} }
It "Fails to rename function which is ReadOnly" { It "Fails to rename function which is ReadOnly" {
Set-Item $nonExistingFunction -Options "ReadOnly" Set-Item $nonExistingFunction -Options "ReadOnly" -Value $functionValue
{ Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand" { Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "CannotRenameFunction,Microsoft.PowerShell.Commands.RenameItemCommand"
} }
It "Renames ReadOnly function when -Force parameter is on" { It "Renames ReadOnly function when -Force parameter is on" {

View file

@ -2,10 +2,15 @@
# Licensed under the MIT License. # Licensed under the MIT License.
Describe "Rename-Item tests" -Tag "CI" { Describe "Rename-Item tests" -Tag "CI" {
BeforeAll { BeforeAll {
$content = "This is content"
Setup -f originalFile.txt -content "This is content" Setup -f originalFile.txt -content "This is content"
$source = "$TESTDRIVE/originalFile.txt" $source = "$TESTDRIVE/originalFile.txt"
$target = "$TESTDRIVE/ItemWhichHasBeenRenamed.txt" $target = "$TESTDRIVE/ItemWhichHasBeenRenamed.txt"
Setup -f [orig-file].txt -content "This is not content"
$sourceSp = "$TestDrive/``[orig-file``].txt"
$targetSpName = "ItemWhichHasBeen[Renamed].txt"
$targetSp = "$TestDrive/ItemWhichHasBeen``[Renamed``].txt"
Setup -Dir [test-dir]
$wdSp = "$TestDrive/``[test-dir``]"
} }
It "Rename-Item will rename a file" { It "Rename-Item will rename a file" {
Rename-Item $source $target Rename-Item $source $target
@ -13,4 +18,40 @@ Describe "Rename-Item tests" -Tag "CI" {
test-path $target | Should -BeTrue test-path $target | Should -BeTrue
"$target" | Should -FileContentMatchExactly "This is content" "$target" | Should -FileContentMatchExactly "This is content"
} }
It "Rename-Item will rename a file when path contains special char" {
Rename-Item $sourceSp $targetSpName
$sourceSp | Should -Not -Exist
$targetSp | Should -Exist
$targetSp | Should -FileContentMatchExactly "This is not content"
}
It "Rename-Item will rename a file when -Path and CWD contains special char" {
$content = "This is content"
$oldSpName = "[orig]file.txt"
$oldSpBName = "``[orig``]file.txt"
$oldSp = "$wdSp/$oldSpBName"
$newSpName = "[renamed]file.txt"
$newSp = "$wdSp/``[renamed``]file.txt"
In $wdSp -Execute {
$null = New-Item -Name $oldSpName -ItemType File -Value $content -Force
Rename-Item -Path $oldSpBName $newSpName
}
$oldSp | Should -Not -Exist
$newSp | Should -Exist
$newSp | Should -FileContentMatchExactly $content
}
It "Rename-Item will rename a file when -LiteralPath and CWD contains special char" {
$content = "This is not content"
$oldSpName = "[orig]file2.txt"
$oldSpBName = "``[orig``]file2.txt"
$oldSp = "$wdSp/$oldSpBName"
$newSpName = "[renamed]file2.txt"
$newSp = "$wdSp/``[renamed``]file2.txt"
In $wdSp -Execute {
$null = New-Item -Name $oldSpName -ItemType File -Value $content -Force
Rename-Item -LiteralPath $oldSpName $newSpName
}
$oldSp | Should -Not -Exist
$newSp | Should -Exist
$newSp | Should -FileContentMatchExactly $content
}
} }