LCOV - code coverage report
Current view: top level - server/git/meta - MetaDataUpdate.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 63 63 100.0 %
Date: 2022-11-19 15:00:39 Functions: 25 25 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2011 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.meta;
      16             : 
      17             : import com.google.gerrit.common.Nullable;
      18             : import com.google.gerrit.entities.Project;
      19             : import com.google.gerrit.server.GerritPersonIdent;
      20             : import com.google.gerrit.server.IdentifiedUser;
      21             : import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
      22             : import com.google.gerrit.server.git.GitRepositoryManager;
      23             : import com.google.inject.Inject;
      24             : import com.google.inject.Provider;
      25             : import com.google.inject.Singleton;
      26             : import com.google.inject.assistedinject.Assisted;
      27             : import java.io.IOException;
      28             : import org.eclipse.jgit.errors.RepositoryNotFoundException;
      29             : import org.eclipse.jgit.lib.BatchRefUpdate;
      30             : import org.eclipse.jgit.lib.CommitBuilder;
      31             : import org.eclipse.jgit.lib.PersonIdent;
      32             : import org.eclipse.jgit.lib.RefUpdate;
      33             : import org.eclipse.jgit.lib.Repository;
      34             : 
      35             : /** Helps with the updating of a {@link VersionedMetaData}. */
      36             : public class MetaDataUpdate implements AutoCloseable {
      37             :   @Singleton
      38             :   public static class User {
      39             :     private final InternalFactory factory;
      40             :     private final GitRepositoryManager mgr;
      41             :     private final Provider<PersonIdent> serverIdentProvider;
      42             :     private final Provider<IdentifiedUser> identifiedUser;
      43             : 
      44             :     @Inject
      45             :     User(
      46             :         InternalFactory factory,
      47             :         GitRepositoryManager mgr,
      48             :         @GerritPersonIdent Provider<PersonIdent> serverIdentProvider,
      49         147 :         Provider<IdentifiedUser> identifiedUser) {
      50         147 :       this.factory = factory;
      51         147 :       this.mgr = mgr;
      52         147 :       this.serverIdentProvider = serverIdentProvider;
      53         147 :       this.identifiedUser = identifiedUser;
      54         147 :     }
      55             : 
      56             :     public PersonIdent getUserPersonIdent() {
      57         135 :       return createPersonIdent(identifiedUser.get());
      58             :     }
      59             : 
      60             :     public MetaDataUpdate create(Project.NameKey name)
      61             :         throws RepositoryNotFoundException, IOException {
      62         144 :       return create(name, identifiedUser.get());
      63             :     }
      64             : 
      65             :     public MetaDataUpdate create(Project.NameKey name, IdentifiedUser user)
      66             :         throws RepositoryNotFoundException, IOException {
      67         145 :       return create(name, user, null);
      68             :     }
      69             : 
      70             :     /**
      71             :      * Create an update using an existing batch ref update.
      72             :      *
      73             :      * <p>This allows batching together updates to multiple metadata refs. For making multiple
      74             :      * commits to a single metadata ref, see {@link VersionedMetaData#openUpdate(MetaDataUpdate)}.
      75             :      *
      76             :      * @param name project name.
      77             :      * @param user user for the update.
      78             :      * @param batch batch update to use; the caller is responsible for committing the update.
      79             :      */
      80             :     public MetaDataUpdate create(Project.NameKey name, IdentifiedUser user, BatchRefUpdate batch)
      81             :         throws RepositoryNotFoundException, IOException {
      82         145 :       Repository repo = mgr.openRepository(name);
      83         145 :       MetaDataUpdate md = create(name, repo, user, batch);
      84         145 :       md.setCloseRepository(true);
      85         145 :       return md;
      86             :     }
      87             : 
      88             :     /**
      89             :      * Create an update using an existing batch ref update.
      90             :      *
      91             :      * <p>This allows batching together updates to multiple metadata refs. For making multiple
      92             :      * commits to a single metadata ref, see {@link VersionedMetaData#openUpdate(MetaDataUpdate)}.
      93             :      *
      94             :      * <p>Important: Create a new MetaDataUpdate instance for each update:
      95             :      *
      96             :      * <pre>
      97             :      * <code>
      98             :      *   try (Repository repo = repoMgr.openRepository(allUsersName);
      99             :      *       RevWalk rw = new RevWalk(repo)) {
     100             :      *     BatchRefUpdate batchUpdate = repo.getRefDatabase().newBatchUpdate();
     101             :      *     // WRONG: create the MetaDataUpdate instance here and reuse it for
     102             :      *     //        all updates in the loop
     103             :      *     for{@code (Map.Entry<Account.Id, DiffPreferencesInfo> e : diffPrefsFromDb)} {
     104             :      *       // CORRECT: create a new MetaDataUpdate instance for each update
     105             :      *       try (MetaDataUpdate md =
     106             :      *           metaDataUpdateFactory.create(allUsersName, batchUpdate)) {
     107             :      *         md.setMessage("Import diff preferences from reviewdb\n");
     108             :      *         VersionedAccountPreferences vPrefs =
     109             :      *             VersionedAccountPreferences.forUser(e.getKey());
     110             :      *         storeSection(vPrefs.getConfig(), UserConfigSections.DIFF, null,
     111             :      *             e.getValue(), DiffPreferencesInfo.defaults());
     112             :      *         vPrefs.commit(md);
     113             :      *       } catch (ConfigInvalidException e) {
     114             :      *         // TODO handle exception
     115             :      *       }
     116             :      *     }
     117             :      *     batchUpdate.execute(rw, NullProgressMonitor.INSTANCE);
     118             :      *   }
     119             :      * </code>
     120             :      * </pre>
     121             :      *
     122             :      * @param name project name.
     123             :      * @param repository the repository to update; the caller is responsible for closing the
     124             :      *     repository.
     125             :      * @param user user for the update.
     126             :      * @param batch batch update to use; the caller is responsible for committing the update.
     127             :      */
     128             :     public MetaDataUpdate create(
     129             :         Project.NameKey name, Repository repository, IdentifiedUser user, BatchRefUpdate batch) {
     130         145 :       MetaDataUpdate md = factory.create(name, repository, batch);
     131         145 :       md.getCommitBuilder().setCommitter(serverIdentProvider.get());
     132         145 :       md.setAuthor(user);
     133         145 :       return md;
     134             :     }
     135             : 
     136             :     private PersonIdent createPersonIdent(IdentifiedUser user) {
     137         135 :       PersonIdent serverIdent = serverIdentProvider.get();
     138         135 :       return user.newCommitterIdent(serverIdent);
     139             :     }
     140             :   }
     141             : 
     142             :   @Singleton
     143             :   public static class Server {
     144             :     private final InternalFactory factory;
     145             :     private final GitRepositoryManager mgr;
     146             :     private final Provider<PersonIdent> serverIdentProvider;
     147             : 
     148             :     @Inject
     149             :     Server(
     150             :         InternalFactory factory,
     151             :         GitRepositoryManager mgr,
     152         147 :         @GerritPersonIdent Provider<PersonIdent> serverIdentProvider) {
     153         147 :       this.factory = factory;
     154         147 :       this.mgr = mgr;
     155         147 :       this.serverIdentProvider = serverIdentProvider;
     156         147 :     }
     157             : 
     158             :     public MetaDataUpdate create(Project.NameKey name)
     159             :         throws RepositoryNotFoundException, IOException {
     160          94 :       return create(name, null);
     161             :     }
     162             : 
     163             :     /** See {@link User#create(Project.NameKey, IdentifiedUser, BatchRefUpdate)} */
     164             :     public MetaDataUpdate create(Project.NameKey name, BatchRefUpdate batch)
     165             :         throws RepositoryNotFoundException, IOException {
     166          94 :       Repository repo = mgr.openRepository(name);
     167          94 :       MetaDataUpdate md = factory.create(name, repo, batch);
     168          94 :       md.setCloseRepository(true);
     169          94 :       PersonIdent serverIdent = serverIdentProvider.get();
     170          94 :       md.getCommitBuilder().setAuthor(serverIdent);
     171          94 :       md.getCommitBuilder().setCommitter(serverIdent);
     172          94 :       return md;
     173             :     }
     174             :   }
     175             : 
     176             :   public interface InternalFactory {
     177             :     MetaDataUpdate create(
     178             :         @Assisted Project.NameKey projectName,
     179             :         @Assisted Repository repository,
     180             :         @Assisted @Nullable BatchRefUpdate batch);
     181             :   }
     182             : 
     183             :   private final GitReferenceUpdated gitRefUpdated;
     184             :   private final Project.NameKey projectName;
     185             :   private final Repository repository;
     186             :   private final BatchRefUpdate batch;
     187             :   private final CommitBuilder commit;
     188             :   private boolean allowEmpty;
     189             :   private boolean insertChangeId;
     190             :   private boolean closeRepository;
     191             :   private IdentifiedUser author;
     192             : 
     193             :   @Inject
     194             :   public MetaDataUpdate(
     195             :       GitReferenceUpdated gitRefUpdated,
     196             :       @Assisted Project.NameKey projectName,
     197             :       @Assisted Repository repository,
     198         152 :       @Assisted @Nullable BatchRefUpdate batch) {
     199         152 :     this.gitRefUpdated = gitRefUpdated;
     200         152 :     this.projectName = projectName;
     201         152 :     this.repository = repository;
     202         152 :     this.batch = batch;
     203         152 :     this.commit = new CommitBuilder();
     204         152 :   }
     205             : 
     206             :   public MetaDataUpdate(
     207             :       GitReferenceUpdated gitRefUpdated, Project.NameKey projectName, Repository repository) {
     208         152 :     this(gitRefUpdated, projectName, repository, null);
     209         152 :   }
     210             : 
     211             :   /** Set the commit message used when committing the update. */
     212             :   public void setMessage(String message) {
     213         151 :     getCommitBuilder().setMessage(message);
     214         151 :   }
     215             : 
     216             :   public void setAuthor(IdentifiedUser author) {
     217         151 :     this.author = author;
     218         151 :     getCommitBuilder().setAuthor(author.newCommitterIdent(getCommitBuilder().getCommitter()));
     219         151 :   }
     220             : 
     221             :   public void setAllowEmpty(boolean allowEmpty) {
     222         151 :     this.allowEmpty = allowEmpty;
     223         151 :   }
     224             : 
     225             :   public void setInsertChangeId(boolean insertChangeId) {
     226           2 :     this.insertChangeId = insertChangeId;
     227           2 :   }
     228             : 
     229             :   public void setCloseRepository(boolean closeRepository) {
     230         145 :     this.closeRepository = closeRepository;
     231         145 :   }
     232             : 
     233             :   /** Returns batch in which to run the update, or {@code null} for no batch. */
     234             :   BatchRefUpdate getBatch() {
     235         152 :     return batch;
     236             :   }
     237             : 
     238             :   /** Close the cached Repository handle. */
     239             :   @Override
     240             :   public void close() {
     241         152 :     if (closeRepository) {
     242         145 :       getRepository().close();
     243             :     }
     244         152 :   }
     245             : 
     246             :   public Project.NameKey getProjectName() {
     247         151 :     return projectName;
     248             :   }
     249             : 
     250             :   public Repository getRepository() {
     251         152 :     return repository;
     252             :   }
     253             : 
     254             :   boolean allowEmpty() {
     255         152 :     return allowEmpty;
     256             :   }
     257             : 
     258             :   boolean insertChangeId() {
     259         152 :     return insertChangeId;
     260             :   }
     261             : 
     262             :   public CommitBuilder getCommitBuilder() {
     263         152 :     return commit;
     264             :   }
     265             : 
     266             :   protected void fireGitRefUpdatedEvent(RefUpdate ru) {
     267         152 :     gitRefUpdated.fire(projectName, ru, author == null ? null : author.state());
     268         152 :   }
     269             : }

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