blob: 02831e6dec80d0d71b4d5e11deec9a3e95dfba90 [file] [log] [blame]
// Copyright (C) 2016 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.googlesource.gerrit.plugins.batch.util;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.NoSuchRefException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.submit.IntegrationException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.batch.util.MergeBuilder.FastForwardMode;
import java.io.IOException;
import java.util.concurrent.Callable;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
public class MergeBranch implements Callable<ObjectId> {
public interface Factory {
MergeBranch create(
@Assisted BranchNameKey destBranch,
@Assisted("destSha") @Nullable String destSha,
@Assisted("sourceRef") String srcName,
@Assisted MergeStrategy strategy,
@Assisted FastForwardMode fastForwardMode,
@Assisted("message") String message);
}
protected final GitRepositoryManager repoManager;
protected final ProjectCache projectCache;
protected final MergeBuilder.Factory builderFactory;
protected final Project.NameKey projectName;
protected final String destName;
protected ObjectId destId;
protected final String srcName;
protected final String message;
protected MergeStrategy strategy;
protected FastForwardMode fastForwardMode = FastForwardMode.FF;
@Inject
MergeBranch(
GitRepositoryManager repoManager,
ProjectCache projectCache,
MergeBuilder.Factory builderFactory,
@Assisted BranchNameKey destBranch,
@Assisted("destSha") @Nullable String destSha,
@Assisted("sourceRef") String srcName,
@Assisted("message") @Nullable String message,
@Assisted @Nullable MergeStrategy strategy,
@Assisted @Nullable FastForwardMode fastForwardMode) {
this.projectCache = projectCache;
this.repoManager = repoManager;
this.builderFactory = builderFactory;
this.projectName = destBranch.project();
destName = RefNames.fullName(destBranch.branch());
if (destSha != null) {
this.destId = ObjectId.fromString(destSha);
}
this.srcName = srcName;
this.message = message;
this.strategy = strategy;
if (fastForwardMode != null) {
this.fastForwardMode = fastForwardMode;
}
}
@Override
public ObjectId call()
throws IOException, NoSuchRefException, RepositoryNotFoundException, IntegrationException,
BadRequestException {
try (Repository repo = repoManager.openRepository(projectName)) {
Ref destRef = repo.getRefDatabase().exactRef(destName);
if (destRef == null) {
throw new NoSuchRefException(destName);
}
if (destId == null) {
destId = repo.resolve(destName);
if (destId == null) {
throw new BadRequestException("Invalid Revision");
}
}
ObjectId srcId = repo.resolve(srcName);
if (srcId == null) {
throw new BadRequestException("Invalid Revision");
}
strategy = defaultStrategy(strategy);
return builderFactory
.create(projectName, message, strategy, fastForwardMode, destId, srcId)
.call();
}
}
protected MergeStrategy defaultStrategy(MergeStrategy strategy) {
if (strategy == null) {
ProjectState project = projectFromName(projectName);
if (project != null && project.is(BooleanProjectConfig.USE_CONTENT_MERGE)) {
return MergeStrategy.RESOLVE;
}
return MergeStrategy.SIMPLE_TWO_WAY_IN_CORE;
}
return strategy;
}
protected ProjectState projectFromName(Project.NameKey name) {
ProjectState ps = projectCache.get(name);
return ps != null ? ps : null;
}
}