diff options
author | Christian Halstrick <christian.halstrick@sap.com> | 2010-08-19 15:52:12 +0200 |
---|---|---|
committer | Chris Aniszczyk <caniszczyk@gmail.com> | 2010-08-19 12:16:39 -0500 |
commit | 75c9b2438594dc6ac125ff1bdf97022c7f429b78 (patch) | |
tree | 7f209395073f7a5ef9e3e61b2e9be31a444ad525 /org.eclipse.jgit | |
parent | 94ba9574cd5589bbf7a3671533390b43936fe65b (diff) | |
download | jgit-75c9b2438594dc6ac125ff1bdf97022c7f429b78.tar.gz jgit-75c9b2438594dc6ac125ff1bdf97022c7f429b78.zip |
Enhance MergeResult to report conflicts, etc
The MergeResult class is enhanced to report more data about a
three-way merge. Information about conflicts and the base, ours,
theirs commits can be retrived.
Change-Id: Iaaf41a1f4002b8fe3ddfa62dc73c787f363460c2
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
Diffstat (limited to 'org.eclipse.jgit')
3 files changed, 136 insertions, 25 deletions
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties index a9878f8d29..faeb1d53f9 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties @@ -222,7 +222,7 @@ lockOnNotHeld=Lock on {0} not held. malformedpersonIdentString=Malformed PersonIdent string (no < was found): {0} mergeStrategyAlreadyExistsAsDefault=Merge strategy "{0}" already exists as a default strategy mergeStrategyDoesNotSupportHeads=merge strategy {0} does not support {1} heads to be merged into HEAD -mergeUsingStrategyResultedInDescription=Merge using strategy {0} resulted in: {1}. {2} +mergeUsingStrategyResultedInDescription=Merge of revisions {0} with base {1} using strategy {2} resulted in: {3}. {4} missingAccesskey=Missing accesskey. missingDeltaBase=delta base missingForwardImageInGITBinaryPatch=Missing forward-image in GIT binary patch diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java index 972aa618ad..4d37c28e0a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java @@ -114,7 +114,8 @@ public class MergeCommand extends GitCommand<MergeResult> { try { Ref head = repo.getRef(Constants.HEAD); if (head == null) - throw new NoHeadException(JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported); + throw new NoHeadException( + JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported); StringBuilder refLogMessage = new StringBuilder("merge "); // Check for FAST_FORWARD, ALREADY_UP_TO_DATE @@ -134,7 +135,8 @@ public class MergeCommand extends GitCommand<MergeResult> { RevCommit srcCommit = revWalk.lookupCommit(objectId); if (revWalk.isMergedInto(srcCommit, headCommit)) { setCallable(false); - return new MergeResult(headCommit, + return new MergeResult(headCommit, srcCommit, + new ObjectId[] { srcCommit, headCommit }, MergeStatus.ALREADY_UP_TO_DATE, mergeStrategy); } else if (revWalk.isMergedInto(headCommit, srcCommit)) { // FAST_FORWARD detected: skip doing a real merge but only @@ -143,11 +145,14 @@ public class MergeCommand extends GitCommand<MergeResult> { checkoutNewHead(revWalk, headCommit, srcCommit); updateHead(refLogMessage, srcCommit, head.getObjectId()); setCallable(false); - return new MergeResult(srcCommit, MergeStatus.FAST_FORWARD, - mergeStrategy); + return new MergeResult(srcCommit, headCommit, + new ObjectId[] { srcCommit, headCommit }, + MergeStatus.FAST_FORWARD, mergeStrategy); } else { return new MergeResult( headCommit, + null, + new ObjectId[] { srcCommit, headCommit }, MergeResult.MergeStatus.NOT_SUPPORTED, mergeStrategy, JGitText.get().onlyAlreadyUpToDateAndFastForwardMergesAreAvailable); @@ -164,7 +169,8 @@ public class MergeCommand extends GitCommand<MergeResult> { } private void checkoutNewHead(RevWalk revWalk, RevCommit headCommit, - RevCommit newHeadCommit) throws IOException, CheckoutConflictException { + RevCommit newHeadCommit) throws IOException, + CheckoutConflictException { GitIndex index = repo.getIndex(); File workDir = repo.getWorkTree(); @@ -184,8 +190,8 @@ public class MergeCommand extends GitCommand<MergeResult> { } } - private void updateHead(StringBuilder refLogMessage, - ObjectId newHeadId, ObjectId oldHeadID) throws IOException, + private void updateHead(StringBuilder refLogMessage, ObjectId newHeadId, + ObjectId oldHeadID) throws IOException, ConcurrentRefUpdateException { RefUpdate refUpdate = repo.updateRef(Constants.HEAD); refUpdate.setNewObjectId(newHeadId); @@ -221,8 +227,7 @@ public class MergeCommand extends GitCommand<MergeResult> { /** * @param commit - * a reference to a commit which is merged with the current - * head + * a reference to a commit which is merged with the current head * @return {@code this} */ public MergeCommand include(Ref commit) { @@ -241,7 +246,8 @@ public class MergeCommand extends GitCommand<MergeResult> { } /** - * @param name a name given to the commit + * @param name + * a name given to the commit * @param commit * the Id of a commit which is merged with the current head * @return {@code this} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java index a293ad0c95..6fcf2ee6d0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.api; import java.text.MessageFormat; +import java.util.Map; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.lib.ObjectId; @@ -84,6 +85,12 @@ public class MergeResult { } }, /** */ + CONFLICTING { + public String toString() { + return "Conflicting"; + } + }, + /** */ NOT_SUPPORTED { public String toString() { return "Not-yet-supported"; @@ -91,8 +98,14 @@ public class MergeResult { } } + private ObjectId[] mergedCommits; + + private ObjectId base; + private ObjectId newHead; + private Map<String, int[][]> conflicts; + private MergeStatus mergeStatus; private String description; @@ -100,26 +113,47 @@ public class MergeResult { private MergeStrategy mergeStrategy; /** - * @param newHead the object the head points at after the merge - * @param mergeStatus the status the merge resulted in - * @param mergeStrategy the used {@link MergeStrategy} + * @param newHead + * the object the head points at after the merge + * @param base + * the common base which was used to produce a content-merge. May + * be <code>null</code> if the merge-result was produced without + * computing a common base + * @param mergedCommits + * all the commits which have been merged together + * @param mergeStatus + * the status the merge resulted in + * @param mergeStrategy + * the used {@link MergeStrategy} */ - public MergeResult(ObjectId newHead, MergeStatus mergeStatus, + public MergeResult(ObjectId newHead, ObjectId base, + ObjectId[] mergedCommits, MergeStatus mergeStatus, MergeStrategy mergeStrategy) { - this.newHead = newHead; - this.mergeStatus = mergeStatus; - this.mergeStrategy = mergeStrategy; + this(newHead, base, mergedCommits, mergeStatus, mergeStrategy, null); } /** - * @param newHead the object the head points at after the merge - * @param mergeStatus the status the merge resulted in - * @param mergeStrategy the used {@link MergeStrategy} - * @param description a user friendly description of the merge result + * @param newHead + * the object the head points at after the merge + * @param base + * the common base which was used to produce a content-merge. May + * be <code>null</code> if the merge-result was produced without + * computing a common base + * @param mergedCommits + * all the commits which have been merged together + * @param mergeStatus + * the status the merge resulted in + * @param mergeStrategy + * the used {@link MergeStrategy} + * @param description + * a user friendly description of the merge result */ - public MergeResult(ObjectId newHead, MergeStatus mergeStatus, + public MergeResult(ObjectId newHead, ObjectId base, + ObjectId[] mergedCommits, MergeStatus mergeStatus, MergeStrategy mergeStrategy, String description) { this.newHead = newHead; + this.mergedCommits = mergedCommits; + this.base = base; this.mergeStatus = mergeStatus; this.mergeStrategy = mergeStrategy; this.description = description; @@ -139,12 +173,83 @@ public class MergeResult { return mergeStatus; } + /** + * @return all the commits which have been merged together + */ + public ObjectId[] getMergedCommits() { + return mergedCommits; + } + + /** + * @return base the common base which was used to produce a content-merge. + * May be <code>null</code> if the merge-result was produced without + * computing a common base + */ + public ObjectId getBase() { + return base; + } + @Override public String toString() { + boolean first = true; + StringBuilder commits = new StringBuilder(); + for (ObjectId commit : mergedCommits) { + if (!first) + commits.append(", "); + else + first = false; + commits.append(ObjectId.toString(commit)); + } return MessageFormat.format( JGitText.get().mergeUsingStrategyResultedInDescription, - mergeStrategy.getName(), mergeStatus, (description == null ? "" - : ", " + description)); + commits, ObjectId.toString(base), mergeStrategy.getName(), + mergeStatus, (description == null ? "" : ", " + description)); } + /** + * @param conflicts + * the conflicts to set + */ + public void setConflicts(Map<String, int[][]> conflicts) { + this.conflicts = conflicts; + } + + /** + * Returns information about the conflicts which occurred during a + * {@link MergeCommand}. The returned value maps the path of a conflicting + * file to a two-dimensional int-array of line-numbers telling where in the + * file conflict markers for which merged commit can be found. + * <p> + * If the returned value contains a mapping "path"->[x][y]=z then this means + * <ul> + * <li>the file with path "path" contains conflicts</li> + * <li>if y < "number of merged commits": for conflict number x in this file + * the chunk which was copied from commit number y starts on line number z. + * All numberings and line numbers start with 0.</li> + * <li>if y == "number of merged commits": the first non-conflicting line + * after conflict number x starts at line number z</li> + * </ul> + * <p> + * Example code how to parse this data: + * <pre> MergeResult m=...; + * Map<String, int[][]> allConflicts = m.getConflicts(); + * for (String path : allConflicts.keySet()) { + * int[][] c = allConflicts.get(path); + * System.out.println("Conflicts in file " + path); + * for (int i = 0; i < c.length; ++i) { + * System.out.println(" Conflict #" + i); + * for (int j = 0; j < (c[i].length) - 1; ++j) { + * if (c[i][j] >= 0) + * System.out.println(" Chunk for " + * + m.getMergedCommits()[j] + " starts on line #" + * + c[i][j]); + * } + * } + * }</pre> + * + * @return the conflicts or <code>null</code> if no conflict occured + */ + public Map<String, int[][]> getConflicts() { + return conflicts; + } } |