summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorMathias Kinzler2010-10-08 08:01:55 (EDT)
committer Chris Aniszczyk2010-10-10 16:38:49 (EDT)
commit7bdef4583bd9aad6e4cb9e51543bdc3c0fb26db4 (patch)
tree8482e545d3af94fb61c23c3397183be5bfee3589
parentbe2ddff6a72cff3d28b87d038a96194a6e2bd272 (diff)
downloadjgit-7bdef4583bd9aad6e4cb9e51543bdc3c0fb26db4.zip
jgit-7bdef4583bd9aad6e4cb9e51543bdc3c0fb26db4.tar.gz
jgit-7bdef4583bd9aad6e4cb9e51543bdc3c0fb26db4.tar.bz2
Add "Branch" commandrefs/changes/04/1704/6
The need for branching becomes more pressing with pull support: we need to make sure the upstream configuration entries are written correctly when creating and renaming branches (and of course are cleaned up when deleting them). This adds support for listing, adding, deleting and renaming branches including the more common options. Bug: 326938 Change-Id: I00bcc19476e835d6fd78fd188acde64946c1505c Signed-off-by: Mathias Kinzler <mathias.kinzler@sap.com> Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java416
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java365
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java197
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java36
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java132
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java207
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CannotDeleteCurrentBranchException.java53
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/InvalidRefNameException.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/NotMergedException.java54
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefAlreadyExistsException.java55
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotFoundException.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java2
14 files changed, 1643 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java
new file mode 100644
index 0000000..07dc560
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api;
+
+import java.util.List;
+
+import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
+import org.eclipse.jgit.api.ListBranchCommand.ListMode;
+import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
+import org.eclipse.jgit.api.errors.DetachedHeadException;
+import org.eclipse.jgit.api.errors.InvalidRefNameException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.api.errors.NotMergedException;
+import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
+import org.eclipse.jgit.api.errors.RefNotFoundException;
+import org.eclipse.jgit.errors.AmbiguousObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryTestCase;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+
+public class BranchCommandTest extends RepositoryTestCase {
+ private Git git;
+
+ RevCommit initialCommit;
+
+ RevCommit secondCommit;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ git = new Git(db);
+ // checkout master
+ git.commit().setMessage("initial commit").call();
+ // commit something
+ writeTrashFile("Test.txt", "Hello world");
+ git.add().addFilepattern("Test.txt").call();
+ initialCommit = git.commit().setMessage("Initial commit").call();
+ writeTrashFile("Test.txt", "Some change");
+ git.add().addFilepattern("Test.txt").call();
+ secondCommit = git.commit().setMessage("Second commit").call();
+ // create a master branch
+ RefUpdate rup = db.updateRef("refs/heads/master");
+ rup.setNewObjectId(initialCommit.getId());
+ rup.setForceUpdate(true);
+ rup.update();
+ }
+
+ private Git setUpRepoWithRemote() throws Exception {
+ Repository remoteRepository = createWorkRepository();
+ Git remoteGit = new Git(remoteRepository);
+ // commit something
+ writeTrashFile("Test.txt", "Hello world");
+ remoteGit.add().addFilepattern("Test.txt").call();
+ initialCommit = remoteGit.commit().setMessage("Initial commit").call();
+ writeTrashFile("Test.txt", "Some change");
+ remoteGit.add().addFilepattern("Test.txt").call();
+ secondCommit = remoteGit.commit().setMessage("Second commit").call();
+ // create a master branch
+ RefUpdate rup = remoteRepository.updateRef("refs/heads/master");
+ rup.setNewObjectId(initialCommit.getId());
+ rup.forceUpdate();
+
+ Repository localRepository = createWorkRepository();
+ Git localGit = new Git(localRepository);
+ StoredConfig config = localRepository.getConfig();
+ RemoteConfig rc = new RemoteConfig(config, "origin");
+ rc.addURI(new URIish(remoteRepository.getDirectory().getPath()));
+ rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ rc.update(config);
+ config.save();
+ FetchResult res = localGit.fetch().setRemote("origin").call();
+ assertFalse(res.getTrackingRefUpdates().isEmpty());
+ rup = localRepository.updateRef("refs/heads/master");
+ rup.setNewObjectId(initialCommit.getId());
+ rup.forceUpdate();
+ rup = localRepository.updateRef(Constants.HEAD);
+ rup.link("refs/heads/master");
+ rup.setNewObjectId(initialCommit.getId());
+ rup.update();
+ return localGit;
+ }
+
+ public void testCreateAndList() throws Exception {
+ int localBefore;
+ int remoteBefore;
+ int allBefore;
+
+ // invalid name not allowed
+ try {
+ git.branchCreate().setName("In va lid").call();
+ fail("Create branch with invalid ref name should fail");
+ } catch (InvalidRefNameException e) {
+ // expected
+ }
+ // existing name not allowed w/o force
+ try {
+ git.branchCreate().setName("master").call();
+ fail("Create branch with existing ref name should fail");
+ } catch (RefAlreadyExistsException e) {
+ // expected
+ }
+
+ localBefore = git.branchList().call().size();
+ remoteBefore = git.branchList().setListMode(ListMode.REMOTE).call()
+ .size();
+ allBefore = git.branchList().setListMode(ListMode.ALL).call().size();
+
+ assertEquals(localBefore + remoteBefore, allBefore);
+ Ref newBranch = createBranch(git, "NewForTestList", false, "master",
+ null);
+ assertEquals("refs/heads/NewForTestList", newBranch.getName());
+
+ assertEquals(1, git.branchList().call().size() - localBefore);
+ assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
+ .size()
+ - remoteBefore);
+ assertEquals(1, git.branchList().setListMode(ListMode.ALL).call()
+ .size()
+ - allBefore);
+ // we can only create local branches
+ newBranch = createBranch(git,
+ "refs/remotes/origin/NewRemoteForTestList", false, "master",
+ null);
+ assertEquals("refs/heads/refs/remotes/origin/NewRemoteForTestList",
+ newBranch.getName());
+ assertEquals(2, git.branchList().call().size() - localBefore);
+ assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
+ .size()
+ - remoteBefore);
+ assertEquals(2, git.branchList().setListMode(ListMode.ALL).call()
+ .size()
+ - allBefore);
+ }
+
+ public void testCreateFromCommit() throws Exception {
+ Ref branch = git.branchCreate().setName("FromInitial").setStartPoint(
+ initialCommit).call();
+ assertEquals(initialCommit.getId(), branch.getObjectId());
+ branch = git.branchCreate().setName("FromInitial2").setStartPoint(
+ initialCommit.getId().name()).call();
+ assertEquals(initialCommit.getId(), branch.getObjectId());
+ try {
+ git.branchCreate().setName("FromInitial").setStartPoint(
+ secondCommit).call();
+ } catch (RefAlreadyExistsException e) {
+ // expected
+ }
+ branch = git.branchCreate().setName("FromInitial").setStartPoint(
+ secondCommit).setForce(true).call();
+ assertEquals(secondCommit.getId(), branch.getObjectId());
+ }
+
+ public void testCreateForce() throws Exception {
+ // using commits
+ Ref newBranch = createBranch(git, "NewForce", false, secondCommit
+ .getId().name(), null);
+ assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
+ try {
+ newBranch = createBranch(git, "NewForce", false, initialCommit
+ .getId().name(), null);
+ fail("Should have failed");
+ } catch (RefAlreadyExistsException e) {
+ // expected
+ }
+ newBranch = createBranch(git, "NewForce", true, initialCommit.getId()
+ .name(), null);
+ assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
+ git.branchDelete().setBranchNames("NewForce").call();
+ // using names
+
+ git.branchCreate().setName("NewForce").setStartPoint("master").call();
+ assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
+ try {
+ git.branchCreate().setName("NewForce").setStartPoint("master")
+ .call();
+ fail("Should have failed");
+ } catch (RefAlreadyExistsException e) {
+ // expected
+ }
+ git.branchCreate().setName("NewForce").setStartPoint("master")
+ .setForce(true).call();
+ assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
+ }
+
+ public void testDelete() throws Exception {
+ createBranch(git, "ForDelete", false, "master", null);
+ git.branchDelete().setBranchNames("ForDelete").call();
+ // now point the branch to a non-merged commit
+ createBranch(git, "ForDelete", false, secondCommit.getId().name(), null);
+ try {
+ git.branchDelete().setBranchNames("ForDelete").call();
+ fail("Deletion of a non-merged branch without force should have failed");
+ } catch (NotMergedException e) {
+ // expected
+ }
+ List<String> deleted = git.branchDelete().setBranchNames("ForDelete")
+ .setForce(true).call();
+ assertEquals(1, deleted.size());
+ assertEquals(Constants.R_HEADS + "ForDelete", deleted.get(0));
+ createBranch(git, "ForDelete", false, "master", null);
+ try {
+ createBranch(git, "ForDelete", false, "master", null);
+ fail("Repeated creation of same branch without force should fail");
+ } catch (RefAlreadyExistsException e) {
+ // expected
+ }
+ // change starting point
+ Ref newBranch = createBranch(git, "ForDelete", true, initialCommit
+ .name(), null);
+ assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
+ newBranch = createBranch(git, "ForDelete", true, secondCommit.name(),
+ null);
+ assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
+ git.branchDelete().setBranchNames("ForDelete").setForce(true);
+ try {
+ git.branchDelete().setBranchNames("master").call();
+ fail("Deletion of checked out branch without force should have failed");
+ } catch (CannotDeleteCurrentBranchException e) {
+ // expected
+ }
+ try {
+ git.branchDelete().setBranchNames("master").setForce(true).call();
+ fail("Deletion of checked out branch with force should have failed");
+ } catch (CannotDeleteCurrentBranchException e) {
+ // expected
+ }
+ }
+
+ public void testPullConfigRemoteBranch() throws Exception {
+ Git localGit = setUpRepoWithRemote();
+ Ref remote = localGit.branchList().setListMode(ListMode.REMOTE).call()
+ .get(0);
+ assertEquals("refs/remotes/origin/master", remote.getName());
+ // by default, we should create pull configuration
+ createBranch(localGit, "newFromRemote", false, remote.getName(), null);
+ assertEquals("origin", localGit.getRepository().getConfig().getString(
+ "branch", "newFromRemote", "remote"));
+ localGit.branchDelete().setBranchNames("newFromRemote").call();
+ // the pull configuration should be gone after deletion
+ assertNull(localGit.getRepository().getConfig().getString("branch",
+ "newFromRemote", "remote"));
+ // use --no-track
+ createBranch(localGit, "newFromRemote", false, remote.getName(),
+ SetupUpstreamMode.NOTRACK);
+ assertNull(localGit.getRepository().getConfig().getString("branch",
+ "newFromRemote", "remote"));
+ localGit.branchDelete().setBranchNames("newFromRemote").call();
+ }
+
+ public void testPullConfigLocalBranch() throws Exception {
+ Git localGit = setUpRepoWithRemote();
+ // by default, we should not create pull configuration
+ createBranch(localGit, "newFromMaster", false, "master", null);
+ assertNull(localGit.getRepository().getConfig().getString("branch",
+ "newFromMaster", "remote"));
+ localGit.branchDelete().setBranchNames("newFromMaster").call();
+ // use --track
+ createBranch(localGit, "newFromMaster", false, "master",
+ SetupUpstreamMode.TRACK);
+ assertEquals(".", localGit.getRepository().getConfig().getString(
+ "branch", "newFromMaster", "remote"));
+ localGit.branchDelete().setBranchNames("newFromMaster").call();
+ // the pull configuration should be gone after deletion
+ assertNull(localGit.getRepository().getConfig().getString("branch",
+ "newFromRemote", "remote"));
+ }
+
+ public void testPullConfigRenameLocalBranch() throws Exception {
+ Git localGit = setUpRepoWithRemote();
+ // by default, we should not create pull configuration
+ createBranch(localGit, "newFromMaster", false, "master", null);
+ assertNull(localGit.getRepository().getConfig().getString("branch",
+ "newFromMaster", "remote"));
+ localGit.branchDelete().setBranchNames("newFromMaster").call();
+ // use --track
+ createBranch(localGit, "newFromMaster", false, "master",
+ SetupUpstreamMode.TRACK);
+ assertEquals(".", localGit.getRepository().getConfig().getString(
+ "branch", "newFromMaster", "remote"));
+ localGit.branchRename().setOldName("newFromMaster").setNewName(
+ "renamed").call();
+ assertNull(".", localGit.getRepository().getConfig().getString(
+ "branch", "newFromMaster", "remote"));
+ assertEquals(".", localGit.getRepository().getConfig().getString(
+ "branch", "renamed", "remote"));
+ localGit.branchDelete().setBranchNames("renamed").call();
+ // the pull configuration should be gone after deletion
+ assertNull(localGit.getRepository().getConfig().getString("branch",
+ "newFromRemote", "remote"));
+ }
+
+ public void testRenameLocalBranch() throws Exception {
+ // null newName not allowed
+ try {
+ git.branchRename().call();
+ } catch (InvalidRefNameException e) {
+ // expected
+ }
+ // invalid newName not allowed
+ try {
+ git.branchRename().setNewName("In va lid").call();
+ } catch (InvalidRefNameException e) {
+ // expected
+ }
+ // not existing name not allowed
+ try {
+ git.branchRename().setOldName("notexistingbranch").setNewName(
+ "newname").call();
+ } catch (RefNotFoundException e) {
+ // expected
+ }
+ // create some branch
+ createBranch(git, "existing", false, "master", null);
+ // a local branch
+ Ref branch = createBranch(git, "fromMasterForRename", false, "master",
+ null);
+ assertEquals(Constants.R_HEADS + "fromMasterForRename", branch
+ .getName());
+ Ref renamed = git.branchRename().setOldName("fromMasterForRename")
+ .setNewName("newName").call();
+ assertEquals(Constants.R_HEADS + "newName", renamed.getName());
+ try {
+ git.branchRename().setOldName(renamed.getName()).setNewName(
+ "existing").call();
+ fail("Should have failed");
+ } catch (RefAlreadyExistsException e) {
+ // expected
+ }
+ try {
+ git.branchRename().setNewName("In va lid").call();
+ fail("Rename with invalid ref name should fail");
+ } catch (InvalidRefNameException e) {
+ // expected
+ }
+ // rename without old name and detached head not allowed
+ RefUpdate rup = git.getRepository().updateRef(Constants.HEAD, true);
+ rup.setNewObjectId(initialCommit);
+ rup.forceUpdate();
+ try {
+ git.branchRename().setNewName("detached").call();
+ } catch (DetachedHeadException e) {
+ // expected
+ }
+ }
+
+ public void testRenameRemoteTrackingBranch() throws Exception {
+ Git localGit = setUpRepoWithRemote();
+ Ref remoteBranch = localGit.branchList().setListMode(ListMode.REMOTE)
+ .call().get(0);
+ Ref renamed = localGit.branchRename()
+ .setOldName(remoteBranch.getName()).setNewName("newRemote")
+ .call();
+ assertEquals(Constants.R_REMOTES + "newRemote", renamed.getName());
+ }
+
+ public Ref createBranch(Git actGit, String name, boolean force,
+ String startPoint, SetupUpstreamMode mode)
+ throws JGitInternalException, RefAlreadyExistsException,
+ AmbiguousObjectException, RefNotFoundException,
+ InvalidRefNameException {
+ CreateBranchCommand cmd = actGit.branchCreate();
+ cmd.setName(name);
+ cmd.setForce(force);
+ cmd.setStartPoint(startPoint);
+ cmd.setUpstreamMode(mode);
+ return cmd.call();
+ }
+}
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
index 2b0bf51..3cc144a 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
@@ -30,6 +30,7 @@ base64InputNotProperlyPadded=Base64 input not properly padded.
baseLengthIncorrect=base length incorrect
bareRepositoryNoWorkdirAndIndex=Bare Repository has neither a working tree, nor an index
blobNotFound=Blob not found: {0}
+branchNameInvalid=Branch name {0} is not allowed
blobNotFoundForPath=Blob not found: {0} for path: {1}
cannotBeCombined=Cannot be combined.
cannotCombineTreeFilterWithRevFilter=Cannot combine TreeFilter {0} with RefFilter {1}.
@@ -40,6 +41,7 @@ cannotConvertScriptToText=Cannot convert script to text
cannotCreateConfig=cannot create config
cannotCreateDirectory=Cannot create directory {0}
cannotCreateHEAD=cannot create HEAD
+cannotDeleteCheckedOutBranch=Branch {0} is checked out and can not be deleted
cannotDeleteFile=Cannot delete file: {0}
cannotDeleteStaleTrackingRef2=Cannot delete stale tracking ref {0}: {1}
cannotDeleteStaleTrackingRef=Cannot delete stale tracking ref {0}
@@ -118,8 +120,11 @@ couldNotRenameTemporaryIndexFileToIndex=Could not rename temporary index file to
couldNotURLEncodeToUTF8=Could not URL encode to UTF-8
couldNotWriteFile=Could not write file {0}
countingObjects=Counting objects
+createBranchFailedUnknownReason=Create branch failed for unknown reason
+createBranchUnexpectedResult=Create branch returned unexpected result {0}
creatingDeltasIsNotImplemented=creating deltas is not implemented
daemonAlreadyRunning=Daemon already running
+deleteBranchUnexpectedResult=Delete branch returned unexpected result {0}
deletingNotSupported=Deleting {0} not supported.
destinationIsNotAWildcard=Destination is not a wildcard.
detachedHeadDetected=HEAD is detached
@@ -277,6 +282,7 @@ notFound=not found.
notValid={0} not valid
nothingToFetch=Nothing to fetch.
nothingToPush=Nothing to push.
+notMergedExceptionMessage=Branch was not deleted as it has not been merged yet; use the force option to delete it anyway
objectAtHasBadZlibStream=Object at {0} in {1} has bad zlib stream
objectAtPathDoesNotHaveId=Object at path "{0}" does not have an id assigned. All object ids must be assigned prior to writing a tree.
objectIsCorrupt=Object {0} is corrupt: {1}
@@ -317,6 +323,8 @@ rawLogMessageDoesNotParseAsLogEntry=Raw log message does not parse as log entry
readTimedOut=Read timed out
readingObjectsFromLocalRepositoryFailed=reading objects from local repository failed: {0}
receivingObjects=Receiving objects
+refAlreadExists=Ref {0} already exists
+refNotResolved=Ref {0} can not be resolved
refUpdateReturnCodeWas=RefUpdate return code was: {0}
reflogsNotYetSupportedByRevisionParser=reflogs not yet supported by revision parser
remoteConfigHasNoURIAssociated=Remote config "{0}" has no URIs associated
@@ -324,6 +332,9 @@ remoteDoesNotHaveSpec=Remote does not have {0} available for fetch.
remoteDoesNotSupportSmartHTTPPush=remote does not support smart HTTP push
remoteHungUpUnexpectedly=remote hung up unexpectedly
remoteNameCantBeNull=Remote name can't be null.
+renameBranchFailedBecauseTag=Can not rename as Ref {0} is a tag
+renameBranchFailedUnknownReason=Rename failed with unknown reason
+renameBranchUnexpectedResult=Unexpected rename result {0}
renamesAlreadyFound=Renames have already been found.
renamesBreakingModifies=Breaking apart modified file pairs
renamesFindingByContent=Finding renames by content similarity
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
index 6019b6a..93b9700 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
@@ -91,6 +91,7 @@ public class JGitText extends TranslationBundle {
/***/ public String bareRepositoryNoWorkdirAndIndex;
/***/ public String blobNotFound;
/***/ public String blobNotFoundForPath;
+ /***/ public String branchNameInvalid;
/***/ public String cannotBeCombined;
/***/ public String cannotCombineTreeFilterWithRevFilter;
/***/ public String cannotCommitOnARepoWithState;
@@ -100,6 +101,7 @@ public class JGitText extends TranslationBundle {
/***/ public String cannotCreateConfig;
/***/ public String cannotCreateDirectory;
/***/ public String cannotCreateHEAD;
+ /***/ public String cannotDeleteCheckedOutBranch;
/***/ public String cannotDeleteFile;
/***/ public String cannotDeleteStaleTrackingRef2;
/***/ public String cannotDeleteStaleTrackingRef;
@@ -178,8 +180,11 @@ public class JGitText extends TranslationBundle {
/***/ public String couldNotURLEncodeToUTF8;
/***/ public String couldNotWriteFile;
/***/ public String countingObjects;
+ /***/ public String createBranchFailedUnknownReason;
+ /***/ public String createBranchUnexpectedResult;
/***/ public String creatingDeltasIsNotImplemented;
/***/ public String daemonAlreadyRunning;
+ /***/ public String deleteBranchUnexpectedResult;
/***/ public String deletingNotSupported;
/***/ public String destinationIsNotAWildcard;
/***/ public String detachedHeadDetected;
@@ -337,6 +342,7 @@ public class JGitText extends TranslationBundle {
/***/ public String notValid;
/***/ public String nothingToFetch;
/***/ public String nothingToPush;
+ /***/ public String notMergedExceptionMessage;
/***/ public String objectAtHasBadZlibStream;
/***/ public String objectAtPathDoesNotHaveId;
/***/ public String objectIsCorrupt;
@@ -377,6 +383,8 @@ public class JGitText extends TranslationBundle {
/***/ public String readTimedOut;
/***/ public String readingObjectsFromLocalRepositoryFailed;
/***/ public String receivingObjects;
+ /***/ public String refAlreadExists;
+ /***/ public String refNotResolved;
/***/ public String refUpdateReturnCodeWas;
/***/ public String reflogsNotYetSupportedByRevisionParser;
/***/ public String remoteConfigHasNoURIAssociated;
@@ -384,6 +392,9 @@ public class JGitText extends TranslationBundle {
/***/ public String remoteDoesNotSupportSmartHTTPPush;
/***/ public String remoteHungUpUnexpectedly;
/***/ public String remoteNameCantBeNull;
+ /***/ public String renameBranchFailedBecauseTag;
+ /***/ public String renameBranchFailedUnknownReason;
+ /***/ public String renameBranchUnexpectedResult;
/***/ public String renamesAlreadyFound;
/***/ public String renamesBreakingModifies;
/***/ public String renamesFindingByContent;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java
new file mode 100644
index 0000000..4c584c3
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.api.errors.InvalidRefNameException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
+import org.eclipse.jgit.api.errors.RefNotFoundException;
+import org.eclipse.jgit.errors.AmbiguousObjectException;
+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.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * Used to create a local branch.
+ *
+ * @see <a
+ * href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html"
+ * >Git documentation about Branch</a>
+ */
+public class CreateBranchCommand extends GitCommand<Ref> {
+ private String name;
+
+ private boolean force = false;
+
+ private SetupUpstreamMode upstreamMode;
+
+ private String startPoint;
+
+ private RevCommit startCommit;
+
+ /**
+ * The modes available for setting up the upstream configuration
+ * (corresponding to the --set-upstream, --track, --no-track options
+ *
+ */
+ public enum SetupUpstreamMode {
+ /**
+ * Corresponds to the --track option
+ */
+ TRACK,
+ /**
+ * Corresponds to the --no-track option
+ */
+ NOTRACK,
+ /**
+ * Corresponds to the --set-upstream option
+ */
+ SET_UPSTREAM;
+ }
+
+ /**
+ * @param repo
+ */
+ protected CreateBranchCommand(Repository repo) {
+ super(repo);
+ }
+
+ /**
+ * @throws RefAlreadyExistsException
+ * when trying to create (without force) a branch with a name
+ * that already exists
+ * @throws RefNotFoundException
+ * if the start point can not be found
+ * @throws AmbiguousObjectException
+ * if the start point is ambiguous
+ * @throws InvalidRefNameException
+ * if the provided name is <code>null</code> or otherwise
+ * invalid
+ * @return the newly created branch
+ */
+ public Ref call() throws JGitInternalException, RefAlreadyExistsException,
+ RefNotFoundException, AmbiguousObjectException,
+ InvalidRefNameException {
+ checkCallable();
+ processOptions();
+ try {
+ boolean exists = repo.getRef(name) != null;
+ if (!force && exists)
+ throw new RefAlreadyExistsException(MessageFormat.format(
+ JGitText.get().refAlreadExists, name));
+
+ ObjectId startAt = getStartPoint();
+ String startPointFullName = null;
+ if (startPoint != null) {
+ Ref baseRef = repo.getRef(startPoint);
+ if (baseRef != null)
+ startPointFullName = baseRef.getName();
+ }
+
+ // determine whether we are based on a commit,
+ // a branch, or a tag and compose the reflog message
+ String refLogMessage;
+ String baseBranch = "";
+ if (startPointFullName == null) {
+ String baseCommit;
+ if (startCommit != null)
+ baseCommit = startCommit.getShortMessage();
+ else {
+ RevCommit commit = new RevWalk(repo).parseCommit(repo
+ .resolve(startPoint));
+ baseCommit = commit.getShortMessage();
+ }
+ if (exists)
+ refLogMessage = "branch: Reset start-point to commit "
+ + baseCommit;
+ else
+ refLogMessage = "branch: Created from commit " + baseCommit;
+
+ } else if (startPointFullName.startsWith(Constants.R_HEADS)
+ || startPointFullName.startsWith(Constants.R_REMOTES)) {
+ baseBranch = startPointFullName;
+ if (exists)
+ refLogMessage = "branch: Reset start-point to branch "
+ + startPointFullName; // TODO
+ else
+ refLogMessage = "branch: Created from branch " + baseBranch;
+ } else {
+ if (exists)
+ refLogMessage = "branch: Reset start-point to tag "
+ + startPointFullName;
+ else
+ refLogMessage = "branch: Created from tag "
+ + startPointFullName;
+ }
+
+ RefUpdate updateRef = repo.updateRef(Constants.R_HEADS + name);
+ updateRef.setNewObjectId(startAt);
+ updateRef.setRefLogMessage(refLogMessage, false);
+ Result updateResult;
+ if (exists && force)
+ updateResult = updateRef.forceUpdate();
+ else
+ updateResult = updateRef.update();
+
+ setCallable(false);
+
+ boolean ok = false;
+ switch (updateResult) {
+ case NEW:
+ ok = !exists;
+ break;
+ case NO_CHANGE:
+ case FAST_FORWARD:
+ case FORCED:
+ ok = exists;
+ break;
+ default:
+ break;
+ }
+
+ if (!ok)
+ throw new JGitInternalException(MessageFormat.format(JGitText
+ .get().createBranchUnexpectedResult, updateResult
+ .name()));
+
+ Ref result = repo.getRef(name);
+ if (result == null)
+ throw new JGitInternalException(
+ JGitText.get().createBranchFailedUnknownReason);
+
+ if (baseBranch.length() == 0) {
+ return result;
+ }
+
+ // if we are based on another branch, see
+ // if we need to configure upstream configuration: first check
+ // whether the setting was done explicitly
+ boolean doConfigure;
+ if (upstreamMode == SetupUpstreamMode.SET_UPSTREAM
+ || upstreamMode == SetupUpstreamMode.TRACK)
+ // explicitly set to configure
+ doConfigure = true;
+ else if (upstreamMode == SetupUpstreamMode.NOTRACK)
+ // explicitly set to not configure
+ doConfigure = false;
+ else {
+ // if there was no explicit setting, check the configuration
+ String autosetupflag = repo.getConfig().getString(
+ ConfigConstants.CONFIG_BRANCH_SECTION, null,
+ ConfigConstants.CONFIG_KEY_AUTOSETUPMERGE);
+ if ("false".equals(autosetupflag)) {
+ doConfigure = false;
+ } else if ("always".equals(autosetupflag)) {
+ doConfigure = true;
+ } else {
+ // in this case, the default is to configure
+ // only in case the base branch was a remote branch
+ doConfigure = baseBranch.startsWith(Constants.R_REMOTES);
+ }
+ }
+
+ if (doConfigure) {
+ StoredConfig config = repo.getConfig();
+ String[] tokens = baseBranch.split("/", 4);
+ boolean isRemote = tokens[1].equals("remotes");
+ if (isRemote) {
+ // refs/remotes/<remote name>/<branch>
+ String remoteName = tokens[2];
+ String branchName = tokens[3];
+ config
+ .setString(ConfigConstants.CONFIG_BRANCH_SECTION,
+ name, ConfigConstants.CONFIG_KEY_REMOTE,
+ remoteName);
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION,
+ name, ConfigConstants.CONFIG_KEY_MERGE,
+ Constants.R_HEADS + branchName);
+ } else {
+ // set "." as remote
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION,
+ name, ConfigConstants.CONFIG_KEY_REMOTE, ".");
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION,
+ name, ConfigConstants.CONFIG_KEY_MERGE, baseBranch);
+ }
+ config.save();
+ }
+ return result;
+ } catch (AmbiguousObjectException e) {
+ throw e;
+ } catch (IOException ioe) {
+ throw new JGitInternalException(ioe.getMessage(), ioe);
+ }
+ }
+
+ private ObjectId getStartPoint() throws AmbiguousObjectException,
+ RefNotFoundException, IOException {
+ if (startCommit != null)
+ return startCommit.getId();
+ ObjectId result = null;
+ try {
+ if (startPoint == null)
+ result = repo.resolve(Constants.HEAD);
+ result = repo.resolve(startPoint);
+ } catch (AmbiguousObjectException e) {
+ throw e;
+ }
+ if (result == null)
+ throw new RefNotFoundException(MessageFormat.format(
+ JGitText.get().refNotResolved,
+ startPoint != null ? startPoint : Constants.HEAD));
+ return result;
+ }
+
+ private void processOptions() throws InvalidRefNameException {
+ if (name == null
+ || !Repository.isValidRefName(Constants.R_HEADS + name))
+ throw new InvalidRefNameException(MessageFormat.format(JGitText
+ .get().branchNameInvalid, name == null ? "<null>" : name));
+ }
+
+ /**
+ * @param name
+ * the name of the new branch
+ * @return this instance
+ */
+ public CreateBranchCommand setName(String name) {
+ checkCallable();
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param force
+ * if <code>true</code> and the branch with the given name
+ * already exists, the start-point of an existing branch will be
+ * set to a new start-point; if false, the existing branch will
+ * not be changed
+ * @return this instance
+ */
+ public CreateBranchCommand setForce(boolean force) {
+ checkCallable();
+ this.force = force;
+ return this;
+ }
+
+ /**
+ * @param startPoint
+ * corresponds to the start-point option; if <code>null</code>,
+ * the current HEAD will be used
+ * @return this instance
+ */
+ public CreateBranchCommand setStartPoint(String startPoint) {
+ checkCallable();
+ this.startPoint = startPoint;
+ this.startCommit = null;
+ return this;
+ }
+
+ /**
+ * @param startPoint
+ * corresponds to the start-point option; if <code>null</code>,
+ * the current HEAD will be used
+ * @return this instance
+ */
+ public CreateBranchCommand setStartPoint(RevCommit startPoint) {
+ checkCallable();
+ this.startCommit = startPoint;
+ this.startPoint = null;
+ return this;
+ }
+
+ /**
+ * @param mode
+ * corresponds to the --track/--no-track/--set-upstream options;
+ * may be <code>null</code>
+ * @return this instance
+ */
+ public CreateBranchCommand setUpstreamMode(SetupUpstreamMode mode) {
+ checkCallable();
+ this.upstreamMode = mode;
+ return this;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
new file mode 100644
index 0000000..c0d95f3
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.api.errors.NotMergedException;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * Used to delete one or several branches.
+ *
+ * The result of {@link #call()} is a list with the (full) names of the deleted
+ * branches.
+ *
+ * Note that we don't have a setter corresponding to the -r option; remote
+ * tracking branches are simply deleted just like local branches.
+ *
+ * @see <a
+ * href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html"
+ * >Git documentation about Branch</a>
+ */
+public class DeleteBranchCommand extends GitCommand<List<String>> {
+ private final Set<String> branchNames = new HashSet<String>();
+
+ private boolean force;
+
+ /**
+ * @param repo
+ */
+ protected DeleteBranchCommand(Repository repo) {
+ super(repo);
+ }
+
+ /**
+ * @throws NotMergedException
+ * when trying to delete a branch which has not been merged into
+ * the currently checked out branch without force
+ * @return the list with the (full) names of the deleted branches
+ */
+ public List<String> call() throws JGitInternalException,
+ NotMergedException, CannotDeleteCurrentBranchException {
+ checkCallable();
+ List<String> result = new ArrayList<String>();
+ if (branchNames.isEmpty())
+ return result;
+ try {
+ String currentBranch = repo.getFullBranch();
+ if (!force) {
+ // check if the branches to be deleted
+ // are all merged into the current branch
+ RevWalk walk = new RevWalk(repo);
+ RevCommit tip = walk.parseCommit(repo.resolve(Constants.HEAD));
+ for (String branchName : branchNames) {
+ if (branchName == null)
+ continue;
+ Ref currentRef = repo.getRef(branchName);
+ if (currentRef == null)
+ continue;
+
+ RevCommit base = walk.parseCommit(repo.resolve(branchName));
+ if (!walk.isMergedInto(base, tip)) {
+ throw new NotMergedException();
+ }
+ }
+ }
+ setCallable(false);
+ for (String branchName : branchNames) {
+ if (branchName == null)
+ continue;
+ Ref currentRef = repo.getRef(branchName);
+ if (currentRef == null)
+ continue;
+ if (currentRef.getName().equals(currentBranch))
+ throw new CannotDeleteCurrentBranchException(
+ MessageFormat
+ .format(
+ JGitText.get().cannotDeleteCheckedOutBranch,
+ branchName));
+ RefUpdate update = repo.updateRef(currentRef.getName());
+ update.setRefLogMessage("branch deleted", false);
+ update.setForceUpdate(true);
+ Result deleteResult = update.delete();
+
+ boolean ok = true;
+ switch (deleteResult) {
+ case IO_FAILURE:
+ case LOCK_FAILURE:
+ case REJECTED:
+ ok = false;
+ break;
+ default:
+ break;
+ }
+
+ if (ok) {
+ result.add(currentRef.getName());
+ // remove upstream configuration if any
+ repo.getConfig().unsetSection(
+ ConfigConstants.CONFIG_BRANCH_SECTION, branchName);
+ repo.getConfig().save();
+ } else
+ throw new JGitInternalException(MessageFormat.format(
+ JGitText.get().deleteBranchUnexpectedResult,
+ deleteResult.name()));
+ }
+ return result;
+ } catch (IOException ioe) {
+ throw new JGitInternalException(ioe.getMessage(), ioe);
+ }
+ }
+
+ /**
+ * @param branchnames
+ * the names of the branches to delete; if not set, this will do
+ * nothing; invalid branch names will simply be ignored
+ * @return this instance
+ */
+ public DeleteBranchCommand setBranchNames(String... branchnames) {
+ checkCallable();
+ this.branchNames.clear();
+ for (String branch : branchnames)
+ this.branchNames.add(branch);
+ return this;
+ }
+
+ /**
+ * @param force
+ * <code>true</code> corresponds to the -D option,
+ * <code>false</code> to the -d option (default) <br>
+ * if <code>false</code> a check will be performed whether the
+ * branch to be deleted is already merged into the current branch
+ * and deletion will be refused in this case
+ * @return this instance
+ */
+ public DeleteBranchCommand setForce(boolean force) {
+ checkCallable();
+ this.force = force;
+ return this;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
index 493019a..eef5ab9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
@@ -143,6 +143,42 @@ public class Git {
}
/**
+ * Returns a command object used to create branches
+ *
+ * @return a {@link CreateBranchCommand}
+ */
+ public CreateBranchCommand branchCreate() {
+ return new CreateBranchCommand(repo);
+ }
+
+ /**
+ * Returns a command object used to delete branches
+ *
+ * @return a {@link DeleteBranchCommand}
+ */
+ public DeleteBranchCommand branchDelete() {
+ return new DeleteBranchCommand(repo);
+ }
+
+ /**
+ * Returns a command object used to list branches
+ *
+ * @return a {@link ListBranchCommand}
+ */
+ public ListBranchCommand branchList() {
+ return new ListBranchCommand(repo);
+ }
+
+ /**
+ * Returns a command object used to rename branches
+ *
+ * @return a {@link RenameBranchCommand}
+ */
+ public RenameBranchCommand branchRename() {
+ return new RenameBranchCommand(repo);
+ }
+
+ /**
* Returns a command object to execute a {@code Add} command
*
* @see <a
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
new file mode 100644
index 0000000..8329fca
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Used to obtain a list of branches.
+ *
+ * @see <a
+ * href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html"
+ * >Git documentation about Branch</a>
+ */
+public class ListBranchCommand extends GitCommand<List<Ref>> {
+ private ListMode listMode;
+
+ /**
+ * The modes available for listing branches (corresponding to the -r and -a
+ * options)
+ */
+ public enum ListMode {
+ /**
+ * Corresponds to the -a option (all branches)
+ */
+ ALL,
+ /**
+ * Corresponds to the -r option (remote branches only)
+ */
+ REMOTE;
+ }
+
+ /**
+ * @param repo
+ */
+ protected ListBranchCommand(Repository repo) {
+ super(repo);
+ }
+
+ /**
+ * @throws JGitInternalException
+ * upon internal failure
+ */
+ public List<Ref> call() throws JGitInternalException {
+ checkCallable();
+ Map<String, Ref> refList;
+ try {
+ if (listMode == null) {
+ refList = repo.getRefDatabase().getRefs(Constants.R_HEADS);
+ } else if (listMode == ListMode.REMOTE) {
+ refList = repo.getRefDatabase().getRefs(Constants.R_REMOTES);
+ } else {
+ refList = repo.getRefDatabase().getRefs(Constants.R_HEADS);
+ refList.putAll(repo.getRefDatabase().getRefs(
+ Constants.R_REMOTES));
+ }
+ } catch (IOException e) {
+ throw new JGitInternalException(e.getMessage(), e);
+ }
+ List<Ref> resultRefs = new ArrayList<Ref>();
+ resultRefs.addAll(refList.values());
+ Collections.sort(resultRefs, new Comparator<Ref>() {
+ public int compare(Ref o1, Ref o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ setCallable(false);
+ return resultRefs;
+ }
+
+ /**
+ * @param listMode
+ * optional: corresponds to the -r/-a options; by default, only
+ * local branches will be listed
+ * @return this instance
+ */
+ public ListBranchCommand setListMode(ListMode listMode) {
+ checkCallable();
+ this.listMode = listMode;
+ return this;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java
new file mode 100644
index 0000000..4654981
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.api.errors.DetachedHeadException;
+import org.eclipse.jgit.api.errors.InvalidRefNameException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
+import org.eclipse.jgit.api.errors.RefNotFoundException;
+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.Repository;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+
+/**
+ * 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;
+
+ /**
+ * @param repo
+ */
+ protected RenameBranchCommand(Repository repo) {
+ super(repo);
+ }
+
+ /**
+ * @throws RefNotFoundException
+ * if the old branch can not be found (branch with provided old
+ * name does not exist or old name resolves to a tag)
+ * @throws InvalidRefNameException
+ * if the provided new name is <code>null</code> or otherwise
+ * invalid
+ * @throws RefAlreadyExistsException
+ * if a branch with the new name already exists
+ * @throws DetachedHeadException
+ * if rename is tried without specifying the old name and HEAD
+ * is detached
+ */
+ public Ref call() throws RefNotFoundException, InvalidRefNameException,
+ RefAlreadyExistsException, DetachedHeadException {
+ checkCallable();
+
+ if (newName == null)
+ throw new InvalidRefNameException(MessageFormat.format(JGitText
+ .get().branchNameInvalid, "<null>"));
+
+ try {
+ String fullOldName;
+ String fullNewName;
+ if (repo.getRef(newName) != null)
+ throw new RefAlreadyExistsException(MessageFormat.format(
+ JGitText.get().refAlreadExists, newName));
+ if (oldName != null) {
+ Ref ref = repo.getRef(oldName);
+ if (ref == null)
+ throw new RefNotFoundException(MessageFormat.format(
+ JGitText.get().refNotResolved, oldName));
+ if (ref.getName().startsWith(Constants.R_TAGS))
+ throw new RefNotFoundException(MessageFormat.format(
+ JGitText.get().renameBranchFailedBecauseTag,
+ oldName));
+ fullOldName = ref.getName();
+ } else {
+ fullOldName = repo.getFullBranch();
+ if (ObjectId.isId(fullOldName))
+ throw new DetachedHeadException();
+ }
+
+ if (fullOldName.startsWith(Constants.R_REMOTES))
+ fullNewName = Constants.R_REMOTES + newName;
+ else {
+ fullNewName = Constants.R_HEADS + newName;
+ }
+
+ if (!Repository.isValidRefName(fullNewName))
+ throw new InvalidRefNameException(MessageFormat.format(JGitText
+ .get().branchNameInvalid, fullNewName));
+
+ RefRename rename = repo.renameRef(fullOldName, fullNewName);
+ Result renameResult = rename.rename();
+
+ setCallable(false);
+
+ boolean ok = Result.RENAMED == renameResult;
+
+ if (ok) {
+ if (fullNewName.startsWith(Constants.R_HEADS)) {
+ // move the upstream configuration over to the new branch
+ String shortOldName = fullOldName
+ .substring(Constants.R_HEADS.length());
+ String oldRemote = repo.getConfig().getString(
+ ConfigConstants.CONFIG_BRANCH_SECTION,
+ shortOldName, ConfigConstants.CONFIG_KEY_REMOTE);
+ if (oldRemote != null) {
+ repo.getConfig().setString(
+ ConfigConstants.CONFIG_BRANCH_SECTION, newName,
+ ConfigConstants.CONFIG_KEY_REMOTE, oldRemote);
+ }
+ String oldMerge = repo.getConfig().getString(
+ ConfigConstants.CONFIG_BRANCH_SECTION,
+ shortOldName, ConfigConstants.CONFIG_KEY_MERGE);
+ if (oldMerge != null) {
+ repo.getConfig().setString(
+ ConfigConstants.CONFIG_BRANCH_SECTION, newName,
+ ConfigConstants.CONFIG_KEY_MERGE, oldMerge);
+ }
+ repo.getConfig()
+ .unsetSection(
+ ConfigConstants.CONFIG_BRANCH_SECTION,
+ shortOldName);
+ repo.getConfig().save();
+ }
+
+ } else
+ throw new JGitInternalException(MessageFormat.format(JGitText
+ .get().renameBranchUnexpectedResult, renameResult
+ .name()));
+
+ Ref resultRef = repo.getRef(newName);
+ if (resultRef == null)
+ throw new JGitInternalException(
+ JGitText.get().renameBranchFailedUnknownReason);
+ return resultRef;
+ } catch (IOException ioe) {
+ throw new JGitInternalException(ioe.getMessage(), ioe);
+ }
+ }
+
+ /**
+ * @param newName
+ * the new name
+ * @return this instance
+ */
+ public RenameBranchCommand setNewName(String newName) {
+ checkCallable();
+ this.newName = newName;
+ return this;
+ }
+
+ /**
+ * @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;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CannotDeleteCurrentBranchException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CannotDeleteCurrentBranchException.java
new file mode 100644
index 0000000..76d7732
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CannotDeleteCurrentBranchException.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010,Mathias Kinzler <mathias.kinzler@sap.com> and
+ * other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v1.0 which accompanies this
+ * distribution, is reproduced below, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api.errors;
+
+/**
+ * Thrown when trying to delete a branch which is currently checked out
+ */
+public class CannotDeleteCurrentBranchException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param message
+ * the message
+ */
+ public CannotDeleteCurrentBranchException(String message) {
+ super(message);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/InvalidRefNameException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/InvalidRefNameException.java
new file mode 100644
index 0000000..139c41c
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/InvalidRefNameException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> and
+ * other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v1.0 which accompanies this
+ * distribution, is reproduced below, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api.errors;
+
+/**
+ * Exception thrown when an invalid Ref name was encountered
+ */
+public class InvalidRefNameException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param msg
+ */
+ public InvalidRefNameException(String msg) {
+ super(msg);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/NotMergedException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/NotMergedException.java
new file mode 100644
index 0000000..917c635
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/NotMergedException.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010,Mathias Kinzler <mathias.kinzler@sap.com> and
+ * other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v1.0 which accompanies this
+ * distribution, is reproduced below, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api.errors;
+
+import org.eclipse.jgit.JGitText;
+
+/**
+ * Thrown when branch deletion fails due to unmerged data
+ */
+public class NotMergedException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The default constructor with a default message
+ */
+ public NotMergedException() {
+ super(JGitText.get().notMergedExceptionMessage);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefAlreadyExistsException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefAlreadyExistsException.java
new file mode 100644
index 0000000..5e3ebf8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefAlreadyExistsException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010,Mathias Kinzler <mathias.kinzler@sap.com> and
+ * other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v1.0 which accompanies this
+ * distribution, is reproduced below, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api.errors;
+
+import org.eclipse.jgit.lib.Ref;
+
+/**
+ * Thrown when trying to create a {@link Ref} with the same name as an exsiting
+ * one
+ */
+public class RefAlreadyExistsException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param message
+ */
+ public RefAlreadyExistsException(String message) {
+ super(message);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotFoundException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotFoundException.java
new file mode 100644
index 0000000..c8d96a0
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotFoundException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010,Mathias Kinzler <mathias.kinzler@sap.com> and
+ * other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v1.0 which accompanies this
+ * distribution, is reproduced below, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.api.errors;
+
+/**
+ * Thrown when a Ref can not be resolved
+ */
+public class RefNotFoundException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param message
+ */
+ public RefNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index e63f4e9..4ca11d0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -87,4 +87,6 @@ public class ConfigConstants {
/** The "url" key */
public static final String CONFIG_KEY_URL = "url";
+ /** The "autosetupmerge" key */
+ public static final String CONFIG_KEY_AUTOSETUPMERGE = "autosetupmerge";
}