blob: c932b96651f265a2d8088c04aafe6a624aa02969 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2010, 2016 Mathias Kinzler <mathias.kinzler@sap.com> and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.egit.core.op;
import java.io.IOException;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.internal.CoreText;
import org.eclipse.egit.core.internal.job.RuleUtil;
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.osgi.util.NLS;
/**
* This class implements creation of a local branch based on a commit or another
* branch
*/
public class CreateLocalBranchOperation implements IEGitOperation {
private final String name;
private final Repository repository;
private final Ref ref;
private final RevCommit commit;
private final BranchRebaseMode upstreamConfig;
/**
* @param repository
* @param name
* the name for the new local branch (without prefix)
* @param ref
* the branch or tag to base the new branch upon
* @param config
* how to do the upstream configuration
*/
public CreateLocalBranchOperation(Repository repository, String name,
Ref ref, BranchRebaseMode config) {
this.name = name;
this.repository = repository;
this.ref = ref;
this.commit = null;
this.upstreamConfig = config;
}
/**
* @param repository
* @param name
* the name for the new local branch (without prefix)
* @param commit
* a commit to base the new branch upon
*/
public CreateLocalBranchOperation(Repository repository, String name,
RevCommit commit) {
this.name = name;
this.repository = repository;
this.ref = null;
this.commit = commit;
this.upstreamConfig = null;
}
@Override
public void execute(IProgressMonitor m) throws CoreException {
IProgressMonitor monitor;
if (m == null)
monitor = new NullProgressMonitor();
else
monitor = m;
IWorkspaceRunnable action = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor actMonitor) throws CoreException {
String taskName = NLS
.bind(
CoreText.CreateLocalBranchOperation_CreatingBranchMessage,
name);
actMonitor.beginTask(taskName, 1);
try (Git git = new Git(repository)) {
if (ref != null) {
SetupUpstreamMode mode;
if (upstreamConfig == null)
mode = SetupUpstreamMode.NOTRACK;
else
mode = SetupUpstreamMode.SET_UPSTREAM;
git.branchCreate().setName(name).setStartPoint(
ref.getName()).setUpstreamMode(mode).call();
}
else
git.branchCreate().setName(name).setStartPoint(commit)
.setUpstreamMode(SetupUpstreamMode.NOTRACK)
.call();
} catch (Exception e) {
throw new CoreException(Activator.error(e.getMessage(), e));
}
if (upstreamConfig != null) {
// set "branch.<name>.rebase"
StoredConfig config = repository.getConfig();
config.setEnum(ConfigConstants.CONFIG_BRANCH_SECTION, name,
ConfigConstants.CONFIG_KEY_REBASE, upstreamConfig);
try {
config.save();
} catch (IOException e) {
throw new CoreException(Activator.error(e.getMessage(),
e));
}
}
actMonitor.worked(1);
actMonitor.done();
}
};
// lock workspace to protect working tree changes
ResourcesPlugin.getWorkspace().run(action, getSchedulingRule(),
IWorkspace.AVOID_UPDATE, monitor);
}
@Override
public ISchedulingRule getSchedulingRule() {
return RuleUtil.getRule(repository);
}
/**
* Get the default upstream config for the specified repository and upstream
* branch ref.
*
* @param repo
* @param upstreamRefName
* @return the default {@link BranchRebaseMode}, or {@code null} if none is
* configured
*/
public static BranchRebaseMode getDefaultUpstreamConfig(Repository repo,
String upstreamRefName) {
boolean isLocalBranch = upstreamRefName.startsWith(Constants.R_HEADS);
boolean isRemoteBranch = upstreamRefName
.startsWith(Constants.R_REMOTES);
if (!isLocalBranch && !isRemoteBranch) {
return null;
}
String autosetupMerge = repo.getConfig().getString(
ConfigConstants.CONFIG_BRANCH_SECTION, null,
ConfigConstants.CONFIG_KEY_AUTOSETUPMERGE);
if (autosetupMerge == null) {
autosetupMerge = ConfigConstants.CONFIG_KEY_TRUE;
}
boolean setupMerge = autosetupMerge
.equals(ConfigConstants.CONFIG_KEY_ALWAYS)
|| (isRemoteBranch && autosetupMerge
.equals(ConfigConstants.CONFIG_KEY_TRUE));
if (!setupMerge) {
return null;
}
String autosetupRebase = repo.getConfig().getString(
ConfigConstants.CONFIG_BRANCH_SECTION, null,
ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE);
if (autosetupRebase == null) {
autosetupRebase = ConfigConstants.CONFIG_KEY_NEVER;
}
boolean setupRebase = autosetupRebase
.equals(ConfigConstants.CONFIG_KEY_ALWAYS)
|| (autosetupRebase.equals(ConfigConstants.CONFIG_KEY_LOCAL)
&& isLocalBranch)
|| (autosetupRebase.equals(ConfigConstants.CONFIG_KEY_REMOTE)
&& isRemoteBranch);
if (setupRebase) {
// Like cgit: plain rebase
return BranchRebaseMode.REBASE;
}
return BranchRebaseMode.NONE;
}
}