Private/Test-AzLocalReadmeReplaceable.ps1
|
function Test-AzLocalReadmeReplaceable { <# .SYNOPSIS Decides whether an existing repo README.md is "empty enough" to be safely replaced by the module-managed README template. .DESCRIPTION Private helper introduced in v0.9.0 for the managed repo README drop in Copy-AzLocalPipelineExample / Update-AzLocalPipelineExample. A README is treated as REPLACEABLE (safe to overwrite with the bundled template) when it carries no operator content worth keeping, specifically: * the file is missing / null / whitespace-only, OR * it is a GitHub "Add a README" default stub - an H1 whose text matches the repository name (case- and punctuation-insensitive), optionally followed by a single short plain-prose description line, and nothing else (no second heading, list, table, code fence, blockquote, link-only line or image). Anything richer than that (two-plus content lines beyond the optional description, any markdown structure, or an H1 that does not match the repo name) is treated as OPERATOR-OWNED and is NOT replaceable. Callers handle the module-managed case (a README carrying an AZLOCAL-README-VERSION marker) separately via Get-AzLocalReadmeTemplateVersion; this helper only judges marker-less content. .PARAMETER Text The full README text. Pass an empty string for a missing file. .PARAMETER RepoName The repository folder name (e.g. Split-Path -Leaf $repoRoot). Used to confirm an H1 is the GitHub default repo-name heading. When empty, a lone heading is treated as operator-owned (conservative: preserve). .OUTPUTS [bool] - $true when the README is safe to overwrite, else $false. .NOTES Author : Neil Bird, Microsoft Module : AzLocal.UpdateManagement Added in : v0.9.0 #> [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory = $true)] [AllowEmptyString()] [string]$Text, [Parameter(Mandatory = $false)] [AllowEmptyString()] [string]$RepoName = '' ) # Missing / whitespace-only -> always safe to write. if ([string]::IsNullOrWhiteSpace($Text)) { return $true } # Non-blank, trimmed content lines. -split uses regex; "`r?`n" matches both # CRLF and LF line endings. $lines = @($Text -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }) if ($lines.Count -eq 0) { return $true } # More than (H1 + one description line) of content -> operator-owned. if ($lines.Count -gt 2) { return $false } # First content line must be a single H1 heading: "# Title". $h1 = [regex]::Match($lines[0], '^#\s+(.+?)\s*$') if (-not $h1.Success) { return $false } # An optional second line must be plain prose - reject any markdown # structure (heading, list, ordered list, blockquote, table, code fence, # image, or a line that is itself a markdown link). if ($lines.Count -eq 2) { if ($lines[1] -match '^(#|-|\*|>|\||```|\d+\.|!\[|\[)') { return $false } } # The H1 must match the repository name (GitHub's default README uses the # repo name verbatim). Normalise by lowercasing and stripping anything that # is not a letter or digit so 'My-Repo' and 'my repo' compare equal. if ([string]::IsNullOrWhiteSpace($RepoName)) { return $false } $h1Norm = ($h1.Groups[1].Value -replace '[^a-zA-Z0-9]', '').ToLowerInvariant() $repoNorm = ($RepoName -replace '[^a-zA-Z0-9]', '').ToLowerInvariant() return ($h1Norm -ne '' -and $h1Norm -eq $repoNorm) } |