mirror of
https://github.com/PowerShell/PowerShell.git
synced 2025-01-07 17:03:34 +08:00
Removing Hardlink from Mode property in default file system format (#8789)
This commit is contained in:
parent
1e49d09d29
commit
9983297254
@ -42,28 +42,33 @@ namespace System.Management.Automation.Runspaces
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_FileSystemTypes(CustomControl[] sharedControls)
|
||||
{
|
||||
const string LengthScriptBlock =
|
||||
@"if ($_ -is [System.IO.DirectoryInfo]) { return '' }
|
||||
if ($_.Attributes -band [System.IO.FileAttributes]::Offline)
|
||||
{
|
||||
return '({0})' -f $_.Length
|
||||
}
|
||||
return $_.Length";
|
||||
|
||||
yield return new FormatViewDefinition("children",
|
||||
TableControl.Create()
|
||||
.GroupByProperty("PSParentPath", customControl: sharedControls[0])
|
||||
.AddHeader(Alignment.Left, label: "Mode", width: 7)
|
||||
.AddHeader(Alignment.Right, label: "LastWriteTime", width: 25)
|
||||
.AddHeader(Alignment.Right, label: "Length", width: 14)
|
||||
.AddHeader()
|
||||
.AddHeader(Alignment.Left, label: "Name")
|
||||
.StartRowDefinition(wrap: true)
|
||||
.AddPropertyColumn("ModeWithoutHardLink")
|
||||
.AddPropertyColumn("LastWriteTimeString")
|
||||
.AddPropertyColumn("LengthString")
|
||||
.AddPropertyColumn("NameString")
|
||||
.EndRowDefinition()
|
||||
.EndTable());
|
||||
|
||||
yield return new FormatViewDefinition("childrenWithHardlink",
|
||||
TableControl.Create()
|
||||
.GroupByProperty("PSParentPath", customControl: sharedControls[0])
|
||||
.AddHeader(Alignment.Left, label: "Mode", width: 7)
|
||||
.AddHeader(Alignment.Right, label: "LastWriteTime", width: 25)
|
||||
.AddHeader(Alignment.Right, label: "Length", width: 14)
|
||||
.AddHeader(Alignment.Left, label: "Name")
|
||||
.StartRowDefinition(wrap: true)
|
||||
.AddPropertyColumn("Mode")
|
||||
.AddScriptBlockColumn(@"
|
||||
[String]::Format(""{0,10} {1,8}"", $_.LastWriteTime.ToString(""d""), $_.LastWriteTime.ToString(""t""))
|
||||
")
|
||||
.AddScriptBlockColumn(LengthScriptBlock)
|
||||
.AddPropertyColumn("Name")
|
||||
.AddPropertyColumn("LastWriteTimeString")
|
||||
.AddPropertyColumn("LengthString")
|
||||
.AddPropertyColumn("NameString")
|
||||
.EndRowDefinition()
|
||||
.EndTable());
|
||||
|
||||
@ -72,7 +77,7 @@ return $_.Length";
|
||||
.GroupByProperty("PSParentPath", customControl: sharedControls[0])
|
||||
.StartEntry(entrySelectedByType: new[] { "System.IO.FileInfo" })
|
||||
.AddItemProperty(@"Name")
|
||||
.AddItemScriptBlock(LengthScriptBlock, label: "Length")
|
||||
.AddItemProperty("LengthString", label: "Length")
|
||||
.AddItemProperty(@"CreationTime")
|
||||
.AddItemProperty(@"LastWriteTime")
|
||||
.AddItemProperty(@"LastAccessTime")
|
||||
|
@ -183,18 +183,28 @@ namespace System.Management.Automation.Runspaces
|
||||
var td19 = new TypeData(@"System.IO.DirectoryInfo", true);
|
||||
td19.Members.Add("Mode",
|
||||
new CodePropertyData("Mode", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "Mode"), null));
|
||||
td19.Members.Add("ModeWithoutHardLink",
|
||||
new CodePropertyData("ModeWithoutHardLink", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "ModeWithoutHardLink"), null));
|
||||
td19.Members.Add("BaseName",
|
||||
new ScriptPropertyData(@"BaseName", GetScriptBlock(@"$this.Name"), null));
|
||||
td19.Members.Add("Target",
|
||||
new CodePropertyData("Target", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetTarget"), null));
|
||||
td19.Members.Add("LinkType",
|
||||
new CodePropertyData("LinkType", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetLinkType"), null));
|
||||
td19.Members.Add("NameString",
|
||||
new CodePropertyData("NameString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "NameString"), null) { IsHidden = true });
|
||||
td19.Members.Add("LengthString",
|
||||
new CodePropertyData("LengthString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LengthString"), null) { IsHidden = true });
|
||||
td19.Members.Add("LastWriteTimeString",
|
||||
new CodePropertyData("LastWriteTimeString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LastWriteTimeString"), null) { IsHidden = true });
|
||||
td19.DefaultDisplayProperty = @"Name";
|
||||
yield return td19;
|
||||
|
||||
var td20 = new TypeData(@"System.IO.FileInfo", true);
|
||||
td20.Members.Add("Mode",
|
||||
new CodePropertyData("Mode", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "Mode"), null));
|
||||
td20.Members.Add("ModeWithoutHardLink",
|
||||
new CodePropertyData("ModeWithoutHardLink", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "ModeWithoutHardLink"), null));
|
||||
td20.Members.Add("VersionInfo",
|
||||
new ScriptPropertyData(@"VersionInfo", GetScriptBlock(@"[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName)"), null));
|
||||
td20.Members.Add("BaseName",
|
||||
@ -203,6 +213,12 @@ namespace System.Management.Automation.Runspaces
|
||||
new CodePropertyData("Target", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetTarget"), null));
|
||||
td20.Members.Add("LinkType",
|
||||
new CodePropertyData("LinkType", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetLinkType"), null));
|
||||
td20.Members.Add("NameString",
|
||||
new CodePropertyData("NameString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "NameString"), null) { IsHidden = true });
|
||||
td20.Members.Add("LengthString",
|
||||
new CodePropertyData("LengthString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LengthString"), null) { IsHidden = true });
|
||||
td20.Members.Add("LastWriteTimeString",
|
||||
new CodePropertyData("LastWriteTimeString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LastWriteTimeString"), null) { IsHidden = true });
|
||||
td20.DefaultDisplayPropertySet =
|
||||
new PropertySetData(new[] { "LastWriteTime", "Length", "Name" }) { Name = "DefaultDisplayPropertySet" };
|
||||
yield return td20;
|
||||
|
@ -1867,33 +1867,99 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// Provides a mode property for FileSystemInfo.
|
||||
/// </summary>
|
||||
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
|
||||
/// <returns>A string representation of the FileAttributes, with one letter per attribute.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
|
||||
public static string Mode(PSObject instance)
|
||||
public static string Mode(PSObject instance) => Mode(instance, excludeHardLink: false);
|
||||
|
||||
/// <summary>
|
||||
/// Provides a ModeWithoutHardLink property for FileSystemInfo, without HardLinks for performance reasons.
|
||||
/// </summary>
|
||||
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
|
||||
/// <returns>A string representation of the FileAttributes, with one letter per attribute.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
|
||||
public static string ModeWithoutHardLink(PSObject instance) => Mode(instance, excludeHardLink: true);
|
||||
|
||||
private static string Mode(PSObject instance, bool excludeHardLink)
|
||||
{
|
||||
if (instance == null)
|
||||
string ToModeString(FileSystemInfo fileSystemInfo)
|
||||
{
|
||||
return string.Empty;
|
||||
FileAttributes fileAttributes = fileSystemInfo.Attributes;
|
||||
|
||||
bool isReparsePoint = InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileSystemInfo);
|
||||
bool isLink = isReparsePoint || (excludeHardLink ? false : InternalSymbolicLinkLinkCodeMethods.IsHardLink(fileSystemInfo));
|
||||
if (!isLink)
|
||||
{
|
||||
// special casing for the common cases - no allocations
|
||||
switch (fileAttributes)
|
||||
{
|
||||
case FileAttributes.Archive:
|
||||
return "-a---";
|
||||
case FileAttributes.Directory:
|
||||
return "d----";
|
||||
case FileAttributes.Normal:
|
||||
return "-----";
|
||||
case FileAttributes.Directory | FileAttributes.ReadOnly:
|
||||
return "d-r--";
|
||||
case FileAttributes.Archive | FileAttributes.ReadOnly:
|
||||
return "-ar--";
|
||||
}
|
||||
}
|
||||
|
||||
bool isDirectory = fileAttributes.HasFlag(FileAttributes.Directory);
|
||||
ReadOnlySpan<char> mode = stackalloc char[]
|
||||
{
|
||||
isLink ? 'l' : isDirectory ? 'd' : '-',
|
||||
fileAttributes.HasFlag(FileAttributes.Archive) ? 'a' : '-',
|
||||
fileAttributes.HasFlag(FileAttributes.ReadOnly) ? 'r' : '-',
|
||||
fileAttributes.HasFlag(FileAttributes.Hidden) ? 'h' : '-',
|
||||
fileAttributes.HasFlag(FileAttributes.System) ? 's' : '-',
|
||||
};
|
||||
return new string(mode);
|
||||
}
|
||||
|
||||
FileSystemInfo fileInfo = (FileSystemInfo)instance.BaseObject;
|
||||
if (fileInfo == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
return instance?.BaseObject is FileSystemInfo fileInfo
|
||||
? ToModeString(fileInfo)
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
char[] mode = new char[6];
|
||||
mode[0] = (fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory ? 'd' : '-';
|
||||
mode[1] = (fileInfo.Attributes & FileAttributes.Archive) == FileAttributes.Archive ? 'a' : '-';
|
||||
mode[2] = (fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? 'r' : '-';
|
||||
mode[3] = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ? 'h' : '-';
|
||||
mode[4] = (fileInfo.Attributes & FileAttributes.System) == FileAttributes.System ? 's' : '-';
|
||||
// Mark the last bit as a "l" if it's a reparsepoint (symbolic link or junction)
|
||||
// Porting note: these need to be handled specially
|
||||
bool isReparsePoint = InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileInfo);
|
||||
bool isHardLink = InternalSymbolicLinkLinkCodeMethods.IsHardLink(fileInfo);
|
||||
mode[5] = isReparsePoint || isHardLink ? 'l' : '-';
|
||||
/// <summary>
|
||||
/// Provides a NameString property for FileSystemInfo.
|
||||
/// </summary>
|
||||
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
|
||||
/// <returns>Name if a file or directory, Name -> Target if symlink.</returns>
|
||||
public static string NameString(PSObject instance)
|
||||
{
|
||||
return instance?.BaseObject is FileSystemInfo fileInfo
|
||||
? InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileInfo)
|
||||
? $"{fileInfo.Name} -> {InternalSymbolicLinkLinkCodeMethods.GetTarget(instance)}"
|
||||
: fileInfo.Name
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
return new string(mode);
|
||||
/// <summary>
|
||||
/// Provides a LengthString property for FileSystemInfo.
|
||||
/// </summary>
|
||||
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
|
||||
/// <returns>Length as a string.</returns>
|
||||
public static string LengthString(PSObject instance)
|
||||
{
|
||||
return instance?.BaseObject is FileInfo fileInfo
|
||||
? fileInfo.Attributes.HasFlag(FileAttributes.Offline)
|
||||
? $"({fileInfo.Length})"
|
||||
: fileInfo.Length.ToString()
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a LastWriteTimeString property for FileSystemInfo.
|
||||
/// </summary>
|
||||
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
|
||||
/// <returns>LastWriteTime formatted as short date + short time.</returns>
|
||||
public static string LastWriteTimeString(PSObject instance)
|
||||
{
|
||||
return instance?.BaseObject is FileSystemInfo fileInfo
|
||||
? string.Format(CultureInfo.CurrentCulture, "{0,10:d} {0,8:t}", fileInfo.LastWriteTime)
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
#region RenameItem
|
||||
@ -2481,8 +2547,8 @@ namespace Microsoft.PowerShell.Commands
|
||||
flags |= NativeMethods.SymbolicLinkFlags.AllowUnprivilegedCreate;
|
||||
}
|
||||
|
||||
int created = NativeMethods.CreateSymbolicLink(path, strTargetPath, flags);
|
||||
return (created == 1) ? true : false;
|
||||
var created = NativeMethods.CreateSymbolicLink(path, strTargetPath, flags);
|
||||
return created;
|
||||
}
|
||||
|
||||
private static bool WinCreateHardLink(string path, string strTargetPath)
|
||||
@ -7013,7 +7079,8 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// <param name="symbolicLinkFlags">Flag values from SymbolicLinkFlags enum.</param>
|
||||
/// <returns>1 on successful creation.</returns>
|
||||
[DllImport(PinvokeDllNames.CreateSymbolicLinkDllName, CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern int CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags);
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
internal static extern bool CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags);
|
||||
|
||||
/// <summary>
|
||||
/// Flags used when creating a symbolic link.
|
||||
@ -7034,7 +7101,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// <summary>
|
||||
/// Allow creation of symbolic link without elevation. Requires Developer mode.
|
||||
/// </summary>
|
||||
AllowUnprivilegedCreate = 2
|
||||
AllowUnprivilegedCreate = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -7709,7 +7776,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// </summary>
|
||||
/// <param name="instance">The object of FileInfo or DirectoryInfo type.</param>
|
||||
/// <returns>The target of the reparse point.</returns>
|
||||
public static IEnumerable<string> GetTarget(PSObject instance)
|
||||
public static string GetTarget(PSObject instance)
|
||||
{
|
||||
if (instance.BaseObject is FileSystemInfo fileSysInfo)
|
||||
{
|
||||
@ -7718,13 +7785,11 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
string linkTarget = WinInternalGetTarget(handle);
|
||||
|
||||
if (linkTarget != null)
|
||||
{
|
||||
return (new string[] { linkTarget });
|
||||
}
|
||||
return linkTarget;
|
||||
}
|
||||
#else
|
||||
return UnixInternalGetTarget(fileSysInfo.FullName);
|
||||
#endif
|
||||
return InternalGetTarget(fileSysInfo.FullName);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -7743,84 +7808,23 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
return InternalGetLinkType(fileSysInfo);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<string> InternalGetTarget(string filePath)
|
||||
{
|
||||
var links = new List<string>();
|
||||
#if UNIX
|
||||
private static string UnixInternalGetTarget(string filePath)
|
||||
{
|
||||
string link = Platform.NonWindowsInternalGetTarget(filePath);
|
||||
if (!string.IsNullOrEmpty(link))
|
||||
{
|
||||
links.Add(link);
|
||||
}
|
||||
else
|
||||
|
||||
if (string.IsNullOrEmpty(link))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
#elif !CORECLR // FindFirstFileName, FindNextFileName and FindClose are not available on Core Clr
|
||||
UInt32 linkStringLength = 0;
|
||||
var linkName = new StringBuilder();
|
||||
|
||||
// First get the length for the linkName buffer.
|
||||
IntPtr fileHandle = InternalSymbolicLinkLinkCodeMethods.FindFirstFileName(filePath, 0, ref linkStringLength, linkName);
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
|
||||
// Return handle is INVALID_HANDLE_VALUE and LastError was ERROR_MORE_DATA
|
||||
if ((fileHandle == (IntPtr)(-1)) && (lastError == 234))
|
||||
{
|
||||
linkName = new StringBuilder((int)linkStringLength);
|
||||
fileHandle = InternalSymbolicLinkLinkCodeMethods.FindFirstFileName(filePath, 0, ref linkStringLength, linkName);
|
||||
lastError = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
if (fileHandle == (IntPtr)(-1))
|
||||
{
|
||||
throw new Win32Exception(lastError);
|
||||
}
|
||||
|
||||
bool continueFind = false;
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
StringBuilder fullName = new StringBuilder();
|
||||
fullName.Append(Path.GetPathRoot(filePath)); // hard link source and target must be on the same drive. So we can use the source for find the path root.
|
||||
fullName.Append(linkName.ToString());
|
||||
FileInfo fInfo = new FileInfo(fullName.ToString());
|
||||
|
||||
// Don't add the target link to the list.
|
||||
if (string.Compare(fInfo.FullName, filePath, StringComparison.OrdinalIgnoreCase) != 0)
|
||||
links.Add(fInfo.FullName);
|
||||
|
||||
continueFind = InternalSymbolicLinkLinkCodeMethods.FindNextFileName(fileHandle, ref linkStringLength, linkName);
|
||||
|
||||
lastError = Marshal.GetLastWin32Error();
|
||||
|
||||
if (!continueFind && lastError == 234) // ERROR_MORE_DATA
|
||||
{
|
||||
linkName = new StringBuilder((int)linkStringLength);
|
||||
continueFind = InternalSymbolicLinkLinkCodeMethods.FindNextFileName(fileHandle, ref linkStringLength, linkName);
|
||||
}
|
||||
|
||||
if (!continueFind && lastError != 38) // ERROR_HANDLE_EOF. No more links.
|
||||
{
|
||||
throw new Win32Exception(lastError);
|
||||
}
|
||||
}
|
||||
while (continueFind);
|
||||
}
|
||||
finally
|
||||
{
|
||||
InternalSymbolicLinkLinkCodeMethods.FindClose(fileHandle);
|
||||
}
|
||||
#endif
|
||||
return links;
|
||||
return link;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static string InternalGetLinkType(FileSystemInfo fileInfo)
|
||||
{
|
||||
@ -7909,16 +7913,9 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
internal static bool IsReparsePoint(FileSystemInfo fileInfo)
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
{
|
||||
// Note that this class also has a enum called FileAttributes, so use fully qualified name
|
||||
return (fileInfo.Attributes & System.IO.FileAttributes.ReparsePoint)
|
||||
== System.IO.FileAttributes.ReparsePoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Platform.NonWindowsIsSymLink(fileInfo);
|
||||
}
|
||||
return Platform.IsWindows
|
||||
? fileInfo.Attributes.HasFlag(System.IO.FileAttributes.ReparsePoint)
|
||||
: Platform.NonWindowsIsSymLink(fileInfo);
|
||||
}
|
||||
|
||||
internal static bool WinIsHardLink(FileSystemInfo fileInfo)
|
||||
|
@ -10,5 +10,10 @@
|
||||
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(IsWindows)' != 'true' ">
|
||||
<DefineConstants>$(DefineConstants);UNIX</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
@ -190,3 +190,51 @@ Describe "Get-ChildItem" -Tags "CI" {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'FileSystem Provider Formatting' -Tag "CI","RequireAdminOnWindows" {
|
||||
|
||||
BeforeAll {
|
||||
$modeTestDir = New-Item -Path "$TestDrive/testmodedirectory" -ItemType Directory -Force
|
||||
$targetFile1 = New-Item -Path "$TestDrive/targetFile1" -ItemType File -Force
|
||||
$targetFile2 = New-Item -Path "$TestDrive/targetFile2" -ItemType File -Force
|
||||
$targetDir1 = New-Item -Path "$TestDrive/targetDir1" -ItemType Directory -Force
|
||||
$targetDir2 = New-Item -Path "$TestDrive/targetDir2" -ItemType Directory -Force
|
||||
|
||||
$testcases = @(
|
||||
@{ expectedMode = "d----"; expectedModeWithoutHardlink = "d----"; itemType = "Directory"; itemName = "Directory"; fileAttributes = [System.IO.FileAttributes] "Directory"; target = $null }
|
||||
@{ expectedMode = "l----"; expectedModeWithoutHardlink = "l----"; itemType = "SymbolicLink"; itemName = "SymbolicLink-Directory"; fileAttributes = [System.IO.FileAttributes]::Directory -bor [System.IO.FileAttributes]::ReparsePoint; target = $targetDir2.FullName }
|
||||
)
|
||||
|
||||
if ($IsWindows)
|
||||
{
|
||||
$testcases += @{ expectedMode = "l----"; expectedModeWithoutHardlink = "l----"; itemType = "Junction"; itemName = "Junction-Directory"; fileAttributes = [System.IO.FileAttributes]::Directory -bor [System.IO.FileAttributes]::ReparsePoint; target = $targetDir1.FullName }
|
||||
$testcases += @{ expectedMode = "-a---"; expectedModeWithoutHardlink = "-a---"; itemType = "File"; itemName = "ArchiveFile"; fileAttributes = [System.IO.FileAttributes] "Archive"; target = $null }
|
||||
$testcases += @{ expectedMode = "la---"; expectedModeWithoutHardlink = "la---"; itemType = "SymbolicLink"; itemName = "SymbolicLink-File"; fileAttributes = [System.IO.FileAttributes]::Archive -bor [System.IO.FileAttributes]::ReparsePoint; target = $targetFile1.FullName }
|
||||
$testcases += @{ expectedMode = "la---"; expectedModeWithoutHardlink = "-a---"; itemType = "HardLink"; itemName = "HardLink"; fileAttributes = [System.IO.FileAttributes] "Archive"; target = $targetFile2.FullName }
|
||||
}
|
||||
}
|
||||
|
||||
It 'Validate Mode property - <itemName>' -TestCases $testcases {
|
||||
|
||||
param($expectedMode, $expectedModeWithoutHardlink, $itemType, $itemName, $fileAttributes, $target)
|
||||
|
||||
$item = if ($target)
|
||||
{
|
||||
New-Item -Path $modeTestDir -Name $itemName -ItemType $itemType -Target $target
|
||||
}
|
||||
else
|
||||
{
|
||||
New-Item -Path $modeTestDir -Name $itemName -ItemType $itemType
|
||||
}
|
||||
|
||||
$item | Should -BeOfType "System.IO.FileSystemInfo"
|
||||
|
||||
$actualMode = [Microsoft.PowerShell.Commands.FileSystemProvider]::Mode($item)
|
||||
$actualMode | Should -BeExactly $expectedMode
|
||||
|
||||
$actualModeWithoutHardlink = [Microsoft.PowerShell.Commands.FileSystemProvider]::ModeWithoutHardlink($item)
|
||||
$actualModeWithoutHardlink | Should -BeExactly $expectedModeWithoutHardlink
|
||||
|
||||
$item.Attributes | Should -Be $fileAttributes
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ Describe "Get-FormatData" -Tags "CI" {
|
||||
$format.TypeNames | Should -HaveCount 2
|
||||
$format.TypeNames[0] | Should -BeExactly "System.IO.DirectoryInfo"
|
||||
$format.TypeNames[1] | Should -BeExactly "System.IO.FileInfo"
|
||||
$format.FormatViewDefinition | Should -HaveCount 3
|
||||
$format.FormatViewDefinition | Should -HaveCount 4
|
||||
}
|
||||
|
||||
It "Should return nothing for format data requiring '-PowerShellVersion 5.1' and not provided" {
|
||||
|
@ -418,7 +418,7 @@ Describe "Type inference Tests" -tags "CI" {
|
||||
It "Infers typeof Select-Object when Parameter is ExcludeProperty" {
|
||||
$res = [AstTypeInference]::InferTypeOf( { [io.fileinfo]::new("file") | Select-Object -ExcludeProperty *Time*, E* }.Ast)
|
||||
$res.Count | Should -Be 1
|
||||
$res[0].Name | Should -Be "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LinkType:Mode:Name:Target:VersionInfo"
|
||||
$res[0].Name | Should -BeExactly "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LengthString:LinkType:Mode:ModeWithoutHardLink:Name:NameString:Target:VersionInfo"
|
||||
$names = $res[0].Members.Name
|
||||
$names -contains "BaseName" | Should -BeTrue
|
||||
$names -contains "Name" | Should -BeTrue
|
||||
|
@ -14,6 +14,8 @@ using System.Management.Automation.Internal.Host;
|
||||
using System.Management.Automation.Provider;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.PowerShell;
|
||||
using Microsoft.PowerShell.Commands;
|
||||
using Xunit;
|
||||
@ -107,9 +109,9 @@ namespace PSTests.Parallel
|
||||
executableObject = new FileInfo(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
|
||||
}
|
||||
|
||||
Assert.Equal("d-----", FileSystemProvider.Mode(PSObject.AsPSObject(directoryObject)).Replace("r", "-"));
|
||||
Assert.Equal("------", FileSystemProvider.Mode(PSObject.AsPSObject(fileObject)).Replace("r", "-").Replace("a", "-"));
|
||||
Assert.Equal("------", FileSystemProvider.Mode(PSObject.AsPSObject(executableObject)).Replace("r", "-").Replace("a", "-"));
|
||||
Assert.Equal("d----", FileSystemProvider.Mode(PSObject.AsPSObject(directoryObject)).Replace("r", "-"));
|
||||
Assert.Equal("-----", FileSystemProvider.Mode(PSObject.AsPSObject(fileObject)).Replace("r", "-").Replace("a", "-"));
|
||||
Assert.Equal("-----", FileSystemProvider.Mode(PSObject.AsPSObject(executableObject)).Replace("r", "-").Replace("a", "-"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -125,13 +127,8 @@ namespace PSTests.Parallel
|
||||
fileSystemProvider.GetProperty(testPath, new Collection<string>(){ "IsReadOnly" });
|
||||
FileInfo fileSystemObject1 = new FileInfo(testPath);
|
||||
PSObject psobject1 = PSObject.AsPSObject(fileSystemObject1);
|
||||
foreach (PSPropertyInfo property in psobject1.Properties)
|
||||
{
|
||||
if (property.Name == "IsReadOnly")
|
||||
{
|
||||
Assert.False((bool)property.Value);
|
||||
}
|
||||
}
|
||||
PSPropertyInfo property = psobject1.Properties["IsReadOnly"];
|
||||
Assert.False((bool)property.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -144,13 +141,9 @@ namespace PSTests.Parallel
|
||||
fileSystemProvider.GetProperty(testPath, new Collection<string>(){ "Name" });
|
||||
FileInfo fileSystemObject1 = new FileInfo(testPath);
|
||||
PSObject psobject1 = PSObject.AsPSObject(fileSystemObject1);
|
||||
foreach (PSPropertyInfo property in psobject1.Properties)
|
||||
{
|
||||
if (property.Name == "FullName")
|
||||
{
|
||||
Assert.Equal(testPath, property.Value);
|
||||
}
|
||||
}
|
||||
PSPropertyInfo property = psobject1.Properties["FullName"];
|
||||
|
||||
Assert.Equal(testPath, property.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
Loading…
Reference in New Issue
Block a user