( filePath: string, diff: ITextDiff, selection: DiffSelection )
| 249 | * @param selection A selection of lines from the diff object that we want to discard. |
| 250 | */ |
| 251 | export function formatPatchToDiscardChanges( |
| 252 | filePath: string, |
| 253 | diff: ITextDiff, |
| 254 | selection: DiffSelection |
| 255 | ): string | null { |
| 256 | let patch = '' |
| 257 | |
| 258 | diff.hunks.forEach((hunk, hunkIndex) => { |
| 259 | let hunkBuf = '' |
| 260 | |
| 261 | let oldCount = 0 |
| 262 | let newCount = 0 |
| 263 | |
| 264 | let anyAdditionsOrDeletions = false |
| 265 | |
| 266 | hunk.lines.forEach((line, lineIndex) => { |
| 267 | const absoluteIndex = hunk.unifiedDiffStart + lineIndex |
| 268 | |
| 269 | // We write our own hunk headers |
| 270 | if (line.type === DiffLineType.Hunk) { |
| 271 | return |
| 272 | } |
| 273 | |
| 274 | // Context lines can always be let through, they will |
| 275 | // never appear for new files. |
| 276 | if (line.type === DiffLineType.Context) { |
| 277 | hunkBuf += `${line.text}\n` |
| 278 | oldCount++ |
| 279 | newCount++ |
| 280 | } else if (selection.isSelected(absoluteIndex)) { |
| 281 | // Reverse the change (if it was an added line, treat it as removed and vice versa). |
| 282 | if (line.type === DiffLineType.Add) { |
| 283 | hunkBuf += `-${line.text.substring(1)}\n` |
| 284 | newCount++ |
| 285 | } else if (line.type === DiffLineType.Delete) { |
| 286 | hunkBuf += `+${line.text.substring(1)}\n` |
| 287 | oldCount++ |
| 288 | } else { |
| 289 | assertNever(line.type, `Unsupported line type ${line.type}`) |
| 290 | } |
| 291 | |
| 292 | anyAdditionsOrDeletions = true |
| 293 | } else { |
| 294 | if (line.type === DiffLineType.Add) { |
| 295 | // An unselected added line will stay in the file after discarding the changes, |
| 296 | // so we just print it untouched on the diff. |
| 297 | oldCount++ |
| 298 | newCount++ |
| 299 | hunkBuf += ` ${line.text.substring(1)}\n` |
| 300 | } else if (line.type === DiffLineType.Delete) { |
| 301 | // An unselected removed line has no impact on this patch since it's not |
| 302 | // found on the current working copy of the file, so we can ignore it. |
| 303 | return |
| 304 | } else { |
| 305 | // Guarantee that we've covered all the line types. |
| 306 | assertNever(line.type, `Unsupported line type ${line.type}`) |
| 307 | } |
| 308 | } |
no test coverage detected