use of org.eclipse.jgit.revwalk.RevTree in project gerrit by GerritCodeReview.
the class VersionedMetaData method openUpdate.
/**
* Open a batch of updates to the same metadata ref.
*
* <p>This allows making multiple commits to a single metadata ref, at the end of which is a
* single ref update. For batching together updates to multiple refs (each consisting of one or
* more commits against their respective refs), create the {@link MetaDataUpdate} with a {@link
* BatchRefUpdate}.
*
* <p>A ref update produced by this {@link BatchMetaDataUpdate} is only committed if there is no
* associated {@link BatchRefUpdate}. As a result, the configured ref updated event is not fired
* if there is an associated batch.
*
* <p>If object inserter, reader and revwalk are provided, then the updates are not flushed,
* allowing callers the flexibility to flush only once after several updates.
*
* @param update helper info about the update.
* @param objInserter Shared object inserter.
* @param objReader Shared object reader.
* @param revWalk Shared rev walk.
* @throws IOException if the update failed.
*/
public BatchMetaDataUpdate openUpdate(MetaDataUpdate update, ObjectInserter objInserter, ObjectReader objReader, RevWalk revWalk) throws IOException {
final Repository db = update.getRepository();
inserter = objInserter == null ? db.newObjectInserter() : objInserter;
reader = objReader == null ? inserter.newReader() : objReader;
final RevWalk rw = revWalk == null ? new RevWalk(reader) : revWalk;
final RevTree tree = revision != null ? rw.parseTree(revision) : null;
newTree = readTree(tree);
return new BatchMetaDataUpdate() {
RevCommit src = revision;
AnyObjectId srcTree = tree;
@Override
public void write(CommitBuilder commit) throws IOException {
write(VersionedMetaData.this, commit);
}
private boolean doSave(VersionedMetaData config, CommitBuilder commit) throws IOException {
DirCache nt = config.newTree;
ObjectReader r = config.reader;
ObjectInserter i = config.inserter;
RevCommit c = config.revision;
try {
config.newTree = newTree;
config.reader = reader;
config.inserter = inserter;
config.revision = src;
return config.onSave(commit);
} catch (ConfigInvalidException e) {
throw new IOException("Cannot update " + getRefName() + " in " + db.getDirectory() + ": " + e.getMessage(), e);
} finally {
config.newTree = nt;
config.reader = r;
config.inserter = i;
config.revision = c;
}
}
@Override
public void write(VersionedMetaData config, CommitBuilder commit) throws IOException {
checkSameRef(config);
if (!doSave(config, commit)) {
return;
}
ObjectId res = newTree.writeTree(inserter);
if (res.equals(srcTree) && !update.allowEmpty() && (commit.getTreeId() == null)) {
// If there are no changes to the content, don't create the commit.
return;
}
// the tree for the updated DirCache.
if (commit.getTreeId() == null) {
commit.setTreeId(res);
} else {
// In this case, the caller populated the tree without using DirCache.
res = commit.getTreeId();
}
if (src != null) {
commit.addParentId(src);
}
if (update.insertChangeId()) {
commit.setMessage(ChangeIdUtil.insertId(commit.getMessage(), CommitMessageUtil.generateChangeId()));
}
src = rw.parseCommit(inserter.insert(commit));
srcTree = res;
}
private void checkSameRef(VersionedMetaData other) {
String thisRef = VersionedMetaData.this.getRefName();
String otherRef = other.getRefName();
checkArgument(otherRef.equals(thisRef), "cannot add %s for %s to %s on %s", other.getClass().getSimpleName(), otherRef, BatchMetaDataUpdate.class.getSimpleName(), thisRef);
}
@Override
public RevCommit createRef(String refName) throws IOException {
if (Objects.equals(src, revision)) {
return revision;
}
return updateRef(ObjectId.zeroId(), src, refName);
}
@Override
public RevCommit commit() throws IOException {
return commitAt(revision);
}
@Override
public RevCommit commitAt(ObjectId expected) throws IOException {
if (Objects.equals(src, expected)) {
return revision;
}
return updateRef(MoreObjects.firstNonNull(expected, ObjectId.zeroId()), src, getRefName());
}
@Override
public void close() {
newTree = null;
if (revWalk == null) {
rw.close();
}
if (objInserter == null && inserter != null) {
inserter.close();
inserter = null;
}
if (objReader == null && reader != null) {
reader.close();
reader = null;
}
}
private RevCommit updateRef(AnyObjectId oldId, AnyObjectId newId, String refName) throws IOException {
BatchRefUpdate bru = update.getBatch();
if (bru != null) {
bru.addCommand(new ReceiveCommand(oldId.toObjectId(), newId.toObjectId(), refName));
if (objInserter == null) {
inserter.flush();
}
revision = rw.parseCommit(newId);
return revision;
}
RefUpdate ru = db.updateRef(refName);
ru.setExpectedOldObjectId(oldId);
ru.setNewObjectId(newId);
ru.setRefLogIdent(update.getCommitBuilder().getAuthor());
String message = update.getCommitBuilder().getMessage();
if (message == null) {
message = "meta data update";
}
try (BufferedReader reader = new BufferedReader(new StringReader(message))) {
// read the subject line and use it as reflog message
ru.setRefLogMessage("commit: " + reader.readLine(), true);
}
logger.atFine().log("Saving commit '%s' on project '%s'", message.trim(), projectName);
inserter.flush();
RefUpdate.Result result = ru.update();
switch(result) {
case NEW:
case FAST_FORWARD:
revision = rw.parseCommit(ru.getNewObjectId());
update.fireGitRefUpdatedEvent(ru);
logger.atFine().log("Saved commit '%s' as revision '%s' on project '%s'", message.trim(), revision.name(), projectName);
return revision;
case LOCK_FAILURE:
throw new LockFailureException(errorMsg(ru, db.getDirectory()), ru);
case FORCED:
case IO_FAILURE:
case NOT_ATTEMPTED:
case NO_CHANGE:
case REJECTED:
case REJECTED_CURRENT_BRANCH:
case RENAMED:
case REJECTED_MISSING_OBJECT:
case REJECTED_OTHER_REASON:
default:
throw new GitUpdateFailureException(errorMsg(ru, db.getDirectory()), ru);
}
}
};
}
use of org.eclipse.jgit.revwalk.RevTree in project gerrit by GerritCodeReview.
the class AbstractSubmoduleSubscription method expectToHaveSubmoduleState.
protected void expectToHaveSubmoduleState(TestRepository<?> repo, String branch, Project.NameKey submodule, ObjectId expectedId) throws Exception {
ObjectId commitId = repo.git().fetch().setRemote("origin").call().getAdvertisedRef("refs/heads/" + branch).getObjectId();
RevWalk rw = repo.getRevWalk();
RevCommit c = rw.parseCommit(commitId);
rw.parseBody(c.getTree());
RevTree tree = c.getTree();
RevObject actualId = repo.get(tree, submodule.get());
assertThat(actualId).isEqualTo(expectedId);
}
use of org.eclipse.jgit.revwalk.RevTree in project gitblit by gitblit.
the class JGitUtils method getNotesOnCommit.
/**
* Returns the list of notes entered about the commit from the refs/notes
* namespace. If the repository does not exist or is empty, an empty list is
* returned.
*
* @param repository
* @param commit
* @return list of notes
*/
public static List<GitNote> getNotesOnCommit(Repository repository, RevCommit commit) {
List<GitNote> list = new ArrayList<GitNote>();
if (!hasCommits(repository)) {
return list;
}
List<RefModel> noteBranches = getNoteBranches(repository, true, -1);
for (RefModel notesRef : noteBranches) {
RevTree notesTree = JGitUtils.getCommit(repository, notesRef.getName()).getTree();
// flat notes list
String notePath = commit.getName();
String text = getStringContent(repository, notesTree, notePath);
if (!StringUtils.isEmpty(text)) {
List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history.size() - 1));
GitNote gitNote = new GitNote(noteRef, text);
list.add(gitNote);
continue;
}
// folder structure
StringBuilder sb = new StringBuilder(commit.getName());
sb.insert(2, '/');
notePath = sb.toString();
text = getStringContent(repository, notesTree, notePath);
if (!StringUtils.isEmpty(text)) {
List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history.size() - 1));
GitNote gitNote = new GitNote(noteRef, text);
list.add(gitNote);
}
}
return list;
}
use of org.eclipse.jgit.revwalk.RevTree in project gitblit by gitblit.
the class BranchTicketService method readTicketsFile.
/**
* Reads a file from the tickets branch.
*
* @param db
* @param file
* @return the file content or null
*/
private String readTicketsFile(Repository db, String file) {
RevWalk rw = null;
try {
ObjectId treeId = db.resolve(BRANCH + "^{tree}");
if (treeId == null) {
return null;
}
rw = new RevWalk(db);
RevTree tree = rw.lookupTree(treeId);
if (tree != null) {
return JGitUtils.getStringContent(db, tree, file, Constants.ENCODING);
}
} catch (IOException e) {
log.error("failed to read " + file, e);
} finally {
if (rw != null) {
rw.close();
}
}
return null;
}
use of org.eclipse.jgit.revwalk.RevTree in project gitblit by gitblit.
the class DiffUtils method getDiff.
/**
* Returns the diff between two commits for the specified file.
*
* @param repository
* @param baseCommit
* if base commit is null the diff is to the primary parent of
* the commit.
* @param commit
* @param path
* if the path is specified, the diff is restricted to that file
* or folder. if unspecified, the diff is for the entire commit.
* @param comparator
* @param outputType
* @param handler
* to use for rendering binary diffs if {@code outputType} is {@link DiffOutputType#HTML HTML}.
* May be {@code null}, resulting in the default behavior.
* @param tabLength
* @return the diff
*/
public static DiffOutput getDiff(Repository repository, RevCommit baseCommit, RevCommit commit, String path, DiffComparator comparator, DiffOutputType outputType, final BinaryDiffHandler handler, int tabLength) {
DiffStat stat = null;
String diff = null;
try {
ByteArrayOutputStream os = null;
DiffFormatter df;
switch(outputType) {
case HTML:
df = new GitBlitDiffFormatter(commit.getName(), repository, path, handler, tabLength);
break;
case PLAIN:
default:
os = new ByteArrayOutputStream();
df = new DiffFormatter(os);
break;
}
df.setRepository(repository);
df.setDiffComparator((comparator == null ? DiffComparator.SHOW_WHITESPACE : comparator).textComparator);
df.setDetectRenames(true);
RevTree commitTree = commit.getTree();
RevTree baseTree;
if (baseCommit == null) {
if (commit.getParentCount() > 0) {
final RevWalk rw = new RevWalk(repository);
RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
rw.dispose();
baseTree = parent.getTree();
} else {
// FIXME initial commit. no parent?!
baseTree = commitTree;
}
} else {
baseTree = baseCommit.getTree();
}
List<DiffEntry> diffEntries = df.scan(baseTree, commitTree);
if (path != null && path.length() > 0) {
for (DiffEntry diffEntry : diffEntries) {
if (diffEntry.getNewPath().equalsIgnoreCase(path)) {
df.format(diffEntry);
break;
}
}
} else {
df.format(diffEntries);
}
df.flush();
if (df instanceof GitBlitDiffFormatter) {
// workaround for complex private methods in DiffFormatter
diff = ((GitBlitDiffFormatter) df).getHtml();
stat = ((GitBlitDiffFormatter) df).getDiffStat();
} else {
diff = os.toString();
}
} catch (Throwable t) {
LOGGER.error("failed to generate commit diff!", t);
}
return new DiffOutput(outputType, diff, stat);
}
Aggregations