Search in sources :

Example 11 with CodeReviewRevWalk

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

the class CreateChange method createNewChange.

// TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
// Instants
@SuppressWarnings("JdkObsolete")
private ChangeInfo createNewChange(ChangeInput input, IdentifiedUser me, ProjectState projectState, BatchUpdate.Factory updateFactory) throws RestApiException, PermissionBackendException, IOException, ConfigInvalidException, UpdateException {
    logger.atFine().log("Creating new change for target branch %s in project %s" + " (new branch = %s, base change = %s, base commit = %s)", input.branch, projectState.getName(), input.newBranch, input.baseChange, input.baseCommit);
    try (Repository git = gitManager.openRepository(projectState.getNameKey());
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(reader)) {
        PatchSet basePatchSet = null;
        List<String> groups = Collections.emptyList();
        if (input.baseChange != null) {
            ChangeNotes baseChange = getBaseChange(input.baseChange);
            basePatchSet = psUtil.current(baseChange);
            groups = basePatchSet.groups();
            logger.atFine().log("base patch set = %s (groups = %s)", basePatchSet.id(), groups);
        }
        ObjectId parentCommit = getParentCommit(git, rw, input.branch, input.newBranch, basePatchSet, input.baseCommit, input.merge);
        logger.atFine().log("parent commit = %s", parentCommit != null ? parentCommit.name() : "NULL");
        RevCommit mergeTip = parentCommit == null ? null : rw.parseCommit(parentCommit);
        Instant now = TimeUtil.now();
        PersonIdent committer = me.newCommitterIdent(now, serverTimeZone);
        PersonIdent author = input.author == null ? committer : new PersonIdent(input.author.name, input.author.email, Date.from(now), serverTimeZone);
        String commitMessage = getCommitMessage(input.subject, me);
        CodeReviewCommit c;
        if (input.merge != null) {
            // create a merge commit
            c = newMergeCommit(git, oi, rw, projectState, mergeTip, input.merge, author, committer, commitMessage);
            if (!c.getFilesWithGitConflicts().isEmpty()) {
                logger.atFine().log("merge commit has conflicts in the following files: %s", c.getFilesWithGitConflicts());
            }
        } else {
            // create an empty commit
            c = newCommit(oi, rw, author, committer, mergeTip, commitMessage);
        }
        // Flush inserter so that commit becomes visible to validators
        oi.flush();
        Change.Id changeId = Change.id(seq.nextChangeId());
        ChangeInserter ins = changeInserterFactory.create(changeId, c, input.branch);
        ins.setMessage(messageForNewChange(ins.getPatchSetId(), c));
        ins.setTopic(input.topic);
        ins.setPrivate(input.isPrivate);
        ins.setWorkInProgress(input.workInProgress || !c.getFilesWithGitConflicts().isEmpty());
        ins.setGroups(groups);
        if (input.validationOptions != null) {
            ImmutableListMultimap.Builder<String, String> validationOptions = ImmutableListMultimap.builder();
            input.validationOptions.entrySet().forEach(e -> validationOptions.put(e.getKey(), e.getValue()));
            ins.setValidationOptions(validationOptions.build());
        }
        try (BatchUpdate bu = updateFactory.create(projectState.getNameKey(), me, now)) {
            bu.setRepository(git, rw, oi);
            bu.setNotify(notifyResolver.resolve(firstNonNull(input.notify, NotifyHandling.ALL), input.notifyDetails));
            bu.insertChange(ins);
            bu.execute();
        }
        ChangeInfo changeInfo = jsonFactory.noOptions().format(ins.getChange());
        changeInfo.containsGitConflicts = !c.getFilesWithGitConflicts().isEmpty() ? true : null;
        return changeInfo;
    } catch (InvalidMergeStrategyException | MergeWithConflictsNotSupportedException e) {
        throw new BadRequestException(e.getMessage());
    }
}
Also used : ChangeInfo(com.google.gerrit.extensions.common.ChangeInfo) ObjectId(org.eclipse.jgit.lib.ObjectId) Instant(java.time.Instant) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) PatchSet(com.google.gerrit.entities.PatchSet) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) Change(com.google.gerrit.entities.Change) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) Repository(org.eclipse.jgit.lib.Repository) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) PersonIdent(org.eclipse.jgit.lib.PersonIdent) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) InvalidMergeStrategyException(com.google.gerrit.exceptions.InvalidMergeStrategyException) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) MergeWithConflictsNotSupportedException(com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) ObjectReader(org.eclipse.jgit.lib.ObjectReader) ChangeInserter(com.google.gerrit.server.change.ChangeInserter) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 12 with CodeReviewRevWalk

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

the class CreateMergePatchSet method apply.

// TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
// Instants
@SuppressWarnings("JdkObsolete")
@Override
public Response<ChangeInfo> apply(ChangeResource rsrc, MergePatchSetInput in) throws IOException, RestApiException, UpdateException, PermissionBackendException {
    // Not allowed to create a new patch set if the current patch set is locked.
    psUtil.checkPatchSetNotLocked(rsrc.getNotes());
    rsrc.permissions().check(ChangePermission.ADD_PATCH_SET);
    if (in.author != null) {
        permissionBackend.currentUser().project(rsrc.getProject()).ref(rsrc.getChange().getDest().branch()).check(RefPermission.FORGE_AUTHOR);
    }
    ProjectState projectState = projectCache.get(rsrc.getProject()).orElseThrow(illegalState(rsrc.getProject()));
    projectState.checkStatePermitsWrite();
    MergeInput merge = in.merge;
    if (merge == null || Strings.isNullOrEmpty(merge.source)) {
        throw new BadRequestException("merge.source must be non-empty");
    }
    if (in.author != null && (Strings.isNullOrEmpty(in.author.email) || Strings.isNullOrEmpty(in.author.name))) {
        throw new BadRequestException("Author must specify name and email");
    }
    in.baseChange = Strings.nullToEmpty(in.baseChange).trim();
    PatchSet ps = psUtil.current(rsrc.getNotes());
    Change change = rsrc.getChange();
    Project.NameKey project = change.getProject();
    BranchNameKey dest = change.getDest();
    try (Repository git = gitManager.openRepository(project);
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(reader)) {
        RevCommit sourceCommit = MergeUtil.resolveCommit(git, rw, merge.source);
        if (!commits.canRead(projectState, git, sourceCommit)) {
            throw new ResourceNotFoundException("cannot find source commit: " + merge.source + " to merge.");
        }
        RevCommit currentPsCommit;
        List<String> groups = null;
        if (!in.inheritParent && !in.baseChange.isEmpty()) {
            PatchSet basePS = findBasePatchSet(in.baseChange);
            currentPsCommit = rw.parseCommit(basePS.commitId());
            groups = basePS.groups();
        } else {
            currentPsCommit = rw.parseCommit(ps.commitId());
        }
        Instant now = TimeUtil.now();
        IdentifiedUser me = user.get().asIdentifiedUser();
        PersonIdent author = in.author == null ? me.newCommitterIdent(now, serverTimeZone) : new PersonIdent(in.author.name, in.author.email, Date.from(now), serverTimeZone);
        CodeReviewCommit newCommit = createMergeCommit(in, projectState, dest, git, oi, rw, currentPsCommit, sourceCommit, author, ObjectId.fromString(change.getKey().get().substring(1)));
        oi.flush();
        PatchSet.Id nextPsId = ChangeUtil.nextPatchSetId(ps.id());
        PatchSetInserter psInserter = patchSetInserterFactory.create(rsrc.getNotes(), nextPsId, newCommit);
        try (BatchUpdate bu = updateFactory.create(project, me, now)) {
            bu.setRepository(git, rw, oi);
            bu.setNotify(NotifyResolver.Result.none());
            psInserter.setMessage(messageForChange(nextPsId, newCommit)).setWorkInProgress(!newCommit.getFilesWithGitConflicts().isEmpty()).setCheckAddPatchSetPermission(false);
            if (groups != null) {
                psInserter.setGroups(groups);
            }
            bu.addOp(rsrc.getId(), psInserter);
            bu.execute();
        }
        ChangeJson json = jsonFactory.create(ListChangesOption.CURRENT_REVISION);
        ChangeInfo changeInfo = json.format(psInserter.getChange());
        changeInfo.containsGitConflicts = !newCommit.getFilesWithGitConflicts().isEmpty() ? true : null;
        return Response.ok(changeInfo);
    } catch (InvalidMergeStrategyException | MergeWithConflictsNotSupportedException e) {
        throw new BadRequestException(e.getMessage());
    }
}
Also used : MergeInput(com.google.gerrit.extensions.common.MergeInput) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) BranchNameKey(com.google.gerrit.entities.BranchNameKey) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) ObjectReader(org.eclipse.jgit.lib.ObjectReader) ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) ChangeJson(com.google.gerrit.server.change.ChangeJson) ChangeInfo(com.google.gerrit.extensions.common.ChangeInfo) Instant(java.time.Instant) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) PatchSet(com.google.gerrit.entities.PatchSet) Change(com.google.gerrit.entities.Change) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) Project(com.google.gerrit.entities.Project) Repository(org.eclipse.jgit.lib.Repository) PersonIdent(org.eclipse.jgit.lib.PersonIdent) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) PatchSetInserter(com.google.gerrit.server.change.PatchSetInserter) InvalidMergeStrategyException(com.google.gerrit.exceptions.InvalidMergeStrategyException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) MergeWithConflictsNotSupportedException(com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException) ProjectState(com.google.gerrit.server.project.ProjectState)

Example 13 with CodeReviewRevWalk

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

the class SubmitStrategyOp method getAlreadyMergedCommit.

private CodeReviewCommit getAlreadyMergedCommit(RepoContext ctx) throws IOException {
    CodeReviewCommit tip = args.mergeTip.getInitialTip();
    if (tip == null) {
        return null;
    }
    CodeReviewRevWalk rw = (CodeReviewRevWalk) ctx.getRevWalk();
    Change.Id id = getId();
    String refPrefix = id.toRefPrefix();
    Map<String, ObjectId> refs = ctx.getRepoView().getRefs(refPrefix);
    List<CodeReviewCommit> commits = new ArrayList<>(refs.size());
    for (Map.Entry<String, ObjectId> e : refs.entrySet()) {
        PatchSet.Id psId = PatchSet.Id.fromRef(refPrefix + e.getKey());
        if (psId == null) {
            continue;
        }
        try {
            CodeReviewCommit c = rw.parseCommit(e.getValue());
            c.setPatchsetId(psId);
            commits.add(c);
        } catch (MissingObjectException | IncorrectObjectTypeException ex) {
            // Bogus ref, can't be merged into tip so we don't care.
            continue;
        }
    }
    commits.sort(comparing((CodeReviewCommit c) -> c.getPatchsetId().get()).reversed());
    CodeReviewCommit result = MergeUtil.findAnyMergedInto(rw, commits, tip);
    if (result == null) {
        return null;
    }
    // Some patch set of this change is actually merged into the target
    // branch, most likely because a previous run of MergeOp failed after
    // updateRepo, during updateChange.
    // 
    // Do the best we can to clean this up: mark the change as merged and set
    // the current patch set. Don't touch the dest branch at all. This can
    // lead to some odd situations like another change in the set merging in
    // a different patch set of this change, but that's unavoidable at this
    // point.  At least the change will end up in the right state.
    // 
    // TODO(dborowitz): Consider deleting later junk patch set refs. They
    // presumably don't have PatchSets pointing to them.
    rw.parseBody(result);
    result.add(args.canMergeFlag);
    PatchSet.Id psId = result.getPatchsetId();
    result.copyFrom(toMerge);
    // Got overwriten by copyFrom.
    result.setPatchsetId(psId);
    result.setStatusCode(CommitMergeStatus.ALREADY_MERGED);
    args.commitStatus.put(result);
    return result;
}
Also used : ObjectId(org.eclipse.jgit.lib.ObjectId) ArrayList(java.util.ArrayList) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) PatchSet(com.google.gerrit.entities.PatchSet) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) Change(com.google.gerrit.entities.Change) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) MissingObjectException(org.eclipse.jgit.errors.MissingObjectException) HashMap(java.util.HashMap) Map(java.util.Map)

Example 14 with CodeReviewRevWalk

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

the class RebaseSorter method isAlreadyMerged.

private boolean isAlreadyMerged(CodeReviewCommit commit, BranchNameKey dest) throws IOException {
    try (CodeReviewRevWalk mirw = CodeReviewCommit.newRevWalk(rw.getObjectReader())) {
        mirw.reset();
        mirw.markStart(commit);
        // check if the commit is merged in other branches
        for (RevCommit accepted : alreadyAccepted) {
            if (mirw.isMergedInto(mirw.parseCommit(commit), mirw.parseCommit(accepted))) {
                logger.atFine().log("Dependency %s merged into branch head %s.", commit.getName(), accepted.getName());
                return true;
            }
        }
        // check if the commit associated change is merged in the same branch
        List<ChangeData> changes = queryProvider.get().byCommit(commit);
        for (ChangeData change : changes) {
            if (change.change().isMerged() && change.change().getDest().equals(dest)) {
                logger.atFine().log("Dependency %s associated with merged change %s.", commit.getName(), change.getId());
                return true;
            }
        }
        return false;
    } catch (StorageException e) {
        throw new IOException(e);
    }
}
Also used : CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) IOException(java.io.IOException) ChangeData(com.google.gerrit.server.query.change.ChangeData) StorageException(com.google.gerrit.exceptions.StorageException) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 15 with CodeReviewRevWalk

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

the class SubmoduleCommitsTest method directUpdateSubmodule.

private CodeReviewCommit directUpdateSubmodule(Project.NameKey project, String refName, Project.NameKey path, AnyObjectId id) throws Exception {
    OpenRepo or = mergeOpRepoManager.getRepo(project);
    Repository serverRepo = or.repo;
    ObjectInserter ins = or.ins;
    CodeReviewRevWalk rw = or.rw;
    Ref ref = serverRepo.exactRef(refName);
    assertWithMessage(refName).that(ref).isNotNull();
    ObjectId oldCommitId = ref.getObjectId();
    DirCache dc = DirCache.newInCore();
    DirCacheBuilder b = dc.builder();
    b.addTree(new byte[0], DirCacheEntry.STAGE_0, rw.getObjectReader(), rw.parseTree(oldCommitId));
    b.finish();
    DirCacheEditor e = dc.editor();
    e.add(new PathEdit(path.get()) {

        @Override
        public void apply(DirCacheEntry ent) {
            ent.setFileMode(FileMode.GITLINK);
            ent.setObjectId(id);
        }
    });
    e.finish();
    CommitBuilder cb = new CommitBuilder();
    cb.addParentId(oldCommitId);
    cb.setTreeId(dc.writeTree(ins));
    cb.setAuthor(ident);
    cb.setCommitter(ident);
    cb.setMessage("Direct update submodule " + path);
    ObjectId newCommitId = ins.insert(cb);
    ins.flush();
    RefUpdate ru = serverRepo.updateRef(refName);
    ru.setExpectedOldObjectId(oldCommitId);
    ru.setNewObjectId(newCommitId);
    assertThat(ru.update()).isEqualTo(RefUpdate.Result.FAST_FORWARD);
    return rw.parseCommit(newCommitId);
}
Also used : DirCacheBuilder(org.eclipse.jgit.dircache.DirCacheBuilder) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) AnyObjectId(org.eclipse.jgit.lib.AnyObjectId) ObjectId(org.eclipse.jgit.lib.ObjectId) PathEdit(org.eclipse.jgit.dircache.DirCacheEditor.PathEdit) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) DirCacheEditor(org.eclipse.jgit.dircache.DirCacheEditor) DirCache(org.eclipse.jgit.dircache.DirCache) TestRepository(org.eclipse.jgit.junit.TestRepository) Repository(org.eclipse.jgit.lib.Repository) Ref(org.eclipse.jgit.lib.Ref) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) RefUpdate(org.eclipse.jgit.lib.RefUpdate)

Aggregations

CodeReviewRevWalk (com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk)15 ObjectId (org.eclipse.jgit.lib.ObjectId)11 RevCommit (org.eclipse.jgit.revwalk.RevCommit)10 Repository (org.eclipse.jgit.lib.Repository)9 IdentifiedUser (com.google.gerrit.server.IdentifiedUser)7 CodeReviewCommit (com.google.gerrit.server.git.CodeReviewCommit)7 ProjectState (com.google.gerrit.server.project.ProjectState)7 ObjectInserter (org.eclipse.jgit.lib.ObjectInserter)7 PersonIdent (org.eclipse.jgit.lib.PersonIdent)7 Change (com.google.gerrit.entities.Change)6 IOException (java.io.IOException)6 MergeConflictException (com.google.gerrit.extensions.restapi.MergeConflictException)5 Map (java.util.Map)5 Preconditions.checkState (com.google.common.base.Preconditions.checkState)4 PatchSet (com.google.gerrit.entities.PatchSet)4 ImmutableList (com.google.common.collect.ImmutableList)3 ImmutableSet (com.google.common.collect.ImmutableSet)3 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)3 Iterables (com.google.common.collect.Iterables)3 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)3