LCOV - code coverage report
Current view: top level - server/edit - ModificationTarget.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 25 28 89.3 %
Date: 2022-11-19 15:00:39 Functions: 10 11 90.9 %

          Line data    Source code
       1             : // Copyright (C) 2020 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.edit;
      16             : 
      17             : import com.google.gerrit.entities.Change;
      18             : import com.google.gerrit.entities.PatchSet;
      19             : import com.google.gerrit.server.project.InvalidChangeOperationException;
      20             : import java.io.IOException;
      21             : import org.eclipse.jgit.lib.Repository;
      22             : import org.eclipse.jgit.revwalk.RevCommit;
      23             : import org.eclipse.jgit.revwalk.RevWalk;
      24             : 
      25             : /**
      26             :  * Target of the modification of a commit.
      27             :  *
      28             :  * <p>This is currently used in the context of change edits which involves both direct actions on
      29             :  * change edits (e.g. creating a change edit; modifying a file of a change edit) as well as indirect
      30             :  * creation/modification of them (e.g. via applying a suggested fix of a robot comment.)
      31             :  *
      32             :  * <p>Depending on the situation and exact action, either an existing {@link ChangeEdit} (-> {@link
      33             :  * EditCommit} or a specific patchset commit (-> {@link PatchsetCommit}) is the target of a
      34             :  * modification.
      35             :  */
      36             : public interface ModificationTarget {
      37             : 
      38             :   void ensureNewEditMayBeBasedOnTarget(Change change) throws InvalidChangeOperationException;
      39             : 
      40             :   void ensureTargetMayBeModifiedDespiteExistingEdit(ChangeEdit changeEdit)
      41             :       throws InvalidChangeOperationException;
      42             : 
      43             :   /** Commit to modify. */
      44             :   RevCommit getCommit(Repository repository) throws IOException;
      45             : 
      46             :   /**
      47             :    * Patchset within whose context the modification happens. This also applies to change edits as
      48             :    * each change edit is based on a specific patchset.
      49             :    */
      50             :   PatchSet getBasePatchset();
      51             : 
      52             :   /** A specific patchset commit is the target of the modification. */
      53             :   class PatchsetCommit implements ModificationTarget {
      54             : 
      55             :     private final PatchSet patchSet;
      56             : 
      57          17 :     PatchsetCommit(PatchSet patchSet) {
      58          17 :       this.patchSet = patchSet;
      59          17 :     }
      60             : 
      61             :     @Override
      62             :     public void ensureTargetMayBeModifiedDespiteExistingEdit(ChangeEdit changeEdit)
      63             :         throws InvalidChangeOperationException {
      64           2 :       if (!isBasedOn(changeEdit, patchSet)) {
      65           2 :         throw new InvalidChangeOperationException(
      66           2 :             String.format(
      67             :                 "Only the patch set %s on which the existing change edit is based may be modified "
      68             :                     + "(specified patch set: %s)",
      69           2 :                 changeEdit.getBasePatchSet().id(), patchSet.id()));
      70             :       }
      71           2 :     }
      72             : 
      73             :     private static boolean isBasedOn(ChangeEdit changeEdit, PatchSet patchSet) {
      74           2 :       PatchSet editBasePatchSet = changeEdit.getBasePatchSet();
      75           2 :       return editBasePatchSet.id().equals(patchSet.id());
      76             :     }
      77             : 
      78             :     @Override
      79             :     public void ensureNewEditMayBeBasedOnTarget(Change change)
      80             :         throws InvalidChangeOperationException {
      81          17 :       PatchSet.Id patchSetId = patchSet.id();
      82          17 :       PatchSet.Id currentPatchSetId = change.currentPatchSetId();
      83          17 :       if (!patchSetId.equals(currentPatchSetId)) {
      84           2 :         throw new InvalidChangeOperationException(
      85           2 :             String.format(
      86             :                 "A change edit may only be created for the current patch set %s (and not for %s)",
      87             :                 currentPatchSetId, patchSetId));
      88             :       }
      89          17 :     }
      90             : 
      91             :     @Override
      92             :     public RevCommit getCommit(Repository repository) throws IOException {
      93          17 :       try (RevWalk revWalk = new RevWalk(repository)) {
      94          17 :         return revWalk.parseCommit(patchSet.commitId());
      95             :       }
      96             :     }
      97             : 
      98             :     @Override
      99             :     public PatchSet getBasePatchset() {
     100          17 :       return patchSet;
     101             :     }
     102             :   }
     103             : 
     104             :   /** An existing {@link ChangeEdit} commit is the target of the modification. */
     105             :   class EditCommit implements ModificationTarget {
     106             : 
     107             :     private final ChangeEdit changeEdit;
     108             : 
     109          12 :     EditCommit(ChangeEdit changeEdit) {
     110          12 :       this.changeEdit = changeEdit;
     111          12 :     }
     112             : 
     113             :     @Override
     114             :     public void ensureNewEditMayBeBasedOnTarget(Change change) {
     115             :       // The current code will never create a new edit if one already exists. It would be a
     116             :       // programmer error if this changes in the future (without adjusting the storage of change
     117             :       // edits).
     118           0 :       throw new IllegalStateException(
     119           0 :           String.format(
     120             :               "Change %d already has a change edit for the calling user. A new change edit can't"
     121             :                   + " be created.",
     122           0 :               changeEdit.getChange().getChangeId()));
     123             :     }
     124             : 
     125             :     @Override
     126             :     public void ensureTargetMayBeModifiedDespiteExistingEdit(ChangeEdit changeEdit) {
     127             :       // The target is the change edit and hence can be modified.
     128          12 :     }
     129             : 
     130             :     @Override
     131             :     public RevCommit getCommit(Repository repository) throws IOException {
     132          12 :       return changeEdit.getEditCommit();
     133             :     }
     134             : 
     135             :     @Override
     136             :     public PatchSet getBasePatchset() {
     137          11 :       return changeEdit.getBasePatchSet();
     138             :     }
     139             :   }
     140             : }

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