LCOV - code coverage report
Current view: top level - server/notedb - IntBlob.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 37 38 97.4 %
Date: 2022-11-19 15:00:39 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2018 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.notedb;
      16             : 
      17             : import static java.nio.charset.StandardCharsets.UTF_8;
      18             : import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
      19             : 
      20             : import com.google.auto.value.AutoValue;
      21             : import com.google.common.annotations.VisibleForTesting;
      22             : import com.google.common.base.CharMatcher;
      23             : import com.google.common.flogger.FluentLogger;
      24             : import com.google.common.primitives.Ints;
      25             : import com.google.gerrit.common.Nullable;
      26             : import com.google.gerrit.entities.Project;
      27             : import com.google.gerrit.exceptions.StorageException;
      28             : import com.google.gerrit.git.RefUpdateUtil;
      29             : import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
      30             : import java.io.IOException;
      31             : import java.util.Optional;
      32             : import org.eclipse.jgit.errors.IncorrectObjectTypeException;
      33             : import org.eclipse.jgit.lib.AnyObjectId;
      34             : import org.eclipse.jgit.lib.ObjectId;
      35             : import org.eclipse.jgit.lib.ObjectInserter;
      36             : import org.eclipse.jgit.lib.ObjectLoader;
      37             : import org.eclipse.jgit.lib.ObjectReader;
      38             : import org.eclipse.jgit.lib.Ref;
      39             : import org.eclipse.jgit.lib.RefUpdate;
      40             : import org.eclipse.jgit.lib.Repository;
      41             : import org.eclipse.jgit.revwalk.RevWalk;
      42             : 
      43             : /** An object blob in a Git repository that stores a single integer value. */
      44             : @AutoValue
      45         151 : public abstract class IntBlob {
      46         151 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      47             : 
      48             :   public static Optional<IntBlob> parse(Repository repo, String refName) throws IOException {
      49         139 :     try (ObjectReader or = repo.newObjectReader()) {
      50         139 :       return parse(repo, refName, or);
      51             :     }
      52             :   }
      53             : 
      54             :   public static Optional<IntBlob> parse(Repository repo, String refName, RevWalk rw)
      55             :       throws IOException {
      56         151 :     return parse(repo, refName, rw.getObjectReader());
      57             :   }
      58             : 
      59             :   private static Optional<IntBlob> parse(Repository repo, String refName, ObjectReader or)
      60             :       throws IOException {
      61         151 :     Ref ref = repo.exactRef(refName);
      62         151 :     if (ref == null) {
      63         151 :       return Optional.empty();
      64             :     }
      65         151 :     ObjectId id = ref.getObjectId();
      66         151 :     ObjectLoader ol = or.open(id, OBJ_BLOB);
      67         151 :     if (ol.getType() != OBJ_BLOB) {
      68             :       // In theory this should be thrown by open but not all implementations may do it properly
      69             :       // (certainly InMemoryRepository doesn't).
      70           0 :       throw new IncorrectObjectTypeException(id, OBJ_BLOB);
      71             :     }
      72         151 :     String str = CharMatcher.whitespace().trimFrom(new String(ol.getCachedBytes(), UTF_8));
      73         151 :     Integer value = Ints.tryParse(str);
      74         151 :     if (value == null) {
      75           1 :       throw new StorageException("invalid value in " + refName + " blob at " + id.name());
      76             :     }
      77         151 :     return Optional.of(IntBlob.create(id, value));
      78             :   }
      79             : 
      80             :   public static RefUpdate tryStore(
      81             :       Repository repo,
      82             :       RevWalk rw,
      83             :       Project.NameKey projectName,
      84             :       String refName,
      85             :       @Nullable ObjectId oldId,
      86             :       int val,
      87             :       GitReferenceUpdated gitRefUpdated)
      88             :       throws IOException {
      89             :     ObjectId newId;
      90         151 :     try (ObjectInserter ins = repo.newObjectInserter()) {
      91         151 :       logger.atFine().log(
      92             :           "storing value %d on %s in %s (oldId: %s)",
      93         151 :           val, refName, projectName, oldId == null ? "null" : oldId.name());
      94         151 :       newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
      95         151 :       ins.flush();
      96         151 :       logger.atFine().log(
      97         151 :           "successfully stored %d on %s as %s in %s", val, refName, newId.name(), projectName);
      98             :     }
      99         151 :     RefUpdate ru = repo.updateRef(refName);
     100         151 :     if (oldId != null) {
     101         151 :       ru.setExpectedOldObjectId(oldId);
     102             :     }
     103         151 :     ru.disableRefLog();
     104         151 :     ru.setNewObjectId(newId);
     105         151 :     ru.setForceUpdate(true); // Required for non-commitish updates.
     106         151 :     RefUpdate.Result result = ru.update(rw);
     107         151 :     if (refUpdated(result)) {
     108         151 :       gitRefUpdated.fire(projectName, ru, null);
     109             :     }
     110         151 :     return ru;
     111             :   }
     112             : 
     113             :   public static void store(
     114             :       Repository repo,
     115             :       RevWalk rw,
     116             :       Project.NameKey projectName,
     117             :       String refName,
     118             :       @Nullable ObjectId oldId,
     119             :       int val,
     120             :       GitReferenceUpdated gitRefUpdated)
     121             :       throws IOException {
     122         151 :     RefUpdateUtil.checkResult(tryStore(repo, rw, projectName, refName, oldId, val, gitRefUpdated));
     123         151 :   }
     124             : 
     125             :   private static boolean refUpdated(RefUpdate.Result result) {
     126         151 :     return result == RefUpdate.Result.NEW || result == RefUpdate.Result.FORCED;
     127             :   }
     128             : 
     129             :   @VisibleForTesting
     130             :   static IntBlob create(AnyObjectId id, int value) {
     131         151 :     return new AutoValue_IntBlob(id.copy(), value);
     132             :   }
     133             : 
     134             :   public abstract ObjectId id();
     135             : 
     136             :   public abstract int value();
     137             : }

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