aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/merge
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/merge')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ContentMergeStrategy.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/EolAwareOutputStream.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java46
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeChunk.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java83
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatterPass.java72
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java36
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java214
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMergeStrategy.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java3
16 files changed, 350 insertions, 174 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ContentMergeStrategy.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ContentMergeStrategy.java
index 6d568643d5..a835a1dfc5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ContentMergeStrategy.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ContentMergeStrategy.java
@@ -23,5 +23,12 @@ public enum ContentMergeStrategy {
OURS,
/** Resolve the conflict hunk using the theirs version. */
- THEIRS
-} \ No newline at end of file
+ THEIRS,
+
+ /**
+ * Resolve the conflict hunk using a union of both ours and theirs versions.
+ *
+ * @since 6.10.1
+ */
+ UNION
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/EolAwareOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/EolAwareOutputStream.java
index e44970abff..8857ef8571 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/EolAwareOutputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/EolAwareOutputStream.java
@@ -74,19 +74,21 @@ class EolAwareOutputStream extends OutputStream {
write('\n');
}
- /** @return true if a new line has just begun. */
+ /**
+ * Whether a new line has just begun
+ *
+ * @return true if a new line has just begun.
+ */
boolean isBeginln() {
return bol;
}
- /** {@inheritDoc} */
@Override
public void write(int val) throws IOException {
out.write(val);
bol = (val == '\n');
}
- /** {@inheritDoc} */
@Override
public void write(byte[] buf, int pos, int cnt) throws IOException {
if (cnt > 0) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
index 80607351ae..d0d4d367b9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
@@ -90,10 +90,16 @@ public final class MergeAlgorithm {
/**
* Does the three way merge between a common base and two sequences.
*
- * @param cmp comparison method for this execution.
- * @param base the common base sequence
- * @param ours the first sequence to be merged
- * @param theirs the second sequence to be merged
+ * @param <S>
+ * type of the sequences
+ * @param cmp
+ * comparison method for this execution.
+ * @param base
+ * the common base sequence
+ * @param ours
+ * the first sequence to be merged
+ * @param theirs
+ * the second sequence to be merged
* @return the resulting content
*/
public <S extends Sequence> MergeResult<S> merge(
@@ -114,6 +120,7 @@ public final class MergeAlgorithm {
result.add(1, 0, 0, ConflictState.NO_CONFLICT);
break;
case THEIRS:
+ case UNION:
result.add(2, 0, theirs.size(),
ConflictState.NO_CONFLICT);
break;
@@ -121,6 +128,8 @@ public final class MergeAlgorithm {
// Let their complete content conflict with empty text
result.add(1, 0, 0,
ConflictState.FIRST_CONFLICTING_RANGE);
+ result.add(0, 0, base.size(),
+ ConflictState.BASE_CONFLICTING_RANGE);
result.add(2, 0, theirs.size(),
ConflictState.NEXT_CONFLICTING_RANGE);
break;
@@ -140,6 +149,7 @@ public final class MergeAlgorithm {
// we modified, they deleted
switch (strategy) {
case OURS:
+ case UNION:
result.add(1, 0, ours.size(), ConflictState.NO_CONFLICT);
break;
case THEIRS:
@@ -149,6 +159,8 @@ public final class MergeAlgorithm {
// Let our complete content conflict with empty text
result.add(1, 0, ours.size(),
ConflictState.FIRST_CONFLICTING_RANGE);
+ result.add(0, 0, base.size(),
+ ConflictState.BASE_CONFLICTING_RANGE);
result.add(2, 0, 0, ConflictState.NEXT_CONFLICTING_RANGE);
break;
}
@@ -208,13 +220,18 @@ public final class MergeAlgorithm {
// set some initial values for the ranges in A and B which we
// want to handle
+ int oursBeginA = oursEdit.getBeginA();
+ int theirsBeginA = theirsEdit.getBeginA();
int oursBeginB = oursEdit.getBeginB();
int theirsBeginB = theirsEdit.getBeginB();
// harmonize the start of the ranges in A and B
if (oursEdit.getBeginA() < theirsEdit.getBeginA()) {
+ theirsBeginA -= theirsEdit.getBeginA()
+ - oursEdit.getBeginA();
theirsBeginB -= theirsEdit.getBeginA()
- oursEdit.getBeginA();
} else {
+ oursBeginA -= oursEdit.getBeginA() - theirsEdit.getBeginA();
oursBeginB -= oursEdit.getBeginA() - theirsEdit.getBeginA();
}
@@ -260,11 +277,15 @@ public final class MergeAlgorithm {
}
// harmonize the end of the ranges in A and B
+ int oursEndA = oursEdit.getEndA();
+ int theirsEndA = theirsEdit.getEndA();
int oursEndB = oursEdit.getEndB();
int theirsEndB = theirsEdit.getEndB();
if (oursEdit.getEndA() < theirsEdit.getEndA()) {
+ oursEndA += theirsEdit.getEndA() - oursEdit.getEndA();
oursEndB += theirsEdit.getEndA() - oursEdit.getEndA();
} else {
+ theirsEndA += oursEdit.getEndA() - theirsEdit.getEndA();
theirsEndB += oursEdit.getEndA() - theirsEdit.getEndA();
}
@@ -314,10 +335,27 @@ public final class MergeAlgorithm {
theirsEndB - commonSuffix,
ConflictState.NO_CONFLICT);
break;
+ case UNION:
+ result.add(1, oursBeginB + commonPrefix,
+ oursEndB - commonSuffix,
+ ConflictState.NO_CONFLICT);
+
+ result.add(2, theirsBeginB + commonPrefix,
+ theirsEndB - commonSuffix,
+ ConflictState.NO_CONFLICT);
+ break;
default:
result.add(1, oursBeginB + commonPrefix,
oursEndB - commonSuffix,
ConflictState.FIRST_CONFLICTING_RANGE);
+
+ int baseBegin = Math.min(oursBeginA, theirsBeginA)
+ + commonPrefix;
+ int baseEnd = Math.min(base.size(),
+ Math.max(oursEndA, theirsEndA)) - commonSuffix;
+ result.add(0, baseBegin, baseEnd,
+ ConflictState.BASE_CONFLICTING_RANGE);
+
result.add(2, theirsBeginB + commonPrefix,
theirsEndB - commonSuffix,
ConflictState.NEXT_CONFLICTING_RANGE);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeChunk.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeChunk.java
index ca998e30bc..7102aa6998 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeChunk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeChunk.java
@@ -29,14 +29,22 @@ public class MergeChunk {
NO_CONFLICT,
/**
- * This chunk does belong to a conflict and is the first one of the
+ * This chunk does belong to a conflict and is the ours section of the
* conflicting chunks
*/
FIRST_CONFLICTING_RANGE,
/**
- * This chunk does belong to a conflict but is not the first one of the
- * conflicting chunks. It's a subsequent one.
+ * This chunk does belong to a conflict and is the base section of the
+ * conflicting chunks
+ *
+ * @since 6.7
+ */
+ BASE_CONFLICTING_RANGE,
+
+ /**
+ * This chunk does belong to a conflict and is the theirs section of
+ * the conflicting chunks. It's a subsequent one.
*/
NEXT_CONFLICTING_RANGE
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
index 18b0ad92c8..079db4a07f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
@@ -22,6 +22,7 @@ import org.eclipse.jgit.diff.RawText;
* A class to convert merge results into a Git conformant textual presentation
*/
public class MergeFormatter {
+
/**
* Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
* objects in a Git conformant way. This method also assumes that the
@@ -39,27 +40,24 @@ public class MergeFormatter {
* name. This name is following the "&lt;&lt;&lt;&lt;&lt;&lt;&lt;
* " or "&gt;&gt;&gt;&gt;&gt;&gt;&gt; " conflict markers. The
* names for the sequences are given in this list
- * @param charsetName
- * the name of the character set used when writing conflict
- * metadata
+ * @param charset
+ * the character set used when writing conflict metadata
* @throws java.io.IOException
- * @deprecated Use
- * {@link #formatMerge(OutputStream, MergeResult, List, Charset)}
- * instead.
+ * if an IO error occurred
+ * @since 5.2
*/
- @Deprecated
public void formatMerge(OutputStream out, MergeResult<RawText> res,
- List<String> seqName, String charsetName) throws IOException {
- formatMerge(out, res, seqName, Charset.forName(charsetName));
+ List<String> seqName, Charset charset) throws IOException {
+ new MergeFormatterPass(out, res, seqName, charset).formatMerge();
}
/**
* Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
- * objects in a Git conformant way. This method also assumes that the
- * {@link org.eclipse.jgit.diff.RawText} objects being merged are line
- * oriented files which use LF as delimiter. This method will also use LF to
- * separate chunks and conflict metadata, therefore it fits only to texts
- * that are LF-separated lines.
+ * objects in a Git conformant way using diff3 style. This method also
+ * assumes that the {@link org.eclipse.jgit.diff.RawText} objects being
+ * merged are line oriented files which use LF as delimiter. This method
+ * will also use LF to separate chunks and conflict metadata, therefore it
+ * fits only to texts that are LF-separated lines.
*
* @param out
* the output stream where to write the textual presentation
@@ -68,16 +66,18 @@ public class MergeFormatter {
* @param seqName
* When a conflict is reported each conflicting range will get a
* name. This name is following the "&lt;&lt;&lt;&lt;&lt;&lt;&lt;
- * " or "&gt;&gt;&gt;&gt;&gt;&gt;&gt; " conflict markers. The
- * names for the sequences are given in this list
+ * ", "|||||||" or "&gt;&gt;&gt;&gt;&gt;&gt;&gt; " conflict
+ * markers. The names for the sequences are given in this list
* @param charset
* the character set used when writing conflict metadata
* @throws java.io.IOException
- * @since 5.2
+ * if an IO error occurred
+ * @since 6.7
*/
- public void formatMerge(OutputStream out, MergeResult<RawText> res,
- List<String> seqName, Charset charset) throws IOException {
- new MergeFormatterPass(out, res, seqName, charset).formatMerge();
+ public void formatMergeDiff3(OutputStream out,
+ MergeResult<RawText> res, List<String> seqName, Charset charset)
+ throws IOException {
+ new MergeFormatterPass(out, res, seqName, charset, true).formatMerge();
}
/**
@@ -98,27 +98,29 @@ public class MergeFormatter {
* the name ranges from ours should get
* @param theirsName
* the name ranges from theirs should get
- * @param charsetName
- * the name of the character set used when writing conflict
- * metadata
+ * @param charset
+ * the character set used when writing conflict metadata
* @throws java.io.IOException
- * @deprecated use
- * {@link #formatMerge(OutputStream, MergeResult, String, String, String, Charset)}
- * instead.
+ * if an IO error occurred
+ * @since 5.2
*/
- @Deprecated
+ @SuppressWarnings("unchecked")
public void formatMerge(OutputStream out, MergeResult res, String baseName,
- String oursName, String theirsName, String charsetName) throws IOException {
- formatMerge(out, res, baseName, oursName, theirsName,
- Charset.forName(charsetName));
+ String oursName, String theirsName, Charset charset)
+ throws IOException {
+ List<String> names = new ArrayList<>(3);
+ names.add(baseName);
+ names.add(oursName);
+ names.add(theirsName);
+ formatMerge(out, res, names, charset);
}
/**
- * Formats the results of a merge of exactly two
- * {@link org.eclipse.jgit.diff.RawText} objects in a Git conformant way.
- * This convenience method accepts the names for the three sequences (base
- * and the two merged sequences) as explicit parameters and doesn't require
- * the caller to specify a List
+ * Formats the results of a merge of three
+ * {@link org.eclipse.jgit.diff.RawText} objects in a Git conformant way,
+ * using diff-3 style. This convenience method accepts the names for the
+ * three sequences (base and the two merged sequences) as explicit
+ * parameters and doesn't require the caller to specify a List
*
* @param out
* the {@link java.io.OutputStream} where to write the textual
@@ -134,16 +136,17 @@ public class MergeFormatter {
* @param charset
* the character set used when writing conflict metadata
* @throws java.io.IOException
- * @since 5.2
+ * if an IO error occurred
+ * @since 6.7
*/
@SuppressWarnings("unchecked")
- public void formatMerge(OutputStream out, MergeResult res, String baseName,
- String oursName, String theirsName, Charset charset)
- throws IOException {
+ public void formatMergeDiff3(OutputStream out,
+ MergeResult res, String baseName, String oursName,
+ String theirsName, Charset charset) throws IOException {
List<String> names = new ArrayList<>(3);
names.add(baseName);
names.add(oursName);
names.add(theirsName);
- formatMerge(out, res, names, charset);
+ formatMergeDiff3(out, res, names, charset);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatterPass.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatterPass.java
index f09b343007..5e80b5fb23 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatterPass.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatterPass.java
@@ -31,6 +31,8 @@ class MergeFormatterPass {
private final boolean threeWayMerge;
+ private final boolean writeBase; // diff3-style requested
+
private String lastConflictingName; // is set to non-null whenever we are in
// a conflict
@@ -50,22 +52,47 @@ class MergeFormatterPass {
*/
MergeFormatterPass(OutputStream out, MergeResult<RawText> res,
List<String> seqName, Charset charset) {
+ this(out, res, seqName, charset, false);
+ }
+
+ /**
+ * @param out
+ * the {@link java.io.OutputStream} where to write the textual
+ * presentation
+ * @param res
+ * the merge result which should be presented
+ * @param seqName
+ * When a conflict is reported each conflicting range will get a
+ * name. This name is following the "&lt;&lt;&lt;&lt;&lt;&lt;&lt;
+ * ", "|||||||" or "&gt;&gt;&gt;&gt;&gt;&gt;&gt; " conflict
+ * markers. The names for the sequences are given in this list
+ * @param charset
+ * the character set used when writing conflict metadata
+ * @param writeBase
+ * base's contribution should be written in conflicts
+ */
+ MergeFormatterPass(OutputStream out, MergeResult<RawText> res,
+ List<String> seqName, Charset charset, boolean writeBase) {
this.out = new EolAwareOutputStream(out);
this.res = res;
this.seqName = seqName;
this.charset = charset;
this.threeWayMerge = (res.getSequences().size() == 3);
+ this.writeBase = writeBase;
}
void formatMerge() throws IOException {
boolean missingNewlineAtEnd = false;
for (MergeChunk chunk : res) {
- RawText seq = res.getSequences().get(chunk.getSequenceIndex());
- writeConflictMetadata(chunk);
- // the lines with conflict-metadata are written. Now write the chunk
- for (int i = chunk.getBegin(); i < chunk.getEnd(); i++)
- writeLine(seq, i);
- missingNewlineAtEnd = seq.isMissingNewlineAtEnd();
+ if (!isBase(chunk) || writeBase) {
+ RawText seq = res.getSequences().get(chunk.getSequenceIndex());
+ writeConflictMetadata(chunk);
+ // the lines with conflict-metadata are written. Now write the
+ // chunk
+ for (int i = chunk.getBegin(); i < chunk.getEnd(); i++)
+ writeLine(seq, i);
+ missingNewlineAtEnd = seq.isMissingNewlineAtEnd();
+ }
}
// one possible leftover: if the merge result ended with a conflict we
// have to close the last conflict here
@@ -77,16 +104,19 @@ class MergeFormatterPass {
private void writeConflictMetadata(MergeChunk chunk) throws IOException {
if (lastConflictingName != null
- && chunk.getConflictState() != ConflictState.NEXT_CONFLICTING_RANGE) {
- // found the end of an conflict
+ && !isTheirs(chunk) && !isBase(chunk)) {
+ // found the end of a conflict
writeConflictEnd();
}
- if (chunk.getConflictState() == ConflictState.FIRST_CONFLICTING_RANGE) {
- // found the start of an conflict
+ if (isOurs(chunk)) {
+ // found the start of a conflict
writeConflictStart(chunk);
- } else if (chunk.getConflictState() == ConflictState.NEXT_CONFLICTING_RANGE) {
- // found another conflicting chunk
+ } else if (isTheirs(chunk)) {
+ // found the theirs conflicting chunk
writeConflictChange(chunk);
+ } else if (isBase(chunk)) {
+ // found the base conflicting chunk
+ writeConflictBase(chunk);
}
}
@@ -113,6 +143,11 @@ class MergeFormatterPass {
+ lastConflictingName);
}
+ private void writeConflictBase(MergeChunk chunk) throws IOException {
+ lastConflictingName = seqName.get(chunk.getSequenceIndex());
+ writeln("||||||| " + lastConflictingName); //$NON-NLS-1$
+ }
+
private void writeln(String s) throws IOException {
out.beginln();
out.write((s + "\n").getBytes(charset)); //$NON-NLS-1$
@@ -125,4 +160,17 @@ class MergeFormatterPass {
if (out.isBeginln())
out.write('\n');
}
+
+ private boolean isBase(MergeChunk chunk) {
+ return chunk.getConflictState() == ConflictState.BASE_CONFLICTING_RANGE;
+ }
+
+ private boolean isOurs(MergeChunk chunk) {
+ return chunk
+ .getConflictState() == ConflictState.FIRST_CONFLICTING_RANGE;
+ }
+
+ private boolean isTheirs(MergeChunk chunk) {
+ return chunk.getConflictState() == ConflictState.NEXT_CONFLICTING_RANGE;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
index e0c083f55c..039d7d844c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
@@ -92,24 +92,6 @@ public class MergeMessageFormatter {
}
/**
- * Add section with conflicting paths to merge message. Lines are prefixed
- * with a hash.
- *
- * @param message
- * the original merge message
- * @param conflictingPaths
- * the paths with conflicts
- * @return merge message with conflicting paths added
- * @deprecated since 6.1; use
- * {@link #formatWithConflicts(String, Iterable, char)} instead
- */
- @Deprecated
- public String formatWithConflicts(String message,
- List<String> conflictingPaths) {
- return formatWithConflicts(message, conflictingPaths, '#');
- }
-
- /**
* Add section with conflicting paths to merge message.
*
* @param message
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java
index 20fc3c339c..acf955303d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java
@@ -97,7 +97,6 @@ public class MergeResult<S extends Sequence> implements Iterable<MergeChunk> {
static final ConflictState[] states = ConflictState.values();
- /** {@inheritDoc} */
@Override
public Iterator<MergeChunk> iterator() {
return new Iterator<>() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java
index df6068925b..f58ef4faba 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java
@@ -18,10 +18,11 @@ package org.eclipse.jgit.merge;
import java.io.IOException;
import java.text.MessageFormat;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
-import java.util.TimeZone;
+import java.util.stream.Collectors;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -123,6 +124,7 @@ public class RecursiveMerger extends ResolveMerger {
* synthetic merge base this commit is visible only the merger's
* RevWalk and will not be in the repository.
* @throws java.io.IOException
+ * if an IO error occurred
* @throws IncorrectObjectTypeException
* one of the input objects is not a commit.
* @throws NoMergeBaseException
@@ -184,12 +186,15 @@ public class RecursiveMerger extends ResolveMerger {
if (mergeTrees(bcTree, currentBase.getTree(),
nextBase.getTree(), true))
currentBase = createCommitForTree(resultTree, parents);
- else
+ else {
+ String failedPaths = failingPathsMessage();
throw new NoMergeBaseException(
NoMergeBaseException.MergeBaseFailureReason.CONFLICTS_DURING_MERGE_BASE_CALCULATION,
MessageFormat.format(
JGitText.get().mergeRecursiveConflictsWhenMergingCommonAncestors,
- currentBase.getName(), nextBase.getName()));
+ currentBase.getName(), nextBase.getName(),
+ failedPaths));
+ }
}
} finally {
inCore = oldIncore;
@@ -213,6 +218,7 @@ public class RecursiveMerger extends ResolveMerger {
* the list of parent commits
* @return a new commit visible only within this merger's RevWalk.
* @throws IOException
+ * if an IO error occurred
*/
private RevCommit createCommitForTree(ObjectId tree, List<RevCommit> parents)
throws IOException {
@@ -227,11 +233,23 @@ public class RecursiveMerger extends ResolveMerger {
private static PersonIdent mockAuthor(List<RevCommit> parents) {
String name = RecursiveMerger.class.getSimpleName();
int time = 0;
- for (RevCommit p : parents)
+ for (RevCommit p : parents) {
time = Math.max(time, p.getCommitTime());
- return new PersonIdent(
- name, name + "@JGit", //$NON-NLS-1$
- new Date((time + 1) * 1000L),
- TimeZone.getTimeZone("GMT+0000")); //$NON-NLS-1$
+ }
+ return new PersonIdent(name, name + "@JGit", //$NON-NLS-1$
+ Instant.ofEpochSecond(time+1), ZoneOffset.UTC);
+ }
+
+ private String failingPathsMessage() {
+ int max = 25;
+ String failedPaths = failingPaths.entrySet().stream().limit(max)
+ .map(entry -> entry.getKey() + ":" + entry.getValue()) //$NON-NLS-1$
+ .collect(Collectors.joining("\n")); //$NON-NLS-1$
+
+ if (failingPaths.size() > max) {
+ failedPaths = String.format("%s\n... (%s failing paths omitted)", //$NON-NLS-1$
+ failedPaths, Integer.valueOf(failingPaths.size() - max));
+ }
+ return failedPaths;
}
}
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 e56513d4e9..dc96f65b87 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -3,8 +3,8 @@
* Copyright (C) 2010-2012, Matthias Sohn <matthias.sohn@sap.com>
* Copyright (C) 2012, Research In Motion Limited
* Copyright (C) 2017, Obeo (mathieu.cartaud@obeo.fr)
- * Copyright (C) 2018, 2022 Thomas Wolf <twolf@apache.org>
- * Copyright (C) 2022, Google Inc. and others
+ * Copyright (C) 2018, 2023 Thomas Wolf <twolf@apache.org>
+ * Copyright (C) 2023, Google Inc. and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -32,7 +32,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -42,11 +41,13 @@ import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.attributes.Attribute;
import org.eclipse.jgit.attributes.Attributes;
+import org.eclipse.jgit.attributes.AttributesNodeProvider;
import org.eclipse.jgit.diff.DiffAlgorithm;
import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.diff.Sequence;
+import org.eclipse.jgit.dircache.Checkout;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
import org.eclipse.jgit.dircache.DirCacheBuilder;
@@ -79,7 +80,6 @@ import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.LfsFactory;
import org.eclipse.jgit.util.LfsFactory.LfsInputStream;
import org.eclipse.jgit.util.TemporaryBuffer;
@@ -106,13 +106,15 @@ public class ResolveMerger extends ThreeWayMerger {
*/
public static class Result {
- private final List<String> modifiedFiles = new LinkedList<>();
+ private final List<String> modifiedFiles = new ArrayList<>();
- private final List<String> failedToDelete = new LinkedList<>();
+ private final List<String> failedToDelete = new ArrayList<>();
private ObjectId treeId = null;
/**
+ * Get modified tree id if any
+ *
* @return Modified tree ID if any, or null otherwise.
*/
public ObjectId getTreeId() {
@@ -120,6 +122,8 @@ public class ResolveMerger extends ThreeWayMerger {
}
/**
+ * Get path of files that couldn't be deleted
+ *
* @return Files that couldn't be deleted.
*/
public List<String> getFailedToDelete() {
@@ -127,6 +131,8 @@ public class ResolveMerger extends ThreeWayMerger {
}
/**
+ * Get path of modified files
+ *
* @return Files modified during this operation.
*/
public List<String> getModifiedFiles() {
@@ -205,6 +211,12 @@ public class ResolveMerger extends ThreeWayMerger {
private boolean indexChangesWritten;
/**
+ * {@link Checkout} to use for actually checking out files if
+ * {@link #inCore} is {@code false}.
+ */
+ private Checkout checkout;
+
+ /**
* @param repo
* the {@link Repository}.
* @param dirCache
@@ -223,6 +235,7 @@ public class ResolveMerger extends ThreeWayMerger {
this.inCoreFileSizeLimit = getInCoreFileSizeLimit(config);
this.checkoutMetadataByPath = new HashMap<>();
this.cleanupMetadataByPath = new HashMap<>();
+ this.checkout = new Checkout(nonNullRepo(), workingTreeOptions);
}
/**
@@ -350,9 +363,8 @@ public class ResolveMerger extends ThreeWayMerger {
}
// All content operations are successfully done. If we can now write
- // the
- // new index we are on quite safe ground. Even if the checkout of
- // files coming from "theirs" fails the user can work around such
+ // the new index we are on quite safe ground. Even if the checkout
+ // of files coming from "theirs" fails the user can work around such
// failures by checking out the index again.
if (!builder.commit()) {
revertModifiedFiles();
@@ -466,7 +478,6 @@ public class ResolveMerger extends ThreeWayMerger {
/**
* Detects if CRLF conversion has been configured.
* <p>
- * </p>
* See {@link EolStreamTypeUtil#detectStreamType} for more info.
*
* @param attributes
@@ -518,14 +529,14 @@ public class ResolveMerger extends ThreeWayMerger {
for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut
.entrySet()) {
DirCacheEntry dirCacheEntry = entry.getValue();
+ String gitPath = entry.getKey();
if (dirCacheEntry.getFileMode() == FileMode.GITLINK) {
- new File(nonNullRepo().getWorkTree(), entry.getKey())
- .mkdirs();
+ checkout.checkoutGitlink(dirCacheEntry, gitPath);
} else {
- DirCacheCheckout.checkoutEntry(repo, dirCacheEntry, reader,
- false, checkoutMetadataByPath.get(entry.getKey()),
- workingTreeOptions);
- result.modifiedFiles.add(entry.getKey());
+ checkout.checkout(dirCacheEntry,
+ checkoutMetadataByPath.get(gitPath), reader,
+ gitPath);
+ result.modifiedFiles.add(gitPath);
}
}
}
@@ -550,9 +561,8 @@ public class ResolveMerger extends ThreeWayMerger {
for (String path : result.modifiedFiles) {
DirCacheEntry entry = dirCache.getEntry(path);
if (entry != null) {
- DirCacheCheckout.checkoutEntry(repo, entry, reader, false,
- cleanupMetadataByPath.get(path),
- workingTreeOptions);
+ checkout.checkout(entry, cleanupMetadataByPath.get(path),
+ reader, path);
}
}
}
@@ -586,6 +596,8 @@ public class ResolveMerger extends ThreeWayMerger {
if (inCore) {
return;
}
+ checkout.safeCreateParentDirectory(path, file.getParentFile(),
+ false);
CheckoutMetadata metadata = new CheckoutMetadata(streamType,
smudgeCommand);
@@ -826,6 +838,13 @@ public class ResolveMerger extends ThreeWayMerger {
@NonNull
private ContentMergeStrategy contentStrategy = ContentMergeStrategy.CONFLICT;
+ /**
+ * The {@link AttributesNodeProvider} to use while merging trees.
+ *
+ * @since 6.10.1
+ */
+ protected AttributesNodeProvider attributesNodeProvider;
+
private static MergeAlgorithm getMergeAlgorithm(Config config) {
SupportedAlgorithm diffAlg = config.getEnum(
CONFIG_DIFF_SECTION, null, CONFIG_KEY_ALGORITHM,
@@ -904,7 +923,6 @@ public class ResolveMerger extends ThreeWayMerger {
: strategy;
}
- /** {@inheritDoc} */
@Override
protected boolean mergeImpl() throws IOException {
return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1],
@@ -915,18 +933,23 @@ public class ResolveMerger extends ThreeWayMerger {
* adds a new path with the specified stage to the index builder
*
* @param path
+ * the new path
* @param p
+ * canonical tree parser
* @param stage
- * @param lastMod
+ * the stage
+ * @param lastModified
+ * lastModified attribute of the file
* @param len
+ * file length
* @return the entry which was added to the index
*/
private DirCacheEntry add(byte[] path, CanonicalTreeParser p, int stage,
- Instant lastMod, long len) {
+ Instant lastModified, long len) {
if (p != null && !p.getEntryFileMode().equals(FileMode.TREE)) {
return workTreeUpdater.addExistingToIndex(p.getEntryObjectId(), path,
p.getEntryFileMode(), stage,
- lastMod, (int) len);
+ lastModified, (int) len);
}
return null;
}
@@ -1056,6 +1079,7 @@ public class ResolveMerger extends ThreeWayMerger {
* didn't match ours or the working-dir file was dirty and a
* conflict occurred
* @throws java.io.IOException
+ * if an IO error occurred
* @since 6.1
*/
protected boolean processEntry(CanonicalTreeParser base,
@@ -1257,10 +1281,22 @@ public class ResolveMerger extends ThreeWayMerger {
default:
break;
}
+ if (ignoreConflicts) {
+ // If the path is selected to be treated as binary via attributes, we do not perform
+ // content merge. When ignoreConflicts = true, we simply keep OURS to allow virtual commit
+ // to be built.
+ keep(ourDce);
+ return true;
+ }
+ // add the conflicting path to merge result
+ String currentPath = tw.getPathString();
+ MergeResult<RawText> result = new MergeResult<>(
+ Collections.emptyList());
+ result.setContainsConflicts(true);
+ mergeResults.put(currentPath, result);
addConflict(base, ours, theirs);
-
// attribute merge issues are conflicts but not failures
- unmergedPaths.add(tw.getPathString());
+ unmergedPaths.add(currentPath);
return true;
}
@@ -1272,38 +1308,52 @@ public class ResolveMerger extends ThreeWayMerger {
MergeResult<RawText> result = null;
boolean hasSymlink = FileMode.SYMLINK.equals(modeO)
|| FileMode.SYMLINK.equals(modeT);
+
+ String currentPath = tw.getPathString();
+ // if the path is not a symlink in ours and theirs
if (!hasSymlink) {
try {
result = contentMerge(base, ours, theirs, attributes,
getContentMergeStrategy());
- } catch (BinaryBlobException e) {
- // result == null
- }
- }
- if (result == null) {
- switch (getContentMergeStrategy()) {
- case OURS:
- keep(ourDce);
- return true;
- case THEIRS:
- DirCacheEntry e = add(tw.getRawPath(), theirs,
- DirCacheEntry.STAGE_0, EPOCH, 0);
- if (e != null) {
- addToCheckout(tw.getPathString(), e, attributes);
+ if (result.containsConflicts() && !ignoreConflicts) {
+ result.setContainsConflicts(true);
+ unmergedPaths.add(currentPath);
+ } else if (ignoreConflicts) {
+ result.setContainsConflicts(false);
}
+ updateIndex(base, ours, theirs, result, attributes[T_OURS]);
+ workTreeUpdater.markAsModified(currentPath);
+ // Entry is null - only add the metadata
+ addToCheckout(currentPath, null, attributes);
return true;
- default:
- result = new MergeResult<>(Collections.emptyList());
- result.setContainsConflicts(true);
- break;
+ } catch (BinaryBlobException e) {
+ // The file is binary in either OURS, THEIRS or BASE
+ if (ignoreConflicts) {
+ // When ignoreConflicts = true, we simply keep OURS to allow virtual commit to be built.
+ keep(ourDce);
+ return true;
+ }
}
}
- if (ignoreConflicts) {
- result.setContainsConflicts(false);
+ switch (getContentMergeStrategy()) {
+ case OURS:
+ keep(ourDce);
+ return true;
+ case THEIRS:
+ DirCacheEntry e = add(tw.getRawPath(), theirs,
+ DirCacheEntry.STAGE_0, EPOCH, 0);
+ if (e != null) {
+ addToCheckout(currentPath, e, attributes);
+ }
+ return true;
+ default:
+ result = new MergeResult<>(Collections.emptyList());
+ result.setContainsConflicts(true);
+ break;
}
- String currentPath = tw.getPathString();
if (hasSymlink) {
if (ignoreConflicts) {
+ result.setContainsConflicts(false);
if (((modeT & FileMode.TYPE_MASK) == FileMode.TYPE_FILE)) {
DirCacheEntry e = add(tw.getRawPath(), theirs,
DirCacheEntry.STAGE_0, EPOCH, 0);
@@ -1312,9 +1362,9 @@ public class ResolveMerger extends ThreeWayMerger {
keep(ourDce);
}
} else {
- // Record the conflict
DirCacheEntry e = addConflict(base, ours, theirs);
mergeResults.put(currentPath, result);
+ unmergedPaths.add(currentPath);
// If theirs is a file, check it out. In link/file
// conflicts, C git prefers the file.
if (((modeT & FileMode.TYPE_MASK) == FileMode.TYPE_FILE)
@@ -1323,14 +1373,14 @@ public class ResolveMerger extends ThreeWayMerger {
}
}
} else {
- updateIndex(base, ours, theirs, result, attributes[T_OURS]);
- }
- if (result.containsConflicts() && !ignoreConflicts) {
+ // This is reachable if contentMerge() call above threw BinaryBlobException, so we don't
+ // need to check ignoreConflicts here, since it's already handled above.
+ result.setContainsConflicts(true);
+ addConflict(base, ours, theirs);
unmergedPaths.add(currentPath);
+ mergeResults.put(currentPath, result);
}
- workTreeUpdater.markAsModified(currentPath);
- // Entry is null - only adds the metadata.
- addToCheckout(currentPath, null, attributes);
+ return true;
} else if (modeO != modeT) {
// OURS or THEIRS has been deleted
if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw
@@ -1432,15 +1482,21 @@ public class ResolveMerger extends ThreeWayMerger {
* specified as <code>null</code> then an empty text will be used instead.
*
* @param base
+ * used to parse base tree
* @param ours
+ * used to parse ours tree
* @param theirs
+ * used to parse theirs tree
* @param attributes
+ * attributes for the different stages
* @param strategy
+ * merge strategy
*
* @return the result of the content merge
* @throws BinaryBlobException
* if any of the blobs looks like a binary blob
* @throws IOException
+ * if an IO error occurred
*/
private MergeResult<RawText> contentMerge(CanonicalTreeParser base,
CanonicalTreeParser ours, CanonicalTreeParser theirs,
@@ -1454,11 +1510,26 @@ public class ResolveMerger extends ThreeWayMerger {
: getRawText(ours.getEntryObjectId(), attributes[T_OURS]);
RawText theirsText = theirs == null ? RawText.EMPTY_TEXT
: getRawText(theirs.getEntryObjectId(), attributes[T_THEIRS]);
- mergeAlgorithm.setContentMergeStrategy(strategy);
+ mergeAlgorithm.setContentMergeStrategy(
+ getAttributesContentMergeStrategy(attributes[T_OURS],
+ strategy));
return mergeAlgorithm.merge(RawTextComparator.DEFAULT, baseText,
ourText, theirsText);
}
+ private ContentMergeStrategy getAttributesContentMergeStrategy(
+ Attributes attributes, ContentMergeStrategy strategy) {
+ Attribute attr = attributes.get(Constants.ATTR_MERGE);
+ if (attr != null) {
+ String attrValue = attr.getValue();
+ if (attrValue != null && attrValue
+ .equals(Constants.ATTR_BUILTIN_UNION_MERGE_DRIVER)) {
+ return ContentMergeStrategy.UNION;
+ }
+ }
+ return strategy;
+ }
+
private boolean isIndexDirty() {
if (inCore) {
return false;
@@ -1516,11 +1587,17 @@ public class ResolveMerger extends ThreeWayMerger {
* correct stages to the index.
*
* @param base
+ * used to parse base tree
* @param ours
+ * used to parse ours tree
* @param theirs
+ * used to parse theirs tree
* @param result
+ * merge result
* @param attributes
+ * the file's attributes
* @throws IOException
+ * if an IO error occurred
*/
private void updateIndex(CanonicalTreeParser base,
CanonicalTreeParser ours, CanonicalTreeParser theirs,
@@ -1571,20 +1648,17 @@ public class ResolveMerger extends ThreeWayMerger {
* the files .gitattributes entries
* @return the working tree file to which the merged content was written.
* @throws IOException
+ * if an IO error occurred
*/
private File writeMergedFile(TemporaryBuffer rawMerged,
Attributes attributes)
throws IOException {
File workTree = nonNullRepo().getWorkTree();
- FS fs = nonNullRepo().getFS();
- File of = new File(workTree, tw.getPathString());
- File parentFolder = of.getParentFile();
+ String gitPath = tw.getPathString();
+ File of = new File(workTree, gitPath);
EolStreamType eol = workTreeUpdater.detectCheckoutStreamType(attributes);
- if (!fs.exists(parentFolder)) {
- parentFolder.mkdirs();
- }
workTreeUpdater.updateFileWithContent(rawMerged::openInputStream,
- eol, tw.getSmudgeCommand(attributes), of.getPath(), of);
+ eol, tw.getSmudgeCommand(attributes), gitPath, of);
return of;
}
@@ -1659,7 +1733,6 @@ public class ResolveMerger extends ThreeWayMerger {
return FileMode.GITLINK.equals(mode);
}
- /** {@inheritDoc} */
@Override
public ObjectId getResultTreeId() {
return (resultTree == null) ? null : resultTree.toObjectId();
@@ -1787,6 +1860,18 @@ public class ResolveMerger extends ThreeWayMerger {
this.workingTreeIterator = workingTreeIterator;
}
+ /**
+ * Sets the {@link AttributesNodeProvider} to be used by this merger.
+ *
+ * @param attributesNodeProvider
+ * the attributeNodeProvider to set
+ * @since 6.10.1
+ */
+ public void setAttributesNodeProvider(
+ AttributesNodeProvider attributesNodeProvider) {
+ this.attributesNodeProvider = attributesNodeProvider;
+ }
+
/**
* The resolve conflict way of three way merging
@@ -1819,6 +1904,7 @@ public class ResolveMerger extends ThreeWayMerger {
* content-merge conflicts.
* @return whether the trees merged cleanly
* @throws java.io.IOException
+ * if an IO error occurred
* @since 3.5
*/
protected boolean mergeTrees(AbstractTreeIterator baseTree,
@@ -1830,6 +1916,9 @@ public class ResolveMerger extends ThreeWayMerger {
WorkTreeUpdater.createWorkTreeUpdater(db, dircache);
dircache = workTreeUpdater.getLockedDirCache();
tw = new NameConflictTreeWalk(db, reader);
+ if (attributesNodeProvider != null) {
+ tw.setAttributesNodeProvider(attributesNodeProvider);
+ }
tw.addTree(baseTree);
tw.setHead(tw.addTree(headTree));
@@ -1878,6 +1967,7 @@ public class ResolveMerger extends ThreeWayMerger {
* {@link org.eclipse.jgit.merge.ResolveMerger#mergeTrees(AbstractTreeIterator, RevTree, RevTree, boolean)}
* @return Whether the trees merged cleanly.
* @throws java.io.IOException
+ * if an IO error occurred
* @since 3.5
*/
protected boolean mergeTreeWalk(TreeWalk treeWalk, boolean ignoreConflicts)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java
index 7055ccd127..6064ebe326 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java
@@ -43,25 +43,21 @@ public class StrategyOneSided extends MergeStrategy {
treeIndex = index;
}
- /** {@inheritDoc} */
@Override
public String getName() {
return strategyName;
}
- /** {@inheritDoc} */
@Override
public Merger newMerger(Repository db) {
return new OneSide(db, treeIndex);
}
- /** {@inheritDoc} */
@Override
public Merger newMerger(Repository db, boolean inCore) {
return new OneSide(db, treeIndex);
}
- /** {@inheritDoc} */
@Override
public Merger newMerger(ObjectInserter inserter, Config config) {
return new OneSide(inserter, treeIndex);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java
index c9512edf63..a74bfc0379 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java
@@ -21,25 +21,21 @@ import org.eclipse.jgit.lib.Repository;
*/
public class StrategyRecursive extends StrategyResolve {
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(Repository db) {
return new RecursiveMerger(db, false);
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(Repository db, boolean inCore) {
return new RecursiveMerger(db, inCore);
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) {
return new RecursiveMerger(inserter, config);
}
- /** {@inheritDoc} */
@Override
public String getName() {
return "recursive"; //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java
index 5991ef68a3..a686fd0964 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java
@@ -19,25 +19,21 @@ import org.eclipse.jgit.lib.Repository;
*/
public class StrategyResolve extends ThreeWayMergeStrategy {
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(Repository db) {
return new ResolveMerger(db, false);
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(Repository db, boolean inCore) {
return new ResolveMerger(db, inCore);
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) {
return new ResolveMerger(inserter, config);
}
- /** {@inheritDoc} */
@Override
public String getName() {
return "resolve"; //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
index ff40fc1d68..c3180abd35 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
@@ -43,26 +43,22 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy {
//
}
- /** {@inheritDoc} */
@Override
public String getName() {
return "simple-two-way-in-core"; //$NON-NLS-1$
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(Repository db) {
return new InCoreMerger(db);
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(Repository db, boolean inCore) {
// This class is always inCore, so ignore the parameter
return newMerger(db);
}
- /** {@inheritDoc} */
@Override
public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) {
return new InCoreMerger(inserter);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMergeStrategy.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMergeStrategy.java
index 411789fd95..8cefa6566e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMergeStrategy.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMergeStrategy.java
@@ -16,11 +16,9 @@ import org.eclipse.jgit.lib.Repository;
* A merge strategy to merge 2 trees, using a common base ancestor tree.
*/
public abstract class ThreeWayMergeStrategy extends MergeStrategy {
- /** {@inheritDoc} */
@Override
public abstract ThreeWayMerger newMerger(Repository db);
- /** {@inheritDoc} */
@Override
public abstract ThreeWayMerger newMerger(Repository db, boolean inCore);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java
index f283edee01..68a1b5e509 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java
@@ -88,7 +88,6 @@ public abstract class ThreeWayMerger extends Merger {
}
}
- /** {@inheritDoc} */
@Override
public boolean merge(AnyObjectId... tips) throws IOException {
if (tips.length != 2)
@@ -96,7 +95,6 @@ public abstract class ThreeWayMerger extends Merger {
return super.merge(tips);
}
- /** {@inheritDoc} */
@Override
public ObjectId getBaseCommitId() {
return baseCommitId;
@@ -108,6 +106,7 @@ public abstract class ThreeWayMerger extends Merger {
* @return an iterator over the caller-specified merge base, or the natural
* merge base of the two input commits.
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected AbstractTreeIterator mergeBase() throws IOException {
if (baseTree != null) {