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;
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.FileInputStream;
import java.io.FileNotFoundException;
@ -76,7 +79,6 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
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.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.TemporaryBuffer;
/**
* A three-way merger performing a content-merge if necessary
@ -756,90 +759,92 @@ public class ResolveMerger extends ThreeWayMerger {
CanonicalTreeParser ours, CanonicalTreeParser theirs,
MergeResult<RawText> result) throws FileNotFoundException,
IOException {
File of = writeMergedFile(result);
File mergedFile = !inCore ? writeMergedFile(result) : null;
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
// A conflict occurred, the file will contain conflict markers
// the index will be populated with the three stages and the
// workdir (if used) contains the halfway merged content.
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
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);
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());
// Set the mode for the new content. Fall back to REGULAR_FILE if
// we can't merge modes of OURS and THEIRS.
int newMode = mergeFileModes(
tw.getRawMode(0),
tw.getRawMode(1),
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 {
dce.setObjectId(getObjectInserter().insert(
Constants.OBJ_BLOB, of.length(), is));
dce.setObjectId(getObjectInserter().insert(OBJ_BLOB, len, is));
} finally {
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}
* is set and we don't have a working tree the content is written to a
* temporary file
* Writes merged file content to the working tree.
*
* @param result
* 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 IOException
*/
private File writeMergedFile(MergeResult<RawText> result)
throws FileNotFoundException, IOException {
MergeFormatter fmt = new MergeFormatter();
File of = null;
FileOutputStream fos;
if (!inCore) {
File workTree = db.getWorkTree();
if (workTree == null)
// TODO: This should be handled by WorkingTreeIterators which
// support write operations
throw new UnsupportedOperationException();
FS fs = db.getFS();
of = new File(workTree, tw.getPathString());
File parentFolder = of.getParentFile();
if (!fs.exists(parentFolder))
parentFolder.mkdirs();
fos = new FileOutputStream(of);
try {
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();
}
File workTree = db.getWorkTree();
if (workTree == null)
// TODO: This should be handled by WorkingTreeIterators which
// support write operations
throw new UnsupportedOperationException();
FS fs = db.getFS();
File of = new File(workTree, tw.getPathString());
File parentFolder = of.getParentFile();
if (!fs.exists(parentFolder))
parentFolder.mkdirs();
FileOutputStream fos = new FileOutputStream(of);
try {
new MergeFormatter().formatMerge(fos, result,
Arrays.asList(commitNames), CHARACTER_ENCODING);
} finally {
fos.close();
}
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
* (compared to base) we choose that one. If ours and theirs have equal
@ -872,7 +877,7 @@ public class ResolveMerger extends ThreeWayMerger {
throws IOException {
if (id.equals(ObjectId.zeroId()))
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) {

Loading…
Cancel
Save