public void testTrivialTwoWay_validSubtreeSort() { DirCache treeB = DirCache.read(db); DirCache treeO = DirCache.read(db); DirCache treeT = DirCache.read(db); { DirCacheBuilder b = treeB.builder(); DirCacheBuilder o = treeO.builder(); DirCacheBuilder t = treeT.builder(); b.add(MakeEntry("libelf-po/a", FileMode.RegularFile)); b.add(MakeEntry("libelf/c", FileMode.RegularFile)); o.add(MakeEntry("Makefile", FileMode.RegularFile)); o.add(MakeEntry("libelf-po/a", FileMode.RegularFile)); o.add(MakeEntry("libelf/c", FileMode.RegularFile)); t.add(MakeEntry("libelf-po/a", FileMode.RegularFile)); t.add(MakeEntry("libelf/c", FileMode.RegularFile, "blah")); b.finish(); o.finish(); t.finish(); } var ow = new ObjectWriter(db); ObjectId B = Commit(ow, treeB, new ObjectId[] { }); ObjectId O = Commit(ow, treeO, new[] { B }); ObjectId T = Commit(ow, treeT, new[] { B }); Merger ourMerger = MergeStrategy.SimpleTwoWayInCore.NewMerger(db); bool merge = ourMerger.Merge(new[] { O, T }); Assert.IsTrue(merge); var tw = new GitSharp.Core.TreeWalk.TreeWalk(db) { Recursive = true }; tw.reset(ourMerger.GetResultTreeId()); Assert.IsTrue(tw.next()); Assert.AreEqual("Makefile", tw.getPathString()); AssertCorrectId(treeO, tw); Assert.IsTrue(tw.next()); Assert.AreEqual("libelf-po/a", tw.getPathString()); AssertCorrectId(treeO, tw); Assert.IsTrue(tw.next()); Assert.AreEqual("libelf/c", tw.getPathString()); AssertCorrectId(treeT, tw); Assert.IsFalse(tw.next()); }
/// <exception cref="System.IO.IOException"></exception> private NonNoteEntry MergeNonNotes(NonNoteEntry baseList, NonNoteEntry oursList, NonNoteEntry theirsList) { if (baseList == null && oursList == null && theirsList == null) { return(null); } ObjectId baseId = Write(baseList); ObjectId oursId = Write(oursList); ObjectId theirsId = Write(theirsList); inserter.Flush(); ObjectId resultTreeId; if (nonNotesMergeStrategy is ThreeWayMergeStrategy) { ThreeWayMerger m = ((ThreeWayMerger)((ThreeWayMergeStrategy)nonNotesMergeStrategy ).NewMerger(db, true)); m.SetBase(baseId); if (!m.Merge(oursId, theirsId)) { throw new NotesMergeConflictException(baseList, oursList, theirsList); } resultTreeId = m.GetResultTreeId(); } else { Merger m = nonNotesMergeStrategy.NewMerger(db, true); if (!m.Merge(new AnyObjectId[] { oursId, theirsId })) { throw new NotesMergeConflictException(baseList, oursList, theirsList); } resultTreeId = m.GetResultTreeId(); } AbbreviatedObjectId none = AbbreviatedObjectId.FromString(string.Empty); return(NoteParser.Parse(none, resultTreeId, reader).nonNotes); }
/// <summary> /// Executes the /// <code>Merge</code> /// command with all the options and parameters /// collected by the setter methods (e.g. /// <see cref="Include(NGit.Ref)">Include(NGit.Ref)</see> /// ) 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. /// </summary> /// <returns>the result of the merge</returns> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException"></exception> /// <exception cref="NGit.Api.Errors.CheckoutConflictException"></exception> /// <exception cref="NGit.Api.Errors.InvalidMergeHeadsException"></exception> /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException"></exception> /// <exception cref="NGit.Api.Errors.NoMessageException"></exception> public override MergeCommandResult Call() { CheckCallable(); if (commits.Count != 1) { throw new InvalidMergeHeadsException(commits.IsEmpty() ? JGitText.Get().noMergeHeadSpecified : MessageFormat.Format(JGitText.Get().mergeStrategyDoesNotSupportHeads, mergeStrategy .GetName(), Sharpen.Extensions.ValueOf(commits.Count))); } RevWalk revWalk = null; DirCacheCheckout dco = null; try { Ref head = repo.GetRef(Constants.HEAD); if (head == null) { throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported ); } StringBuilder refLogMessage = new StringBuilder("merge "); // Check for FAST_FORWARD, ALREADY_UP_TO_DATE revWalk = new RevWalk(repo); // we know for now there is only one commit Ref @ref = commits[0]; refLogMessage.Append(@ref.GetName()); // handle annotated tags 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.Tree); dco.SetFailOnConflict(true); dco.Checkout(); RefUpdate refUpdate = repo.UpdateRef(head.GetTarget().GetName()); refUpdate.SetNewObjectId(objectId); refUpdate.SetExpectedOldObjectId(null); refUpdate.SetRefLogMessage("initial pull", false); if (refUpdate.Update() != RefUpdate.Result.NEW) { throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported ); } SetCallable(false); return(new MergeCommandResult(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 MergeCommandResult(headCommit, srcCommit, new ObjectId[] { headCommit, srcCommit }, MergeStatus.ALREADY_UP_TO_DATE, mergeStrategy, null, null)); } else { if (revWalk.IsMergedInto(headCommit, srcCommit)) { // FAST_FORWARD detected: skip doing a real merge but only // update HEAD refLogMessage.Append(": " + MergeStatus.FAST_FORWARD); dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache(), srcCommit. Tree); dco.SetFailOnConflict(true); dco.Checkout(); string msg = null; ObjectId newHead; ObjectId @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; IList <RevCommit> squashedCommits = RevWalkUtils.Find(revWalk, srcCommit, headCommit ); string squashMessage = new SquashMessageFormatter().Format(squashedCommits, head); repo.WriteSquashCommitMsg(squashMessage); } SetCallable(false); return(new MergeCommandResult(newHead, @base, new ObjectId[] { headCommit, srcCommit }, mergeStatus, mergeStrategy, null, msg)); } else { string mergeMessage = string.Empty; if (!squash) { mergeMessage = new MergeMessageFormatter().Format(commits, head); repo.WriteMergeCommitMsg(mergeMessage); repo.WriteMergeHeads(Arrays.AsList(@ref.GetObjectId())); } else { IList <RevCommit> squashedCommits = RevWalkUtils.Find(revWalk, srcCommit, headCommit ); string squashMessage = new SquashMessageFormatter().Format(squashedCommits, head); repo.WriteSquashCommitMsg(squashMessage); } Merger merger = mergeStrategy.NewMerger(repo); bool noProblems; IDictionary <string, MergeResult <NGit.Diff.Sequence> > lowLevelResults = null; IDictionary <string, ResolveMerger.MergeFailureReason> failingPaths = null; IList <string> unmergedPaths = null; if (merger is ResolveMerger) { ResolveMerger resolveMerger = (ResolveMerger)merger; resolveMerger.SetCommitNames(new string[] { "BASE", "HEAD", @ref.GetName() }); resolveMerger.SetWorkingTreeIterator(new FileTreeIterator(repo)); noProblems = merger.Merge(headCommit, srcCommit); lowLevelResults = resolveMerger.GetMergeResults(); failingPaths = resolveMerger.GetFailingPaths(); unmergedPaths = resolveMerger.GetUnmergedPaths(); } else { noProblems = merger.Merge(headCommit, srcCommit); } refLogMessage.Append(": Merge made by "); refLogMessage.Append(mergeStrategy.GetName()); refLogMessage.Append('.'); if (noProblems) { dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache(), merger.GetResultTreeId ()); dco.SetFailOnConflict(true); dco.Checkout(); string msg = null; RevCommit newHead = null; MergeStatus mergeStatus = null; if (!squash) { newHead = new Git(GetRepository()).Commit().SetReflogComment(refLogMessage.ToString ()).Call(); mergeStatus = MergeStatus.MERGED; } else { msg = JGitText.Get().squashCommitNotUpdatingHEAD; newHead = headCommit; mergeStatus = MergeStatus.MERGED_SQUASHED; } return(new MergeCommandResult(newHead.Id, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, mergeStatus, mergeStrategy, null, msg)); } else { if (failingPaths != null) { repo.WriteMergeCommitMsg(null); repo.WriteMergeHeads(null); return(new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.FAILED, mergeStrategy, lowLevelResults , failingPaths, null)); } else { string mergeMessageWithConflicts = new MergeMessageFormatter().FormatWithConflicts (mergeMessage, unmergedPaths); repo.WriteMergeCommitMsg(mergeMessageWithConflicts); return(new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.CONFLICTING, mergeStrategy, lowLevelResults , null)); } } } } } catch (NGit.Errors.CheckoutConflictException e) { IList <string> conflicts = (dco == null) ? Sharpen.Collections.EmptyList <string>() : dco.GetConflicts(); throw new NGit.Api.Errors.CheckoutConflictException(conflicts, e); } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionCaughtDuringExecutionOfMergeCommand , e), e); } finally { if (revWalk != null) { revWalk.Release(); } } }