LCOV - code coverage report
Current view: top level - server/restapi/change - GetMetaDiff.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 48 53 90.6 %
Date: 2022-11-19 15:00:39 Functions: 10 13 76.9 %

          Line data    Source code
       1             : // Copyright (C) 2021 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.restapi.change;
      16             : 
      17             : import static com.google.gerrit.entities.RefNames.changeMetaRef;
      18             : 
      19             : import com.google.gerrit.common.Nullable;
      20             : import com.google.gerrit.extensions.client.ListChangesOption;
      21             : import com.google.gerrit.extensions.client.ListOption;
      22             : import com.google.gerrit.extensions.common.ChangeInfo;
      23             : import com.google.gerrit.extensions.common.ChangeInfoDiffer;
      24             : import com.google.gerrit.extensions.common.ChangeInfoDifference;
      25             : import com.google.gerrit.extensions.restapi.BadRequestException;
      26             : import com.google.gerrit.extensions.restapi.PreconditionFailedException;
      27             : import com.google.gerrit.extensions.restapi.Response;
      28             : import com.google.gerrit.extensions.restapi.RestApiException;
      29             : import com.google.gerrit.extensions.restapi.RestReadView;
      30             : import com.google.gerrit.server.DynamicOptions;
      31             : import com.google.gerrit.server.DynamicOptions.DynamicBean;
      32             : import com.google.gerrit.server.change.ChangeResource;
      33             : import com.google.gerrit.server.git.GitRepositoryManager;
      34             : import com.google.inject.Inject;
      35             : import com.google.inject.Provider;
      36             : import java.io.IOException;
      37             : import java.util.EnumSet;
      38             : import java.util.HashMap;
      39             : import java.util.Map;
      40             : import org.eclipse.jgit.errors.InvalidObjectIdException;
      41             : import org.eclipse.jgit.errors.MissingObjectException;
      42             : import org.eclipse.jgit.lib.ObjectId;
      43             : import org.eclipse.jgit.lib.Repository;
      44             : import org.eclipse.jgit.revwalk.RevCommit;
      45             : import org.eclipse.jgit.revwalk.RevWalk;
      46             : import org.kohsuke.args4j.Option;
      47             : 
      48             : /** Gets the diff for a change at two NoteDb meta SHA-1s. */
      49             : public class GetMetaDiff
      50             :     implements RestReadView<ChangeResource>,
      51             :         DynamicOptions.BeanReceiver,
      52             :         DynamicOptions.BeanProvider {
      53             : 
      54          57 :   private final EnumSet<ListChangesOption> options = EnumSet.noneOf(ListChangesOption.class);
      55          57 :   private final Map<String, DynamicBean> dynamicBeans = new HashMap<>();
      56             : 
      57             :   private final Provider<GetChange> getChangeProvider;
      58             :   private final GitRepositoryManager repoManager;
      59             : 
      60             :   @Option(name = "-o", usage = "Output options")
      61             :   public void addOption(ListChangesOption o) {
      62           1 :     options.add(o);
      63           1 :   }
      64             : 
      65             :   @Option(name = "-O", usage = "Output option flags, in hex")
      66             :   void setOptionFlagsHex(String hex) throws BadRequestException {
      67           0 :     options.addAll(ListOption.fromHexString(ListChangesOption.class, hex));
      68           0 :   }
      69             : 
      70          57 :   @Option(name = "--old", usage = "old NoteDb meta SHA-1")
      71             :   String oldMetaRevId = "";
      72             : 
      73             :   public void setOldMetaRevId(@Nullable String oldMetaRevId) {
      74           1 :     this.oldMetaRevId = oldMetaRevId == null ? "" : oldMetaRevId;
      75           1 :   }
      76             : 
      77          57 :   @Option(name = "--meta", usage = "new NoteDb meta SHA-1")
      78             :   String metaRevId = "";
      79             : 
      80             :   public void setNewMetaRevId(@Nullable String metaRevId) {
      81           1 :     this.metaRevId = metaRevId == null ? "" : metaRevId;
      82           1 :   }
      83             : 
      84             :   @Inject
      85          57 :   GetMetaDiff(Provider<GetChange> getChangeProvider, GitRepositoryManager repoManager) {
      86          57 :     this.getChangeProvider = getChangeProvider;
      87          57 :     this.repoManager = repoManager;
      88          57 :   }
      89             : 
      90             :   @Override
      91             :   public void setDynamicBean(String plugin, DynamicOptions.DynamicBean dynamicBean) {
      92           0 :     dynamicBeans.put(plugin, dynamicBean);
      93           0 :   }
      94             : 
      95             :   @Override
      96             :   public DynamicBean getDynamicBean(String plugin) {
      97           0 :     return dynamicBeans.get(plugin);
      98             :   }
      99             : 
     100             :   @Override
     101             :   public Response<ChangeInfoDifference> apply(ChangeResource resource)
     102             :       throws RestApiException, IOException {
     103           1 :     return Response.ok(
     104           1 :         ChangeInfoDiffer.getDifference(getOldChangeInfo(resource), getNewChangeInfo(resource)));
     105             :   }
     106             : 
     107             :   private ChangeInfo getOldChangeInfo(ChangeResource resource)
     108             :       throws RestApiException, IOException {
     109           1 :     GetChange getChange = createGetChange();
     110           1 :     getChange.setMetaRevId(getOldMetaRevId(resource));
     111             :     ChangeInfo oldChangeInfo;
     112             :     try {
     113           1 :       oldChangeInfo = getChange.apply(resource).value();
     114           1 :     } catch (PreconditionFailedException e) {
     115           1 :       oldChangeInfo = new ChangeInfo();
     116           1 :     }
     117           1 :     return oldChangeInfo;
     118             :   }
     119             : 
     120             :   private String getOldMetaRevId(ChangeResource resource)
     121             :       throws IOException, BadRequestException, PreconditionFailedException {
     122           1 :     if (!oldMetaRevId.isEmpty()) {
     123           1 :       return oldMetaRevId;
     124             :     }
     125           1 :     String newMetaRevId = getNewMetaRevId(resource);
     126           1 :     try (Repository repo = repoManager.openRepository(resource.getProject());
     127           1 :         RevWalk rw = new RevWalk(repo)) {
     128           1 :       ObjectId resourceId = ObjectId.fromString(newMetaRevId);
     129           1 :       RevCommit commit = rw.parseCommit(resourceId);
     130           1 :       return commit.getParentCount() == 0
     131           1 :           ? resourceId.getName()
     132           1 :           : commit.getParent(0).getId().getName();
     133           1 :     } catch (InvalidObjectIdException e) {
     134           1 :       throw new BadRequestException("invalid meta SHA1: " + newMetaRevId, e);
     135           1 :     } catch (MissingObjectException e) {
     136           1 :       throw new PreconditionFailedException(e.getMessage());
     137             :     }
     138             :   }
     139             : 
     140             :   private ChangeInfo getNewChangeInfo(ChangeResource resource)
     141             :       throws RestApiException, IOException {
     142           1 :     GetChange getChange = createGetChange();
     143           1 :     getChange.setMetaRevId(getNewMetaRevId(resource));
     144           1 :     return getChange.apply(resource).value();
     145             :   }
     146             : 
     147             :   private String getNewMetaRevId(ChangeResource resource) throws IOException {
     148           1 :     if (!metaRevId.isEmpty()) {
     149           1 :       return metaRevId;
     150             :     }
     151           1 :     try (Repository repo = repoManager.openRepository(resource.getProject())) {
     152           1 :       return repo.exactRef(changeMetaRef(resource.getId())).getObjectId().getName();
     153             :     }
     154             :   }
     155             : 
     156             :   private GetChange createGetChange() {
     157           1 :     GetChange getChange = getChangeProvider.get();
     158           1 :     options.forEach(getChange::addOption);
     159           1 :     dynamicBeans.forEach(getChange::setDynamicBean);
     160           1 :     return getChange;
     161             :   }
     162             : }

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