microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v3.3.10

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

.github/skills/shared/pr-reference/scripts/read-diff.ps1

333lines · modecode

1# Copyright (c) Microsoft Corporation.
2# SPDX-License-Identifier: MIT
3#Requires -Version 7.0
4
5<#
6.SYNOPSIS
7Reads diff content from a PR reference XML with chunking and file filtering.
8
9.DESCRIPTION
10Provides structured access to pr-reference.xml content including chunk-based
11reading, line range extraction, and single-file diff isolation.
12
13.PARAMETER InputPath
14Path to the PR reference XML file. Defaults to .copilot-tracking/pr/pr-reference.xml.
15
16.PARAMETER Chunk
17Chunk number to read (1-based).
18
19.PARAMETER ChunkSize
20Number of lines per chunk. Defaults to 500.
21
22.PARAMETER Lines
23Line range to read in format "START,END" or "START-END".
24
25.PARAMETER File
26Extract diff for a specific file path.
27
28.PARAMETER Summary
29Show diff summary with file list and change stats.
30
31.PARAMETER Info
32Show chunk information without content.
33
34.EXAMPLE
35./read-diff.ps1 -Chunk 1
36Reads the first 500 lines of the diff.
37
38.EXAMPLE
39./read-diff.ps1 -Chunk 2 -ChunkSize 300
40Reads lines 301-600 of the diff.
41
42.EXAMPLE
43./read-diff.ps1 -File "src/main.ts"
44Extracts the diff for a specific file.
45
46.EXAMPLE
47./read-diff.ps1 -Info
48Shows chunk breakdown without content.
49#>
50
51[CmdletBinding(DefaultParameterSetName = 'Default')]
52param(
53 [Parameter()]
54 [Alias('i', 'Input')]
55 [string]$InputPath = "",
56
57 [Parameter(ParameterSetName = 'Chunk')]
58 [Alias('c')]
59 [int]$Chunk = 0,
60
61 [Parameter()]
62 [Alias('s')]
63 [int]$ChunkSize = 500,
64
65 [Parameter(ParameterSetName = 'Lines')]
66 [Alias('l')]
67 [string]$Lines = "",
68
69 [Parameter(ParameterSetName = 'File')]
70 [Alias('f')]
71 [string]$File = "",
72
73 [Parameter(ParameterSetName = 'Summary')]
74 [switch]$Summary,
75
76 [Parameter(ParameterSetName = 'Info')]
77 [switch]$Info
78)
79
80$ErrorActionPreference = 'Stop'
81
82Import-Module (Join-Path $PSScriptRoot 'shared.psm1') -Force
83
84function Get-ChunkInfo {
85 [OutputType([PSCustomObject])]
86 param(
87 [Parameter(Mandatory)]
88 [int]$TotalLines,
89
90 [Parameter(Mandatory)]
91 [int]$ChunkSize
92 )
93
94 $totalChunks = [math]::Ceiling($TotalLines / $ChunkSize)
95
96 return [PSCustomObject]@{
97 TotalLines = $TotalLines
98 ChunkSize = $ChunkSize
99 TotalChunks = $totalChunks
100 }
101}
102
103function Get-ChunkRange {
104 [OutputType([PSCustomObject])]
105 param(
106 [Parameter(Mandatory)]
107 [int]$ChunkNumber,
108
109 [Parameter(Mandatory)]
110 [int]$ChunkSize,
111
112 [Parameter(Mandatory)]
113 [int]$TotalLines
114 )
115
116 $start = (($ChunkNumber - 1) * $ChunkSize) + 1
117 $end = [math]::Min($ChunkNumber * $ChunkSize, $TotalLines)
118
119 return [PSCustomObject]@{
120 Start = $start
121 End = $end
122 }
123}
124
125function Get-FileDiff {
126 [OutputType([string])]
127 param(
128 [Parameter(Mandatory)]
129 [AllowEmptyString()]
130 [string[]]$Content,
131
132 [Parameter(Mandatory)]
133 [string]$FilePath
134 )
135
136 $inTargetFile = $false
137 $diffLines = @()
138 $escapedPath = [regex]::Escape($FilePath)
139
140 foreach ($line in $Content) {
141 if ($line -match "^diff --git") {
142 if ($line -match "a/$escapedPath b/") {
143 $inTargetFile = $true
144 }
145 elseif ($inTargetFile) {
146 break
147 }
148 }
149
150 if ($inTargetFile) {
151 $diffLines += $line
152 }
153 }
154
155 return $diffLines -join [Environment]::NewLine
156}
157
158function Get-DiffSummary {
159 [OutputType([string])]
160 param(
161 [Parameter(Mandatory)]
162 [AllowEmptyString()]
163 [string[]]$Content
164 )
165
166 $files = @()
167 $currentFile = $null
168 $added = 0
169 $removed = 0
170
171 foreach ($line in $Content) {
172 if ($line -match "^diff --git a/(.+?) b/") {
173 if ($currentFile) {
174 $files += [PSCustomObject]@{
175 Path = $currentFile
176 Added = $added
177 Removed = $removed
178 }
179 }
180 $currentFile = $Matches[1]
181 $added = 0
182 $removed = 0
183 }
184 elseif ($currentFile) {
185 if ($line -match "^\+[^+]") { $added++ }
186 elseif ($line -match "^-[^-]") { $removed++ }
187 }
188 }
189
190 if ($currentFile) {
191 $files += [PSCustomObject]@{
192 Path = $currentFile
193 Added = $added
194 Removed = $removed
195 }
196 }
197
198 $output = @("Changed files:")
199 foreach ($file in ($files | Sort-Object Path)) {
200 $output += " $($file.Path) (+$($file.Added)/-$($file.Removed))"
201 }
202
203 return $output -join [Environment]::NewLine
204}
205
206function Invoke-ReadDiff {
207 [CmdletBinding()]
208 param(
209 [Parameter()]
210 [string]$InputPath = "",
211
212 [Parameter()]
213 [int]$Chunk = 0,
214
215 [Parameter()]
216 [int]$ChunkSize = 500,
217
218 [Parameter()]
219 [string]$Lines = "",
220
221 [Parameter()]
222 [string]$File = "",
223
224 [Parameter()]
225 [switch]$Summary,
226
227 [Parameter()]
228 [switch]$Info
229 )
230
231 $repoRoot = Get-RepositoryRoot
232 $xmlPath = if ($InputPath) {
233 $InputPath
234 } else {
235 Join-Path $repoRoot '.copilot-tracking/pr/pr-reference.xml'
236 }
237
238 if (-not (Test-Path -LiteralPath $xmlPath)) {
239 throw "PR reference file not found: $xmlPath`nRun generate.ps1 first to create the PR reference."
240 }
241
242 $content = Get-Content -LiteralPath $xmlPath
243 $totalLines = $content.Count
244 $chunkInfo = Get-ChunkInfo -TotalLines $totalLines -ChunkSize $ChunkSize
245
246 # Info mode
247 if ($Info) {
248 Write-Output "File: $xmlPath"
249 Write-Output "Total lines: $totalLines"
250 Write-Output "Chunk size: $ChunkSize"
251 Write-Output "Total chunks: $($chunkInfo.TotalChunks)"
252 Write-Output ""
253 Write-Output "Chunk breakdown:"
254 for ($i = 1; $i -le $chunkInfo.TotalChunks; $i++) {
255 $range = Get-ChunkRange -ChunkNumber $i -ChunkSize $ChunkSize -TotalLines $totalLines
256 Write-Output " Chunk ${i}: lines $($range.Start)-$($range.End)"
257 }
258 return
259 }
260
261 # Summary mode
262 if ($Summary) {
263 $summaryOutput = Get-DiffSummary -Content $content
264 Write-Output $summaryOutput
265 return
266 }
267
268 # File extraction mode
269 if ($File) {
270 $fileDiff = Get-FileDiff -Content $content -FilePath $File
271 if ($fileDiff) {
272 Write-Output $fileDiff
273 }
274 else {
275 Write-Warning "No diff found for file: $File"
276 }
277 return
278 }
279
280 # Chunk mode
281 if ($Chunk -gt 0) {
282 if ($Chunk -gt $chunkInfo.TotalChunks) {
283 throw "Chunk $Chunk exceeds file (only $($chunkInfo.TotalChunks) chunks available)"
284 }
285
286 $range = Get-ChunkRange -ChunkNumber $Chunk -ChunkSize $ChunkSize -TotalLines $totalLines
287 Write-Output "# Chunk $Chunk/$($chunkInfo.TotalChunks) (lines $($range.Start)-$($range.End) of $totalLines)"
288 Write-Output ""
289 $content[($range.Start - 1)..($range.End - 1)] | ForEach-Object { Write-Output $_ }
290 return
291 }
292
293 # Line range mode
294 if ($Lines) {
295 $rangeParts = $Lines -replace ',', '-' -split '-'
296 if ($rangeParts.Count -ne 2) {
297 throw "Invalid line range format. Use START,END or START-END"
298 }
299
300 $start = [int]$rangeParts[0]
301 $end = [math]::Min([int]$rangeParts[1], $totalLines)
302
303 if ($start -gt $totalLines) {
304 throw "Start line $start exceeds file length ($totalLines lines)"
305 }
306
307 Write-Output "# Lines $start-$end of $totalLines"
308 Write-Output ""
309 $content[($start - 1)..($end - 1)] | ForEach-Object { Write-Output $_ }
310 return
311 }
312
313 # Default: show info
314 Write-Output "File: $xmlPath"
315 Write-Output "Total lines: $totalLines"
316 Write-Output "Total chunks: $($chunkInfo.TotalChunks) (at $ChunkSize lines/chunk)"
317 Write-Output ""
318 Write-Output "Use -Chunk N to read a specific chunk, -Lines START,END for a range,"
319 Write-Output "or -File PATH to extract a specific file's diff."
320}
321
322#region Main Execution
323if ($MyInvocation.InvocationName -ne '.') {
324 try {
325 Invoke-ReadDiff -InputPath $InputPath -Chunk $Chunk -ChunkSize $ChunkSize -Lines $Lines -File $File -Summary:$Summary -Info:$Info
326 exit 0
327 }
328 catch {
329 Write-Error -ErrorAction Continue $_.Exception.Message
330 exit 1
331 }
332}
333#endregion
334