Skip to content

Commit 4a32df2

Browse files
committed
✨ Get-CachedCommand.ps1 & Get-PathUsage.ps1
- resolves brianary#61
1 parent 8fe5a1f commit 4a32df2

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

Get-CachedCommand.ps1

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<#
2+
.SYNOPSIS
3+
Caches the output of a command for recall if called again.
4+
5+
.FUNCTIONALITY
6+
Command
7+
8+
.EXAMPLE
9+
Get-CachedCommand.ps1 {Invoke-RestMethod https://example.org/endpoint} -Session
10+
11+
Returns the result of executing the script block, or the previous cached output if available.
12+
#>
13+
14+
#Requires -Version 7
15+
[CmdletBinding()] Param(
16+
# Specifies the expression to cache the output of.
17+
[Parameter(Position=0,Mandatory=$true)][scriptblock] $Expression,
18+
# Parameters to the script block.
19+
[Parameter(Position=1,ValueFromRemainingArguments=$true)][psobject[]] $BlockArgs = @(),
20+
# The rolling duration to cache the output for (updated with each call).
21+
[Parameter(ParameterSetName='ExpiresAfter')][timespan] $ExpiresAfter,
22+
# Point in time to cache the output until.
23+
[Parameter(ParameterSetName='Expires')][datetime] $Expires,
24+
# Caches the output for this session.
25+
[Parameter(ParameterSetName='Session')][switch] $Session
26+
)
27+
Begin
28+
{
29+
$Script:Hash = [Security.Cryptography.MD5]::Create()
30+
function Get-ScriptBlockHash
31+
{
32+
[CmdletBinding()] Param(
33+
[Parameter(Position=0)][scriptblock] $ScriptBlock,
34+
[Parameter(Position=1)][psobject[]] $BlockArgs = @()
35+
)
36+
return (@("$ScriptBlock") + @($BlockArgs |ForEach-Object {ConvertTo-Json $_ -Compress}) |
37+
ForEach-Object {ConvertTo-Base64.ps1 $Script:Hash.ComputeHash([Text.Encoding]::UTF8.GetBytes($_)) -UriStyle}) -join '.'
38+
}
39+
40+
$Script:SessionCacheName = "$(Split-Path $PSCommandPath -LeafBase)#$PID"
41+
$Script:SessionCache = Get-Variable $Script:SessionCacheName -Scope Global -ErrorAction Ignore
42+
if(!$Script:SessionCache)
43+
{
44+
$Script:SessionCache = Set-Variable $Script:SessionCacheName @{} -Scope Global -Option Constant -PassThru `
45+
-Description 'Cached command output'
46+
}
47+
$Script:CacheDir = if($IsWindows)
48+
{
49+
Join-Path $env:LocalAppData (Split-Path $PSCommandPath -LeafBase)
50+
}
51+
elseif($IsLinux)
52+
{
53+
Join-Path ($env:XDG_CACHE_HOME ?? "$HOME/.cache") (Split-Path $PSCommandPath -LeafBase)
54+
}
55+
else
56+
{
57+
Join-Path $env:TEMP (Split-Path $PSCommandPath -LeafBase)
58+
}
59+
New-Item $Script:CacheDir -Type Directory -ErrorAction Ignore |Out-Null
60+
Get-ChildItem $Script:CacheDir |
61+
Where-Object LastWriteTime -lt (Get-Date) |
62+
Remove-Item
63+
function Get-CachedOutput
64+
{
65+
[CmdletBinding()] Param(
66+
[Parameter(Position=0)][scriptblock] $ScriptBlock,
67+
[Parameter(Position=1)][psobject[]] $BlockArgs = @(),
68+
[datetime] $Expires
69+
)
70+
$now = Get-Date
71+
$cacheFileName = Join-Path $Script:CacheDir "$(Get-ScriptBlockHash $ScriptBlock).xml"
72+
if(Test-Path $cacheFileName -Type Leaf)
73+
{
74+
$cacheFile = Get-Item $cacheFileName
75+
if($now -gt $cacheFile.LastWriteTime)
76+
{
77+
$ScriptBlock.InvokeReturnAsIs($BlockArgs) |Export-Clixml $cacheFileName -Force
78+
}
79+
}
80+
else
81+
{
82+
$ScriptBlock.InvokeReturnAsIs($BlockArgs) |Export-Clixml $cacheFileName
83+
$cacheFile = Get-Item $cacheFileName
84+
}
85+
$cacheFile.LastWriteTime = $now
86+
Import-Clixml $cacheFileName
87+
}
88+
}
89+
Process
90+
{
91+
switch($PSCmdlet.ParameterSetName)
92+
{
93+
ExpiresAfter {Get-CachedOutput $Expression -BlockArgs $BlockArgs -Expires (Get-Date).Add($ExpiresAfter)}
94+
ExpiresAfter {Get-CachedOutput $Expression -BlockArgs $BlockArgs -Expires $Expires}
95+
Session
96+
{
97+
$key = Get-ScriptBlockHash $Expression -BlockArgs $BlockArgs
98+
if(!$Script:SessionCache.Value.ContainsKey($key))
99+
{
100+
$Script:SessionCache.Value[$key] = $Expression.InvokeReturnAsIs($BlockArgs)
101+
}
102+
return $Script:SessionCache.Value[$key]
103+
}
104+
}
105+
}

Get-PathUsage.ps1

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<#
2+
.SYNOPSIS
3+
Returns the list of directories in the path, and the commands found in each.
4+
#>
5+
6+
#Requires -Version 7
7+
[CmdletBinding()] Param()
8+
$AllCommandPaths = Get-Command -Type Application,ExternalScript
9+
($env:Path -split ';') -replace '[/\\]\z' |
10+
Where-Object {$AllCommandPaths -like "$_\*" |Measure-Object |Where-Object Count -lt 3} -pv pathitem |
11+
ForEach-Object {[pscustomobject]@{ PathDirectory = $pathitem
12+
Commands = @($AllCommandPaths |Where-Object Path -like "$pathitem\*")
13+
PathExtMatch = @($env:PATHEXT -split ';' |
14+
ForEach-Object {Get-ChildItem $pathitem -Filter "*$_"} |
15+
Select-Object -ExpandProperty Name) }}

0 commit comments

Comments
 (0)