示例#1
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);
        }
示例#2
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.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;

            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);
                    DirCacheCheckout 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);
                        DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache
                                                                        (), srcCommit.Tree);
                        dco.SetFailOnConflict(true);
                        dco.Checkout();
                        UpdateHead(refLogMessage, srcCommit, headId);
                        SetCallable(false);
                        return(new MergeCommandResult(srcCommit, srcCommit, new ObjectId[] { headCommit,
                                                                                             srcCommit }, MergeStatus.FAST_FORWARD, mergeStrategy, null, null));
                    }
                    else
                    {
                        repo.WriteMergeCommitMsg(new MergeMessageFormatter().Format(commits, head));
                        repo.WriteMergeHeads(Arrays.AsList(@ref.GetObjectId()));
                        ThreeWayMerger merger = (ThreeWayMerger)mergeStrategy.NewMerger(repo);
                        bool           noProblems;
                        IDictionary <string, MergeResult <NGit.Diff.Sequence> > lowLevelResults = null;
                        IDictionary <string, ResolveMerger.MergeFailureReason>  failingPaths    = 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();
                        }
                        else
                        {
                            noProblems = merger.Merge(headCommit, srcCommit);
                        }
                        if (noProblems)
                        {
                            DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache
                                                                            (), merger.GetResultTreeId());
                            dco.SetFailOnConflict(true);
                            dco.Checkout();
                            RevCommit newHead = new Git(GetRepository()).Commit().Call();
                            return(new MergeCommandResult(newHead.Id, null, new ObjectId[] { headCommit.Id, srcCommit
                                                                                             .Id }, MergeStatus.MERGED, mergeStrategy, null, null));
                        }
                        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
                                                              , null));
                            }
                            else
                            {
                                return(new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] {
                                    headCommit.Id, srcCommit.Id
                                }, MergeStatus.CONFLICTING, mergeStrategy, lowLevelResults
                                                              , null));
                            }
                        }
                    }
                }
            }
            catch (IOException e)
            {
                throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionCaughtDuringExecutionOfMergeCommand
                                                                     , e), e);
            }
            finally
            {
                if (revWalk != null)
                {
                    revWalk.Release();
                }
            }
        }