Modules/businessdev.ALbuild.Apps/Private/Get-BcAlProjectRoot.ps1
|
function Get-BcAlProjectRoot { <# .SYNOPSIS Returns the AL project an .al file belongs to (the nearest ancestor folder holding an app.json). .DESCRIPTION Used to tell the test side of a repository from the production side: an assertion may only be expected in the app that declares the tests, so a call the assertion gate follows has to stay inside a project that contains [Test] procedures. Without that boundary the gate would resolve any call into production code, where `Error(` is on nearly every page - and pass every test. .PARAMETER FilePath The .al file. .PARAMETER Cache Optional dictionary, directory -> project root, so a repository is walked once per folder. .OUTPUTS The project root path, or '<none>' when no app.json stands above the file. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $FilePath, [System.Collections.IDictionary] $Cache ) $dir = Split-Path -Parent $FilePath if (-not $dir) { return '<none>' } if ($Cache -and $Cache.Contains($dir)) { return [string] $Cache[$dir] } $walked = [System.Collections.Generic.List[string]]::new() $answer = '<none>' $current = $dir while ($current) { if ($Cache -and $Cache.Contains($current)) { $answer = [string] $Cache[$current]; break } $walked.Add($current) if (Test-Path -LiteralPath (Join-Path -Path $current -ChildPath 'app.json')) { $answer = $current; break } $parent = Split-Path -Parent $current if (-not $parent -or $parent -eq $current) { break } $current = $parent } if ($Cache) { foreach ($w in $walked) { $Cache[$w] = $answer } } return $answer } |