Example #1
0
 /// <param name="newHead">the object the head points at after the merge</param>
 /// <param name="base">
 /// the common base which was used to produce a content-merge. May
 /// be <code>null</code> if the merge-result was produced without
 /// computing a common base
 /// </param>
 /// <param name="mergedCommits">all the commits which have been merged together</param>
 /// <param name="mergeStatus">the status the merge resulted in</param>
 /// <param name="mergeStrategy">
 /// the used
 /// <see cref="NGit.Merge.MergeStrategy">NGit.Merge.MergeStrategy</see>
 /// </param>
 /// <param name="lowLevelResults">
 /// merge results as returned by
 /// <see cref="NGit.Merge.ResolveMerger.GetMergeResults()">NGit.Merge.ResolveMerger.GetMergeResults()
 ///     </see>
 /// </param>
 /// <param name="description">a user friendly description of the merge result</param>
 public MergeCommandResult(ObjectId newHead, ObjectId @base, ObjectId[] mergedCommits
                           , MergeStatus mergeStatus, MergeStrategy mergeStrategy, IDictionary <string, NGit.Merge.MergeResult
                                                                                                <Sequence> > lowLevelResults, string description)
 {
     this.newHead       = newHead;
     this.mergedCommits = mergedCommits;
     this.@base         = @base;
     this.mergeStatus   = mergeStatus;
     this.mergeStrategy = mergeStrategy;
     this.description   = description;
     if (lowLevelResults != null)
     {
         foreach (KeyValuePair <string, NGit.Merge.MergeResult <Sequence> > result in lowLevelResults
                  .EntrySet())
         {
             AddConflict(result.Key, result.Value);
         }
     }
 }
Example #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.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();
                }
            }
        }
Example #3
0
 /// <param name="newHead">the object the head points at after the merge</param>
 /// <param name="base">
 /// the common base which was used to produce a content-merge. May
 /// be <code>null</code> if the merge-result was produced without
 /// computing a common base
 /// </param>
 /// <param name="mergedCommits">all the commits which have been merged together</param>
 /// <param name="mergeStatus">the status the merge resulted in</param>
 /// <param name="mergeStrategy">
 /// the used
 /// <see cref="NGit.Merge.MergeStrategy">NGit.Merge.MergeStrategy</see>
 /// </param>
 /// <param name="lowLevelResults">
 /// merge results as returned by
 /// <see cref="NGit.Merge.ResolveMerger.GetMergeResults()">NGit.Merge.ResolveMerger.GetMergeResults()
 ///     </see>
 /// </param>
 /// <since>2.0</since>
 public MergeCommandResult(ObjectId newHead, ObjectId @base, ObjectId[] mergedCommits
                           , MergeStatus mergeStatus, MergeStrategy mergeStrategy, IDictionary <string, MergeResult
                                                                                                <Sequence> > lowLevelResults) : this(newHead, @base, mergedCommits, mergeStatus, mergeStrategy
                                                                                                                                     , lowLevelResults, null)
 {
 }