Browse Source

Merge "Process most in-core merges without local temp files"

stable-3.5
Shawn Pearce 10 years ago committed by Gerrit Code Review @ Eclipse.org
parent
commit
73a687fead
  1. 129
      org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

129
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

@ -44,6 +44,9 @@
*/ */
package org.eclipse.jgit.merge; package org.eclipse.jgit.merge;
import static org.eclipse.jgit.lib.Constants.CHARACTER_ENCODING;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -76,7 +79,6 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ObjectReader;
@ -89,6 +91,7 @@ import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator; import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.TemporaryBuffer;
/** /**
* A three-way merger performing a content-merge if necessary * A three-way merger performing a content-merge if necessary
@ -756,90 +759,92 @@ public class ResolveMerger extends ThreeWayMerger {
CanonicalTreeParser ours, CanonicalTreeParser theirs, CanonicalTreeParser ours, CanonicalTreeParser theirs,
MergeResult<RawText> result) throws FileNotFoundException, MergeResult<RawText> result) throws FileNotFoundException,
IOException { IOException {
File of = writeMergedFile(result); File mergedFile = !inCore ? writeMergedFile(result) : null;
if (result.containsConflicts()) { if (result.containsConflicts()) {
// a conflict occurred, the file will contain conflict markers // A conflict occurred, the file will contain conflict markers
// the index will be populated with the three stages and only the // the index will be populated with the three stages and the
// workdir (if used) contains the halfways merged content // workdir (if used) contains the halfway merged content.
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0); add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0); add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
mergeResults.put(tw.getPathString(), result); mergeResults.put(tw.getPathString(), result);
} else { return;
// 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()); // No conflict occurred, the file will contain fully merged content.
int newMode = mergeFileModes(tw.getRawMode(0), tw.getRawMode(1), // The index will be populated with the new merged version.
tw.getRawMode(2)); DirCacheEntry dce = new DirCacheEntry(tw.getPathString());
// set the mode for the new content. Fall back to REGULAR_FILE if
// you can't merge modes of OURS and THEIRS // Set the mode for the new content. Fall back to REGULAR_FILE if
dce.setFileMode((newMode == FileMode.MISSING.getBits()) ? FileMode.REGULAR_FILE // we can't merge modes of OURS and THEIRS.
: FileMode.fromBits(newMode)); int newMode = mergeFileModes(
dce.setLastModified(of.lastModified()); tw.getRawMode(0),
dce.setLength((int) of.length()); tw.getRawMode(1),
InputStream is = new FileInputStream(of); tw.getRawMode(2));
dce.setFileMode(newMode == FileMode.MISSING.getBits()
? FileMode.REGULAR_FILE
: FileMode.fromBits(newMode));
if (mergedFile != null) {
long len = mergedFile.length();
dce.setLastModified(mergedFile.lastModified());
dce.setLength((int) len);
InputStream is = new FileInputStream(mergedFile);
try { try {
dce.setObjectId(getObjectInserter().insert( dce.setObjectId(getObjectInserter().insert(OBJ_BLOB, len, is));
Constants.OBJ_BLOB, of.length(), is));
} finally { } finally {
is.close(); is.close();
if (inCore)
FileUtils.delete(of);
} }
builder.add(dce); } else
} dce.setObjectId(insertMergeResult(result));
builder.add(dce);
} }
/** /**
* Writes merged file content to the working tree. In case {@link #inCore} * Writes merged file content to the working tree.
* is set and we don't have a working tree the content is written to a
* temporary file
* *
* @param result * @param result
* the result of the content merge * the result of the content merge
* @return the file to which the merged content was written * @return the working tree file to which the merged content was written.
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws IOException * @throws IOException
*/ */
private File writeMergedFile(MergeResult<RawText> result) private File writeMergedFile(MergeResult<RawText> result)
throws FileNotFoundException, IOException { throws FileNotFoundException, IOException {
MergeFormatter fmt = new MergeFormatter(); File workTree = db.getWorkTree();
File of = null; if (workTree == null)
FileOutputStream fos; // TODO: This should be handled by WorkingTreeIterators which
if (!inCore) { // support write operations
File workTree = db.getWorkTree(); throw new UnsupportedOperationException();
if (workTree == null)
// TODO: This should be handled by WorkingTreeIterators which FS fs = db.getFS();
// support write operations File of = new File(workTree, tw.getPathString());
throw new UnsupportedOperationException(); File parentFolder = of.getParentFile();
if (!fs.exists(parentFolder))
FS fs = db.getFS(); parentFolder.mkdirs();
of = new File(workTree, tw.getPathString()); FileOutputStream fos = new FileOutputStream(of);
File parentFolder = of.getParentFile(); try {
if (!fs.exists(parentFolder)) new MergeFormatter().formatMerge(fos, result,
parentFolder.mkdirs(); Arrays.asList(commitNames), CHARACTER_ENCODING);
fos = new FileOutputStream(of); } finally {
try { fos.close();
fmt.formatMerge(fos, result, Arrays.asList(commitNames),
Constants.CHARACTER_ENCODING);
} finally {
fos.close();
}
} else if (!result.containsConflicts()) {
// When working inCore, only trivial merges can be handled,
// so we generate objects only in conflict free cases
of = File.createTempFile("merge_", "_temp", null); //$NON-NLS-1$ //$NON-NLS-2$
fos = new FileOutputStream(of);
try {
fmt.formatMerge(fos, result, Arrays.asList(commitNames),
Constants.CHARACTER_ENCODING);
} finally {
fos.close();
}
} }
return of; return of;
} }
private ObjectId insertMergeResult(MergeResult<RawText> result)
throws IOException {
TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile(10 << 20);
try {
new MergeFormatter().formatMerge(buf, result,
Arrays.asList(commitNames), CHARACTER_ENCODING);
buf.close();
return getObjectInserter().insert(OBJ_BLOB, buf.length(),
buf.openInputStream());
} finally {
buf.destroy();
}
}
/** /**
* Try to merge filemodes. If only ours or theirs have changed the mode * Try to merge filemodes. If only ours or theirs have changed the mode
* (compared to base) we choose that one. If ours and theirs have equal * (compared to base) we choose that one. If ours and theirs have equal
@ -872,7 +877,7 @@ public class ResolveMerger extends ThreeWayMerger {
throws IOException { throws IOException {
if (id.equals(ObjectId.zeroId())) if (id.equals(ObjectId.zeroId()))
return new RawText(new byte[] {}); return new RawText(new byte[] {});
return new RawText(db.open(id, Constants.OBJ_BLOB).getCachedBytes()); return new RawText(db.open(id, OBJ_BLOB).getCachedBytes());
} }
private static boolean nonTree(final int mode) { private static boolean nonTree(final int mode) {

Loading…
Cancel
Save