[Feature] Fix Move-Item -Path with wildcard char (#7397)

Unescape non-literal, non-glob path in ProccessRecord and
set the context.SuppressWildcardExpansion in RenameItem.
This solve the issue where Rename-Item complains -Path does not exist
when both -Path and CWD contains special characters.
This commit is contained in:
kwkam
2018-08-05 17:31:06 +05:00
committed by Ilya
parent dbdcf6e5eb
commit fbfbb4f005
2 changed files with 150 additions and 148 deletions
@@ -3225,7 +3225,7 @@ namespace Microsoft.PowerShell.Commands
{
if (base.SuppressWildcardExpansion)
{
MoveItem(path);
MoveItem(path, literalPath: true);
}
else
{
@@ -3234,173 +3234,165 @@ namespace Microsoft.PowerShell.Commands
foreach (PathInfo resolvedPathInfo in resolvedPaths)
{
string resolvedPath = resolvedPathInfo.Path;
MoveItem(resolvedPath);
MoveItem(resolvedPath, literalPath: true);
}
}
}
} // ProcessRecord
}
private void MoveItem(string path)
private void MoveItem(string path, bool literalPath = false)
{
CmdletProviderContext currentContext = CmdletProviderContext;
currentContext.SuppressWildcardExpansion = literalPath;
do
try
{
try
{
string escapedPath = path;
if (!base.SuppressWildcardExpansion) { escapedPath = WildcardPattern.Escape(path); }
if (!InvokeProvider.Item.Exists(escapedPath, currentContext))
{
PSInvalidOperationException invalidOperation =
(PSInvalidOperationException)
PSTraceSource.NewInvalidOperationException(
NavigationResources.MoveItemDoesntExist,
path);
WriteError(
new ErrorRecord(
invalidOperation.ErrorRecord,
invalidOperation));
continue;
}
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
continue;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
continue;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
continue;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
continue;
}
// See if the item to be moved is in use.
bool isCurrentLocationOrAncestor = false;
try
{
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(path, currentContext);
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
continue;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
continue;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
continue;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
continue;
}
if (isCurrentLocationOrAncestor)
if (!InvokeProvider.Item.Exists(path, currentContext))
{
PSInvalidOperationException invalidOperation =
(PSInvalidOperationException)
PSTraceSource.NewInvalidOperationException(
NavigationResources.MoveItemInUse,
NavigationResources.MoveItemDoesntExist,
path);
WriteError(
new ErrorRecord(
invalidOperation.ErrorRecord,
invalidOperation));
continue;
}
// Default to the CmdletProviderContext that will direct output to
// the pipeline.
CmdletProviderContext currentCommandContext = currentContext;
currentCommandContext.PassThru = PassThru;
tracer.WriteLine("Moving {0} to {1}", path, Destination);
try
{
// Now do the move
string escapedPath = path;
if (!base.SuppressWildcardExpansion) { escapedPath = WildcardPattern.Escape(path); }
InvokeProvider.Item.Move(escapedPath, Destination, currentCommandContext);
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
continue;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
continue;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
continue;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
continue;
return;
}
}
while (false);
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
return;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
return;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
return;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
return;
}
// See if the item to be moved is in use.
bool isCurrentLocationOrAncestor = false;
try
{
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(path, currentContext);
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
return;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
return;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
return;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
return;
}
if (isCurrentLocationOrAncestor)
{
PSInvalidOperationException invalidOperation =
(PSInvalidOperationException)
PSTraceSource.NewInvalidOperationException(
NavigationResources.MoveItemInUse,
path);
WriteError(
new ErrorRecord(
invalidOperation.ErrorRecord,
invalidOperation));
return;
}
// Default to the CmdletProviderContext that will direct output to
// the pipeline.
currentContext.PassThru = PassThru;
tracer.WriteLine("Moving {0} to {1}", path, Destination);
try
{
// Now do the move
InvokeProvider.Item.Move(path, Destination, currentContext);
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
return;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
return;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
return;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
return;
}
}
#endregion Command code
@@ -6,6 +6,10 @@ Describe "Move-Item tests" -Tag "CI" {
Setup -f originalfile.txt -content "This is content"
$source = "$TESTDRIVE/originalfile.txt"
$target = "$TESTDRIVE/ItemWhichHasBeenMoved.txt"
Setup -f [orig-file].txt -content "This is not content"
$sourceSp = "$TestDrive/``[orig-file``].txt"
$targetSpName = "$TestDrive/ItemWhichHasBeen[Moved].txt"
$targetSp = "$TestDrive/ItemWhichHasBeen``[Moved``].txt"
}
It "Move-Item will move a file" {
Move-Item $source $target
@@ -13,6 +17,12 @@ Describe "Move-Item tests" -Tag "CI" {
$target | Should -Exist
"$target" | Should -FileContentMatchExactly "This is content"
}
It "Move-Item will move a file when path contains special char" {
Move-Item $sourceSp $targetSpName
$sourceSp | Should -Not -Exist
$targetSp | Should -Exist
$targetSp | Should -FileContentMatchExactly "This is not content"
}
Context "Move-Item with filters" {
BeforeAll {