Package org.machanism.machai.gw.tools
Class PatchApplier
java.lang.Object
org.machanism.machai.gw.tools.PatchApplier
Applies unified and simplified search-and-replace diff patches to text files.
The utility parses patch hunks, locates their original context near the position indicated by a unified-diff header, and writes the resulting lines using the caller-supplied character set. It rejects patches that cannot be matched, make no changes, or would erase a nonempty file. This class has no mutable shared state and exposes only static operations.
- Since:
- 1.2.0
- Author:
- Viktor Tovstyi
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classRepresents a patch hunk and its preferred zero-based starting position.private static final classRepresents a parsed context, addition, or removal line in a patch hunk. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprivatePrevents instantiation of this static utility class. -
Method Summary
Modifier and TypeMethodDescriptionprivate static intadvancePastContext(List<String> lines, String content, int index) Advances beyond a context line, searching forward when its expected position no longer matches exactly.private static voidapplyHunk(List<String> resultLines, PatchApplier.Hunk hunk, String header) Locates and applies a hunk to the mutable result lines.static voidapplyPatch(File file, List<String> patchLines, Charset charset) Applies a unified or simplified diff patch to a file.private static intapplyPatchLine(List<String> lines, PatchApplier.PatchLine patchLine, int index) Applies one parsed hunk line at the current result-file index.private static intcountAdded(List<String> lines) Counts addition lines in a hunk.private static intcountRemoved(List<String> lines) Counts removal lines in a hunk.private static voidcreateParentDirectory(Path path) Creates the target file's parent directory when it does not exist.expectedOriginalLines(List<String> hunkLines) Extracts the original-file lines required by a hunk.private static intfindHunkStart(List<String> fileLines, List<String> hunkLines, int expectedStart) Finds the first complete original-context match nearest the expected start.private static intgetExpectedStart(String header, int offsetDelta) Calculates the preferred result-file position from a unified-diff header.private static intindexOfLine(List<String> lines, String expectedLine, int startIndex) Finds a line at or after the supplied index.private static booleanisHunkBoundary(String line) Determines whether a line begins another hunk or file section.private static booleanChecks whether expected lines match the file at an index.private static booleanmatchLines(List<String> fileLines, List<String> expectedLines, int startOffset) Compares expected lines to a consecutive segment of file lines.private static PatchApplier.PatchLineparsePatchLine(String hunkLine) Parses one hunk line into its operation and unprefixed content.private static PatchApplier.HunkReads the hunk beginning at a patch header.private static voidremoveLine(List<String> lines, int index) Removes a line at the current patch position.private static voidRejects unsafe or ineffective patch results.
-
Constructor Details
-
PatchApplier
private PatchApplier()Prevents instantiation of this static utility class.
-
-
Method Details
-
parsePatchLine
Parses one hunk line into its operation and unprefixed content.- Parameters:
hunkLine- raw patch line- Returns:
- parsed patch line; unprefixed input is treated as context
-
advancePastContext
Advances beyond a context line, searching forward when its expected position no longer matches exactly.- Parameters:
lines- modified file linescontent- expected context contentindex- current line index- Returns:
- index immediately after the matching or expected context line
-
removeLine
Removes a line at the current patch position.- Parameters:
lines- modified file linesindex- index of the line to remove- Throws:
IOException- if the removal is beyond the available file context
-
applyPatch
public static void applyPatch(File file, List<String> patchLines, Charset charset) throws IOException Applies a unified or simplified diff patch to a file.Standard unified-diff headers, such as
@@ -1,5 +1,6 @@, and simplified@@headers are supported.- Parameters:
file- target file to patch; it is created when absentpatchLines- ordered lines from the patch filecharset- character set used to read and write the target file- Throws:
IOException- if file operations fail, a hunk cannot be applied, or validation rejects the resulting content
-
readHunk
private static PatchApplier.Hunk readHunk(List<String> patchLines, int headerIndex, int offsetDelta) Reads the hunk beginning at a patch header.- Parameters:
patchLines- complete patch linesheaderIndex- index of the headeroffsetDelta- cumulative line-count delta from preceding hunks- Returns:
- parsed hunk
-
isHunkBoundary
Determines whether a line begins another hunk or file section.- Parameters:
line- candidate patch line- Returns:
truewhen the line is a recognized boundary
-
getExpectedStart
Calculates the preferred result-file position from a unified-diff header.- Parameters:
header- hunk headeroffsetDelta- cumulative prior line-count delta- Returns:
- zero-based preferred position, or zero for a simplified or invalid header
-
applyHunk
private static void applyHunk(List<String> resultLines, PatchApplier.Hunk hunk, String header) throws IOException Locates and applies a hunk to the mutable result lines.- Parameters:
resultLines- mutable result file lineshunk- parsed hunkheader- original hunk header for diagnostics- Throws:
IOException- if no matching hunk context is found
-
applyPatchLine
private static int applyPatchLine(List<String> lines, PatchApplier.PatchLine patchLine, int index) throws IOException Applies one parsed hunk line at the current result-file index.- Parameters:
lines- mutable result linespatchLine- parsed operation and contentindex- current result-file index- Returns:
- index at which the next operation should occur
- Throws:
IOException- if a removal exceeds available context
-
countAdded
Counts addition lines in a hunk.- Parameters:
lines- raw hunk lines- Returns:
- number of additions
-
countRemoved
Counts removal lines in a hunk.- Parameters:
lines- raw hunk lines- Returns:
- number of removals
-
createParentDirectory
Creates the target file's parent directory when it does not exist.- Parameters:
path- target path- Throws:
IOException- if the directory cannot be created
-
validatePatchResult
private static void validatePatchResult(List<String> original, List<String> modified, String fileName) throws IOException Rejects unsafe or ineffective patch results.- Parameters:
original- original file linesmodified- patched file linesfileName- file name for diagnostics- Throws:
IOException- if the patch erases a nonempty file or makes no change
-
findHunkStart
Finds the first complete original-context match nearest the expected start.- Parameters:
fileLines- candidate file lineshunkLines- raw hunk linesexpectedStart- preferred zero-based position- Returns:
- matching index, or
-1when no match exists
-
expectedOriginalLines
Extracts the original-file lines required by a hunk.- Parameters:
hunkLines- raw hunk lines- Returns:
- context and removal content in original-file order
-
matchesAt
private static boolean matchesAt(List<String> fileLines, List<String> expectedLines, int startOffset) Checks whether expected lines match the file at an index.- Parameters:
fileLines- file linesexpectedLines- expected consecutive linesstartOffset- candidate start index- Returns:
trueif all expected lines match in bounds
-
matchLines
private static boolean matchLines(List<String> fileLines, List<String> expectedLines, int startOffset) Compares expected lines to a consecutive segment of file lines.- Parameters:
fileLines- file linesexpectedLines- expected linesstartOffset- start of the candidate segment- Returns:
trueif every line matches
-
indexOfLine
Finds a line at or after the supplied index.- Parameters:
lines- lines to searchexpectedLine- line to locatestartIndex- first index to examine- Returns:
- matching index, or
-1when absent
-