RevWalk rw)
throws IOException {
ObjectInserter inserter = null;
// get DirCacheBuilder for existing index
DirCacheBuilder existingBuilder = index.builder();
// get DirCacheBuilder for newly created in-core index to build a
// temporary index for this commit
DirCache inCoreIndex = DirCache.newInCore();
DirCacheBuilder tempBuilder = inCoreIndex.builder();
onlyProcessed = new boolean[only.size()];
boolean emptyCommit = true;
TreeWalk treeWalk = new TreeWalk(repo);
int dcIdx = treeWalk.addTree(new DirCacheBuildIterator(existingBuilder));
int fIdx = treeWalk.addTree(new FileTreeIterator(repo));
int hIdx = -1;
if (headId != null)
hIdx = treeWalk.addTree(rw.parseTree(headId));
treeWalk.setRecursive(true);
String lastAddedFile = null;
while (treeWalk.next()) {
String path = treeWalk.getPathString();
// check if current entry's path matches a specified path
int pos = lookupOnly(path);
CanonicalTreeParser hTree = null;
if (hIdx != -1)
hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
DirCacheIterator.class);
if (pos >= 0) {
// include entry in commit
FileTreeIterator fTree = treeWalk.getTree(fIdx,
FileTreeIterator.class);
// check if entry refers to a tracked file
boolean tracked = dcTree != null || hTree != null;
if (!tracked)
break;
// for an unmerged path, DirCacheBuildIterator will yield 3
// entries, we only want to add one
if (path.equals(lastAddedFile))
continue;
lastAddedFile = path;
if (fTree != null) {
// create a new DirCacheEntry with data retrieved from disk
final DirCacheEntry dcEntry = new DirCacheEntry(path);
long entryLength = fTree.getEntryLength();
dcEntry.setLength(entryLength);
dcEntry.setLastModified(fTree.getEntryLastModified());
dcEntry.setFileMode(fTree.getIndexFileMode(dcTree));
boolean objectExists = (dcTree != null && fTree
.idEqual(dcTree))
|| (hTree != null && fTree.idEqual(hTree));
if (objectExists) {
dcEntry.setObjectId(fTree.getEntryObjectId());
} else {
if (FileMode.GITLINK.equals(dcEntry.getFileMode()))
dcEntry.setObjectId(fTree.getEntryObjectId());
else {
// insert object
if (inserter == null)
inserter = repo.newObjectInserter();
long contentLength = fTree.getEntryContentLength();
InputStream inputStream = fTree.openEntryStream();
try {
dcEntry.setObjectId(inserter.insert(
Constants.OBJ_BLOB, contentLength,
inputStream));
} finally {
inputStream.close();
}
}
}
// add to existing index
existingBuilder.add(dcEntry);
// add to temporary in-core index
tempBuilder.add(dcEntry);
if (emptyCommit
&& (hTree == null || !hTree.idEqual(fTree) || hTree
.getEntryRawMode() != fTree
.getEntryRawMode()))
// this is a change
emptyCommit = false;
} else {
// if no file exists on disk, neither add it to
// index nor to temporary in-core index
if (emptyCommit && hTree != null)
// this is a change
emptyCommit = false;
}
// keep track of processed path
onlyProcessed[pos] = true;
} else {
// add entries from HEAD for all other paths
if (hTree != null) {
// create a new DirCacheEntry with data retrieved from HEAD
final DirCacheEntry dcEntry = new DirCacheEntry(path);
dcEntry.setObjectId(hTree.getEntryObjectId());
dcEntry.setFileMode(hTree.getEntryFileMode());
// add to temporary in-core index
tempBuilder.add(dcEntry);
}
// preserve existing entry in index
if (dcTree != null)
existingBuilder.add(dcTree.getDirCacheEntry());
}
}
// there must be no unprocessed paths left at this point; otherwise an
// untracked or unknown path has been specified
for (int i = 0; i < onlyProcessed.length; i++)
if (!onlyProcessed[i])
throw new JGitInternalException(MessageFormat.format(
JGitText.get().entryNotFoundByPath, only.get(i)));
// there must be at least one change
if (emptyCommit)
throw new JGitInternalException(JGitText.get().emptyCommit);
// update index
existingBuilder.commit();
// finish temporary in-core index used for this commit
tempBuilder.finish();
return inCoreIndex;
}