LCOV - code coverage report
Current view: top level - server - PatchSetUtil.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 54 56 96.4 %
Date: 2022-11-19 15:00:39 Functions: 11 11 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2016 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server;
      16             : 
      17             : import static com.google.common.base.Preconditions.checkArgument;
      18             : import static com.google.gerrit.server.project.ProjectCache.illegalState;
      19             : import static java.util.Objects.requireNonNull;
      20             : 
      21             : import com.google.common.collect.ImmutableCollection;
      22             : import com.google.common.collect.ImmutableMap;
      23             : import com.google.common.collect.Maps;
      24             : import com.google.gerrit.common.Nullable;
      25             : import com.google.gerrit.entities.Change;
      26             : import com.google.gerrit.entities.LabelFunction;
      27             : import com.google.gerrit.entities.LabelType;
      28             : import com.google.gerrit.entities.PatchSet;
      29             : import com.google.gerrit.entities.PatchSetApproval;
      30             : import com.google.gerrit.entities.Project;
      31             : import com.google.gerrit.extensions.restapi.ResourceConflictException;
      32             : import com.google.gerrit.server.approval.ApprovalsUtil;
      33             : import com.google.gerrit.server.git.GitRepositoryManager;
      34             : import com.google.gerrit.server.notedb.ChangeNotes;
      35             : import com.google.gerrit.server.notedb.ChangeUpdate;
      36             : import com.google.gerrit.server.project.ProjectCache;
      37             : import com.google.gerrit.server.project.ProjectState;
      38             : import com.google.inject.Inject;
      39             : import com.google.inject.Provider;
      40             : import com.google.inject.Singleton;
      41             : import java.io.IOException;
      42             : import java.util.List;
      43             : import java.util.Optional;
      44             : import java.util.Set;
      45             : import org.eclipse.jgit.lib.ObjectId;
      46             : import org.eclipse.jgit.lib.Repository;
      47             : import org.eclipse.jgit.revwalk.RevCommit;
      48             : import org.eclipse.jgit.revwalk.RevWalk;
      49             : 
      50             : /** Utilities for manipulating patch sets. */
      51             : @Singleton
      52             : public class PatchSetUtil {
      53             :   private final Provider<ApprovalsUtil> approvalsUtilProvider;
      54             :   private final ProjectCache projectCache;
      55             :   private final GitRepositoryManager repoManager;
      56             : 
      57             :   @Inject
      58             :   PatchSetUtil(
      59             :       Provider<ApprovalsUtil> approvalsUtilProvider,
      60             :       ProjectCache projectCache,
      61         150 :       GitRepositoryManager repoManager) {
      62         150 :     this.approvalsUtilProvider = approvalsUtilProvider;
      63         150 :     this.projectCache = projectCache;
      64         150 :     this.repoManager = repoManager;
      65         150 :   }
      66             : 
      67             :   public PatchSet current(ChangeNotes notes) {
      68          90 :     return get(notes, notes.getChange().currentPatchSetId());
      69             :   }
      70             : 
      71             :   public PatchSet get(ChangeNotes notes, PatchSet.Id psId) {
      72         102 :     return notes.load().getPatchSets().get(psId);
      73             :   }
      74             : 
      75             :   public ImmutableCollection<PatchSet> byChange(ChangeNotes notes) {
      76         103 :     return notes.load().getPatchSets().values();
      77             :   }
      78             : 
      79             :   public ImmutableMap<PatchSet.Id, PatchSet> byChangeAsMap(ChangeNotes notes) {
      80           1 :     return notes.load().getPatchSets();
      81             :   }
      82             : 
      83             :   public ImmutableMap<PatchSet.Id, PatchSet> getAsMap(
      84             :       ChangeNotes notes, Set<PatchSet.Id> patchSetIds) {
      85           9 :     return ImmutableMap.copyOf(Maps.filterKeys(notes.load().getPatchSets(), patchSetIds::contains));
      86             :   }
      87             : 
      88             :   public PatchSet insert(
      89             :       RevWalk rw,
      90             :       ChangeUpdate update,
      91             :       PatchSet.Id psId,
      92             :       ObjectId commit,
      93             :       List<String> groups,
      94             :       @Nullable String pushCertificate,
      95             :       @Nullable String description)
      96             :       throws IOException {
      97         103 :     requireNonNull(groups, "groups may not be null");
      98         103 :     ensurePatchSetMatches(psId, update);
      99             : 
     100         103 :     update.setCommit(rw, commit, pushCertificate);
     101         103 :     update.setPsDescription(description);
     102         103 :     update.setGroups(groups);
     103             : 
     104         103 :     return PatchSet.builder()
     105         103 :         .id(psId)
     106         103 :         .commitId(commit)
     107         103 :         .uploader(update.getAccountId())
     108         103 :         .createdOn(update.getWhen())
     109         103 :         .groups(groups)
     110         103 :         .pushCertificate(Optional.ofNullable(pushCertificate))
     111         103 :         .description(Optional.ofNullable(description))
     112         103 :         .build();
     113             :   }
     114             : 
     115             :   private static void ensurePatchSetMatches(PatchSet.Id psId, ChangeUpdate update) {
     116         103 :     Change.Id changeId = update.getId();
     117         103 :     checkArgument(
     118         103 :         psId.changeId().equals(changeId),
     119             :         "cannot modify patch set %s on update for change %s",
     120             :         psId,
     121             :         changeId);
     122         103 :     if (update.getPatchSetId() != null) {
     123         103 :       checkArgument(
     124         103 :           update.getPatchSetId().equals(psId),
     125             :           "cannot modify patch set %s on update for %s",
     126             :           psId,
     127         103 :           update.getPatchSetId());
     128             :     } else {
     129           0 :       update.setPatchSetId(psId);
     130             :     }
     131         103 :   }
     132             : 
     133             :   /** Check if the current patch set of the change is locked. */
     134             :   public void checkPatchSetNotLocked(ChangeNotes notes) throws ResourceConflictException {
     135          46 :     if (isPatchSetLocked(notes)) {
     136           1 :       throw new ResourceConflictException(
     137           1 :           String.format("The current patch set of change %s is locked", notes.getChangeId()));
     138             :     }
     139          46 :   }
     140             : 
     141             :   /** Is the current patch set locked against state changes? */
     142             :   public boolean isPatchSetLocked(ChangeNotes notes) {
     143          73 :     Change change = notes.getChange();
     144          73 :     if (change.isMerged()) {
     145           0 :       return false;
     146             :     }
     147             : 
     148          73 :     ProjectState projectState =
     149          73 :         projectCache.get(notes.getProjectName()).orElseThrow(illegalState(notes.getProjectName()));
     150             : 
     151          73 :     ApprovalsUtil approvalsUtil = approvalsUtilProvider.get();
     152          73 :     for (PatchSetApproval ap : approvalsUtil.byPatchSet(notes, change.currentPatchSetId())) {
     153          30 :       Optional<LabelType> type = projectState.getLabelTypes(notes).byLabel(ap.label());
     154          30 :       if (type.isPresent()
     155          30 :           && ap.value() == 1
     156          19 :           && type.get().getFunction() == LabelFunction.PATCH_SET_LOCK) {
     157           4 :         return true;
     158             :       }
     159          30 :     }
     160          73 :     return false;
     161             :   }
     162             : 
     163             :   /** Returns the commit for the given project at the given patchset revision */
     164             :   public RevCommit getRevCommit(Project.NameKey project, PatchSet patchSet) throws IOException {
     165           4 :     try (Repository repo = repoManager.openRepository(project);
     166           4 :         RevWalk rw = new RevWalk(repo)) {
     167           4 :       RevCommit src = rw.parseCommit(patchSet.commitId());
     168           4 :       rw.parseBody(src);
     169           4 :       return src;
     170             :     }
     171             :   }
     172             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750