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>
This commit is contained in:
parent
8f7d0a4fbe
commit
5b84e25fa3
|
@ -61,6 +61,7 @@
|
||||||
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 void testPullFastForwardWithBranchInSource() throws Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
|
|
@ -203,62 +203,63 @@ public PullCommand setRebase(BranchRebaseMode rebaseMode) {
|
||||||
@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…
Reference in New Issue