Skip to content

Commit

Permalink
Add the parameter -RelativeBasePath to Resolve-Path (PowerShell#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinGC94 committed Mar 22, 2023
1 parent 098be48 commit 48c9d68
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class ResolvePathCommand : CoreCommandWithCredentialsBase
/// </summary>
[Parameter(Position = 0, ParameterSetName = "Path",
Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0, ParameterSetName = "PathWithRelativeBase",
Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
public string[] Path
{
get
Expand All @@ -40,6 +42,8 @@ public string[] Path
/// </summary>
[Parameter(ParameterSetName = "LiteralPath",
Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = "LiteralPathWithRelativeBase",
Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)]
[Alias("PSPath", "LP")]
public string[] LiteralPath
{
Expand All @@ -59,7 +63,8 @@ public string[] LiteralPath
/// Gets or sets the value that determines if the resolved path should
/// be resolved to its relative version.
/// </summary>
[Parameter()]
[Parameter(ParameterSetName = "Path")]
[Parameter(ParameterSetName = "LiteralPath")]
public SwitchParameter Relative
{
get
Expand All @@ -75,6 +80,25 @@ public SwitchParameter Relative

private SwitchParameter _relative;

/// <summary>
/// Gets or sets the path the resolved relative path should be based off.
/// </summary>
[Parameter(Mandatory = true, ParameterSetName = "PathWithRelativeBase")]
[Parameter(Mandatory = true, ParameterSetName = "LiteralPathWithRelativeBase")]
public string RelativeBasePath
{
get
{
return _relativeBasePath;
}

set
{
_relative = true;
_relativeBasePath = value;
}
}

#endregion Parameters

#region parameter data
Expand All @@ -84,10 +108,68 @@ public SwitchParameter Relative
/// </summary>
private string[] _paths;

private PSDriveInfo _relativeDrive;
private string _relativeBasePath;

#endregion parameter data

#region Command code

/// <summary>
/// Finds the path and drive that should be used for relative path resolution
/// represents.
/// </summary>
protected override void BeginProcessing()
{
if (_relative)
{
if (!string.IsNullOrEmpty(RelativeBasePath))
{
try
{
_relativeBasePath = SessionState.Internal.Globber.GetProviderPath(RelativeBasePath, CmdletProviderContext, out _, out _relativeDrive);
}
catch (ProviderNotFoundException providerNotFound)
{
ThrowTerminatingError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
}
catch (DriveNotFoundException driveNotFound)
{
ThrowTerminatingError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
}
catch (ProviderInvocationException providerInvocation)
{
ThrowTerminatingError(
new ErrorRecord(
providerInvocation.ErrorRecord,
providerInvocation));
}
catch (NotSupportedException notSupported)
{
ThrowTerminatingError(
new ErrorRecord(notSupported, "ProviderIsNotNavigationCmdletProvider", ErrorCategory.InvalidArgument, RelativeBasePath));
}
catch (InvalidOperationException invalidOperation)
{
ThrowTerminatingError(
new ErrorRecord(invalidOperation, "InvalidHomeLocation", ErrorCategory.InvalidOperation, RelativeBasePath));
}

return;
}

_relativeDrive = SessionState.Path.CurrentLocation.Drive;
_relativeBasePath = SessionState.Path.CurrentLocation.ProviderPath;
return;
}
}

/// <summary>
/// Resolves the path containing glob characters to the PowerShell paths that it
/// represents.
Expand All @@ -109,10 +191,9 @@ protected override void ProcessRecord()
{
// When result path and base path is on different PSDrive
// (../)*path should not go beyond the root of base path
if (currentPath.Drive != SessionState.Path.CurrentLocation.Drive &&
SessionState.Path.CurrentLocation.Drive != null &&
!currentPath.ProviderPath.StartsWith(
SessionState.Path.CurrentLocation.Drive.Root, StringComparison.OrdinalIgnoreCase))
if (currentPath.Drive != _relativeDrive &&
_relativeDrive != null &&
!currentPath.ProviderPath.StartsWith(_relativeDrive.Root, StringComparison.OrdinalIgnoreCase))
{
WriteObject(currentPath.Path, enumerateCollection: false);
continue;
Expand All @@ -127,8 +208,7 @@ protected override void ProcessRecord()
}

baseCache = basePath;
string adjustedPath = SessionState.Path.NormalizeRelativePath(currentPath.Path,
SessionState.Path.CurrentLocation.ProviderPath);
string adjustedPath = SessionState.Path.NormalizeRelativePath(currentPath.Path, _relativeBasePath);

// Do not insert './' if result path is not relative
if (!adjustedPath.StartsWith(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ Describe "Resolve-Path returns proper path" -Tag "CI" {
Pop-Location
}
}
It 'Resolve-Path should support user specified base paths' {
$Expected = Join-Path -Path .\ -ChildPath fakeroot
Resolve-Path -Path $fakeRoot -RelativeBasePath $testRoot | Should -BeExactly $Expected
}
}

0 comments on commit 48c9d68

Please sign in to comment.