use of org.eclipse.jgit.revwalk.RevCommit in project che by eclipse.
the class JGitConnection method commit.
@Override
public Revision commit(CommitParams params) throws GitException {
try {
// Check repository state
RepositoryState repositoryState = repository.getRepositoryState();
if (!repositoryState.canCommit()) {
throw new GitException(format(MESSAGE_COMMIT_NOT_POSSIBLE, repositoryState.getDescription()));
}
if (params.isAmend() && !repositoryState.canAmend()) {
throw new GitException(format(MESSAGE_COMMIT_AMEND_NOT_POSSIBLE, repositoryState.getDescription()));
}
// Check committer
GitUser committer = getUser();
if (committer == null) {
throw new GitException("Committer can't be null");
}
String committerName = committer.getName();
String committerEmail = committer.getEmail();
if (committerName == null || committerEmail == null) {
throw new GitException("Git user name and (or) email wasn't set", ErrorCodes.NO_COMMITTER_NAME_OR_EMAIL_DEFINED);
}
// Check commit message
String message = params.getMessage();
if (message == null) {
throw new GitException("Message wasn't set");
}
Status status = status(StatusFormat.SHORT);
List<String> specified = params.getFiles();
List<String> staged = new ArrayList<>();
staged.addAll(status.getAdded());
staged.addAll(status.getChanged());
staged.addAll(status.getRemoved());
List<String> changed = new ArrayList<>(staged);
changed.addAll(status.getModified());
changed.addAll(status.getMissing());
List<String> specifiedStaged = specified.stream().filter(path -> staged.stream().anyMatch(s -> s.startsWith(path))).collect(Collectors.toList());
List<String> specifiedChanged = specified.stream().filter(path -> changed.stream().anyMatch(c -> c.startsWith(path))).collect(Collectors.toList());
// Check that there are changes present for commit, if 'isAmend' is disabled
if (!params.isAmend()) {
// Check that there are staged changes present for commit, or any changes if 'isAll' is enabled
if (status.isClean()) {
throw new GitException("Nothing to commit, working directory clean");
} else if (!params.isAll() && (specified.isEmpty() ? staged.isEmpty() : specifiedStaged.isEmpty())) {
throw new GitException("No changes added to commit");
}
} else {
/*
By default Jgit doesn't allow to commit not changed specified paths. According to setAllowEmpty method documentation,
setting this flag to true must allow such commit, but it won't because Jgit has a bug:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=510685. As a workaround, specified paths of the commit command will contain
only changed and specified paths. If other changes are present, but the list of changed and specified paths is empty,
throw exception to prevent committing other paths. TODO Remove this check when the bug will be fixed.
*/
if (!specified.isEmpty() && !(params.isAll() ? changed.isEmpty() : staged.isEmpty()) && specifiedChanged.isEmpty()) {
throw new GitException(format("Changes are present but not changed path%s specified for commit.", specified.size() > 1 ? "s were" : " was"));
}
}
// TODO add 'setAllowEmpty(params.isAmend())' when https://bugs.eclipse.org/bugs/show_bug.cgi?id=510685 will be fixed
CommitCommand commitCommand = getGit().commit().setCommitter(committerName, committerEmail).setAuthor(committerName, committerEmail).setMessage(message).setAll(params.isAll()).setAmend(params.isAmend());
if (!params.isAll()) {
// TODO change to 'specified.forEach(commitCommand::setOnly)' when https://bugs.eclipse.org/bugs/show_bug.cgi?id=510685 will be fixed. See description above.
specifiedChanged.forEach(commitCommand::setOnly);
}
// Check if repository is configured with Gerrit Support
String gerritSupportConfigValue = repository.getConfig().getString(ConfigConstants.CONFIG_GERRIT_SECTION, null, ConfigConstants.CONFIG_KEY_CREATECHANGEID);
boolean isGerritSupportConfigured = gerritSupportConfigValue != null ? Boolean.valueOf(gerritSupportConfigValue) : false;
commitCommand.setInsertChangeId(isGerritSupportConfigured);
RevCommit result = commitCommand.call();
GitUser gitUser = newDto(GitUser.class).withName(committerName).withEmail(committerEmail);
return newDto(Revision.class).withBranch(getCurrentBranch()).withId(result.getId().getName()).withMessage(result.getFullMessage()).withCommitTime(MILLISECONDS.convert(result.getCommitTime(), SECONDS)).withCommitter(gitUser);
} catch (GitAPIException exception) {
throw new GitException(exception.getMessage(), exception);
}
}
use of org.eclipse.jgit.revwalk.RevCommit in project che by eclipse.
the class JGitConnection method log.
/** @see org.eclipse.che.api.git.GitConnection#log(LogParams) */
@Override
public LogPage log(LogParams params) throws GitException {
LogCommand logCommand = getGit().log();
try {
setRevisionRange(logCommand, params);
logCommand.setSkip(params.getSkip());
logCommand.setMaxCount(params.getMaxCount());
List<String> fileFilter = params.getFileFilter();
if (fileFilter != null) {
fileFilter.forEach(logCommand::addPath);
}
String filePath = params.getFilePath();
if (!isNullOrEmpty(filePath)) {
logCommand.addPath(filePath);
}
Iterator<RevCommit> revIterator = logCommand.call().iterator();
List<Revision> commits = new ArrayList<>();
while (revIterator.hasNext()) {
RevCommit commit = revIterator.next();
Revision revision = getRevision(commit, filePath);
commits.add(revision);
}
return new LogPage(commits);
} catch (GitAPIException | IOException exception) {
String errorMessage = exception.getMessage();
if (ERROR_LOG_NO_HEAD_EXISTS.equals(errorMessage)) {
throw new GitException(errorMessage, ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED);
} else {
LOG.error("Failed to retrieve log. ", exception);
throw new GitException(exception);
}
}
}
use of org.eclipse.jgit.revwalk.RevCommit in project gerrit by GerritCodeReview.
the class RebaseUtil method findBaseRevision.
/**
* Find the commit onto which a patch set should be rebased.
*
* <p>This is defined as the latest patch set of the change corresponding to this commit's parent,
* or the destination branch tip in the case where the parent's change is merged.
*
* @param patchSet patch set for which the new base commit should be found.
* @param destBranch the destination branch.
* @param git the repository.
* @param rw the RevWalk.
* @return the commit onto which the patch set should be rebased.
* @throws RestApiException if rebase is not possible.
* @throws IOException if accessing the repository fails.
* @throws OrmException if accessing the database fails.
*/
ObjectId findBaseRevision(PatchSet patchSet, Branch.NameKey destBranch, Repository git, RevWalk rw) throws RestApiException, IOException, OrmException {
String baseRev = null;
RevCommit commit = rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get()));
if (commit.getParentCount() > 1) {
throw new UnprocessableEntityException("Cannot rebase a change with multiple parents.");
} else if (commit.getParentCount() == 0) {
throw new UnprocessableEntityException("Cannot rebase a change without any parents (is this the initial commit?).");
}
RevId parentRev = new RevId(commit.getParent(0).name());
CHANGES: for (ChangeData cd : queryProvider.get().byBranchCommit(destBranch, parentRev.get())) {
for (PatchSet depPatchSet : cd.patchSets()) {
if (!depPatchSet.getRevision().equals(parentRev)) {
continue;
}
Change depChange = cd.change();
if (depChange.getStatus() == Status.ABANDONED) {
throw new ResourceConflictException("Cannot rebase a change with an abandoned parent: " + depChange.getKey());
}
if (depChange.getStatus().isOpen()) {
if (depPatchSet.getId().equals(depChange.currentPatchSetId())) {
throw new ResourceConflictException("Change is already based on the latest patch set of the dependent change.");
}
baseRev = cd.currentPatchSet().getRevision().get();
}
break CHANGES;
}
}
if (baseRev == null) {
// We are dependent on a merged PatchSet or have no PatchSet
// dependencies at all.
Ref destRef = git.getRefDatabase().exactRef(destBranch.get());
if (destRef == null) {
throw new UnprocessableEntityException("The destination branch does not exist: " + destBranch.get());
}
baseRev = destRef.getObjectId().getName();
if (baseRev.equals(parentRev.get())) {
throw new ResourceConflictException("Change is already up to date.");
}
}
return ObjectId.fromString(baseRev);
}
use of org.eclipse.jgit.revwalk.RevCommit in project gerrit by GerritCodeReview.
the class Revert method revert.
private Change.Id revert(BatchUpdate.Factory updateFactory, ChangeControl ctl, String message) throws OrmException, IOException, RestApiException, UpdateException {
Change.Id changeIdToRevert = ctl.getChange().getId();
PatchSet.Id patchSetId = ctl.getChange().currentPatchSetId();
PatchSet patch = psUtil.get(db.get(), ctl.getNotes(), patchSetId);
if (patch == null) {
throw new ResourceNotFoundException(changeIdToRevert.toString());
}
Project.NameKey project = ctl.getProject().getNameKey();
CurrentUser user = ctl.getUser();
try (Repository git = repoManager.openRepository(project);
ObjectInserter oi = git.newObjectInserter();
ObjectReader reader = oi.newReader();
RevWalk revWalk = new RevWalk(reader)) {
RevCommit commitToRevert = revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get()));
if (commitToRevert.getParentCount() == 0) {
throw new ResourceConflictException("Cannot revert initial commit");
}
Timestamp now = TimeUtil.nowTs();
PersonIdent committerIdent = new PersonIdent(serverIdent, now);
PersonIdent authorIdent = user.asIdentifiedUser().newCommitterIdent(now, committerIdent.getTimeZone());
RevCommit parentToCommitToRevert = commitToRevert.getParent(0);
revWalk.parseHeaders(parentToCommitToRevert);
CommitBuilder revertCommitBuilder = new CommitBuilder();
revertCommitBuilder.addParentId(commitToRevert);
revertCommitBuilder.setTreeId(parentToCommitToRevert.getTree());
revertCommitBuilder.setAuthor(authorIdent);
revertCommitBuilder.setCommitter(authorIdent);
Change changeToRevert = ctl.getChange();
if (message == null) {
message = MessageFormat.format(ChangeMessages.get().revertChangeDefaultMessage, changeToRevert.getSubject(), patch.getRevision().get());
}
ObjectId computedChangeId = ChangeIdUtil.computeChangeId(parentToCommitToRevert.getTree(), commitToRevert, authorIdent, committerIdent, message);
revertCommitBuilder.setMessage(ChangeIdUtil.insertId(message, computedChangeId, true));
Change.Id changeId = new Change.Id(seq.nextChangeId());
ObjectId id = oi.insert(revertCommitBuilder);
RevCommit revertCommit = revWalk.parseCommit(id);
ChangeInserter ins = changeInserterFactory.create(changeId, revertCommit, ctl.getChange().getDest().get()).setTopic(changeToRevert.getTopic());
ins.setMessage("Uploaded patch set 1.");
Set<Account.Id> reviewers = new HashSet<>();
reviewers.add(changeToRevert.getOwner());
reviewers.addAll(approvalsUtil.getReviewers(db.get(), ctl.getNotes()).all());
reviewers.remove(user.getAccountId());
ins.setReviewers(reviewers);
try (BatchUpdate bu = updateFactory.create(db.get(), project, user, now)) {
bu.setRepository(git, revWalk, oi);
bu.insertChange(ins);
bu.addOp(changeId, new NotifyOp(ctl.getChange(), ins));
bu.addOp(changeToRevert.getId(), new PostRevertedMessageOp(computedChangeId));
bu.execute();
}
return changeId;
} catch (RepositoryNotFoundException e) {
throw new ResourceNotFoundException(changeIdToRevert.toString(), e);
}
}
use of org.eclipse.jgit.revwalk.RevCommit in project gerrit by GerritCodeReview.
the class Submit method findCommits.
private HashMap<Change.Id, RevCommit> findCommits(Collection<ChangeData> changes, Project.NameKey project) throws IOException, OrmException {
HashMap<Change.Id, RevCommit> commits = new HashMap<>();
try (Repository repo = repoManager.openRepository(project);
RevWalk walk = new RevWalk(repo)) {
for (ChangeData change : changes) {
RevCommit commit = walk.parseCommit(ObjectId.fromString(psUtil.current(dbProvider.get(), change.notes()).getRevision().get()));
commits.put(change.getId(), commit);
}
}
return commits;
}
Aggregations