( opts: DiffWithDeps, dir: string, from: string, to: string, )
| 194 | // lists — git's own object database, no working-tree probes — |
| 195 | // and resolve each path's blob in both commits. |
| 196 | async function collectRefToRef( |
| 197 | opts: DiffWithDeps, |
| 198 | dir: string, |
| 199 | from: string, |
| 200 | to: string, |
| 201 | ): Promise<DiffEntry[]> { |
| 202 | let fromOid: string; |
| 203 | let toOid: string; |
| 204 | try { |
| 205 | fromOid = await opts.git.resolveRef({ fs: opts.fs, dir, ref: from }); |
| 206 | toOid = await opts.git.resolveRef({ fs: opts.fs, dir, ref: to }); |
| 207 | } catch { |
| 208 | return []; |
| 209 | } |
| 210 | const fromFiles = new Set(await listFilesAt(opts.git, opts.fs, dir, from)); |
| 211 | const toFiles = new Set(await listFilesAt(opts.git, opts.fs, dir, to)); |
| 212 | const union = new Set<string>([...fromFiles, ...toFiles]); |
| 213 | const pathFilter = makePathFilter(opts.paths); |
| 214 | |
| 215 | const entries: DiffEntry[] = []; |
| 216 | for (const filepath of [...union].sort()) { |
| 217 | if (!pathFilter(filepath)) continue; |
| 218 | const inFrom = fromFiles.has(filepath); |
| 219 | const inTo = toFiles.has(filepath); |
| 220 | const a = inFrom |
| 221 | ? await readBlobAsText(opts.git, opts.fs, dir, fromOid, filepath, opts.cache) |
| 222 | : ""; |
| 223 | const b = inTo ? await readBlobAsText(opts.git, opts.fs, dir, toOid, filepath, opts.cache) : ""; |
| 224 | if (a === b) continue; |
| 225 | const status: DiffEntry["status"] = !inFrom ? "A" : !inTo ? "D" : "M"; |
| 226 | entries.push({ path: filepath, status, oldText: a, newText: b }); |
| 227 | } |
| 228 | return entries; |
| 229 | } |
| 230 | |
| 231 | /** |
| 232 | * Count added / removed content lines in a unified patch. Only |
no test coverage detected