/// <summary>checks if we can fast-forward and returns the new head if it is possible /// </summary> /// <param name="newCommit"></param> /// <returns>the new head, or null</returns> /// <exception cref="NGit.Api.Errors.RefNotFoundException">NGit.Api.Errors.RefNotFoundException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public virtual RevCommit TryFastForward(RevCommit newCommit) { Ref head = repo.GetRef(Constants.HEAD); if (head == null || head.GetObjectId() == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , Constants.HEAD)); } ObjectId headId = head.GetObjectId(); if (headId == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , Constants.HEAD)); } RevCommit headCommit = walk.LookupCommit(headId); if (walk.IsMergedInto(newCommit, headCommit)) { return(newCommit); } string headName; if (head.IsSymbolic()) { headName = head.GetTarget().GetName(); } else { headName = "detached HEAD"; } return(TryFastForward(headName, headCommit, newCommit)); }
/// <exception cref="System.IO.IOException"></exception> private RefUpdate.Result UpdateImpl(RevWalk walk, RefUpdate.Store store) { RevObject newObj; RevObject oldObj; if (GetRefDatabase().IsNameConflicting(GetName())) { return(RefUpdate.Result.LOCK_FAILURE); } try { if (!TryLock(true)) { return(RefUpdate.Result.LOCK_FAILURE); } if (expValue != null) { ObjectId o; o = oldValue != null ? oldValue : ObjectId.ZeroId; if (!AnyObjectId.Equals(expValue, o)) { return(RefUpdate.Result.LOCK_FAILURE); } } if (oldValue == null) { return(store.Execute(RefUpdate.Result.NEW)); } newObj = SafeParse(walk, newValue); oldObj = SafeParse(walk, oldValue); if (newObj == oldObj && !detachingSymbolicRef) { return(store.Execute(RefUpdate.Result.NO_CHANGE)); } if (newObj is RevCommit && oldObj is RevCommit) { if (walk.IsMergedInto((RevCommit)oldObj, (RevCommit)newObj)) { return(store.Execute(RefUpdate.Result.FAST_FORWARD)); } } if (IsForceUpdate()) { return(store.Execute(RefUpdate.Result.FORCED)); } return(RefUpdate.Result.REJECTED); } finally { Unlock(); } }
/// <summary>Update the type of this command by checking for fast-forward.</summary> /// <remarks> /// Update the type of this command by checking for fast-forward. /// <p> /// If the command's current type is UPDATE, a merge test will be performed /// using the supplied RevWalk to determine if /// <see cref="GetOldId()">GetOldId()</see> /// is fully /// merged into /// <see cref="GetNewId()">GetNewId()</see> /// . If some commits are not merged the /// update type is changed to /// <see cref="Type.UPDATE_NONFASTFORWARD">Type.UPDATE_NONFASTFORWARD</see> /// . /// </remarks> /// <param name="walk"> /// an instance to perform the merge test with. The caller must /// allocate and release this object. /// </param> /// <exception cref="System.IO.IOException"> /// either oldId or newId is not accessible in the repository /// used by the RevWalk. This usually indicates data corruption, /// and the command cannot be processed. /// </exception> public virtual void UpdateType(RevWalk walk) { if (typeIsCorrect) { return; } if (type == ReceiveCommand.Type.UPDATE && !AnyObjectId.Equals(oldId, newId)) { RevObject o = walk.ParseAny(oldId); RevObject n = walk.ParseAny(newId); if (!(o is RevCommit) || !(n is RevCommit) || !walk.IsMergedInto((RevCommit)o, (RevCommit )n)) { SetType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD); } } typeIsCorrect = true; }
/// <summary>Update the type of this command by checking for fast-forward.</summary> /// <remarks> /// Update the type of this command by checking for fast-forward. /// <p> /// If the command's current type is UPDATE, a merge test will be performed /// using the supplied RevWalk to determine if /// <see cref="GetOldId()">GetOldId()</see> /// is fully /// merged into /// <see cref="GetNewId()">GetNewId()</see> /// . If some commits are not merged the /// update type is changed to /// <see cref="Type.UPDATE_NONFASTFORWARD">Type.UPDATE_NONFASTFORWARD</see> /// . /// </remarks> /// <param name="walk"> /// an instance to perform the merge test with. The caller must /// allocate and release this object. /// </param> /// <exception cref="System.IO.IOException"> /// either oldId or newId is not accessible in the repository /// used by the RevWalk. This usually indicates data corruption, /// and the command cannot be processed. /// </exception> public virtual void UpdateType(RevWalk walk) { if (typeIsCorrect) { return; } if (type == ReceiveCommand.Type.UPDATE && !AnyObjectId.Equals(oldId, newId)) { RevObject o = walk.ParseAny(oldId); RevObject n = walk.ParseAny(newId); if (!(o is RevCommit) || !(n is RevCommit) || !walk.IsMergedInto((RevCommit)o, (RevCommit )n)) { SetType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD); } } typeIsCorrect = true; }
public bool IsBranchMerged (string branchName) { // check if a branch is merged into HEAD RevWalk walk = new RevWalk(RootRepository); RevCommit tip = walk.ParseCommit(RootRepository.Resolve(Constants.HEAD)); Ref currentRef = RootRepository.GetRef(branchName); if (currentRef == null) return true; RevCommit @base = walk.ParseCommit(RootRepository.Resolve(branchName)); return walk.IsMergedInto(@base, tip); }
/// <exception cref="NGit.Api.Errors.NotMergedException"> /// when trying to delete a branch which has not been merged into /// the currently checked out branch without force /// </exception> /// <exception cref="NGit.Api.Errors.CannotDeleteCurrentBranchException">NGit.Api.Errors.CannotDeleteCurrentBranchException /// </exception> /// <returns>the list with the (full) names of the deleted branches</returns> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override IList <string> Call() { CheckCallable(); IList <string> result = new AList <string>(); if (branchNames.IsEmpty()) { return(result); } try { string currentBranch = repo.GetFullBranch(); if (!force) { // check if the branches to be deleted // are all merged into the current branch RevWalk walk = new RevWalk(repo); RevCommit tip = walk.ParseCommit(repo.Resolve(Constants.HEAD)); foreach (string branchName in branchNames) { if (branchName == null) { continue; } Ref currentRef = repo.GetRef(branchName); if (currentRef == null) { continue; } RevCommit @base = walk.ParseCommit(repo.Resolve(branchName)); if (!walk.IsMergedInto(@base, tip)) { throw new NotMergedException(); } } } SetCallable(false); foreach (string branchName_1 in branchNames) { if (branchName_1 == null) { continue; } Ref currentRef = repo.GetRef(branchName_1); if (currentRef == null) { continue; } string fullName = currentRef.GetName(); if (fullName.Equals(currentBranch)) { throw new CannotDeleteCurrentBranchException(MessageFormat.Format(JGitText.Get(). cannotDeleteCheckedOutBranch, branchName_1)); } RefUpdate update = repo.UpdateRef(fullName); update.SetRefLogMessage("branch deleted", false); update.SetForceUpdate(true); RefUpdate.Result deleteResult = update.Delete(); bool ok = true; switch (deleteResult) { case RefUpdate.Result.IO_FAILURE: case RefUpdate.Result.LOCK_FAILURE: case RefUpdate.Result.REJECTED: { ok = false; break; } default: { break; break; } } if (ok) { result.AddItem(fullName); if (fullName.StartsWith(Constants.R_HEADS)) { string shortenedName = Sharpen.Runtime.Substring(fullName, Constants.R_HEADS.Length ); // remove upstream configuration if any StoredConfig cfg = repo.GetConfig(); cfg.UnsetSection(ConfigConstants.CONFIG_BRANCH_SECTION, shortenedName); cfg.Save(); } } else { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().deleteBranchUnexpectedResult , deleteResult.ToString())); } } return(result); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } }
/// <exception cref="System.IO.IOException"></exception> private RefUpdate.Result UpdateImpl(RevWalk walk, RefUpdate.Store store) { RevObject newObj; RevObject oldObj; if (GetRefDatabase().IsNameConflicting(GetName())) { return RefUpdate.Result.LOCK_FAILURE; } try { if (!TryLock(true)) { return RefUpdate.Result.LOCK_FAILURE; } if (expValue != null) { ObjectId o; o = oldValue != null ? oldValue : ObjectId.ZeroId; if (!AnyObjectId.Equals(expValue, o)) { return RefUpdate.Result.LOCK_FAILURE; } } if (oldValue == null) { return store.Execute(RefUpdate.Result.NEW); } newObj = SafeParse(walk, newValue); oldObj = SafeParse(walk, oldValue); if (newObj == oldObj && !detachingSymbolicRef) { return store.Execute(RefUpdate.Result.NO_CHANGE); } if (newObj is RevCommit && oldObj is RevCommit) { if (walk.IsMergedInto((RevCommit)oldObj, (RevCommit)newObj)) { return store.Execute(RefUpdate.Result.FAST_FORWARD); } } if (IsForceUpdate()) { return store.Execute(RefUpdate.Result.FORCED); } return RefUpdate.Result.REJECTED; } finally { Unlock(); } }
/// <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(); } } }
} // End Sub ListAllBranches // https://stackoverflow.com/questions/15822544/jgit-how-to-get-all-commits-of-a-branch-without-changes-to-the-working-direct public static void WalkCommits() { string dir = GetRepoPath(); Git git = Git.Open(dir); Repository repo = git.GetRepository(); RevWalk walk = new RevWalk(repo); System.Collections.Generic.IList<Ref> branches = git.BranchList().Call(); // https://stackoverflow.com/questions/15822544/jgit-how-to-get-all-commits-of-a-branch-without-changes-to-the-working-direct foreach (Ref branch in branches) { string branchName = branch.GetName(); System.Console.WriteLine("Commits of branch: " + branchName); System.Console.WriteLine("-------------------------------------"); Sharpen.Iterable<RevCommit> commits = git.Log().All().Call(); foreach (RevCommit commit in commits) { bool foundInThisBranch = false; RevCommit targetCommit = walk.ParseCommit(repo.Resolve(commit.Name)); foreach (System.Collections.Generic.KeyValuePair<string, Ref> e in repo.GetAllRefs()) { if (e.Key.StartsWith(Constants.R_HEADS)) { if (walk.IsMergedInto(targetCommit, walk.ParseCommit(e.Value.GetObjectId()))) { string foundInBranch = e.Value.GetName(); if (branchName.Equals(foundInBranch)) { foundInThisBranch = true; break; } // End if (branchName.Equals(foundInBranch)) } // End if (walk.IsMergedInto(targetCommit, walk.ParseCommit(e.Value.GetObjectId()))) } // End if (e.Key.StartsWith(Constants.R_HEADS)) } // Next e if (foundInThisBranch) { System.Console.WriteLine(commit.Name); System.Console.WriteLine(commit.GetAuthorIdent().GetName()); // System.DateTime dt = new System.DateTime(commit.CommitTime); System.DateTime dt = UnixTimeStampToDateTime(commit.CommitTime); System.Console.WriteLine(dt); System.Console.WriteLine(commit.GetFullMessage()); } // End if (foundInThisBranch) } // Next commit } // Next branch // Handle disposing of NGit's locks repo.Close(); repo.ObjectDatabase.Close(); repo = null; git = null; } // End Sub
/// <exception cref="NGit.Errors.TransportException"></exception> private IDictionary <string, RemoteRefUpdate> PrepareRemoteUpdates() { IDictionary <string, RemoteRefUpdate> result = new Dictionary <string, RemoteRefUpdate >(); foreach (RemoteRefUpdate rru in toPush.Values) { Ref advertisedRef = connection.GetRef(rru.GetRemoteName()); ObjectId advertisedOld = (advertisedRef == null ? ObjectId.ZeroId : advertisedRef .GetObjectId()); if (rru.GetNewObjectId().Equals(advertisedOld)) { if (rru.IsDelete()) { // ref does exist neither locally nor remotely rru.SetStatus(RemoteRefUpdate.Status.NON_EXISTING); } else { // same object - nothing to do rru.SetStatus(RemoteRefUpdate.Status.UP_TO_DATE); } continue; } // caller has explicitly specified expected old object id, while it // has been changed in the mean time - reject if (rru.IsExpectingOldObjectId() && !rru.GetExpectedOldObjectId().Equals(advertisedOld )) { rru.SetStatus(RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED); continue; } // create ref (hasn't existed on remote side) and delete ref // are always fast-forward commands, feasible at this level if (advertisedOld.Equals(ObjectId.ZeroId) || rru.IsDelete()) { rru.SetFastForward(true); result.Put(rru.GetRemoteName(), rru); continue; } // check for fast-forward: // - both old and new ref must point to commits, AND // - both of them must be known for us, exist in repository, AND // - old commit must be ancestor of new commit bool fastForward = true; try { RevObject oldRev = walker.ParseAny(advertisedOld); RevObject newRev = walker.ParseAny(rru.GetNewObjectId()); if (!(oldRev is RevCommit) || !(newRev is RevCommit) || !walker.IsMergedInto((RevCommit )oldRev, (RevCommit)newRev)) { fastForward = false; } } catch (MissingObjectException) { fastForward = false; } catch (Exception x) { throw new TransportException(transport.GetURI(), MessageFormat.Format(JGitText.Get ().readingObjectsFromLocalRepositoryFailed, x.Message), x); } rru.SetFastForward(fastForward); if (!fastForward && !rru.IsForceUpdate()) { rru.SetStatus(RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD); } else { result.Put(rru.GetRemoteName(), rru); } } return(result); }
/// <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); }