示例#1
0
        public Commit GetCommit(string commitId)
        {
            //commitId = repository.Resolve(commitId).Name;
            //return Commits.Where(c => c.Id.StartsWith(commitId)).FirstOrDefault();
            var id = repository.Resolve(commitId);

            if (id == null)
            {
                return(null);
            }

            RevWalk   walk   = new RevWalk(repository);
            RevCommit commit = walk.ParseCommit(id);

            walk.Dispose();
            return(commit == null || commit.Tree == null ? null : new Commit
            {
                Id = commit.Id.Name,
                ParentIds = commit.Parents.Select(p => p.Id.Name).ToList(),
                CommitDateRelative = RelativeDateFormatter.Format(commit.GetAuthorIdent().GetWhen()),
                CommitterName = commit.GetCommitterIdent().GetName(),
                CommitterEmail = commit.GetCommitterIdent().GetEmailAddress(),
                CommitDate = commit.GetCommitterIdent().GetWhen(),
                Message = commit.GetShortMessage(),
            });
        }
        public virtual void LogAllCommitsWithSkip()
        {
            Git git = Git.Wrap(db);
            IList <RevCommit>    commits = CreateCommits(git);
            Iterator <RevCommit> log     = git.Log().All().SetSkip(1).Call().Iterator();

            NUnit.Framework.Assert.IsTrue(log.HasNext());
            RevCommit commit = log.Next();

            NUnit.Framework.Assert.IsTrue(commits.Contains(commit));
            NUnit.Framework.Assert.AreEqual("commit#2", commit.GetShortMessage());
            NUnit.Framework.Assert.IsTrue(log.HasNext());
            commit = log.Next();
            NUnit.Framework.Assert.IsTrue(commits.Contains(commit));
            NUnit.Framework.Assert.AreEqual("commit#1", commit.GetShortMessage());
            NUnit.Framework.Assert.IsFalse(log.HasNext());
        }
示例#3
0
 private static Commit ToCommit(RevCommit commit, Repository repository)
 {
     return(new Commit
            (
                repository,
                commit.Name,
                commit.GetShortMessage(),
                ToPerson(commit.GetAuthorIdent()),
                ToPerson(commit.GetCommitterIdent()),
                commit.GetCommitterIdent().GetWhen(),
                commit.Parents.Select(p => p.Name)
            ));
 }
        public virtual void LogPathWithMaxCount()
        {
            Git git = Git.Wrap(db);
            IList <RevCommit>    commits = CreateCommits(git);
            Iterator <RevCommit> log     = git.Log().AddPath("Test.txt").SetMaxCount(1).Call().Iterator
                                               ();

            NUnit.Framework.Assert.IsTrue(log.HasNext());
            RevCommit commit = log.Next();

            NUnit.Framework.Assert.IsTrue(commits.Contains(commit));
            NUnit.Framework.Assert.AreEqual("commit#2", commit.GetShortMessage());
            NUnit.Framework.Assert.IsFalse(log.HasNext());
        }
        /// <exception cref="NGit.Api.Errors.RefAlreadyExistsException">
        /// when trying to create (without force) a branch with a name
        /// that already exists
        /// </exception>
        /// <exception cref="NGit.Api.Errors.RefNotFoundException">if the start point can not be found
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.InvalidRefNameException">
        /// if the provided name is <code>null</code> or otherwise
        /// invalid
        /// </exception>
        /// <returns>the newly created branch</returns>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        public override Ref Call()
        {
            CheckCallable();
            ProcessOptions();
            RevWalk revWalk = new RevWalk(repo);

            try
            {
                Ref  refToCheck = repo.GetRef(name);
                bool exists     = refToCheck != null && refToCheck.GetName().StartsWith(Constants.R_HEADS
                                                                                        );
                if (!force && exists)
                {
                    throw new RefAlreadyExistsException(MessageFormat.Format(JGitText.Get().refAlreadyExists1
                                                                             , name));
                }
                ObjectId startAt            = GetStartPoint();
                string   startPointFullName = null;
                if (startPoint != null)
                {
                    Ref baseRef = repo.GetRef(startPoint);
                    if (baseRef != null)
                    {
                        startPointFullName = baseRef.GetName();
                    }
                }
                // determine whether we are based on a commit,
                // a branch, or a tag and compose the reflog message
                string refLogMessage;
                string baseBranch = string.Empty;
                if (startPointFullName == null)
                {
                    string baseCommit;
                    if (startCommit != null)
                    {
                        baseCommit = startCommit.GetShortMessage();
                    }
                    else
                    {
                        RevCommit commit = revWalk.ParseCommit(repo.Resolve(startPoint));
                        baseCommit = commit.GetShortMessage();
                    }
                    if (exists)
                    {
                        refLogMessage = "branch: Reset start-point to commit " + baseCommit;
                    }
                    else
                    {
                        refLogMessage = "branch: Created from commit " + baseCommit;
                    }
                }
                else
                {
                    if (startPointFullName.StartsWith(Constants.R_HEADS) || startPointFullName.StartsWith
                            (Constants.R_REMOTES))
                    {
                        baseBranch = startPointFullName;
                        if (exists)
                        {
                            refLogMessage = "branch: Reset start-point to branch " + startPointFullName;
                        }
                        else
                        {
                            // TODO
                            refLogMessage = "branch: Created from branch " + baseBranch;
                        }
                    }
                    else
                    {
                        startAt = revWalk.Peel(revWalk.ParseAny(startAt));
                        if (exists)
                        {
                            refLogMessage = "branch: Reset start-point to tag " + startPointFullName;
                        }
                        else
                        {
                            refLogMessage = "branch: Created from tag " + startPointFullName;
                        }
                    }
                }
                RefUpdate updateRef = repo.UpdateRef(Constants.R_HEADS + name);
                updateRef.SetNewObjectId(startAt);
                updateRef.SetRefLogMessage(refLogMessage, false);
                RefUpdate.Result updateResult;
                if (exists && force)
                {
                    updateResult = updateRef.ForceUpdate();
                }
                else
                {
                    updateResult = updateRef.Update();
                }
                SetCallable(false);
                bool ok = false;
                switch (updateResult)
                {
                case RefUpdate.Result.NEW:
                {
                    ok = !exists;
                    break;
                }

                case RefUpdate.Result.NO_CHANGE:
                case RefUpdate.Result.FAST_FORWARD:
                case RefUpdate.Result.FORCED:
                {
                    ok = exists;
                    break;
                }

                default:
                {
                    break;
                    break;
                }
                }
                if (!ok)
                {
                    throw new JGitInternalException(MessageFormat.Format(JGitText.Get().createBranchUnexpectedResult
                                                                         , updateResult.ToString()));
                }
                Ref result = repo.GetRef(name);
                if (result == null)
                {
                    throw new JGitInternalException(JGitText.Get().createBranchFailedUnknownReason);
                }
                if (baseBranch.Length == 0)
                {
                    return(result);
                }
                // if we are based on another branch, see
                // if we need to configure upstream configuration: first check
                // whether the setting was done explicitly
                bool doConfigure;
                if (upstreamMode == CreateBranchCommand.SetupUpstreamMode.SET_UPSTREAM || upstreamMode
                    == CreateBranchCommand.SetupUpstreamMode.TRACK)
                {
                    // explicitly set to configure
                    doConfigure = true;
                }
                else
                {
                    if (upstreamMode == CreateBranchCommand.SetupUpstreamMode.NOTRACK)
                    {
                        // explicitly set to not configure
                        doConfigure = false;
                    }
                    else
                    {
                        // if there was no explicit setting, check the configuration
                        string autosetupflag = repo.GetConfig().GetString(ConfigConstants.CONFIG_BRANCH_SECTION
                                                                          , null, ConfigConstants.CONFIG_KEY_AUTOSETUPMERGE);
                        if ("false".Equals(autosetupflag))
                        {
                            doConfigure = false;
                        }
                        else
                        {
                            if ("always".Equals(autosetupflag))
                            {
                                doConfigure = true;
                            }
                            else
                            {
                                // in this case, the default is to configure
                                // only in case the base branch was a remote branch
                                doConfigure = baseBranch.StartsWith(Constants.R_REMOTES);
                            }
                        }
                    }
                }
                if (doConfigure)
                {
                    StoredConfig config   = repo.GetConfig();
                    string[]     tokens   = baseBranch.RegexSplit("/", 4);
                    bool         isRemote = tokens[1].Equals("remotes");
                    if (isRemote)
                    {
                        // refs/remotes/<remote name>/<branch>
                        string remoteName = tokens[2];
                        string branchName = tokens[3];
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE
                                         , remoteName);
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE
                                         , Constants.R_HEADS + branchName);
                    }
                    else
                    {
                        // set "." as remote
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE
                                         , ".");
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE
                                         , baseBranch);
                    }
                    config.Save();
                }
                return(result);
            }
            catch (IOException ioe)
            {
                throw new JGitInternalException(ioe.Message, ioe);
            }
            finally
            {
                revWalk.Release();
            }
        }
示例#6
0
        /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="NGit.Api.Errors.NoHeadException"></exception>
        /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
        private RebaseResult InitFilesAndRewind()
        {
            // we need to store everything into files so that we can implement
            // --skip, --continue, and --abort
            // first of all, we determine the commits to be applied
            IList <RevCommit> cherryPickList = new AList <RevCommit>();
            Ref head = repo.GetRef(Constants.HEAD);

            if (head == null || head.GetObjectId() == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            string headName;

            if (head.IsSymbolic())
            {
                headName = head.GetTarget().GetName();
            }
            else
            {
                headName = "detached HEAD";
            }
            ObjectId headId = head.GetObjectId();

            if (headId == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            RevCommit headCommit = walk.LookupCommit(headId);

            monitor.BeginTask(JGitText.Get().obtainingCommitsForCherryPick, ProgressMonitor.UNKNOWN
                              );
            LogCommand           cmd          = new Git(repo).Log().AddRange(upstreamCommit, headCommit);
            Iterable <RevCommit> commitsToUse = cmd.Call();

            foreach (RevCommit commit in commitsToUse)
            {
                cherryPickList.AddItem(commit);
            }
            // if the upstream commit is in a direct line to the current head,
            // the log command will not report any commits; in this case,
            // we create the cherry-pick list ourselves
            if (cherryPickList.IsEmpty())
            {
                Iterable <RevCommit> parents = new Git(repo).Log().Add(upstreamCommit).Call();
                foreach (RevCommit parent in parents)
                {
                    if (parent.Equals(headCommit))
                    {
                        break;
                    }
                    if (parent.ParentCount != 1)
                    {
                        throw new JGitInternalException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent
                                                        );
                    }
                    cherryPickList.AddItem(parent);
                }
            }
            // nothing to do: return with UP_TO_DATE_RESULT
            if (cherryPickList.IsEmpty())
            {
                return(RebaseResult.UP_TO_DATE_RESULT);
            }
            Sharpen.Collections.Reverse(cherryPickList);
            // create the folder for the meta information
            FileUtils.Mkdir(rebaseDir);
            CreateFile(repo.Directory, Constants.ORIG_HEAD, headId.Name);
            CreateFile(rebaseDir, REBASE_HEAD, headId.Name);
            CreateFile(rebaseDir, HEAD_NAME, headName);
            CreateFile(rebaseDir, ONTO, upstreamCommit.Name);
            CreateFile(rebaseDir, INTERACTIVE, string.Empty);
            BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream
                                                                              (new FilePath(rebaseDir, GIT_REBASE_TODO)), Constants.CHARACTER_ENCODING));

            fw.Write("# Created by EGit: rebasing " + upstreamCommit.Name + " onto " + headId
                     .Name);
            fw.NewLine();
            try
            {
                StringBuilder sb     = new StringBuilder();
                ObjectReader  reader = walk.GetObjectReader();
                foreach (RevCommit commit_1 in cherryPickList)
                {
                    sb.Length = 0;
                    sb.Append(RebaseCommand.Action.PICK.ToToken());
                    sb.Append(" ");
                    sb.Append(reader.Abbreviate(commit_1).Name);
                    sb.Append(" ");
                    sb.Append(commit_1.GetShortMessage());
                    fw.Write(sb.ToString());
                    fw.NewLine();
                }
            }
            finally
            {
                fw.Close();
            }
            monitor.EndTask();
            // we rewind to the upstream commit
            monitor.BeginTask(MessageFormat.Format(JGitText.Get().rewinding, upstreamCommit.GetShortMessage
                                                       ()), ProgressMonitor.UNKNOWN);
            CheckoutCommit(upstreamCommit);
            monitor.EndTask();
            return(null);
        }
示例#7
0
        /// <summary>
        /// Executes the
        /// <code>Rebase</code>
        /// command with all the options and parameters
        /// collected by the setter methods 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>an object describing the result of this command</returns>
        /// <exception cref="NGit.Api.Errors.NoHeadException"></exception>
        /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
        /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        public override RebaseResult Call()
        {
            RevCommit newHead            = null;
            bool      lastStepWasForward = false;

            CheckCallable();
            CheckParameters();
            try
            {
                switch (operation)
                {
                case RebaseCommand.Operation.ABORT:
                {
                    try
                    {
                        return(Abort());
                    }
                    catch (IOException ioe)
                    {
                        throw new JGitInternalException(ioe.Message, ioe);
                    }
                    goto case RebaseCommand.Operation.SKIP;
                }

                case RebaseCommand.Operation.SKIP:
                case RebaseCommand.Operation.CONTINUE:
                {
                    // fall through
                    string upstreamCommitName = ReadFile(rebaseDir, ONTO);
                    this.upstreamCommit = walk.ParseCommit(repo.Resolve(upstreamCommitName));
                    break;
                }

                case RebaseCommand.Operation.BEGIN:
                {
                    RebaseResult res = InitFilesAndRewind();
                    if (res != null)
                    {
                        return(res);
                    }
                    break;
                }
                }
                if (monitor.IsCancelled())
                {
                    return(Abort());
                }
                if (this.operation == RebaseCommand.Operation.CONTINUE)
                {
                    newHead = ContinueRebase();
                }
                if (this.operation == RebaseCommand.Operation.SKIP)
                {
                    newHead = CheckoutCurrentHead();
                }
                ObjectReader or = repo.NewObjectReader();
                IList <RebaseCommand.Step> steps = LoadSteps();
                foreach (RebaseCommand.Step step in steps)
                {
                    PopSteps(1);
                    ICollection <ObjectId> ids = or.Resolve(step.commit);
                    if (ids.Count != 1)
                    {
                        throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID"
                                                        );
                    }
                    RevCommit commitToPick = walk.ParseCommit(ids.Iterator().Next());
                    if (monitor.IsCancelled())
                    {
                        return(new RebaseResult(commitToPick));
                    }
                    monitor.BeginTask(MessageFormat.Format(JGitText.Get().applyingCommit, commitToPick
                                                           .GetShortMessage()), ProgressMonitor.UNKNOWN);
                    // if the first parent of commitToPick is the current HEAD,
                    // we do a fast-forward instead of cherry-pick to avoid
                    // unnecessary object rewriting
                    newHead            = TryFastForward(commitToPick);
                    lastStepWasForward = newHead != null;
                    if (!lastStepWasForward)
                    {
                        // TODO if the content of this commit is already merged here
                        // we should skip this step in order to avoid confusing
                        // pseudo-changed
                        newHead = new Git(repo).CherryPick().Include(commitToPick).Call();
                    }
                    monitor.EndTask();
                    if (newHead == null)
                    {
                        return(Stop(commitToPick));
                    }
                }
                if (newHead != null)
                {
                    // point the previous head (if any) to the new commit
                    string headName = ReadFile(rebaseDir, HEAD_NAME);
                    if (headName.StartsWith(Constants.R_REFS))
                    {
                        RefUpdate rup = repo.UpdateRef(headName);
                        rup.SetNewObjectId(newHead);
                        RefUpdate.Result res_1 = rup.ForceUpdate();
                        switch (res_1)
                        {
                        case RefUpdate.Result.FAST_FORWARD:
                        case RefUpdate.Result.FORCED:
                        case RefUpdate.Result.NO_CHANGE:
                        {
                            break;
                        }

                        default:
                        {
                            throw new JGitInternalException("Updating HEAD failed");
                        }
                        }
                        rup   = repo.UpdateRef(Constants.HEAD);
                        res_1 = rup.Link(headName);
                        switch (res_1)
                        {
                        case RefUpdate.Result.FAST_FORWARD:
                        case RefUpdate.Result.FORCED:
                        case RefUpdate.Result.NO_CHANGE:
                        {
                            break;
                        }

                        default:
                        {
                            throw new JGitInternalException("Updating HEAD failed");
                        }
                        }
                    }
                    FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE);
                    if (lastStepWasForward)
                    {
                        return(new RebaseResult(RebaseResult.Status.FAST_FORWARD));
                    }
                    return(new RebaseResult(RebaseResult.Status.OK));
                }
                return(new RebaseResult(RebaseResult.Status.UP_TO_DATE));
            }
            catch (IOException ioe)
            {
                throw new JGitInternalException(ioe.Message, ioe);
            }
        }
示例#8
0
        /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="NGit.Api.Errors.NoHeadException"></exception>
        /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
        private RebaseResult InitFilesAndRewind()
        {
            // we need to store everything into files so that we can implement
            // --skip, --continue, and --abort
            Ref head = repo.GetRef(Constants.HEAD);

            if (head == null || head.GetObjectId() == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            string headName;

            if (head.IsSymbolic())
            {
                headName = head.GetTarget().GetName();
            }
            else
            {
                headName = "detached HEAD";
            }
            ObjectId headId = head.GetObjectId();

            if (headId == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            RevCommit headCommit = walk.LookupCommit(headId);
            RevCommit upstream   = walk.LookupCommit(upstreamCommit.Id);

            if (walk.IsMergedInto(upstream, headCommit))
            {
                return(RebaseResult.UP_TO_DATE_RESULT);
            }
            else
            {
                if (walk.IsMergedInto(headCommit, upstream))
                {
                    // head is already merged into upstream, fast-foward
                    monitor.BeginTask(MessageFormat.Format(JGitText.Get().resettingHead, upstreamCommit
                                                           .GetShortMessage()), ProgressMonitor.UNKNOWN);
                    CheckoutCommit(upstreamCommit);
                    monitor.EndTask();
                    UpdateHead(headName, upstreamCommit);
                    return(RebaseResult.FAST_FORWARD_RESULT);
                }
            }
            monitor.BeginTask(JGitText.Get().obtainingCommitsForCherryPick, ProgressMonitor.UNKNOWN
                              );
            // determine the commits to be applied
            LogCommand           cmd            = new Git(repo).Log().AddRange(upstreamCommit, headCommit);
            Iterable <RevCommit> commitsToUse   = cmd.Call();
            IList <RevCommit>    cherryPickList = new AList <RevCommit>();

            foreach (RevCommit commit in commitsToUse)
            {
                if (commit.ParentCount != 1)
                {
                    throw new JGitInternalException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent
                                                    );
                }
                cherryPickList.AddItem(commit);
            }
            Sharpen.Collections.Reverse(cherryPickList);
            // create the folder for the meta information
            FileUtils.Mkdir(rebaseDir);
            CreateFile(repo.Directory, Constants.ORIG_HEAD, headId.Name);
            CreateFile(rebaseDir, REBASE_HEAD, headId.Name);
            CreateFile(rebaseDir, HEAD_NAME, headName);
            CreateFile(rebaseDir, ONTO, upstreamCommit.Name);
            CreateFile(rebaseDir, INTERACTIVE, string.Empty);
            BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream
                                                                              (new FilePath(rebaseDir, GIT_REBASE_TODO)), Constants.CHARACTER_ENCODING));

            fw.Write("# Created by EGit: rebasing " + upstreamCommit.Name + " onto " + headId
                     .Name);
            fw.NewLine();
            try
            {
                StringBuilder sb     = new StringBuilder();
                ObjectReader  reader = walk.GetObjectReader();
                foreach (RevCommit commit_1 in cherryPickList)
                {
                    sb.Length = 0;
                    sb.Append(RebaseCommand.Action.PICK.ToToken());
                    sb.Append(" ");
                    sb.Append(reader.Abbreviate(commit_1).Name);
                    sb.Append(" ");
                    sb.Append(commit_1.GetShortMessage());
                    fw.Write(sb.ToString());
                    fw.NewLine();
                }
            }
            finally
            {
                fw.Close();
            }
            monitor.EndTask();
            // we rewind to the upstream commit
            monitor.BeginTask(MessageFormat.Format(JGitText.Get().rewinding, upstreamCommit.GetShortMessage
                                                       ()), ProgressMonitor.UNKNOWN);
            bool checkoutOk = false;

            try
            {
                checkoutOk = CheckoutCommit(upstreamCommit);
            }
            finally
            {
                if (!checkoutOk)
                {
                    FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE);
                }
            }
            monitor.EndTask();
            return(null);
        }
示例#9
0
        /// <summary>
        /// Executes the
        /// <code>Rebase</code>
        /// command with all the options and parameters
        /// collected by the setter methods 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>an object describing the result of this command</returns>
        /// <exception cref="NGit.Api.Errors.NoHeadException"></exception>
        /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
        /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        public override RebaseResult Call()
        {
            RevCommit newHead            = null;
            bool      lastStepWasForward = false;

            CheckCallable();
            CheckParameters();
            try
            {
                switch (operation)
                {
                case RebaseCommand.Operation.ABORT:
                {
                    try
                    {
                        return(Abort(RebaseResult.ABORTED_RESULT));
                    }
                    catch (IOException ioe)
                    {
                        throw new JGitInternalException(ioe.Message, ioe);
                    }
                    goto case RebaseCommand.Operation.SKIP;
                }

                case RebaseCommand.Operation.SKIP:
                case RebaseCommand.Operation.CONTINUE:
                {
                    // fall through
                    string upstreamCommitName = ReadFile(rebaseDir, ONTO);
                    this.upstreamCommit = walk.ParseCommit(repo.Resolve(upstreamCommitName));
                    break;
                }

                case RebaseCommand.Operation.BEGIN:
                {
                    RebaseResult res = InitFilesAndRewind();
                    if (res != null)
                    {
                        return(res);
                    }
                    break;
                }
                }
                if (monitor.IsCancelled())
                {
                    return(Abort(RebaseResult.ABORTED_RESULT));
                }
                if (operation == RebaseCommand.Operation.CONTINUE)
                {
                    newHead = ContinueRebase();
                }
                if (operation == RebaseCommand.Operation.SKIP)
                {
                    newHead = CheckoutCurrentHead();
                }
                ObjectReader or = repo.NewObjectReader();
                IList <RebaseCommand.Step> steps = LoadSteps();
                foreach (RebaseCommand.Step step in steps)
                {
                    PopSteps(1);
                    ICollection <ObjectId> ids = or.Resolve(step.commit);
                    if (ids.Count != 1)
                    {
                        throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID"
                                                        );
                    }
                    RevCommit commitToPick = walk.ParseCommit(ids.Iterator().Next());
                    if (monitor.IsCancelled())
                    {
                        return(new RebaseResult(commitToPick));
                    }
                    try
                    {
                        monitor.BeginTask(MessageFormat.Format(JGitText.Get().applyingCommit, commitToPick
                                                               .GetShortMessage()), ProgressMonitor.UNKNOWN);
                        // if the first parent of commitToPick is the current HEAD,
                        // we do a fast-forward instead of cherry-pick to avoid
                        // unnecessary object rewriting
                        newHead            = TryFastForward(commitToPick);
                        lastStepWasForward = newHead != null;
                        if (!lastStepWasForward)
                        {
                            // TODO if the content of this commit is already merged
                            // here we should skip this step in order to avoid
                            // confusing pseudo-changed
                            CherryPickResult cherryPickResult = new Git(repo).CherryPick().Include(commitToPick
                                                                                                   ).Call();
                            switch (cherryPickResult.GetStatus())
                            {
                            case CherryPickResult.CherryPickStatus.FAILED:
                            {
                                if (operation == RebaseCommand.Operation.BEGIN)
                                {
                                    return(Abort(new RebaseResult(cherryPickResult.GetFailingPaths())));
                                }
                                else
                                {
                                    return(Stop(commitToPick));
                                }
                                goto case CherryPickResult.CherryPickStatus.CONFLICTING;
                            }

                            case CherryPickResult.CherryPickStatus.CONFLICTING:
                            {
                                return(Stop(commitToPick));
                            }

                            case CherryPickResult.CherryPickStatus.OK:
                            {
                                newHead = cherryPickResult.GetNewHead();
                                break;
                            }
                            }
                        }
                    }
                    finally
                    {
                        monitor.EndTask();
                    }
                }
                if (newHead != null)
                {
                    string headName = ReadFile(rebaseDir, HEAD_NAME);
                    UpdateHead(headName, newHead);
                    FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE);
                    if (lastStepWasForward)
                    {
                        return(RebaseResult.FAST_FORWARD_RESULT);
                    }
                    return(RebaseResult.OK_RESULT);
                }
                return(RebaseResult.FAST_FORWARD_RESULT);
            }
            catch (IOException ioe)
            {
                throw new JGitInternalException(ioe.Message, ioe);
            }
        }
示例#10
0
        /// <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">NGit.Api.Errors.GitAPIException
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">NGit.Api.Errors.WrongRepositoryStateException
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException">NGit.Api.Errors.ConcurrentRefUpdateException
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.UnmergedPathsException">NGit.Api.Errors.UnmergedPathsException
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.NoMessageException">NGit.Api.Errors.NoMessageException
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.NoHeadException">NGit.Api.Errors.NoHeadException
        ///     </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(MessageFormat.Format(JGitText.Get().
                                                                                          canOnlyCherryPickCommitsWithOneParent, srcCommit.Name, Sharpen.Extensions.ValueOf
                                                                                              (srcCommit.ParentCount)));
                    }
                    RevCommit srcParent = srcCommit.GetParent(0);
                    revWalk.ParseHeaders(srcParent);
                    string ourName        = CalculateOurName(headRef);
                    string cherryPickName = srcCommit.Id.Abbreviate(7).Name + " " + srcCommit.GetShortMessage
                                                ();
                    ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger
                                                               (repo));
                    merger.SetWorkingTreeIterator(new FileTreeIterator(repo));
                    merger.SetBase(srcParent.Tree);
                    merger.SetCommitNames(new string[] { "BASE", ourName, cherryPickName });
                    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()
                                                                               ).SetReflogComment("cherry-pick: " + srcCommit.GetShortMessage()).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));
        }