示例#1
0
        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());
        }
示例#2
0
        /// <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);
        }
示例#3
0
        /// <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();
                }
            }
        }