LCOV - code coverage report
Current view: top level - server/query/change - HasSubmoduleUpdatePredicate.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 23 31 74.2 %
Date: 2022-11-19 15:00:39 Functions: 3 4 75.0 %

          Line data    Source code
       1             : // Copyright (C) 2022 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.query.change;
      16             : 
      17             : import static com.google.gerrit.server.query.change.SubmitRequirementChangeQueryBuilder.SUBMODULE_UPDATE_HAS_ARG;
      18             : 
      19             : import com.google.gerrit.entities.Patch.FileMode;
      20             : import com.google.gerrit.exceptions.StorageException;
      21             : import com.google.gerrit.server.git.GitRepositoryManager;
      22             : import com.google.gerrit.server.patch.DiffNotAvailableException;
      23             : import com.google.gerrit.server.patch.DiffOperations;
      24             : import com.google.gerrit.server.patch.DiffOptions;
      25             : import com.google.gerrit.server.patch.filediff.FileDiffOutput;
      26             : import com.google.inject.Inject;
      27             : import com.google.inject.assistedinject.Assisted;
      28             : import java.io.IOException;
      29             : import java.util.Map;
      30             : import java.util.Optional;
      31             : import org.eclipse.jgit.lib.Repository;
      32             : import org.eclipse.jgit.revwalk.RevCommit;
      33             : import org.eclipse.jgit.revwalk.RevWalk;
      34             : 
      35             : /**
      36             :  * Submit requirement predicate that returns true if the diff of the latest patchset against the
      37             :  * parent number identified by {@link #base} has a submodule modified file, that is, a .gitmodules
      38             :  * or a git link file.
      39             :  */
      40             : public class HasSubmoduleUpdatePredicate extends SubmitRequirementPredicate {
      41             :   private static final String GIT_MODULES_FILE = ".gitmodules";
      42             : 
      43             :   private final DiffOperations diffOperations;
      44             :   private final GitRepositoryManager repoManager;
      45             :   private final int base;
      46             : 
      47             :   public interface Factory {
      48             :     HasSubmoduleUpdatePredicate create(int base);
      49             :   }
      50             : 
      51             :   @Inject
      52             :   HasSubmoduleUpdatePredicate(
      53             :       DiffOperations diffOperations, GitRepositoryManager repoManager, @Assisted int base) {
      54           1 :     super("has", SUBMODULE_UPDATE_HAS_ARG);
      55           1 :     this.diffOperations = diffOperations;
      56           1 :     this.repoManager = repoManager;
      57           1 :     this.base = base;
      58           1 :   }
      59             : 
      60             :   @Override
      61             :   public boolean match(ChangeData cd) {
      62             :     try {
      63           1 :       try (Repository repo = repoManager.openRepository(cd.project());
      64           1 :           RevWalk rw = new RevWalk(repo)) {
      65           1 :         RevCommit revCommit = rw.parseCommit(cd.currentPatchSet().commitId());
      66           1 :         if (base > revCommit.getParentCount()) {
      67           1 :           return false;
      68             :         }
      69           1 :       }
      70           1 :       Map<String, FileDiffOutput> diffList =
      71           1 :           diffOperations.listModifiedFilesAgainstParent(
      72           1 :               cd.project(), cd.currentPatchSet().commitId(), base, DiffOptions.DEFAULTS);
      73           1 :       return diffList.values().stream().anyMatch(HasSubmoduleUpdatePredicate::isGitLink);
      74           0 :     } catch (DiffNotAvailableException e) {
      75           0 :       throw new StorageException(
      76           0 :           String.format(
      77             :               "Failed to evaluate the diff for commit %s against parent number %d",
      78           0 :               cd.currentPatchSet().commitId(), base),
      79             :           e);
      80           0 :     } catch (IOException e) {
      81           0 :       throw new StorageException(
      82           0 :           String.format("Failed to open repo for project %s", cd.project()), e);
      83             :     }
      84             :   }
      85             : 
      86             :   /**
      87             :    * Return true if the modified file is a {@link #GIT_MODULES_FILE} or a git link regardless of if
      88             :    * the modification type is add, remove or modify.
      89             :    */
      90             :   private static boolean isGitLink(FileDiffOutput fileDiffOutput) {
      91           1 :     Optional<String> oldPath = fileDiffOutput.oldPath();
      92           1 :     Optional<String> newPath = fileDiffOutput.newPath();
      93           1 :     Optional<FileMode> oldMode = fileDiffOutput.oldMode();
      94           1 :     Optional<FileMode> newMode = fileDiffOutput.newMode();
      95             : 
      96           1 :     return (oldPath.isPresent() && oldPath.get().equals(GIT_MODULES_FILE))
      97           1 :         || (newPath.isPresent() && newPath.get().equals(GIT_MODULES_FILE))
      98           1 :         || (oldMode.isPresent() && oldMode.get().equals(FileMode.GITLINK))
      99           1 :         || (newMode.isPresent() && newMode.get().equals(FileMode.GITLINK));
     100             :   }
     101             : 
     102             :   @Override
     103             :   public int getCost() {
     104           0 :     return 1;
     105             :   }
     106             : }

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