Browse Source

Add "Pull" command

This is the minimal implementation of a "Pull" command. It does not
have any parameters besides the generic progress monitor and timeout.
It works on the currently checked-out branch and assumes that the
configuration contains the keys "branch.<branch name>.remote" and
"branch.<branch name>.merge" to determine the remote configuration
for the fetch and the remote branch name for the merge.

Bug: 303404
Change-Id: I7fe09029996d0cfc09a7d8f097b5d6af1488fa93
Signed-off-by: Mathias Kinzler <mathias.kinzler@sap.com>
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
stable-0.10
Mathias Kinzler 14 years ago committed by Chris Aniszczyk
parent
commit
db55d13f5f
  1. 200
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
  2. 6
      org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
  3. 6
      org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
  4. 9
      org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
  5. 260
      org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
  6. 100
      org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java
  7. 53
      org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CanceledException.java
  8. 71
      org.eclipse.jgit/src/org/eclipse/jgit/api/errors/DetachedHeadException.java
  9. 61
      org.eclipse.jgit/src/org/eclipse/jgit/api/errors/InvalidConfigurationException.java
  10. 6
      org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java

200
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java

@ -0,0 +1,200 @@
/*
* 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.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.eclipse.jgit.api.MergeResult.MergeStatus;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
public class PullCommandTest extends RepositoryTestCase {
/** Second Test repository */
protected FileRepository dbTarget;
private Git source;
private Git target;
private File sourceFile;
private File targetFile;
public void testPullFastForward() throws Exception {
PullResult res = target.pull().call();
// nothing to update since we don't have different data yet
assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty());
assertTrue(res.getMergeResult().getMergeStatus().equals(
MergeStatus.ALREADY_UP_TO_DATE));
assertFileContentsEqual(targetFile, "Hello world");
// change the source file
writeToFile(sourceFile, "Another change");
source.add().addFilepattern("SomeFile.txt").call();
source.commit().setMessage("Some change in remote").call();
res = target.pull().call();
assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty());
assertEquals(res.getMergeResult().getMergeStatus(),
MergeStatus.FAST_FORWARD);
assertFileContentsEqual(targetFile, "Another change");
}
public void testPullConflict() throws Exception {
PullResult res = target.pull().call();
// nothing to update since we don't have different data yet
assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty());
assertTrue(res.getMergeResult().getMergeStatus().equals(
MergeStatus.ALREADY_UP_TO_DATE));
assertFileContentsEqual(targetFile, "Hello world");
// change the source file
writeToFile(sourceFile, "Source change");
source.add().addFilepattern("SomeFile.txt").call();
source.commit().setMessage("Source change in remote").call();
// change the target file
writeToFile(targetFile, "Target change");
target.add().addFilepattern("SomeFile.txt").call();
target.commit().setMessage("Target change in local").call();
res = target.pull().call();
String sourceChangeString = "Source change\n>>>>>>> branch 'refs/heads/master' of "
+ target.getRepository().getConfig().getString("remote",
"origin", "url");
assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty());
assertEquals(res.getMergeResult().getMergeStatus(),
MergeStatus.CONFLICTING);
String result = "<<<<<<< HEAD\nTarget change\n=======\n"
+ sourceChangeString + "\n";
assertFileContentsEqual(targetFile, result);
}
@Override
protected void setUp() throws Exception {
super.setUp();
dbTarget = createWorkRepository();
source = new Git(db);
target = new Git(dbTarget);
// put some file in the source repo
sourceFile = new File(db.getWorkTree(), "SomeFile.txt");
writeToFile(sourceFile, "Hello world");
// and commit it
source.add().addFilepattern("SomeFile.txt").call();
RevCommit commit = source.commit().setMessage(
"Initial commit for source").call();
// point the master branch to the new commit
RefUpdate upd = dbTarget.updateRef("refs/heads/master");
upd.setNewObjectId(commit.getId());
upd.update();
// configure the target repo to connect to the source via "origin"
StoredConfig targetConfig = dbTarget.getConfig();
targetConfig.setString("branch", "master", "remote", "origin");
targetConfig
.setString("branch", "master", "merge", "refs/heads/master");
RemoteConfig config = new RemoteConfig(targetConfig, "origin");
config
.addURI(new URIish(source.getRepository().getWorkTree()
.getPath()));
config.addFetchRefSpec(new RefSpec(
"+refs/heads/*:refs/remotes/origin/*"));
targetConfig.save();
config.update(targetConfig);
targetFile = new File(dbTarget.getWorkTree(), "SomeFile.txt");
writeToFile(targetFile, "Hello world");
// make sure we have the same content
target.pull().call();
}
private void writeToFile(File actFile, String string) throws IOException {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(actFile);
fos.write(string.getBytes("UTF-8"));
fos.close();
} finally {
if (fos != null)
fos.close();
}
}
private void assertFileContentsEqual(File actFile, String string)
throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = null;
byte[] buffer = new byte[100];
try {
fis = new FileInputStream(actFile);
int read = fis.read(buffer);
while (read > 0) {
bos.write(buffer, 0, read);
read = fis.read(buffer);
}
String content = new String(bos.toByteArray(), "UTF-8");
assertEquals(string, content);
} finally {
if (fis != null)
fis.close();
}
}
}

6
org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties

@ -56,6 +56,7 @@ cannotMoveIndexTo=Cannot move index to {0}
cannotMovePackTo=Cannot move pack to {0} cannotMovePackTo=Cannot move pack to {0}
cannotOpenService=cannot open {0} cannotOpenService=cannot open {0}
cannotParseGitURIish=Cannot parse Git URI-ish cannotParseGitURIish=Cannot parse Git URI-ish
cannotPullOnARepoWithState=Cannot pull into a repository with state: {0}
cannotRead=Cannot read {0} cannotRead=Cannot read {0}
cannotReadBlob=Cannot read blob {0} cannotReadBlob=Cannot read blob {0}
cannotReadCommit=Cannot read commit {0} cannotReadCommit=Cannot read commit {0}
@ -121,6 +122,7 @@ creatingDeltasIsNotImplemented=creating deltas is not implemented
daemonAlreadyRunning=Daemon already running daemonAlreadyRunning=Daemon already running
deletingNotSupported=Deleting {0} not supported. deletingNotSupported=Deleting {0} not supported.
destinationIsNotAWildcard=Destination is not a wildcard. destinationIsNotAWildcard=Destination is not a wildcard.
detachedHeadDetected=HEAD is detached
dirCacheDoesNotHaveABackingFile=DirCache does not have a backing file dirCacheDoesNotHaveABackingFile=DirCache does not have a backing file
dirCacheFileIsNotLocked=DirCache {0} not locked dirCacheFileIsNotLocked=DirCache {0} not locked
dirCacheIsNotLocked=DirCache is not locked dirCacheIsNotLocked=DirCache is not locked
@ -153,6 +155,7 @@ exceptionCaughtDuringExecutionOfCommitCommand=Exception caught during execution
exceptionCaughtDuringExecutionOfFetchCommand=Exception caught during execution of fetch command exceptionCaughtDuringExecutionOfFetchCommand=Exception caught during execution of fetch command
exceptionCaughtDuringExecutionOfMergeCommand=Exception caught during execution of merge command. {0} exceptionCaughtDuringExecutionOfMergeCommand=Exception caught during execution of merge command. {0}
exceptionCaughtDuringExecutionOfPushCommand=Exception caught during execution of push command exceptionCaughtDuringExecutionOfPushCommand=Exception caught during execution of push command
exceptionCaughtDuringExecutionOfPullCommand=Exception caught during execution of pull command
exceptionCaughtDuringExecutionOfTagCommand=Exception caught during execution of tag command exceptionCaughtDuringExecutionOfTagCommand=Exception caught during execution of tag command
exceptionOccuredDuringAddingOfOptionToALogCommand=Exception occured during adding of {0} as option to a Log command exceptionOccuredDuringAddingOfOptionToALogCommand=Exception occured during adding of {0} as option to a Log command
exceptionOccuredDuringReadingOfGIT_DIR=Exception occured during reading of $GIT_DIR/{0}. {1} exceptionOccuredDuringReadingOfGIT_DIR=Exception occured during reading of $GIT_DIR/{0}. {1}
@ -241,6 +244,7 @@ mergeStrategyAlreadyExistsAsDefault=Merge strategy "{0}" already exists as a def
mergeStrategyDoesNotSupportHeads=merge strategy {0} does not support {1} heads to be merged into HEAD mergeStrategyDoesNotSupportHeads=merge strategy {0} does not support {1} heads to be merged into HEAD
mergeUsingStrategyResultedInDescription=Merge of revisions {0} with base {1} using strategy {2} resulted in: {3}. {4} mergeUsingStrategyResultedInDescription=Merge of revisions {0} with base {1} using strategy {2} resulted in: {3}. {4}
missingAccesskey=Missing accesskey. missingAccesskey=Missing accesskey.
missingConfigurationForKey=No value for key {0} found in configuration
missingDeltaBase=delta base missingDeltaBase=delta base
missingForwardImageInGITBinaryPatch=Missing forward-image in GIT binary patch missingForwardImageInGITBinaryPatch=Missing forward-image in GIT binary patch
missingObject=Missing {0} {1} missingObject=Missing {0} {1}
@ -284,6 +288,7 @@ onlyOneFetchSupported=Only one fetch supported
onlyOneOperationCallPerConnectionIsSupported=Only one operation call per connection is supported. onlyOneOperationCallPerConnectionIsSupported=Only one operation call per connection is supported.
openFilesMustBeAtLeast1=Open files must be >= 1 openFilesMustBeAtLeast1=Open files must be >= 1
openingConnection=Opening connection openingConnection=Opening connection
operationCanceled=Operation {0} was canceled
outputHasAlreadyBeenStarted=Output has already been started. outputHasAlreadyBeenStarted=Output has already been started.
packChecksumMismatch=Pack checksum mismatch packChecksumMismatch=Pack checksum mismatch
packCorruptedWhileWritingToFilesystem=Pack corrupted while writing to filesystem packCorruptedWhileWritingToFilesystem=Pack corrupted while writing to filesystem
@ -304,6 +309,7 @@ prefixRemote=remote:
problemWithResolvingPushRefSpecsLocally=Problem with resolving push ref specs locally: {0} problemWithResolvingPushRefSpecsLocally=Problem with resolving push ref specs locally: {0}
progressMonUploading=Uploading {0} progressMonUploading=Uploading {0}
propertyIsAlreadyNonNull=Property is already non null propertyIsAlreadyNonNull=Property is already non null
pullTaskName=Pull
pushCancelled=push cancelled pushCancelled=push cancelled
pushIsNotSupportedForBundleTransport=Push is not supported for bundle transport pushIsNotSupportedForBundleTransport=Push is not supported for bundle transport
pushNotPermitted=push not permitted pushNotPermitted=push not permitted

6
org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java

@ -116,6 +116,7 @@ public class JGitText extends TranslationBundle {
/***/ public String cannotMovePackTo; /***/ public String cannotMovePackTo;
/***/ public String cannotOpenService; /***/ public String cannotOpenService;
/***/ public String cannotParseGitURIish; /***/ public String cannotParseGitURIish;
/***/ public String cannotPullOnARepoWithState;
/***/ public String cannotRead; /***/ public String cannotRead;
/***/ public String cannotReadBlob; /***/ public String cannotReadBlob;
/***/ public String cannotReadCommit; /***/ public String cannotReadCommit;
@ -181,6 +182,7 @@ public class JGitText extends TranslationBundle {
/***/ public String daemonAlreadyRunning; /***/ public String daemonAlreadyRunning;
/***/ public String deletingNotSupported; /***/ public String deletingNotSupported;
/***/ public String destinationIsNotAWildcard; /***/ public String destinationIsNotAWildcard;
/***/ public String detachedHeadDetected;
/***/ public String dirCacheDoesNotHaveABackingFile; /***/ public String dirCacheDoesNotHaveABackingFile;
/***/ public String dirCacheFileIsNotLocked; /***/ public String dirCacheFileIsNotLocked;
/***/ public String dirCacheIsNotLocked; /***/ public String dirCacheIsNotLocked;
@ -213,6 +215,7 @@ public class JGitText extends TranslationBundle {
/***/ public String exceptionCaughtDuringExecutionOfFetchCommand; /***/ public String exceptionCaughtDuringExecutionOfFetchCommand;
/***/ public String exceptionCaughtDuringExecutionOfMergeCommand; /***/ public String exceptionCaughtDuringExecutionOfMergeCommand;
/***/ public String exceptionCaughtDuringExecutionOfPushCommand; /***/ public String exceptionCaughtDuringExecutionOfPushCommand;
/***/ public String exceptionCaughtDuringExecutionOfPullCommand;
/***/ public String exceptionCaughtDuringExecutionOfTagCommand; /***/ public String exceptionCaughtDuringExecutionOfTagCommand;
/***/ public String exceptionOccuredDuringAddingOfOptionToALogCommand; /***/ public String exceptionOccuredDuringAddingOfOptionToALogCommand;
/***/ public String exceptionOccuredDuringReadingOfGIT_DIR; /***/ public String exceptionOccuredDuringReadingOfGIT_DIR;
@ -301,6 +304,7 @@ public class JGitText extends TranslationBundle {
/***/ public String mergeStrategyDoesNotSupportHeads; /***/ public String mergeStrategyDoesNotSupportHeads;
/***/ public String mergeUsingStrategyResultedInDescription; /***/ public String mergeUsingStrategyResultedInDescription;
/***/ public String missingAccesskey; /***/ public String missingAccesskey;
/***/ public String missingConfigurationForKey;
/***/ public String missingDeltaBase; /***/ public String missingDeltaBase;
/***/ public String missingForwardImageInGITBinaryPatch; /***/ public String missingForwardImageInGITBinaryPatch;
/***/ public String missingObject; /***/ public String missingObject;
@ -344,6 +348,7 @@ public class JGitText extends TranslationBundle {
/***/ public String onlyOneOperationCallPerConnectionIsSupported; /***/ public String onlyOneOperationCallPerConnectionIsSupported;
/***/ public String openFilesMustBeAtLeast1; /***/ public String openFilesMustBeAtLeast1;
/***/ public String openingConnection; /***/ public String openingConnection;
/***/ public String operationCanceled;
/***/ public String outputHasAlreadyBeenStarted; /***/ public String outputHasAlreadyBeenStarted;
/***/ public String packChecksumMismatch; /***/ public String packChecksumMismatch;
/***/ public String packCorruptedWhileWritingToFilesystem; /***/ public String packCorruptedWhileWritingToFilesystem;
@ -364,6 +369,7 @@ public class JGitText extends TranslationBundle {
/***/ public String problemWithResolvingPushRefSpecsLocally; /***/ public String problemWithResolvingPushRefSpecsLocally;
/***/ public String progressMonUploading; /***/ public String progressMonUploading;
/***/ public String propertyIsAlreadyNonNull; /***/ public String propertyIsAlreadyNonNull;
/***/ public String pullTaskName;
/***/ public String pushCancelled; /***/ public String pushCancelled;
/***/ public String pushIsNotSupportedForBundleTransport; /***/ public String pushIsNotSupportedForBundleTransport;
/***/ public String pushNotPermitted; /***/ public String pushNotPermitted;

9
org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java

@ -133,6 +133,15 @@ public class Git {
return new MergeCommand(repo); return new MergeCommand(repo);
} }
/**
* Returns a command object to execute a {@code Pull} command
*
* @return a {@link PullCommand}
*/
public PullCommand pull() {
return new PullCommand(repo);
}
/** /**
* Returns a command object to execute a {@code Add} command * Returns a command object to execute a {@code Add} command
* *

260
org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java

@ -0,0 +1,260 @@
/*
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
* 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.io.IOException;
import java.text.MessageFormat;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.api.errors.CheckoutConflictException;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.DetachedHeadException;
import org.eclipse.jgit.api.errors.InvalidConfigurationException;
import org.eclipse.jgit.api.errors.InvalidMergeHeadsException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.transport.FetchResult;
/**
* The Pull command
*
* @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-pull.html"
* >Git documentation about Pull</a>
*/
public class PullCommand extends GitCommand<PullResult> {
private int timeout = 0;
private final static String DOT = ".";
private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
/**
* @param repo
*/
protected PullCommand(Repository repo) {
super(repo);
}
/**
* @param timeout
* in seconds
* @return this instance
*/
public PullCommand setTimeout(int timeout) {
this.timeout = timeout;
return this;
}
/**
* @param monitor
* a progress monitor
* @return this instance
*/
public PullCommand setProgressMonitor(ProgressMonitor monitor) {
this.monitor = monitor;
return this;
}
/**
* Executes the {@code Pull} command with all the options and parameters
* collected by the setter methods (e.g.
* {@link #setProgressMonitor(ProgressMonitor)}) of this class. Each
* instance of this class should only be used for one invocation of the
* command. Don't call this method twice on an instance.
*
* @return the result of the pull
*/
public PullResult call() throws WrongRepositoryStateException,
InvalidConfigurationException, DetachedHeadException,
InvalidRemoteException, CanceledException {
checkCallable();
monitor.beginTask(JGitText.get().pullTaskName, 2);
String branchName;
try {
String fullBranch = repo.getFullBranch();
if (!fullBranch.startsWith(Constants.R_HEADS)) {
// we can not pull if HEAD is detached and branch is not
// specified explicitly
throw new DetachedHeadException();
}
branchName = fullBranch.substring(Constants.R_HEADS.length());
} catch (IOException e) {
throw new JGitInternalException(
JGitText.get().exceptionCaughtDuringExecutionOfPullCommand,
e);
}
if (!repo.getRepositoryState().equals(RepositoryState.SAFE))
throw new WrongRepositoryStateException(MessageFormat.format(
JGitText.get().cannotPullOnARepoWithState, repo
.getRepositoryState().name()));
// get the configured remote for the currently checked out branch
// stored in configuration key branch.<branch name>.remote
Config repoConfig = repo.getConfig();
final String remote = repoConfig.getString(
ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_REMOTE);
if (remote == null) {
String missingKey = ConfigConstants.CONFIG_BRANCH_SECTION + DOT
+ branchName + DOT + ConfigConstants.CONFIG_KEY_REMOTE;
throw new InvalidConfigurationException(MessageFormat.format(
JGitText.get().missingConfigurationForKey, missingKey));
}
final String remoteUri = repo.getConfig().getString("remote", remote,
ConfigConstants.CONFIG_KEY_URL);
if (remoteUri == null) {
String missingKey = ConfigConstants.CONFIG_REMOTE_SECTION + DOT
+ remote + DOT + ConfigConstants.CONFIG_KEY_URL;
throw new InvalidConfigurationException(MessageFormat.format(
JGitText.get().missingConfigurationForKey, missingKey));
}
// get the name of the branch in the remote repository
// stored in configuration key branch.<branch name>.merge
String remoteBranchName = repoConfig.getString(
ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_MERGE);
if (remoteBranchName == null) {
// check if the branch is configured for pull-rebase
remoteBranchName = repoConfig.getString(
ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_MERGE);
if (remoteBranchName != null) {
// TODO implement pull-rebase
throw new JGitInternalException(
"Pull with rebase is not yet supported");
}
}
if (remoteBranchName == null) {
String missingKey = ConfigConstants.CONFIG_BRANCH_SECTION + DOT
+ branchName + DOT + ConfigConstants.CONFIG_KEY_MERGE;
throw new InvalidConfigurationException(MessageFormat.format(
JGitText.get().missingConfigurationForKey, missingKey));
}
if (monitor.isCancelled())
throw new CanceledException(MessageFormat.format(
JGitText.get().operationCanceled,
JGitText.get().pullTaskName));
FetchCommand fetch = new FetchCommand(repo);
fetch.setRemote(remote);
if (monitor != null)
fetch.setProgressMonitor(monitor);
fetch.setTimeout(this.timeout);
FetchResult fetchRes = fetch.call();
monitor.update(1);
// we check the updates to see which of the updated branches corresponds
// to the remote branch name
AnyObjectId commitToMerge = null;
Ref r = fetchRes.getAdvertisedRef(remoteBranchName);
if (r == null)
r = fetchRes.getAdvertisedRef(Constants.R_HEADS + remoteBranchName);
if (r == null) {
// TODO: we should be able to get the mapping also if nothing was
// updated by the fetch; for the time being, use the naming
// convention as fall back
String remoteTrackingBranch = Constants.R_REMOTES + remote + '/'
+ branchName;
try {
commitToMerge = repo.resolve(remoteTrackingBranch);
} catch (IOException e) {
throw new JGitInternalException(
JGitText.get().exceptionCaughtDuringExecutionOfPullCommand,
e);
}
} else
commitToMerge = r.getObjectId();
if (monitor.isCancelled())
throw new CanceledException(MessageFormat.format(
JGitText.get().operationCanceled,
JGitText.get().pullTaskName));
MergeCommand merge = new MergeCommand(repo);
merge.include("branch \'" + remoteBranchName + "\' of " + remoteUri,
commitToMerge);
MergeResult mergeRes;
try {
mergeRes = merge.call();
monitor.update(1);
} catch (NoHeadException e) {
throw new JGitInternalException(e.getMessage(), e);
} catch (ConcurrentRefUpdateException e) {
throw new JGitInternalException(e.getMessage(), e);
} catch (CheckoutConflictException e) {
throw new JGitInternalException(e.getMessage(), e);
} catch (InvalidMergeHeadsException e) {
throw new JGitInternalException(e.getMessage(), e);
} catch (WrongRepositoryStateException e) {
throw new JGitInternalException(e.getMessage(), e);
} catch (NoMessageException e) {
throw new JGitInternalException(e.getMessage(), e);
}
monitor.endTask();
return new PullResult(fetchRes, remote, mergeRes);
}
}

100
org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java

@ -0,0 +1,100 @@
/*
* 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 org.eclipse.jgit.transport.FetchResult;
/**
* Encapsulates the result of a {@link PullCommand}
*/
public class PullResult {
private final FetchResult fetchResult;
private final MergeResult mergeResult;
private final String fetchedFrom;
PullResult(FetchResult fetchResult, String fetchedFrom,
MergeResult mergeResult) {
this.fetchResult = fetchResult;
this.fetchedFrom = fetchedFrom;
this.mergeResult = mergeResult;
}
/**
* @return the fetch result, or <code>null</code>
*/
public FetchResult getFetchResult() {
return this.fetchResult;
}
/**
* @return the merge result, or <code>null</code>
*/
public MergeResult getMergeResult() {
return this.mergeResult;
}
/**
* @return the name of the remote configuration from which fetch was tried,
* or <code>null</code>
*/
public String getFetchedFrom() {
return this.fetchedFrom;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (fetchResult != null)
sb.append(fetchResult.toString());
else
sb.append("No fetch result");
sb.append("\n");
if (mergeResult != null)
sb.append(mergeResult.toString());
else
sb.append("No merge result");
return sb.toString();
}
}

53
org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CanceledException.java

@ -0,0 +1,53 @@
/*
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
* 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 operation was canceled
*/
public class CanceledException extends GitAPIException {
private static final long serialVersionUID = 1L;
/**
* @param message
*/
public CanceledException(String message) {
super(message);
}
}

71
org.eclipse.jgit/src/org/eclipse/jgit/api/errors/DetachedHeadException.java

@ -0,0 +1,71 @@
/*
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
* 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;
/**
* Exception thrown when a command expected a non-detached {@code HEAD}
* reference
*/
public class DetachedHeadException extends GitAPIException {
private static final long serialVersionUID = 1L;
/**
* The default constructor with a default message
*/
public DetachedHeadException() {
this(JGitText.get().detachedHeadDetected);
}
/**
* @param message
* @param cause
*/
public DetachedHeadException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public DetachedHeadException(String message) {
super(message);
}
}

61
org.eclipse.jgit/src/org/eclipse/jgit/api/errors/InvalidConfigurationException.java

@ -0,0 +1,61 @@
/*
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
* 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 a command fails due to an invalid configuration
*/
public class InvalidConfigurationException extends GitAPIException {
private static final long serialVersionUID = 1L;
/**
* @param message
* @param cause
*/
public InvalidConfigurationException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public InvalidConfigurationException(String message) {
super(message);
}
}

6
org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java

@ -54,6 +54,9 @@ public class ConfigConstants {
/** The "branch" section */ /** The "branch" section */
public static final String CONFIG_BRANCH_SECTION = "branch"; public static final String CONFIG_BRANCH_SECTION = "branch";
/** The "remote" section */
public static final String CONFIG_REMOTE_SECTION = "remote";
/** The "autocrlf" key */ /** The "autocrlf" key */
public static final String CONFIG_KEY_AUTOCRLF = "autocrlf"; public static final String CONFIG_KEY_AUTOCRLF = "autocrlf";
@ -81,4 +84,7 @@ public class ConfigConstants {
/** The "rebase" key */ /** The "rebase" key */
public static final String CONFIG_KEY_REBASE = "rebase"; public static final String CONFIG_KEY_REBASE = "rebase";
/** The "url" key */
public static final String CONFIG_KEY_URL = "url";
} }

Loading…
Cancel
Save