コード例 #1
0
ファイル: MergeCommand.cs プロジェクト: TetradogOther/NGit
        /// <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();
                }
            }
        }
コード例 #2
0
ファイル: CherryPickCommand.cs プロジェクト: shoff/ngit
        /// <summary>
        /// Executes the
        /// <code>Cherry-Pick</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 cherry-pick</returns>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        public override CherryPickResult Call()
        {
            RevCommit   newHead          = null;
            IList <Ref> cherryPickedRefs = new List <Ref>();

            CheckCallable();
            RevWalk revWalk = new RevWalk(repo);

            try
            {
                // get the head commit
                Ref headRef = repo.GetRef(Constants.HEAD);
                if (headRef == null)
                {
                    throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported
                                              );
                }
                RevCommit headCommit = revWalk.ParseCommit(headRef.GetObjectId());
                newHead = headCommit;
                // loop through all refs to be cherry-picked
                foreach (Ref src in commits)
                {
                    // get the commit to be cherry-picked
                    // handle annotated tags
                    ObjectId srcObjectId = src.GetPeeledObjectId();
                    if (srcObjectId == null)
                    {
                        srcObjectId = src.GetObjectId();
                    }
                    RevCommit srcCommit = revWalk.ParseCommit(srcObjectId);
                    // get the parent of the commit to cherry-pick
                    if (srcCommit.ParentCount != 1)
                    {
                        throw new MultipleParentsNotAllowedException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent
                                                                     );
                    }
                    RevCommit srcParent = srcCommit.GetParent(0);
                    revWalk.ParseHeaders(srcParent);
                    ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger
                                                               (repo));
                    merger.SetWorkingTreeIterator(new FileTreeIterator(repo));
                    merger.SetBase(srcParent.Tree);
                    if (merger.Merge(headCommit, srcCommit))
                    {
                        if (AnyObjectId.Equals(headCommit.Tree.Id, merger.GetResultTreeId()))
                        {
                            continue;
                        }
                        DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache
                                                                        (), merger.GetResultTreeId());
                        dco.SetFailOnConflict(true);
                        dco.Checkout();
                        newHead = new Git(GetRepository()).Commit().SetMessage(srcCommit.GetFullMessage()
                                                                               ).SetAuthor(srcCommit.GetAuthorIdent()).Call();
                        cherryPickedRefs.AddItem(src);
                    }
                    else
                    {
                        if (merger.Failed())
                        {
                            return(new CherryPickResult(merger.GetFailingPaths()));
                        }
                        // there are merge conflicts
                        string message = new MergeMessageFormatter().FormatWithConflicts(srcCommit.GetFullMessage
                                                                                             (), merger.GetUnmergedPaths());
                        repo.WriteCherryPickHead(srcCommit.Id);
                        repo.WriteMergeCommitMsg(message);
                        return(CherryPickResult.CONFLICT);
                    }
                }
            }
            catch (IOException e)
            {
                throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionCaughtDuringExecutionOfCherryPickCommand
                                                                     , e), e);
            }
            finally
            {
                revWalk.Release();
            }
            return(new CherryPickResult(newHead, cherryPickedRefs));
        }