public MergeResult call()

in org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java [219:426]


	public MergeResult call() throws GitAPIException, NoHeadException,
			ConcurrentRefUpdateException, CheckoutConflictException,
			InvalidMergeHeadsException, WrongRepositoryStateException, NoMessageException {
		checkCallable();
		fallBackToConfiguration();
		checkParameters();

		DirCacheCheckout dco = null;
		try (RevWalk revWalk = new RevWalk(repo)) {
			Ref head = repo.exactRef(Constants.HEAD);
			if (head == null)
				throw new NoHeadException(
						JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported);
			StringBuilder refLogMessage = new StringBuilder("merge "); //$NON-NLS-1$

			// Check for FAST_FORWARD, ALREADY_UP_TO_DATE

			// we know for now there is only one commit
			Ref ref = commits.get(0);

			refLogMessage.append(ref.getName());

			// handle annotated tags
			ref = repo.getRefDatabase().peel(ref);
			ObjectId objectId = ref.getPeeledObjectId();
			if (objectId == null)
				objectId = ref.getObjectId();

			RevCommit srcCommit = revWalk.lookupCommit(objectId);

			ObjectId headId = head.getObjectId();
			if (headId == null) {
				revWalk.parseHeaders(srcCommit);
				dco = new DirCacheCheckout(repo,
						repo.lockDirCache(), srcCommit.getTree());
				dco.setFailOnConflict(true);
				dco.setProgressMonitor(monitor);
				dco.checkout();
				RefUpdate refUpdate = repo
						.updateRef(head.getTarget().getName());
				refUpdate.setNewObjectId(objectId);
				refUpdate.setExpectedOldObjectId(null);
				refUpdate.setRefLogMessage("initial pull", false); //$NON-NLS-1$
				if (refUpdate.update() != Result.NEW)
					throw new NoHeadException(
							JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported);
				setCallable(false);
				return new MergeResult(srcCommit, srcCommit, new ObjectId[] {
						null, srcCommit }, MergeStatus.FAST_FORWARD,
						mergeStrategy, null, null);
			}

			RevCommit headCommit = revWalk.lookupCommit(headId);

			if (revWalk.isMergedInto(srcCommit, headCommit)) {
				setCallable(false);
				return new MergeResult(headCommit, srcCommit, new ObjectId[] {
						headCommit, srcCommit },
						MergeStatus.ALREADY_UP_TO_DATE, mergeStrategy, null, null);
			} else if (revWalk.isMergedInto(headCommit, srcCommit)
					&& fastForwardMode != FastForwardMode.NO_FF) {
				// FAST_FORWARD detected: skip doing a real merge but only
				// update HEAD
				refLogMessage.append(": " + MergeStatus.FAST_FORWARD); //$NON-NLS-1$
				dco = new DirCacheCheckout(repo,
						headCommit.getTree(), repo.lockDirCache(),
						srcCommit.getTree());
				dco.setProgressMonitor(monitor);
				dco.setFailOnConflict(true);
				dco.checkout();
				String msg = null;
				ObjectId newHead, base = null;
				MergeStatus mergeStatus = null;
				if (!squash) {
					updateHead(refLogMessage, srcCommit, headId);
					newHead = base = srcCommit;
					mergeStatus = MergeStatus.FAST_FORWARD;
				} else {
					msg = JGitText.get().squashCommitNotUpdatingHEAD;
					newHead = base = headId;
					mergeStatus = MergeStatus.FAST_FORWARD_SQUASHED;
					List<RevCommit> squashedCommits = RevWalkUtils.find(
							revWalk, srcCommit, headCommit);
					String squashMessage = new SquashMessageFormatter().format(
							squashedCommits, head);
					repo.writeSquashCommitMsg(squashMessage);
				}
				setCallable(false);
				return new MergeResult(newHead, base, new ObjectId[] {
						headCommit, srcCommit }, mergeStatus, mergeStrategy,
						null, msg);
			} else {
				if (fastForwardMode == FastForwardMode.FF_ONLY) {
					return new MergeResult(headCommit, srcCommit,
							new ObjectId[] { headCommit, srcCommit },
							MergeStatus.ABORTED, mergeStrategy, null, null);
				}
				String mergeMessage = ""; //$NON-NLS-1$
				if (!squash) {
					if (message != null)
						mergeMessage = message;
					else
						mergeMessage = new MergeMessageFormatter().format(
							commits, head);
					repo.writeMergeCommitMsg(mergeMessage);
					repo.writeMergeHeads(Arrays.asList(ref.getObjectId()));
				} else {
					List<RevCommit> squashedCommits = RevWalkUtils.find(
							revWalk, srcCommit, headCommit);
					String squashMessage = new SquashMessageFormatter().format(
							squashedCommits, head);
					repo.writeSquashCommitMsg(squashMessage);
				}
				Merger merger = mergeStrategy.newMerger(repo);
				merger.setProgressMonitor(monitor);
				boolean noProblems;
				Map<String, org.eclipse.jgit.merge.MergeResult<?>> lowLevelResults = null;
				Map<String, MergeFailureReason> failingPaths = null;
				List<String> unmergedPaths = null;
				if (merger instanceof ResolveMerger) {
					ResolveMerger resolveMerger = (ResolveMerger) merger;
					resolveMerger.setContentMergeStrategy(contentStrategy);
					resolveMerger.setCommitNames(new String[] {
							"BASE", "HEAD", ref.getName() }); //$NON-NLS-1$ //$NON-NLS-2$
					resolveMerger.setWorkingTreeIterator(new FileTreeIterator(repo));
					noProblems = merger.merge(headCommit, srcCommit);
					lowLevelResults = resolveMerger
							.getMergeResults();
					failingPaths = resolveMerger.getFailingPaths();
					unmergedPaths = resolveMerger.getUnmergedPaths();
					if (!resolveMerger.getModifiedFiles().isEmpty()) {
						repo.fireEvent(new WorkingTreeModifiedEvent(
								resolveMerger.getModifiedFiles(), null));
					}
				} else
					noProblems = merger.merge(headCommit, srcCommit);
				refLogMessage.append(": Merge made by "); //$NON-NLS-1$
				if (!revWalk.isMergedInto(headCommit, srcCommit))
					refLogMessage.append(mergeStrategy.getName());
				else
					refLogMessage.append("recursive"); //$NON-NLS-1$
				refLogMessage.append('.');
				if (noProblems) {
					dco = new DirCacheCheckout(repo,
							headCommit.getTree(), repo.lockDirCache(),
							merger.getResultTreeId());
					dco.setFailOnConflict(true);
					dco.setProgressMonitor(monitor);
					dco.checkout();

					String msg = null;
					ObjectId newHeadId = null;
					MergeStatus mergeStatus = null;
					if (!commit && squash) {
						mergeStatus = MergeStatus.MERGED_SQUASHED_NOT_COMMITTED;
					}
					if (!commit && !squash) {
						mergeStatus = MergeStatus.MERGED_NOT_COMMITTED;
					}
					if (commit && !squash) {
						try (Git git = new Git(getRepository())) {
							newHeadId = git.commit()
									.setReflogComment(refLogMessage.toString())
									.setInsertChangeId(insertChangeId)
									.call().getId();
						}
						mergeStatus = MergeStatus.MERGED;
						getRepository().autoGC(monitor);
					}
					if (commit && squash) {
						msg = JGitText.get().squashCommitNotUpdatingHEAD;
						newHeadId = headCommit.getId();
						mergeStatus = MergeStatus.MERGED_SQUASHED;
					}
					return new MergeResult(newHeadId, null,
							new ObjectId[] { headCommit.getId(),
									srcCommit.getId() }, mergeStatus,
							mergeStrategy, null, msg);
				}
				if (failingPaths != null) {
					repo.writeMergeCommitMsg(null);
					repo.writeMergeHeads(null);
					return new MergeResult(null, merger.getBaseCommitId(),
							new ObjectId[] { headCommit.getId(),
									srcCommit.getId() },
							MergeStatus.FAILED, mergeStrategy, lowLevelResults,
							failingPaths, null);
				}
				String mergeMessageWithConflicts = new MergeMessageFormatter()
						.formatWithConflicts(mergeMessage, unmergedPaths, '#');
				repo.writeMergeCommitMsg(mergeMessageWithConflicts);
				return new MergeResult(null, merger.getBaseCommitId(),
						new ObjectId[] { headCommit.getId(),
								srcCommit.getId() },
						MergeStatus.CONFLICTING, mergeStrategy, lowLevelResults,
						null);
			}
		} catch (org.eclipse.jgit.errors.CheckoutConflictException e) {
			List<String> conflicts = (dco == null) ? Collections
					.<String> emptyList() : dco.getConflicts();
			throw new CheckoutConflictException(conflicts, e);
		} catch (IOException e) {
			throw new JGitInternalException(
					MessageFormat.format(
							JGitText.get().exceptionCaughtDuringExecutionOfMergeCommand,
							e), e);
		}
	}