/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> private NGit.Api.LogCommand Add(bool include, AnyObjectId start) { CheckCallable(); try { if (include) { walk.MarkStart(walk.LookupCommit(start)); startSpecified = true; } else { walk.MarkUninteresting(walk.LookupCommit(start)); } return(this); } catch (MissingObjectException e) { throw; } catch (IncorrectObjectTypeException e) { throw; } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionOccuredDuringAddingOfOptionToALogCommand , start), e); } }
/// <summary>Parse a commit from its canonical format.</summary> /// <remarks> /// Parse a commit from its canonical format. /// This method inserts the commit directly into the caller supplied revision /// pool, making it appear as though the commit exists in the repository, /// even if it doesn't. The repository under the pool is not affected. /// </remarks> /// <param name="rw"> /// the revision pool to allocate the commit within. The commit's /// tree and parent pointers will be obtained from this pool. /// </param> /// <param name="raw">the canonical formatted commit to be parsed.</param> /// <returns> /// the parsed commit, in an isolated revision pool that is not /// available to the caller. /// </returns> public static NGit.Revwalk.RevCommit Parse(RevWalk rw, byte[] raw) { ObjectInserter.Formatter fmt = new ObjectInserter.Formatter(); bool retain = rw.IsRetainBody(); rw.SetRetainBody(true); NGit.Revwalk.RevCommit r = rw.LookupCommit(fmt.IdFor(Constants.OBJ_COMMIT, raw)); r.ParseCanonical(rw, raw); rw.SetRetainBody(retain); return(r); }
/// <exception cref="System.Exception"></exception> public virtual void Setup(int count) { Git git = new Git(db); for (int i = 0; i < count; i++) { git.Commit().SetCommitter(committer).SetAuthor(author).SetMessage("commit " + i). Call(); } list = new RevCommitList<RevCommit>(); RevWalk w = new RevWalk(db); w.MarkStart(w.LookupCommit(db.Resolve(Constants.HEAD))); list.Source(w); }
/// <exception cref="System.Exception"></exception> public virtual void Setup(int count) { Git git = new Git(db); for (int i = 0; i < count; i++) { git.Commit().SetCommitter(committer).SetAuthor(author).SetMessage("commit " + i). Call(); } list = new RevCommitList <RevCommit>(); RevWalk w = new RevWalk(db); w.MarkStart(w.LookupCommit(db.Resolve(Constants.HEAD))); list.Source(w); }
public virtual void TestFillToCommit() { Setup(3); RevWalk w = new RevWalk(db); w.MarkStart(w.LookupCommit(db.Resolve(Constants.HEAD))); w.Next(); RevCommit c = w.Next(); NUnit.Framework.Assert.IsNotNull(c, "should have found 2. commit"); list.FillTo(c, 5); NUnit.Framework.Assert.AreEqual(2, list.Count); NUnit.Framework.Assert.AreEqual("commit 1", list[1].GetFullMessage()); NUnit.Framework.Assert.IsNull(list[3]); }
/// <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); }
internal virtual void ParseCanonical(RevWalk walk, byte[] raw) { MutableObjectId idBuffer = walk.idBuffer; idBuffer.FromString(raw, 5); tree = walk.LookupTree(idBuffer); int ptr = 46; if (parents == null) { NGit.Revwalk.RevCommit[] pList = new NGit.Revwalk.RevCommit[1]; int nParents = 0; for (; ;) { if (raw[ptr] != 'p') { break; } idBuffer.FromString(raw, ptr + 7); NGit.Revwalk.RevCommit p = walk.LookupCommit(idBuffer); if (nParents == 0) { pList[nParents++] = p; } else { if (nParents == 1) { pList = new NGit.Revwalk.RevCommit[] { pList[0], p }; nParents = 2; } else { if (pList.Length <= nParents) { NGit.Revwalk.RevCommit[] old = pList; pList = new NGit.Revwalk.RevCommit[pList.Length + 32]; System.Array.Copy(old, 0, pList, 0, nParents); } pList[nParents++] = p; } } ptr += 48; } if (nParents != pList.Length) { NGit.Revwalk.RevCommit[] old = pList; pList = new NGit.Revwalk.RevCommit[nParents]; System.Array.Copy(old, 0, pList, 0, nParents); } parents = pList; } // extract time from "committer " ptr = RawParseUtils.Committer(raw, ptr); if (ptr > 0) { ptr = RawParseUtils.NextLF(raw, ptr, '>'); // In 2038 commitTime will overflow unless it is changed to long. commitTime = RawParseUtils.ParseBase10(raw, ptr, null); } if (walk.IsRetainBody()) { buffer = raw; } flags |= PARSED; }
/// <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(); } } }
/// <summary>Parse a commit from its canonical format.</summary> /// <remarks> /// Parse a commit from its canonical format. /// This method inserts the commit directly into the caller supplied revision /// pool, making it appear as though the commit exists in the repository, /// even if it doesn't. The repository under the pool is not affected. /// </remarks> /// <param name="rw"> /// the revision pool to allocate the commit within. The commit's /// tree and parent pointers will be obtained from this pool. /// </param> /// <param name="raw">the canonical formatted commit to be parsed.</param> /// <returns> /// the parsed commit, in an isolated revision pool that is not /// available to the caller. /// </returns> public static NGit.Revwalk.RevCommit Parse(RevWalk rw, byte[] raw) { ObjectInserter.Formatter fmt = new ObjectInserter.Formatter(); bool retain = rw.IsRetainBody(); rw.SetRetainBody(true); NGit.Revwalk.RevCommit r = rw.LookupCommit(fmt.IdFor(Constants.OBJ_COMMIT, raw)); r.ParseCanonical(rw, raw); rw.SetRetainBody(retain); return r; }
internal virtual void ParseCanonical(RevWalk walk, byte[] raw) { MutableObjectId idBuffer = walk.idBuffer; idBuffer.FromString(raw, 5); tree = walk.LookupTree(idBuffer); int ptr = 46; if (parents == null) { NGit.Revwalk.RevCommit[] pList = new NGit.Revwalk.RevCommit[1]; int nParents = 0; for (; ; ) { if (raw[ptr] != 'p') { break; } idBuffer.FromString(raw, ptr + 7); NGit.Revwalk.RevCommit p = walk.LookupCommit(idBuffer); if (nParents == 0) { pList[nParents++] = p; } else { if (nParents == 1) { pList = new NGit.Revwalk.RevCommit[] { pList[0], p }; nParents = 2; } else { if (pList.Length <= nParents) { NGit.Revwalk.RevCommit[] old = pList; pList = new NGit.Revwalk.RevCommit[pList.Length + 32]; System.Array.Copy(old, 0, pList, 0, nParents); } pList[nParents++] = p; } } ptr += 48; } if (nParents != pList.Length) { NGit.Revwalk.RevCommit[] old = pList; pList = new NGit.Revwalk.RevCommit[nParents]; System.Array.Copy(old, 0, pList, 0, nParents); } parents = pList; } // extract time from "committer " ptr = RawParseUtils.Committer(raw, ptr); if (ptr > 0) { ptr = RawParseUtils.NextLF(raw, ptr, '>'); // In 2038 commitTime will overflow unless it is changed to long. commitTime = RawParseUtils.ParseBase10(raw, ptr, null); } if (walk.IsRetainBody()) { buffer = raw; } flags |= PARSED; }
/// <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); }