LCOV - code coverage report
Current view: top level - server/git - PermissionAwareReadOnlyRefDatabase.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 28 67 41.8 %
Date: 2022-11-19 15:00:39 Functions: 6 20 30.0 %

          Line data    Source code
       1             : // Copyright (C) 2019 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.git;
      16             : 
      17             : import static java.util.stream.Collectors.toMap;
      18             : 
      19             : import com.google.common.base.Preconditions;
      20             : import com.google.common.collect.ImmutableList;
      21             : import com.google.common.collect.Iterables;
      22             : import com.google.gerrit.server.permissions.PermissionBackend;
      23             : import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
      24             : import com.google.gerrit.server.permissions.PermissionBackendException;
      25             : import java.io.IOException;
      26             : import java.util.ArrayList;
      27             : import java.util.Collection;
      28             : import java.util.Collections;
      29             : import java.util.HashMap;
      30             : import java.util.HashSet;
      31             : import java.util.List;
      32             : import java.util.Map;
      33             : import java.util.Set;
      34             : import java.util.function.Function;
      35             : import java.util.stream.Collectors;
      36             : import java.util.stream.Stream;
      37             : import org.eclipse.jgit.annotations.NonNull;
      38             : import org.eclipse.jgit.annotations.Nullable;
      39             : import org.eclipse.jgit.lib.BatchRefUpdate;
      40             : import org.eclipse.jgit.lib.ObjectId;
      41             : import org.eclipse.jgit.lib.Ref;
      42             : import org.eclipse.jgit.lib.RefRename;
      43             : import org.eclipse.jgit.lib.RefUpdate;
      44             : import org.eclipse.jgit.lib.Repository;
      45             : 
      46             : /**
      47             :  * Wrapper around {@link DelegateRefDatabase} that filters all refs using {@link
      48             :  * com.google.gerrit.server.permissions.PermissionBackend}.
      49             :  */
      50             : public class PermissionAwareReadOnlyRefDatabase extends DelegateRefDatabase {
      51             : 
      52             :   private final PermissionBackend.ForProject forProject;
      53             : 
      54             :   PermissionAwareReadOnlyRefDatabase(
      55             :       Repository delegateRepository, PermissionBackend.ForProject forProject) {
      56         134 :     super(delegateRepository);
      57         134 :     this.forProject = forProject;
      58         134 :   }
      59             : 
      60             :   @Override
      61             :   public boolean isNameConflicting(String name) {
      62           0 :     throw new UnsupportedOperationException("PermissionAwareReadOnlyRefDatabase is read-only");
      63             :   }
      64             : 
      65             :   @Override
      66             :   public Collection<String> getConflictingNames(String name) throws IOException {
      67           0 :     throw new UnsupportedOperationException("PermissionAwareReadOnlyRefDatabase is read-only");
      68             :   }
      69             : 
      70             :   @Override
      71             :   public RefUpdate newUpdate(String name, boolean detach) {
      72           0 :     throw new UnsupportedOperationException("PermissionAwareReadOnlyRefDatabase is read-only");
      73             :   }
      74             : 
      75             :   @Override
      76             :   public RefRename newRename(String fromName, String toName) {
      77           0 :     throw new UnsupportedOperationException("PermissionAwareReadOnlyRefDatabase is read-only");
      78             :   }
      79             : 
      80             :   @Override
      81             :   public BatchRefUpdate newBatchUpdate() {
      82           0 :     throw new UnsupportedOperationException("PermissionAwareReadOnlyRefDatabase is read-only");
      83             :   }
      84             : 
      85             :   @Nullable
      86             :   @Override
      87             :   public Ref exactRef(String name) throws IOException {
      88          64 :     Ref ref = getDelegate().getRefDatabase().exactRef(name);
      89          64 :     if (ref == null) {
      90           1 :       return null;
      91             :     }
      92             : 
      93             :     Collection<Ref> result;
      94             :     try {
      95          64 :       result = forProject.filter(ImmutableList.of(ref), getDelegate(), RefFilterOptions.defaults());
      96           0 :     } catch (PermissionBackendException e) {
      97           0 :       if (e.getCause() instanceof IOException) {
      98           0 :         throw (IOException) e.getCause();
      99             :       }
     100           0 :       throw new IOException(e);
     101          64 :     }
     102          64 :     if (result.isEmpty()) {
     103           2 :       return null;
     104             :     }
     105             : 
     106          64 :     Preconditions.checkState(
     107          64 :         result.size() == 1, "Only one element expected, but was: " + result.size());
     108          64 :     return Iterables.getOnlyElement(result);
     109             :   }
     110             : 
     111             :   // WARNING: This method is deprecated in JGit's RefDatabase and it will be removed on master.
     112             :   // Do not add any logic here but rather enrich the getRefsByPrefix method below.
     113             :   @Override
     114             :   public Map<String, Ref> getRefs(String prefix) throws IOException {
     115           0 :     return buildPrefixRefMap(prefix, getRefsByPrefix(prefix));
     116             :   }
     117             : 
     118             :   private Map<String, Ref> buildPrefixRefMap(String prefix, Collection<Ref> refs) {
     119           0 :     int prefixSlashPos = prefix.lastIndexOf('/') + 1;
     120           0 :     if (prefixSlashPos > 0) {
     121           0 :       return refs.stream()
     122           0 :           .collect(
     123           0 :               Collectors.toMap(
     124           0 :                   (Ref ref) -> ref.getName().substring(prefixSlashPos), Function.identity()));
     125             :     }
     126             : 
     127           0 :     return refs.stream().collect(toMap(Ref::getName, r -> r));
     128             :   }
     129             : 
     130             :   @Override
     131             :   public List<Ref> getRefsByPrefix(String prefix) throws IOException {
     132         134 :     List<Ref> refs = getDelegate().getRefDatabase().getRefsByPrefix(prefix);
     133         134 :     if (refs.isEmpty()) {
     134          14 :       return Collections.emptyList();
     135             :     }
     136             : 
     137             :     Collection<Ref> result;
     138             :     try {
     139         134 :       result = forProject.filter(refs, getDelegate(), RefFilterOptions.defaults());
     140           0 :     } catch (PermissionBackendException e) {
     141           0 :       throw new IOException("", e);
     142         134 :     }
     143         134 :     return result.stream().collect(Collectors.toList());
     144             :   }
     145             : 
     146             :   @Override
     147             :   public List<Ref> getRefsByPrefixWithExclusions(String include, Set<String> excludes)
     148             :       throws IOException {
     149           0 :     Stream<Ref> refs = getRefs(include).values().stream();
     150           0 :     for (String exclude : excludes) {
     151           0 :       refs = refs.filter(r -> !r.getName().startsWith(exclude));
     152           0 :     }
     153           0 :     return Collections.unmodifiableList(refs.collect(Collectors.toList()));
     154             :   }
     155             : 
     156             :   @Override
     157             :   public List<Ref> getRefsByPrefix(String... prefixes) throws IOException {
     158          13 :     List<Ref> result = new ArrayList<>();
     159          13 :     for (String prefix : prefixes) {
     160          13 :       result.addAll(getRefsByPrefix(prefix));
     161             :     }
     162          13 :     return Collections.unmodifiableList(result);
     163             :   }
     164             : 
     165             :   @Override
     166             :   @NonNull
     167             :   public Map<String, Ref> exactRef(String... refs) throws IOException {
     168           0 :     Map<String, Ref> result = new HashMap<>(refs.length);
     169           0 :     for (String name : refs) {
     170           0 :       Ref ref = exactRef(name);
     171           0 :       if (ref != null) {
     172           0 :         result.put(name, ref);
     173             :       }
     174             :     }
     175           0 :     return result;
     176             :   }
     177             : 
     178             :   @Override
     179             :   @Nullable
     180             :   public Ref firstExactRef(String... refs) throws IOException {
     181           0 :     for (String name : refs) {
     182           0 :       Ref ref = exactRef(name);
     183           0 :       if (ref != null) {
     184           0 :         return ref;
     185             :       }
     186             :     }
     187           0 :     return null;
     188             :   }
     189             : 
     190             :   @Override
     191             :   public List<Ref> getRefs() throws IOException {
     192         134 :     return getRefsByPrefix(ALL);
     193             :   }
     194             : 
     195             :   @Override
     196             :   @NonNull
     197             :   public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
     198           1 :     Set<Ref> unfiltered = super.getTipsWithSha1(id);
     199           1 :     Set<Ref> result = new HashSet<>(unfiltered.size());
     200           1 :     for (Ref ref : unfiltered) {
     201           0 :       if (exactRef(ref.getName()) != null) {
     202           0 :         result.add(ref);
     203             :       }
     204           0 :     }
     205           1 :     return result;
     206             :   }
     207             : 
     208             :   @Override
     209             :   public boolean hasRefs() throws IOException {
     210           0 :     return !getRefs().isEmpty();
     211             :   }
     212             : }

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