From 6eebd3a5245e9ec94f8daa2a11255fca4b7b3eb3 Mon Sep 17 00:00:00 2001 From: Santiago Squarzon Date: Tue, 3 Sep 2024 12:53:33 -0300 Subject: [PATCH 1/6] makes Depth public. adds logic for child item and total child item count. --- src/PSTree/Commands/GetPSTreeCommand.cs | 10 +++++----- src/PSTree/PSTreeDirectory.cs | 15 +++++++++++++-- src/PSTree/PSTreeFileSystemInfo.cs | 2 +- src/PSTree/PSTreeIndexer.cs | 23 +++++++++++++++++++---- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/PSTree/Commands/GetPSTreeCommand.cs b/src/PSTree/Commands/GetPSTreeCommand.cs index c1b44c3..953978d 100644 --- a/src/PSTree/Commands/GetPSTreeCommand.cs +++ b/src/PSTree/Commands/GetPSTreeCommand.cs @@ -143,18 +143,17 @@ private PSTreeFileSystemInfo[] Traverse( while (_stack.Count > 0) { - IOrderedEnumerable enumerator; PSTreeDirectory next = _stack.Pop(); int level = next.Depth + 1; long size = 0; + int childCount = 0; try { - enumerator = next.GetSortedEnumerable(_comparer); bool keepProcessing = level <= Depth; - - foreach (FileSystemInfo item in enumerator) + foreach (FileSystemInfo item in next.GetSortedEnumerable(_comparer)) { + childCount++; if (!Force.IsPresent && item.IsHidden()) { continue; @@ -190,10 +189,11 @@ private PSTreeFileSystemInfo[] Traverse( } next.Length = size; + _indexer.IndexItemCount(next, childCount); if (RecursiveSize.IsPresent) { - _indexer.Index(next, size); + _indexer.IndexLength(next, size); } if (next.Depth <= Depth) diff --git a/src/PSTree/PSTreeDirectory.cs b/src/PSTree/PSTreeDirectory.cs index c1cbf08..5561ad4 100644 --- a/src/PSTree/PSTreeDirectory.cs +++ b/src/PSTree/PSTreeDirectory.cs @@ -6,8 +6,16 @@ namespace PSTree; public sealed class PSTreeDirectory : PSTreeFileSystemInfo { + private string[]? _parents; + public DirectoryInfo Parent => Instance.Parent; + public int ItemCount { get; internal set; } + + public int RecursiveItemCount { get; internal set; } + + internal string[] Parents { get => _parents ??= GetParents(); } + internal PSTreeDirectory(DirectoryInfo directoryInfo, int depth, string source) : base(directoryInfo, depth, source) { } @@ -25,15 +33,18 @@ public IEnumerable EnumerateDirectories() => public IEnumerable EnumerateFileSystemInfos() => Instance.EnumerateFileSystemInfos(); - public IEnumerable GetParents() + public string[] GetParents() { int index = -1; string path = Instance.FullName; + List parents = []; while ((index = path.IndexOf(Path.DirectorySeparatorChar, index + 1)) != -1) { - yield return path.Substring(0, index); + parents.Add(path.Substring(0, index)); } + + return [.. parents]; } internal IOrderedEnumerable GetSortedEnumerable(PSTreeComparer comparer) => diff --git a/src/PSTree/PSTreeFileSystemInfo.cs b/src/PSTree/PSTreeFileSystemInfo.cs index 43df42b..10f7376 100644 --- a/src/PSTree/PSTreeFileSystemInfo.cs +++ b/src/PSTree/PSTreeFileSystemInfo.cs @@ -4,7 +4,7 @@ public abstract class PSTreeFileSystemInfo(string hierarchy, string source) { internal string Source { get; set; } = source; - internal int Depth { get; set; } + public int Depth { get; set; } public string Hierarchy { get; internal set; } = hierarchy; diff --git a/src/PSTree/PSTreeIndexer.cs b/src/PSTree/PSTreeIndexer.cs index 02a1a74..56a2474 100644 --- a/src/PSTree/PSTreeIndexer.cs +++ b/src/PSTree/PSTreeIndexer.cs @@ -7,15 +7,30 @@ internal sealed class PSTreeIndexer { private readonly Dictionary _indexer = []; - internal void Index(PSTreeDirectory directory, long length) + internal void IndexLength(PSTreeDirectory directory, long length) { _indexer[directory.FullName.TrimEnd(Path.DirectorySeparatorChar)] = directory; - foreach (string parent in directory.GetParents()) + foreach (string parent in directory.Parents) { - if (_indexer.ContainsKey(parent)) + if (_indexer.TryGetValue(parent, out PSTreeDirectory paretDir)) { - _indexer[parent].Length += length; + paretDir.Length += length; + } + } + } + + internal void IndexItemCount(PSTreeDirectory directory, int count) + { + directory.ItemCount = count; + directory.RecursiveItemCount = count; + _indexer[directory.FullName.TrimEnd(Path.DirectorySeparatorChar)] = directory; + + foreach (string parent in directory.Parents) + { + if (_indexer.TryGetValue(parent, out PSTreeDirectory parentDir)) + { + parentDir.RecursiveItemCount += count; } } } From 0a39787168c7042361d1a22fbd34eceec82202c1 Mon Sep 17 00:00:00 2001 From: Santiago Squarzon Date: Tue, 3 Sep 2024 13:00:32 -0300 Subject: [PATCH 2/6] fixing pester test --- tests/GetPSTreeCommand.tests.ps1 | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/GetPSTreeCommand.tests.ps1 b/tests/GetPSTreeCommand.tests.ps1 index 4b7bd5b..27d69af 100644 --- a/tests/GetPSTreeCommand.tests.ps1 +++ b/tests/GetPSTreeCommand.tests.ps1 @@ -95,19 +95,14 @@ Describe 'Get-PSTree' { Should -BeIn ([PSTree.PSTreeFile], [PSTree.PSTreeDirectory]) } - It 'Excludes PSTressFile instances with -Directory' { + It 'Excludes PSTreeFile instances with -Directory' { Get-PSTree -LiteralPath $testPath -Directory | Should -BeOfType ([PSTree.PSTreeDirectory]) } It 'Controls recursion with -Depth parameter' { - $method = [PSTree.PSTreeFileSystemInfo].GetProperty( - 'Depth', - [System.Reflection.BindingFlags] 'NonPublic, Instance') - $tree = Get-PSTree $testPath -Depth 1 - - $tree | ForEach-Object { $method.GetValue($_) } | + $tree | ForEach-Object Depth | Should -Not -BeGreaterThan 2 $ref = (Get-ChildItem $testPath -Directory | Get-ChildItem).FullName From 170a8ed8a8fa399e2c995eb09f181868597b284b Mon Sep 17 00:00:00 2001 From: Santiago Squarzon Date: Tue, 3 Sep 2024 16:14:29 -0300 Subject: [PATCH 3/6] adding pester tests --- src/PSTree/Commands/GetPSTreeCommand.cs | 2 +- src/PSTree/PSTreeDirectory.cs | 9 ++++----- src/PSTree/PSTreeIndexer.cs | 4 ++-- tests/PSTreeDirectory.tests.ps1 | 14 ++++++++------ 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/PSTree/Commands/GetPSTreeCommand.cs b/src/PSTree/Commands/GetPSTreeCommand.cs index 953978d..83d96ec 100644 --- a/src/PSTree/Commands/GetPSTreeCommand.cs +++ b/src/PSTree/Commands/GetPSTreeCommand.cs @@ -9,7 +9,7 @@ namespace PSTree.Commands; [Cmdlet(VerbsCommon.Get, "PSTree", DefaultParameterSetName = "Path")] [OutputType(typeof(PSTreeDirectory), typeof(PSTreeFile))] [Alias("pstree")] -public sealed partial class GetPSTreeCommand : PSCmdlet +public sealed class GetPSTreeCommand : PSCmdlet { private bool _isLiteral; diff --git a/src/PSTree/PSTreeDirectory.cs b/src/PSTree/PSTreeDirectory.cs index 5561ad4..b4ad436 100644 --- a/src/PSTree/PSTreeDirectory.cs +++ b/src/PSTree/PSTreeDirectory.cs @@ -8,13 +8,13 @@ public sealed class PSTreeDirectory : PSTreeFileSystemInfo { private string[]? _parents; + internal string[] Parents { get => _parents ??= GetParents(FullName); } + public DirectoryInfo Parent => Instance.Parent; public int ItemCount { get; internal set; } - public int RecursiveItemCount { get; internal set; } - - internal string[] Parents { get => _parents ??= GetParents(); } + public int TotalItemCount { get; internal set; } internal PSTreeDirectory(DirectoryInfo directoryInfo, int depth, string source) : base(directoryInfo, depth, source) @@ -33,10 +33,9 @@ public IEnumerable EnumerateDirectories() => public IEnumerable EnumerateFileSystemInfos() => Instance.EnumerateFileSystemInfos(); - public string[] GetParents() + private static string[] GetParents(string path) { int index = -1; - string path = Instance.FullName; List parents = []; while ((index = path.IndexOf(Path.DirectorySeparatorChar, index + 1)) != -1) diff --git a/src/PSTree/PSTreeIndexer.cs b/src/PSTree/PSTreeIndexer.cs index 56a2474..912837a 100644 --- a/src/PSTree/PSTreeIndexer.cs +++ b/src/PSTree/PSTreeIndexer.cs @@ -23,14 +23,14 @@ internal void IndexLength(PSTreeDirectory directory, long length) internal void IndexItemCount(PSTreeDirectory directory, int count) { directory.ItemCount = count; - directory.RecursiveItemCount = count; + directory.TotalItemCount = count; _indexer[directory.FullName.TrimEnd(Path.DirectorySeparatorChar)] = directory; foreach (string parent in directory.Parents) { if (_indexer.TryGetValue(parent, out PSTreeDirectory parentDir)) { - parentDir.RecursiveItemCount += count; + parentDir.TotalItemCount += count; } } } diff --git a/tests/PSTreeDirectory.tests.ps1 b/tests/PSTreeDirectory.tests.ps1 index e648ecd..1cd0ccf 100644 --- a/tests/PSTreeDirectory.tests.ps1 +++ b/tests/PSTreeDirectory.tests.ps1 @@ -23,11 +23,13 @@ Describe 'PSTreeDirectory' { Should -BeIn ([System.IO.FileInfo], [System.IO.DirectoryInfo]) } - It 'Can enumerate its parent directories with .GetParents()' { - $treedir = $testPath | Get-PSTree -Depth 0 - $parent = $treedir.Parent - $parent | Should -BeOfType ([System.IO.DirectoryInfo]) - $paths = $parent.FullName.Split([System.IO.Path]::DirectorySeparatorChar) - $treedir.GetParents() | Should -HaveCount $paths.Count + It 'ItemCount gets the count of direct childs' { + $childCount = @(Get-ChildItem -Force $testPath).Count + (Get-PSTree $testPath -Depth 1 -Force)[0].ItemCount | Should -BeExactly $childCount + } + + It 'TotalItemCount gets the recursive count of childs' { + $childCount = @(Get-ChildItem -Force $testPath -Recurse).Count + (Get-PSTree $testPath -Recurse -Force)[0].TotalItemCount | Should -BeExactly $childCount } } From 6324c891a478222ba897446f48239330281c5bff Mon Sep 17 00:00:00 2001 From: Santiago Squarzon Date: Tue, 3 Sep 2024 16:24:53 -0300 Subject: [PATCH 4/6] adds pester test for .Parent --- tests/PSTreeDirectory.tests.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/PSTreeDirectory.tests.ps1 b/tests/PSTreeDirectory.tests.ps1 index 1cd0ccf..c3abe37 100644 --- a/tests/PSTreeDirectory.tests.ps1 +++ b/tests/PSTreeDirectory.tests.ps1 @@ -23,6 +23,10 @@ Describe 'PSTreeDirectory' { Should -BeIn ([System.IO.FileInfo], [System.IO.DirectoryInfo]) } + It '.Parent property gets the PSTreeDirectory Parent DirectoryInfo instance' { + (Get-PSTree $testPath -Depth 0).Parent | Should -BeOfType ([System.IO.DirectoryInfo]) + } + It 'ItemCount gets the count of direct childs' { $childCount = @(Get-ChildItem -Force $testPath).Count (Get-PSTree $testPath -Depth 1 -Force)[0].ItemCount | Should -BeExactly $childCount From 4c7c7783377f5887a5ab29085de71a8130d9192c Mon Sep 17 00:00:00 2001 From: Santiago Squarzon Date: Tue, 3 Sep 2024 16:39:26 -0300 Subject: [PATCH 5/6] make Depth setter internal --- src/PSTree/Internal/_FormattingInternals.cs | 3 +-- src/PSTree/PSTreeFileSystemInfo.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/PSTree/Internal/_FormattingInternals.cs b/src/PSTree/Internal/_FormattingInternals.cs index 1c04d7a..716cf0a 100644 --- a/src/PSTree/Internal/_FormattingInternals.cs +++ b/src/PSTree/Internal/_FormattingInternals.cs @@ -28,8 +28,7 @@ public static string GetFormattedDate(DateTime date) => string.Format(CultureInfo.CurrentCulture, "{0,10:d} {0,8:t}", date); [Hidden, EditorBrowsable(EditorBrowsableState.Never)] - public static string GetSource(PSTreeFileSystemInfo item) => - item.Source; + public static string GetSource(PSTreeFileSystemInfo item) => item.Source; [Hidden, EditorBrowsable(EditorBrowsableState.Never)] public static string GetFormattedLength(long length) diff --git a/src/PSTree/PSTreeFileSystemInfo.cs b/src/PSTree/PSTreeFileSystemInfo.cs index 10f7376..e279a44 100644 --- a/src/PSTree/PSTreeFileSystemInfo.cs +++ b/src/PSTree/PSTreeFileSystemInfo.cs @@ -4,7 +4,7 @@ public abstract class PSTreeFileSystemInfo(string hierarchy, string source) { internal string Source { get; set; } = source; - public int Depth { get; set; } + public int Depth { get; protected set; } public string Hierarchy { get; internal set; } = hierarchy; From 9eb485c35fc0ca89f222fc3e562de293e9797145 Mon Sep 17 00:00:00 2001 From: Santiago Squarzon Date: Tue, 3 Sep 2024 17:35:08 -0300 Subject: [PATCH 6/6] bump module version. update changelog. --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++++ module/PSTree.psd1 | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8319d89..a995173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,42 @@ # CHANGELOG +- __09/03/2024__ + - Makes `.Depth` property public for `PSTreeFileSystemInfo` instances. + - Makes `.GetParents()` method private, absolutely no reason to have it public. + - Added property `ItemCount` and `TotalItemCount` to `PSTreeDirectory` instances, requested in [__Issue #34__][2]. + + ```powershell + PS ..\PSTree> pstree -Recurse -Force -Directory | Select-Object Hierarchy, Depth, ItemCount, TotalItemCount -First 15 + + Hierarchy Depth ItemCount TotalItemCount + --------- ----- --------- -------------- + PSTree 0 15 1476 + ├── .git 1 13 1078 + │ ├── hooks 2 13 13 + │ ├── info 2 1 1 + │ ├── logs 2 2 24 + │ │ └── refs 3 2 22 + │ │ ├── heads 4 9 9 + │ │ └── remotes 4 1 11 + │ │ └── origin 5 10 10 + │ ├── objects 2 244 995 + │ │ ├── 00 3 3 3 + │ │ ├── 01 3 2 2 + │ │ ├── 02 3 3 3 + │ │ ├── 03 3 4 4 + │ │ ├── 04 3 2 2 + + PS ..\PSTree> (Get-ChildItem -Force).Count + 15 + PS ..\PSTree> (Get-ChildItem -Force -Recurse).Count + 1476 + PS ..\PSTree> (Get-ChildItem .git -Force -Recurse).Count + 1078 + PS ..\PSTree> (Get-ChildItem .git -Force).Count + 13 + PS ..\PSTree> + ``` + - __08/29/2024__ - Added method `.GetUnderlyingObject()`. Outputs the underlying `FileSystemInfo` instance. - Fixes [__Issue #9: Sort by ascending values__][1]: @@ -233,3 +270,4 @@ d---- └── Format 1.83 Kb [18]: https://github.com/jborean93/ [19]: /docs/en-US/Get-PSTree.md [20]: https://www.powershellgallery.com/ +[2]: https://github.com/santisq/PSTree/issues/34 diff --git a/module/PSTree.psd1 b/module/PSTree.psd1 index cf4959a..10e1089 100644 --- a/module/PSTree.psd1 +++ b/module/PSTree.psd1 @@ -11,7 +11,7 @@ RootModule = 'bin/netstandard2.0/PSTree.dll' # Version number of this module. - ModuleVersion = '2.1.17' + ModuleVersion = '2.1.18' # Supported PSEditions # CompatiblePSEditions = @()