Search in sources :

Example 36 with CodeReviewCommit

use of com.google.gerrit.server.git.CodeReviewCommit in project gerrit by GerritCodeReview.

the class MergeOp method getAlreadyAccepted.

private Set<RevCommit> getAlreadyAccepted(OpenRepo or, CodeReviewCommit branchTip) {
    Set<RevCommit> alreadyAccepted = new HashSet<>();
    if (branchTip != null) {
        alreadyAccepted.add(branchTip);
    }
    try {
        for (Ref r : or.repo.getRefDatabase().getRefsByPrefix(Constants.R_HEADS)) {
            try {
                CodeReviewCommit aac = or.rw.parseCommit(r.getObjectId());
                if (!commitStatus.commits.values().contains(aac)) {
                    alreadyAccepted.add(aac);
                }
            } catch (IncorrectObjectTypeException iote) {
            // Not a commit? Skip over it.
            }
        }
    } catch (IOException e) {
        throw new StorageException("Failed to determine already accepted commits.", e);
    }
    logger.atFine().log("Found %d existing heads: %s", alreadyAccepted.size(), alreadyAccepted);
    return alreadyAccepted;
}
Also used : Ref(org.eclipse.jgit.lib.Ref) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) IOException(java.io.IOException) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) StorageException(com.google.gerrit.exceptions.StorageException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 37 with CodeReviewCommit

use of com.google.gerrit.server.git.CodeReviewCommit in project gerrit by GerritCodeReview.

the class SubmitStrategy method addOps.

/**
 * Add operations to a batch update that execute this submit strategy.
 *
 * <p>Guarantees exactly one op is added to the update for each change in the input set.
 *
 * @param bu batch update to add operations to.
 * @param toMerge the set of submitted commits that should be merged using this submit strategy.
 *     Implementations are responsible for ordering of commits, and will not modify the input in
 *     place.
 */
public final void addOps(BatchUpdate bu, Set<CodeReviewCommit> toMerge) {
    List<SubmitStrategyOp> ops = buildOps(toMerge);
    Set<CodeReviewCommit> added = Sets.newHashSetWithExpectedSize(ops.size());
    for (SubmitStrategyOp op : ops) {
        added.add(op.getCommit());
    }
    // First add ops for any implicitly merged changes.
    List<CodeReviewCommit> difference = new ArrayList<>(Sets.difference(toMerge, added));
    Collections.reverse(difference);
    for (CodeReviewCommit c : difference) {
        Change.Id id = c.change().getId();
        bu.addOp(id, args.setPrivateOpFactory.create(false, null));
        ImplicitIntegrateOp implicitIntegrateOp = new ImplicitIntegrateOp(args, c);
        bu.addOp(id, implicitIntegrateOp);
        maybeAddTestHelperOp(bu, id);
        this.submitStrategyOps.add(implicitIntegrateOp);
    }
    // Then ops for explicitly merged changes
    for (SubmitStrategyOp op : ops) {
        bu.addOp(op.getId(), args.setPrivateOpFactory.create(false, null));
        bu.addOp(op.getId(), op);
        maybeAddTestHelperOp(bu, op.getId());
        this.submitStrategyOps.add(op);
    }
}
Also used : ArrayList(java.util.ArrayList) Change(com.google.gerrit.entities.Change) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit)

Example 38 with CodeReviewCommit

use of com.google.gerrit.server.git.CodeReviewCommit in project gerrit by GerritCodeReview.

the class SubmitStrategyListener method checkCommitStatus.

private List<Change.Id> checkCommitStatus() throws ResourceConflictException {
    List<Change.Id> alreadyMerged = new ArrayList<>(commitStatus.getChangeIds().size());
    for (Change.Id id : commitStatus.getChangeIds()) {
        CodeReviewCommit commit = commitStatus.get(id);
        CommitMergeStatus s = commit != null ? commit.getStatusCode() : null;
        requireNonNull(s, String.format("change %d: change not processed by merge strategy", id.get()));
        if (commit.getStatusMessage().isPresent()) {
            logger.atFine().log("change %d: Status for commit %s is %s. %s", id.get(), commit.name(), s, commit.getStatusMessage().get());
        } else {
            logger.atFine().log("change %d: Status for commit %s is %s.", id.get(), commit.name(), s);
        }
        switch(s) {
            case CLEAN_MERGE:
            case CLEAN_REBASE:
            case CLEAN_PICK:
            case SKIPPED_IDENTICAL_TREE:
                // Merge strategy accepted this change.
                break;
            case ALREADY_MERGED:
                // Already an ancestor of tip.
                alreadyMerged.add(commit.getPatchsetId().changeId());
                break;
            case PATH_CONFLICT:
            case REBASE_MERGE_CONFLICT:
            case MANUAL_RECURSIVE_MERGE:
            case CANNOT_CHERRY_PICK_ROOT:
            case CANNOT_REBASE_ROOT:
            case NOT_FAST_FORWARD:
            case EMPTY_COMMIT:
            case MISSING_DEPENDENCY:
            case FAST_FORWARD_INDEPENDENT_CHANGES:
                // TODO(dborowitz): Reformat these messages to be more appropriate for
                // short problem descriptions.
                String message = s.getDescription();
                if (commit.getStatusMessage().isPresent()) {
                    message += " " + commit.getStatusMessage().get();
                }
                commitStatus.problem(id, CharMatcher.is('\n').collapseFrom(message, ' '));
                break;
            default:
                commitStatus.problem(id, "unspecified merge failure: " + s);
                break;
        }
    }
    commitStatus.maybeFailVerbose();
    return alreadyMerged;
}
Also used : ArrayList(java.util.ArrayList) Change(com.google.gerrit.entities.Change) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit)

Example 39 with CodeReviewCommit

use of com.google.gerrit.server.git.CodeReviewCommit in project gerrit by GerritCodeReview.

the class SubmoduleCommits method updateSubmodule.

private RevCommit updateSubmodule(DirCache dc, DirCacheEditor ed, StringBuilder msgbuf, SubmoduleSubscription s) throws SubmoduleConflictException, IOException {
    logger.atFine().log("Updating gitlink for %s", s);
    OpenRepo subOr;
    try {
        subOr = orm.getRepo(s.getSubmodule().project());
    } catch (NoSuchProjectException | IOException e) {
        throw new StorageException("Cannot access submodule", e);
    }
    DirCacheEntry dce = dc.getEntry(s.getPath());
    RevCommit oldCommit = null;
    if (dce != null) {
        if (!dce.getFileMode().equals(FileMode.GITLINK)) {
            String errMsg = "Requested to update gitlink " + s.getPath() + " in " + s.getSubmodule().project().get() + " but entry " + "doesn't have gitlink file mode.";
            throw new SubmoduleConflictException(errMsg);
        }
        // making things worse by updating the gitlink to something else.
        try {
            oldCommit = subOr.getCodeReviewRevWalk().parseCommit(dce.getObjectId());
        } catch (IOException e) {
            // Broken gitlink; sanity check failed. Warn and continue so the submit operation can
            // proceed, it will just skip this gitlink update.
            logger.atSevere().withCause(e).log("Failed to read commit %s", dce.getObjectId().name());
            return null;
        }
    }
    Optional<CodeReviewCommit> maybeNewCommit = branchTips.getTip(s.getSubmodule(), subOr);
    if (!maybeNewCommit.isPresent()) {
        // For whatever reason, this submodule was not updated as part of this submit batch, but the
        // superproject is still subscribed to this branch. Re-read the ref to see if anything has
        // changed since the last time the gitlink was updated, and roll that update into the same
        // commit as all other submodule updates.
        ed.add(new DeletePath(s.getPath()));
        return null;
    }
    CodeReviewCommit newCommit = maybeNewCommit.get();
    if (Objects.equals(newCommit, oldCommit)) {
        // gitlink have already been updated for this submodule
        return null;
    }
    ed.add(new PathEdit(s.getPath()) {

        @Override
        public void apply(DirCacheEntry ent) {
            ent.setFileMode(FileMode.GITLINK);
            ent.setObjectId(newCommit.getId());
        }
    });
    if (verboseSuperProject != VerboseSuperprojectUpdate.FALSE) {
        createSubmoduleCommitMsg(msgbuf, s, subOr, newCommit, oldCommit);
    }
    subOr.getCodeReviewRevWalk().parseBody(newCommit);
    return newCommit;
}
Also used : DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) PathEdit(org.eclipse.jgit.dircache.DirCacheEditor.PathEdit) IOException(java.io.IOException) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) DeletePath(org.eclipse.jgit.dircache.DirCacheEditor.DeletePath) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) StorageException(com.google.gerrit.exceptions.StorageException) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 40 with CodeReviewCommit

use of com.google.gerrit.server.git.CodeReviewCommit in project gerrit by GerritCodeReview.

the class SubmoduleCommits method composeGitlinksCommit.

/**
 * Create a separate gitlink commit
 *
 * @param subscriber superproject (and branch)
 * @param subscriptions subprojects the superproject is subscribed to
 * @return a new commit on top of subscriber with gitlinks update to the tips of the subprojects;
 *     empty if nothing has changed. Subproject tips are read from the cached branched tips
 *     (defaulting to the mergeOpRepoManager).
 */
Optional<CodeReviewCommit> composeGitlinksCommit(BranchNameKey subscriber, Collection<SubmoduleSubscription> subscriptions) throws IOException, SubmoduleConflictException {
    OpenRepo or;
    try {
        or = orm.getRepo(subscriber.project());
    } catch (NoSuchProjectException | IOException e) {
        throw new StorageException("Cannot access superproject", e);
    }
    CodeReviewCommit currentCommit = branchTips.getTip(subscriber, or).orElseThrow(() -> new SubmoduleConflictException("The branch was probably deleted from the subscriber repository"));
    StringBuilder msgbuf = new StringBuilder();
    PersonIdent author = null;
    DirCache dc = readTree(or.getCodeReviewRevWalk(), currentCommit);
    DirCacheEditor ed = dc.editor();
    int count = 0;
    for (SubmoduleSubscription s : sortByPath(subscriptions)) {
        if (count > 0) {
            msgbuf.append("\n\n");
        }
        RevCommit newCommit = updateSubmodule(dc, ed, msgbuf, s);
        count++;
        if (newCommit != null) {
            PersonIdent newCommitAuthor = newCommit.getAuthorIdent();
            if (author == null) {
                author = new PersonIdent(newCommitAuthor, myIdent.getWhen());
            } else if (!author.getName().equals(newCommitAuthor.getName()) || !author.getEmailAddress().equals(newCommitAuthor.getEmailAddress())) {
                author = myIdent;
            }
        }
    }
    ed.finish();
    ObjectId newTreeId = dc.writeTree(or.ins);
    // Gitlinks are already in the branch, return null
    if (newTreeId.equals(currentCommit.getTree())) {
        return Optional.empty();
    }
    CommitBuilder commit = new CommitBuilder();
    commit.setTreeId(newTreeId);
    commit.setParentId(currentCommit);
    StringBuilder commitMsg = new StringBuilder("Update git submodules\n\n");
    if (verboseSuperProject != VerboseSuperprojectUpdate.FALSE) {
        commitMsg.append(msgbuf);
    }
    commit.setMessage(commitMsg.toString());
    commit.setAuthor(author);
    commit.setCommitter(myIdent);
    ObjectId id = or.ins.insert(commit);
    return Optional.of(or.getCodeReviewRevWalk().parseCommit(id));
}
Also used : NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) ObjectId(org.eclipse.jgit.lib.ObjectId) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) IOException(java.io.IOException) DirCacheEditor(org.eclipse.jgit.dircache.DirCacheEditor) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) DirCache(org.eclipse.jgit.dircache.DirCache) PersonIdent(org.eclipse.jgit.lib.PersonIdent) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) SubmoduleSubscription(com.google.gerrit.entities.SubmoduleSubscription) StorageException(com.google.gerrit.exceptions.StorageException) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Aggregations

CodeReviewCommit (com.google.gerrit.server.git.CodeReviewCommit)45 ArrayList (java.util.ArrayList)13 ObjectId (org.eclipse.jgit.lib.ObjectId)11 RevCommit (org.eclipse.jgit.revwalk.RevCommit)11 IOException (java.io.IOException)10 StorageException (com.google.gerrit.exceptions.StorageException)9 PersonIdent (org.eclipse.jgit.lib.PersonIdent)9 BranchNameKey (com.google.gerrit.entities.BranchNameKey)7 Change (com.google.gerrit.entities.Change)7 PatchSet (com.google.gerrit.entities.PatchSet)7 CodeReviewRevWalk (com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk)7 ImmutableList (com.google.common.collect.ImmutableList)6 Repository (org.eclipse.jgit.lib.Repository)6 GerritPersonIdent (com.google.gerrit.server.GerritPersonIdent)5 IdentifiedUser (com.google.gerrit.server.IdentifiedUser)5 ProjectState (com.google.gerrit.server.project.ProjectState)5 OpenRepo (com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo)5 SubmoduleSubscription (com.google.gerrit.entities.SubmoduleSubscription)4 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)4 MergeConflictException (com.google.gerrit.extensions.restapi.MergeConflictException)4