RenameBranchCommand.java
- /*
- * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
- * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com> and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- package org.eclipse.jgit.api;
- import java.io.IOException;
- import java.text.MessageFormat;
- import java.util.Arrays;
- import org.eclipse.jgit.api.errors.DetachedHeadException;
- import org.eclipse.jgit.api.errors.GitAPIException;
- import org.eclipse.jgit.api.errors.InvalidRefNameException;
- import org.eclipse.jgit.api.errors.JGitInternalException;
- import org.eclipse.jgit.api.errors.NoHeadException;
- import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
- import org.eclipse.jgit.api.errors.RefNotFoundException;
- import org.eclipse.jgit.internal.JGitText;
- import org.eclipse.jgit.lib.ConfigConstants;
- import org.eclipse.jgit.lib.Constants;
- import org.eclipse.jgit.lib.ObjectId;
- import org.eclipse.jgit.lib.Ref;
- import org.eclipse.jgit.lib.RefRename;
- import org.eclipse.jgit.lib.RefUpdate.Result;
- import org.eclipse.jgit.lib.Repository;
- import org.eclipse.jgit.lib.StoredConfig;
- /**
- * Used to rename branches.
- *
- * @see <a
- * href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html"
- * >Git documentation about Branch</a>
- */
- public class RenameBranchCommand extends GitCommand<Ref> {
- private String oldName;
- private String newName;
- /**
- * <p>
- * Constructor for RenameBranchCommand.
- * </p>
- *
- * @param repo
- * the {@link org.eclipse.jgit.lib.Repository}
- */
- protected RenameBranchCommand(Repository repo) {
- super(repo);
- }
- /** {@inheritDoc} */
- @Override
- public Ref call() throws GitAPIException, RefNotFoundException, InvalidRefNameException,
- RefAlreadyExistsException, DetachedHeadException {
- checkCallable();
- if (newName == null) {
- throw new InvalidRefNameException(MessageFormat.format(JGitText
- .get().branchNameInvalid, "<null>")); //$NON-NLS-1$
- }
- try {
- String fullOldName;
- String fullNewName;
- if (oldName != null) {
- // Don't just rely on findRef -- if there are local and remote
- // branches with the same name, and oldName is a short name, it
- // does not uniquely identify the ref and we might end up
- // renaming the wrong branch or finding a tag instead even
- // if a unique branch for the name exists!
- //
- // OldName may be a either a short or a full name.
- Ref ref = repo.exactRef(oldName);
- if (ref == null) {
- ref = repo.exactRef(Constants.R_HEADS + oldName);
- Ref ref2 = repo.exactRef(Constants.R_REMOTES + oldName);
- if (ref != null && ref2 != null) {
- throw new RefNotFoundException(MessageFormat.format(
- JGitText.get().renameBranchFailedAmbiguous,
- oldName, ref.getName(), ref2.getName()));
- } else if (ref == null) {
- if (ref2 != null) {
- ref = ref2;
- } else {
- throw new RefNotFoundException(MessageFormat.format(
- JGitText.get().refNotResolved, oldName));
- }
- }
- }
- fullOldName = ref.getName();
- } else {
- fullOldName = repo.getFullBranch();
- if (fullOldName == null) {
- throw new NoHeadException(
- JGitText.get().invalidRepositoryStateNoHead);
- }
- if (ObjectId.isId(fullOldName))
- throw new DetachedHeadException();
- }
- if (fullOldName.startsWith(Constants.R_REMOTES)) {
- fullNewName = Constants.R_REMOTES + newName;
- } else if (fullOldName.startsWith(Constants.R_HEADS)) {
- fullNewName = Constants.R_HEADS + newName;
- } else {
- throw new RefNotFoundException(MessageFormat.format(
- JGitText.get().renameBranchFailedNotABranch,
- fullOldName));
- }
- if (!Repository.isValidRefName(fullNewName)) {
- throw new InvalidRefNameException(MessageFormat.format(JGitText
- .get().branchNameInvalid, fullNewName));
- }
- if (repo.exactRef(fullNewName) != null) {
- throw new RefAlreadyExistsException(MessageFormat
- .format(JGitText.get().refAlreadyExists1, fullNewName));
- }
- RefRename rename = repo.renameRef(fullOldName, fullNewName);
- Result renameResult = rename.rename();
- setCallable(false);
- if (Result.RENAMED != renameResult) {
- throw new JGitInternalException(MessageFormat.format(JGitText
- .get().renameBranchUnexpectedResult, renameResult
- .name()));
- }
- if (fullNewName.startsWith(Constants.R_HEADS)) {
- String shortOldName = fullOldName.substring(Constants.R_HEADS
- .length());
- final StoredConfig repoConfig = repo.getConfig();
- // Copy all configuration values over to the new branch
- for (String name : repoConfig.getNames(
- ConfigConstants.CONFIG_BRANCH_SECTION, shortOldName)) {
- String[] values = repoConfig.getStringList(
- ConfigConstants.CONFIG_BRANCH_SECTION,
- shortOldName, name);
- if (values.length == 0) {
- continue;
- }
- // Keep any existing values already configured for the
- // new branch name
- String[] existing = repoConfig.getStringList(
- ConfigConstants.CONFIG_BRANCH_SECTION, newName,
- name);
- if (existing.length > 0) {
- String[] newValues = new String[values.length
- + existing.length];
- System.arraycopy(existing, 0, newValues, 0,
- existing.length);
- System.arraycopy(values, 0, newValues, existing.length,
- values.length);
- values = newValues;
- }
- repoConfig.setStringList(
- ConfigConstants.CONFIG_BRANCH_SECTION, newName,
- name, Arrays.asList(values));
- }
- repoConfig.unsetSection(ConfigConstants.CONFIG_BRANCH_SECTION,
- shortOldName);
- repoConfig.save();
- }
- Ref resultRef = repo.exactRef(fullNewName);
- if (resultRef == null) {
- throw new JGitInternalException(
- JGitText.get().renameBranchFailedUnknownReason);
- }
- return resultRef;
- } catch (IOException ioe) {
- throw new JGitInternalException(ioe.getMessage(), ioe);
- }
- }
- /**
- * Sets the new short name of the branch.
- * <p>
- * The full name is constructed using the prefix of the branch to be renamed
- * defined by either {@link #setOldName(String)} or HEAD. If that old branch
- * is a local branch, the renamed branch also will be, and if the old branch
- * is a remote branch, so will be the renamed branch.
- * </p>
- *
- * @param newName
- * the new name
- * @return this instance
- */
- public RenameBranchCommand setNewName(String newName) {
- checkCallable();
- this.newName = newName;
- return this;
- }
- /**
- * Sets the old name of the branch.
- * <p>
- * {@code oldName} may be a short or a full name. Using a full name is
- * recommended to unambiguously identify the branch to be renamed.
- * </p>
- *
- * @param oldName
- * the name of the branch to rename; if not set, the currently
- * checked out branch (if any) will be renamed
- * @return this instance
- */
- public RenameBranchCommand setOldName(String oldName) {
- checkCallable();
- this.oldName = oldName;
- return this;
- }
- }