Browse Source

Support pull on detached HEAD

Bug: 485396
Change-Id: I82be09385c9b0bcc0054fea5a9cb9d178a41e278
Signed-off-by: Mickael Istria <mistria@redhat.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
stable-4.8
Mickael Istria 8 years ago committed by Matthias Sohn
parent
commit
5b84e25fa3
  1. 52
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandWithRebaseTest.java
  2. 47
      org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java

52
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandWithRebaseTest.java

@ -61,6 +61,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.lib.StoredConfig;
@ -147,6 +148,57 @@ public class PullCommandWithRebaseTest extends RepositoryTestCase {
} }
@Test
public void testPullFastForwardDetachedHead() throws Exception {
Repository repository = source.getRepository();
writeToFile(sourceFile, "2nd commit");
source.add().addFilepattern("SomeFile.txt").call();
source.commit().setMessage("2nd commit").call();
try (RevWalk revWalk = new RevWalk(repository)) {
// git checkout HEAD^
String initialBranch = repository.getBranch();
Ref initialRef = repository.findRef(Constants.HEAD);
RevCommit initialCommit = revWalk
.parseCommit(initialRef.getObjectId());
assertEquals("this test need linear history", 1,
initialCommit.getParentCount());
source.checkout().setName(initialCommit.getParent(0).getName())
.call();
assertFalse("expected detached HEAD",
repository.getFullBranch().startsWith(Constants.R_HEADS));
// change and commit another file
File otherFile = new File(sourceFile.getParentFile(),
System.currentTimeMillis() + ".tst");
writeToFile(otherFile, "other 2nd commit");
source.add().addFilepattern(otherFile.getName()).call();
RevCommit newCommit = source.commit().setMessage("other 2nd commit")
.call();
// git pull --rebase initialBranch
source.pull().setRebase(true).setRemote(".")
.setRemoteBranchName(initialBranch)
.call();
assertEquals(RepositoryState.SAFE,
source.getRepository().getRepositoryState());
Ref head = source.getRepository().findRef(Constants.HEAD);
RevCommit headCommit = revWalk.parseCommit(head.getObjectId());
// HEAD^ == initialCommit, no merge commit
assertEquals(1, headCommit.getParentCount());
assertEquals(initialCommit, headCommit.getParent(0));
// both contributions for both commits are available
assertFileContentsEqual(sourceFile, "2nd commit");
assertFileContentsEqual(otherFile, "other 2nd commit");
// HEAD has same message as rebased commit
assertEquals(newCommit.getShortMessage(),
headCommit.getShortMessage());
}
}
@Test @Test
public void testPullConflict() throws Exception { public void testPullConflict() throws Exception {
PullResult res = target.pull().call(); PullResult res = target.pull().call();

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

@ -203,62 +203,63 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
@Override @Override
public PullResult call() throws GitAPIException, public PullResult call() throws GitAPIException,
WrongRepositoryStateException, InvalidConfigurationException, WrongRepositoryStateException, InvalidConfigurationException,
DetachedHeadException, InvalidRemoteException, CanceledException, InvalidRemoteException, CanceledException,
RefNotFoundException, RefNotAdvertisedException, NoHeadException, RefNotFoundException, RefNotAdvertisedException, NoHeadException,
org.eclipse.jgit.api.errors.TransportException { org.eclipse.jgit.api.errors.TransportException {
checkCallable(); checkCallable();
monitor.beginTask(JGitText.get().pullTaskName, 2); monitor.beginTask(JGitText.get().pullTaskName, 2);
Config repoConfig = repo.getConfig();
String branchName; String branchName = null;
try { try {
String fullBranch = repo.getFullBranch(); String fullBranch = repo.getFullBranch();
if (fullBranch == null) if (fullBranch != null
throw new NoHeadException( && fullBranch.startsWith(Constants.R_HEADS)) {
JGitText.get().pullOnRepoWithoutHEADCurrentlyNotSupported); branchName = fullBranch.substring(Constants.R_HEADS.length());
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) { } catch (IOException e) {
throw new JGitInternalException( throw new JGitInternalException(
JGitText.get().exceptionCaughtDuringExecutionOfPullCommand, JGitText.get().exceptionCaughtDuringExecutionOfPullCommand,
e); e);
} }
if (remoteBranchName == null && branchName != null) {
// get the name of the branch in the remote repository
// stored in configuration key branch.<branch name>.merge
remoteBranchName = repoConfig.getString(
ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_MERGE);
}
if (remoteBranchName == null) {
remoteBranchName = branchName;
}
if (remoteBranchName == null) {
throw new NoHeadException(
JGitText.get().cannotCheckoutFromUnbornBranch);
}
if (!repo.getRepositoryState().equals(RepositoryState.SAFE)) if (!repo.getRepositoryState().equals(RepositoryState.SAFE))
throw new WrongRepositoryStateException(MessageFormat.format( throw new WrongRepositoryStateException(MessageFormat.format(
JGitText.get().cannotPullOnARepoWithState, repo JGitText.get().cannotPullOnARepoWithState, repo
.getRepositoryState().name())); .getRepositoryState().name()));
Config repoConfig = repo.getConfig(); if (remote == null && branchName != null) {
if (remote == null) {
// get the configured remote for the currently checked out branch // get the configured remote for the currently checked out branch
// stored in configuration key branch.<branch name>.remote // stored in configuration key branch.<branch name>.remote
remote = repoConfig.getString( remote = repoConfig.getString(
ConfigConstants.CONFIG_BRANCH_SECTION, branchName, ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_REMOTE); ConfigConstants.CONFIG_KEY_REMOTE);
} }
if (remote == null) if (remote == null) {
// fall back to default remote // fall back to default remote
remote = Constants.DEFAULT_REMOTE_NAME; remote = Constants.DEFAULT_REMOTE_NAME;
}
if (remoteBranchName == null)
// get the name of the branch in the remote repository
// stored in configuration key branch.<branch name>.merge
remoteBranchName = repoConfig.getString(
ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_MERGE);
// determines whether rebase should be used after fetching // determines whether rebase should be used after fetching
if (pullRebaseMode == null) { if (pullRebaseMode == null && branchName != null) {
pullRebaseMode = getRebaseMode(branchName, repoConfig); pullRebaseMode = getRebaseMode(branchName, repoConfig);
} }
if (remoteBranchName == null)
remoteBranchName = branchName;
final boolean isRemote = !remote.equals("."); //$NON-NLS-1$ final boolean isRemote = !remote.equals("."); //$NON-NLS-1$
String remoteUri; String remoteUri;

Loading…
Cancel
Save