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. 91
      org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

91
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,57 +759,57 @@ 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
// 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()); DirCacheEntry dce = new DirCacheEntry(tw.getPathString());
int newMode = mergeFileModes(tw.getRawMode(0), tw.getRawMode(1),
// 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)); tw.getRawMode(2));
// set the mode for the new content. Fall back to REGULAR_FILE if dce.setFileMode(newMode == FileMode.MISSING.getBits()
// you can't merge modes of OURS and THEIRS ? FileMode.REGULAR_FILE
dce.setFileMode((newMode == FileMode.MISSING.getBits()) ? FileMode.REGULAR_FILE
: FileMode.fromBits(newMode)); : FileMode.fromBits(newMode));
dce.setLastModified(of.lastModified()); if (mergedFile != null) {
dce.setLength((int) of.length()); long len = mergedFile.length();
InputStream is = new FileInputStream(of); 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);
} }
} else
dce.setObjectId(insertMergeResult(result));
builder.add(dce); 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 of = null;
FileOutputStream fos;
if (!inCore) {
File workTree = db.getWorkTree(); File workTree = db.getWorkTree();
if (workTree == null) if (workTree == null)
// TODO: This should be handled by WorkingTreeIterators which // TODO: This should be handled by WorkingTreeIterators which
@ -814,31 +817,33 @@ public class ResolveMerger extends ThreeWayMerger {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
FS fs = db.getFS(); FS fs = db.getFS();
of = new File(workTree, tw.getPathString()); File of = new File(workTree, tw.getPathString());
File parentFolder = of.getParentFile(); File parentFolder = of.getParentFile();
if (!fs.exists(parentFolder)) if (!fs.exists(parentFolder))
parentFolder.mkdirs(); parentFolder.mkdirs();
fos = new FileOutputStream(of); FileOutputStream fos = new FileOutputStream(of);
try { try {
fmt.formatMerge(fos, result, Arrays.asList(commitNames), new MergeFormatter().formatMerge(fos, result,
Constants.CHARACTER_ENCODING); Arrays.asList(commitNames), CHARACTER_ENCODING);
} finally { } finally {
fos.close(); fos.close();
} }
} else if (!result.containsConflicts()) { return of;
// 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$ private ObjectId insertMergeResult(MergeResult<RawText> result)
fos = new FileOutputStream(of); throws IOException {
TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile(10 << 20);
try { try {
fmt.formatMerge(fos, result, Arrays.asList(commitNames), new MergeFormatter().formatMerge(buf, result,
Constants.CHARACTER_ENCODING); Arrays.asList(commitNames), CHARACTER_ENCODING);
buf.close();
return getObjectInserter().insert(OBJ_BLOB, buf.length(),
buf.openInputStream());
} finally { } finally {
fos.close(); buf.destroy();
} }
} }
return of;
}
/** /**
* 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
@ -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