blob: 772277bdab680fcdc5664e3568d9d1b73404d103 [file] [log] [blame]
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.plugins.codeowners.testing.backend;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigParser;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.Optional;
import java.util.function.Consumer;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.RawParseUtils;
/** Test utility to read/write code owner configs directly from/to a repository. */
public class TestCodeOwnerConfigStorage {
public interface Factory {
TestCodeOwnerConfigStorage create(String fileName, CodeOwnerConfigParser codeOwnerConfigParser);
}
private final String defaultFileName;
private final GitRepositoryManager repoManager;
private final CodeOwnerConfigParser codeOwnerConfigParser;
@Inject
TestCodeOwnerConfigStorage(
GitRepositoryManager repoManager,
@Assisted String defaultFileName,
@Assisted CodeOwnerConfigParser codeOwnerConfigParser) {
this.defaultFileName = defaultFileName;
this.repoManager = repoManager;
this.codeOwnerConfigParser = codeOwnerConfigParser;
}
/**
* Write a code owner config directly to a repository.
*
* <p>Requires that the repository and the branch in which the code owner config should be stored
* already exist.
*
* @param codeOwnerConfigKey the key of the code owner config that should be written
* @param codeOwnerConfigUpdater consumer for a code owner config builder on which the code owner
* config properties should be set
* @return the code owner config that was written
*/
public CodeOwnerConfig writeCodeOwnerConfig(
CodeOwnerConfig.Key codeOwnerConfigKey,
Consumer<CodeOwnerConfig.Builder> codeOwnerConfigUpdater)
throws Exception {
CodeOwnerConfig.Builder codeOwnerConfigBuilder =
readCodeOwnerConfig(codeOwnerConfigKey)
.map(key -> key.toBuilder())
.orElse(
CodeOwnerConfig.builder(
codeOwnerConfigKey,
ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")));
codeOwnerConfigUpdater.accept(codeOwnerConfigBuilder);
CodeOwnerConfig codeOwnerConfig = codeOwnerConfigBuilder.build();
String formattedCodeOwnerConfig = codeOwnerConfigParser.formatAsString(codeOwnerConfig);
try (TestRepository<Repository> testRepo =
new TestRepository<>(repoManager.openRepository(codeOwnerConfigKey.project()))) {
Ref ref = testRepo.getRepository().exactRef(codeOwnerConfigKey.ref());
RevCommit head = testRepo.getRevWalk().parseCommit(ref.getObjectId());
RevCommit revision =
testRepo.update(
codeOwnerConfigKey.ref(),
testRepo
.commit()
.parent(head)
.message("Add test code owner config")
.add(
JgitPath.of(codeOwnerConfigKey.filePath(defaultFileName)).get(),
formattedCodeOwnerConfig));
return codeOwnerConfig.toBuilder().setRevision(revision).build();
}
}
/**
* Reads a code owner config directly from a repository.
*
* @param codeOwnerConfigKey the key of the code owner config that should be read
* @return the code owner config if it exist, otherwise {@link Optional#empty()}
*/
public Optional<CodeOwnerConfig> readCodeOwnerConfig(CodeOwnerConfig.Key codeOwnerConfigKey)
throws Exception {
try (TestRepository<Repository> testRepo =
new TestRepository<>(repoManager.openRepository(codeOwnerConfigKey.project()))) {
Ref ref = testRepo.getRepository().exactRef(codeOwnerConfigKey.ref());
if (ref == null) {
// branch does not exist
return Optional.empty();
}
RevCommit commit = testRepo.getRevWalk().parseCommit(ref.getObjectId());
String filePath = JgitPath.of(codeOwnerConfigKey.filePath(defaultFileName)).get();
try (TreeWalk tw =
TreeWalk.forPath(testRepo.getRevWalk().getObjectReader(), filePath, commit.getTree())) {
if (tw == null) {
// file does not exist
return Optional.empty();
}
}
RevObject blob = testRepo.get(commit.getTree(), filePath);
byte[] data = testRepo.getRepository().open(blob).getCachedBytes(Integer.MAX_VALUE);
return Optional.of(
codeOwnerConfigParser.parse(commit, codeOwnerConfigKey, RawParseUtils.decode(data)));
}
}
}