From 200d3f5aafd77958150ff0132f26717235b73272 Mon Sep 17 00:00:00 2001 From: Christian Halstrick Date: Thu, 20 Oct 2011 00:33:47 +0200 Subject: [PATCH] Refactor ResolveMerger The places where ResolveMerger was doing content merges have been refactored. The goal was to have one single method where content merge was done and to factor out other topics (updating the index, updating the working tree) into own methods. This was done to allow adding pluggable content mergers in change I7817e2123d254f3eeb315b47a61d2c55bd202c12 Change-Id: I8529697b197372a284bcd5ab2c9ba1adb925a520 Signed-off-by: Christian Halstrick --- .../org/eclipse/jgit/merge/ResolveMerger.java | 155 +++++++++++------- 1 file changed, 96 insertions(+), 59 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index 8211780ca..fce1f1a58 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -487,9 +487,12 @@ public class ResolveMerger extends ThreeWayMerger { // Check worktree before modifying files if (isWorktreeDirty()) return false; - if (!contentMerge(base, ours, theirs)) { + + MergeResult result = contentMerge(base, ours, theirs); + File of = writeMergedFile(result); + updateIndex(base, ours, theirs, result, of); + if (result.containsConflicts()) unmergedPaths.add(tw.getPathString()); - } modifiedFiles.add(tw.getPathString()); } else if (modeO != modeT) { // OURS or THEIRS has been deleted @@ -515,21 +518,38 @@ public class ResolveMerger extends ThreeWayMerger { unmergedPaths.add(tw.getPathString()); // generate a MergeResult for the deleted file - RawText baseText = base == null ? RawText.EMPTY_TEXT - : getRawText(base.getEntryObjectId(), db); - RawText ourText = ours == null ? RawText.EMPTY_TEXT - : getRawText(ours.getEntryObjectId(), db); - RawText theirsText = theirs == null ? RawText.EMPTY_TEXT - : getRawText(theirs.getEntryObjectId(), db); - MergeResult result = mergeAlgorithm.merge( - RawTextComparator.DEFAULT, baseText, ourText, - theirsText); - mergeResults.put(tw.getPathString(), result); + mergeResults.put(tw.getPathString(), + contentMerge(base, ours, theirs)); } } return true; } + /** + * Does the content merge. The three texts base, ours and theirs are + * specified with {@link CanonicalTreeParser}. If any of the parsers is + * specified as null then an empty text will be used instead. + * + * @param base + * @param ours + * @param theirs + * + * @return the result of the content merge + * @throws IOException + */ + private MergeResult contentMerge(CanonicalTreeParser base, + CanonicalTreeParser ours, CanonicalTreeParser theirs) + throws IOException { + RawText baseText = base == null ? RawText.EMPTY_TEXT : getRawText( + base.getEntryObjectId(), db); + RawText ourText = ours == null ? RawText.EMPTY_TEXT : getRawText( + ours.getEntryObjectId(), db); + RawText theirsText = theirs == null ? RawText.EMPTY_TEXT : getRawText( + theirs.getEntryObjectId(), db); + return (mergeAlgorithm.merge(RawTextComparator.DEFAULT, baseText, + ourText, theirsText)); + } + private boolean isIndexDirty() { final int modeI = tw.getRawMode(T_INDEX); final int modeO = tw.getRawMode(T_OURS); @@ -559,20 +579,70 @@ public class ResolveMerger extends ThreeWayMerger { return isDirty; } - private boolean contentMerge(CanonicalTreeParser base, - CanonicalTreeParser ours, CanonicalTreeParser theirs) - throws FileNotFoundException, IllegalStateException, IOException { - MergeFormatter fmt = new MergeFormatter(); - - RawText baseText = base == null ? RawText.EMPTY_TEXT : getRawText( - base.getEntryObjectId(), db); - - // do the merge - MergeResult result = mergeAlgorithm.merge( - RawTextComparator.DEFAULT, baseText, - getRawText(ours.getEntryObjectId(), db), - getRawText(theirs.getEntryObjectId(), db)); + /** + * Updates the index after a content merge has happened. If no conflict has + * occurred this includes persisting the merged content to the object + * database. In case of conflicts this method takes care to write the + * correct stages to the index. + * + * @param base + * @param ours + * @param theirs + * @param result + * @param of + * @throws FileNotFoundException + * @throws IOException + */ + private void updateIndex(CanonicalTreeParser base, + CanonicalTreeParser ours, CanonicalTreeParser theirs, + MergeResult result, File of) throws FileNotFoundException, + IOException { + if (result.containsConflicts()) { + // a conflict occurred, the file will contain conflict markers + // the index will be populated with the three stages and only the + // workdir (if used) contains the halfways merged content + add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); + add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); + add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3); + mergeResults.put(tw.getPathString(), result); + } else { + // no conflict occurred, the file will contain fully merged content. + // the index will be populated with the new merged version + DirCacheEntry dce = new DirCacheEntry(tw.getPathString()); + int newMode = mergeFileModes(tw.getRawMode(0), tw.getRawMode(1), + tw.getRawMode(2)); + // set the mode for the new content. Fall back to REGULAR_FILE if + // you can't merge modes of OURS and THEIRS + dce.setFileMode((newMode == FileMode.MISSING.getBits()) ? FileMode.REGULAR_FILE + : FileMode.fromBits(newMode)); + dce.setLastModified(of.lastModified()); + dce.setLength((int) of.length()); + InputStream is = new FileInputStream(of); + try { + dce.setObjectId(oi.insert(Constants.OBJ_BLOB, of.length(), is)); + } finally { + is.close(); + if (inCore) + FileUtils.delete(of); + } + builder.add(dce); + } + } + /** + * Writes merged file content to the working tree. In case {@link #inCore} + * is set and we don't have a working tree the content is written to a + * temporary file + * + * @param result + * the result of the content merge + * @return the file to which the merged content was written + * @throws FileNotFoundException + * @throws IOException + */ + private File writeMergedFile(MergeResult result) + throws FileNotFoundException, IOException { + MergeFormatter fmt = new MergeFormatter(); File of = null; FileOutputStream fos; if (!inCore) { @@ -603,40 +673,7 @@ public class ResolveMerger extends ThreeWayMerger { fos.close(); } } - - if (result.containsConflicts()) { - // a conflict occurred, the file will contain conflict markers - // the index will be populated with the three stages and only the - // workdir (if used) contains the halfways merged content - add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); - add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); - add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3); - mergeResults.put(tw.getPathString(), result); - return false; - } else { - // no conflict occurred, the file will contain fully merged content. - // the index will be populated with the new merged version - DirCacheEntry dce = new DirCacheEntry(tw.getPathString()); - int newMode = mergeFileModes(tw.getRawMode(0), tw.getRawMode(1), - tw.getRawMode(2)); - // set the mode for the new content. Fall back to REGULAR_FILE if - // you can't merge modes of OURS and THEIRS - dce.setFileMode((newMode == FileMode.MISSING.getBits()) ? FileMode.REGULAR_FILE - : FileMode.fromBits(newMode)); - dce.setLastModified(of.lastModified()); - dce.setLength((int) of.length()); - InputStream is = new FileInputStream(of); - try { - dce.setObjectId(oi.insert(Constants.OBJ_BLOB, of.length(), - is)); - } finally { - is.close(); - if (inCore) - FileUtils.delete(of); - } - builder.add(dce); - return true; - } + return of; } /**