/// <exception cref="System.IO.IOException"></exception> private void CommitNoteMap(RevWalk walk, NoteMap map, RevCommit notesCommit, ObjectInserter inserter, string msg) { // commit the note NGit.CommitBuilder builder = new NGit.CommitBuilder(); builder.TreeId = map.WriteTree(inserter); builder.Author = new PersonIdent(repo); builder.Committer = builder.Author; builder.Message = msg; if (notesCommit != null) { builder.SetParentIds(notesCommit); } ObjectId commit = inserter.Insert(builder); inserter.Flush(); RefUpdate refUpdate = repo.UpdateRef(notesRef); if (notesCommit != null) { refUpdate.SetExpectedOldObjectId(notesCommit); } else { refUpdate.SetExpectedOldObjectId(ObjectId.ZeroId); } refUpdate.SetNewObjectId(commit); refUpdate.Update(walk); }
/// <exception cref="System.IO.IOException"></exception> private void CheckoutCommit(RevCommit commit) { try { RevCommit head = walk.ParseCommit(repo.Resolve(Constants.HEAD)); DirCacheCheckout dco = new DirCacheCheckout(repo, head.Tree, repo.LockDirCache(), commit.Tree); dco.SetFailOnConflict(true); dco.Checkout(); // update the HEAD RefUpdate refUpdate = repo.UpdateRef(Constants.HEAD, true); refUpdate.SetExpectedOldObjectId(head); refUpdate.SetNewObjectId(commit); RefUpdate.Result res = refUpdate.ForceUpdate(); switch (res) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.NO_CHANGE: case RefUpdate.Result.FORCED: { break; } default: { throw new IOException("Could not rewind to upstream commit"); } } } finally { walk.Release(); monitor.EndTask(); } }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException"></exception> private void UpdateHead(StringBuilder refLogMessage, ObjectId newHeadId, ObjectId oldHeadID) { RefUpdate refUpdate = repo.UpdateRef(Constants.HEAD); refUpdate.SetNewObjectId(newHeadId); refUpdate.SetRefLogMessage(refLogMessage.ToString(), false); refUpdate.SetExpectedOldObjectId(oldHeadID); RefUpdate.Result rc = refUpdate.Update(); switch (rc) { case RefUpdate.Result.NEW: case RefUpdate.Result.FAST_FORWARD: { return; } case RefUpdate.Result.REJECTED: case RefUpdate.Result.LOCK_FAILURE: { throw new ConcurrentRefUpdateException(JGitText.Get().couldNotLockHEAD, refUpdate .GetRef(), rc); } default: { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().updatingRefFailed , Constants.HEAD, newHeadId.ToString(), rc)); } } }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> private RevCommit TryFastForward(string headName, RevCommit oldCommit, RevCommit newCommit) { bool tryRebase = false; foreach (RevCommit parentCommit in newCommit.Parents) { if (parentCommit.Equals(oldCommit)) { tryRebase = true; } } if (!tryRebase) { return(null); } CheckoutCommand co = new CheckoutCommand(repo); try { co.SetName(newCommit.Name).Call(); if (headName.StartsWith(Constants.R_HEADS)) { RefUpdate rup = repo.UpdateRef(headName); rup.SetExpectedOldObjectId(oldCommit); rup.SetNewObjectId(newCommit); rup.SetRefLogMessage("Fast-foward from " + oldCommit.Name + " to " + newCommit.Name , false); RefUpdate.Result res = rup.Update(walk); switch (res) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.NO_CHANGE: case RefUpdate.Result.FORCED: { break; } default: { throw new IOException("Could not fast-forward"); } } } return(newCommit); } catch (RefAlreadyExistsException e) { throw new JGitInternalException(e.Message, e); } catch (RefNotFoundException e) { throw new JGitInternalException(e.Message, e); } catch (InvalidRefNameException e) { throw new JGitInternalException(e.Message, e); } }
/// <exception cref="System.IO.IOException"></exception> private RefUpdate CreateRefUpdate(Ref stashRef) { RefUpdate update = repo.UpdateRef(Constants.R_STASH); update.DisableRefLog(); update.SetExpectedOldObjectId(stashRef.GetObjectId()); update.SetForceUpdate(true); return(update); }
/// <exception cref="System.IO.IOException"></exception> private void UpdateStashRef(ObjectId commitId, PersonIdent refLogIdent, string refLogMessage ) { Ref currentRef = repo.GetRef(@ref); RefUpdate refUpdate = repo.UpdateRef(@ref); refUpdate.SetNewObjectId(commitId); refUpdate.SetRefLogIdent(refLogIdent); refUpdate.SetRefLogMessage(refLogMessage, false); if (currentRef != null) { refUpdate.SetExpectedOldObjectId(currentRef.GetObjectId()); } else { refUpdate.SetExpectedOldObjectId(ObjectId.ZeroId); } refUpdate.ForceUpdate(); }
public virtual void TestUpdateRefLockFailureWrongOldValue() { ObjectId pid = db.Resolve("refs/heads/master"); RefUpdate updateRef = db.UpdateRef("refs/heads/master"); updateRef.SetNewObjectId(pid); updateRef.SetExpectedOldObjectId(db.Resolve("refs/heads/master^")); RefUpdate.Result update = updateRef.Update(); NUnit.Framework.Assert.AreEqual(RefUpdate.Result.LOCK_FAILURE, update); NUnit.Framework.Assert.AreEqual(pid, db.Resolve("refs/heads/master")); }
/// <summary>Execute this command during a receive-pack session.</summary> /// <remarks> /// Execute this command during a receive-pack session. /// <p> /// Sets the status of the command as a side effect. /// </remarks> /// <param name="rp">receive-pack session.</param> /// <since>2.0</since> public virtual void Execute(BaseReceivePack rp) { try { RefUpdate ru = rp.GetRepository().UpdateRef(GetRefName()); ru.SetRefLogIdent(rp.GetRefLogIdent()); switch (GetType()) { case ReceiveCommand.Type.DELETE: { if (!ObjectId.ZeroId.Equals(GetOldId())) { // We can only do a CAS style delete if the client // didn't bork its delete request by sending the // wrong zero id rather than the advertised one. // ru.SetExpectedOldObjectId(GetOldId()); } ru.SetForceUpdate(true); SetResult(ru.Delete(rp.GetRevWalk())); break; } case ReceiveCommand.Type.CREATE: case ReceiveCommand.Type.UPDATE: case ReceiveCommand.Type.UPDATE_NONFASTFORWARD: { ru.SetForceUpdate(rp.IsAllowNonFastForwards()); ru.SetExpectedOldObjectId(GetOldId()); ru.SetNewObjectId(GetNewId()); ru.SetRefLogMessage("push", true); SetResult(ru.Update(rp.GetRevWalk())); break; } } } catch (IOException err) { Reject(err); } }
public virtual void TestCreateFromLightweightTag() { RefUpdate rup = db.UpdateRef("refs/tags/V10"); rup.SetNewObjectId(initialCommit); rup.SetExpectedOldObjectId(ObjectId.ZeroId); rup.Update(); Ref branch = git.BranchCreate().SetName("FromLightweightTag").SetStartPoint("refs/tags/V10" ).Call(); NUnit.Framework.Assert.AreEqual(initialCommit.Id, branch.GetObjectId()); }
public virtual void TestUpdateRefForwardWithCheck1() { ObjectId ppid = db.Resolve("refs/heads/master^"); ObjectId pid = db.Resolve("refs/heads/master"); RefUpdate updateRef = db.UpdateRef("refs/heads/master"); updateRef.SetNewObjectId(ppid); updateRef.SetForceUpdate(true); RefUpdate.Result update = updateRef.Update(); NUnit.Framework.Assert.AreEqual(RefUpdate.Result.FORCED, update); NUnit.Framework.Assert.AreEqual(ppid, db.Resolve("refs/heads/master")); // real test RefUpdate updateRef2 = db.UpdateRef("refs/heads/master"); updateRef2.SetExpectedOldObjectId(ppid); updateRef2.SetNewObjectId(pid); RefUpdate.Result update2 = updateRef2.Update(); NUnit.Framework.Assert.AreEqual(RefUpdate.Result.FAST_FORWARD, update2); NUnit.Framework.Assert.AreEqual(pid, db.Resolve("refs/heads/master")); }
/// <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(); } } }
/// <exception cref="System.IO.IOException"></exception> protected internal override RefUpdate.Result DoRename() { if (source.GetRef().IsSymbolic()) { return(RefUpdate.Result.IO_FAILURE); } // not supported objId = source.GetOldObjectId(); updateHEAD = NeedToUpdateHEAD(); tmp = refdb.NewTemporaryUpdate(); RevWalk rw = new RevWalk(refdb.GetRepository()); try { // First backup the source so its never unreachable. tmp.SetNewObjectId(objId); tmp.SetForceUpdate(true); tmp.DisableRefLog(); switch (tmp.Update(rw)) { case RefUpdate.Result.NEW: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { return(tmp.GetResult()); break; } } // Save the source's log under the temporary name, we must do // this before we delete the source, otherwise we lose the log. if (!RenameLog(source, tmp)) { return(RefUpdate.Result.IO_FAILURE); } // If HEAD has to be updated, link it now to destination. // We have to link before we delete, otherwise the delete // fails because its the current branch. RefUpdate dst = destination; if (updateHEAD) { if (!LinkHEAD(destination)) { RenameLog(tmp, source); return(RefUpdate.Result.LOCK_FAILURE); } // Replace the update operation so HEAD will log the rename. dst = ((RefDirectoryUpdate)refdb.NewUpdate(Constants.HEAD, false)); dst.SetRefLogIdent(destination.GetRefLogIdent()); dst.SetRefLogMessage(destination.GetRefLogMessage(), false); } // Delete the source name so its path is free for replacement. source.SetExpectedOldObjectId(objId); source.SetForceUpdate(true); source.DisableRefLog(); if (source.Delete(rw) != RefUpdate.Result.FORCED) { RenameLog(tmp, source); if (updateHEAD) { LinkHEAD(source); } return(source.GetResult()); } // Move the log to the destination. if (!RenameLog(tmp, destination)) { RenameLog(tmp, source); source.SetExpectedOldObjectId(ObjectId.ZeroId); source.SetNewObjectId(objId); source.Update(rw); if (updateHEAD) { LinkHEAD(source); } return(RefUpdate.Result.IO_FAILURE); } // Create the destination, logging the rename during the creation. dst.SetExpectedOldObjectId(ObjectId.ZeroId); dst.SetNewObjectId(objId); if (dst.Update(rw) != RefUpdate.Result.NEW) { // If we didn't create the destination we have to undo // our work. Put the log back and restore source. if (RenameLog(destination, tmp)) { RenameLog(tmp, source); } source.SetExpectedOldObjectId(ObjectId.ZeroId); source.SetNewObjectId(objId); source.Update(rw); if (updateHEAD) { LinkHEAD(source); } return(dst.GetResult()); } return(RefUpdate.Result.RENAMED); } finally { // Always try to free the temporary name. try { refdb.Delete(tmp); } catch (IOException) { FileUtils.Delete(refdb.FileFor(tmp.GetName())); } rw.Release(); } }
/// <summary> /// Executes the /// <code>commit</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 (means: one /// call to /// <see cref="Call()">Call()</see> /// ) /// </summary> /// <returns> /// a /// <see cref="NGit.Revwalk.RevCommit">NGit.Revwalk.RevCommit</see> /// object representing the successful commit. /// </returns> /// <exception cref="NGit.Api.Errors.NoHeadException">when called on a git repo without a HEAD reference /// </exception> /// <exception cref="NGit.Api.Errors.NoMessageException">when called without specifying a commit message /// </exception> /// <exception cref="NGit.Api.Errors.UnmergedPathsException">when the current index contained unmerged paths (conflicts) /// </exception> /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException"> /// when HEAD or branch ref is updated concurrently by someone /// else /// </exception> /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">when repository is not in the right state for committing /// </exception> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override RevCommit Call() { CheckCallable(); RepositoryState state = repo.GetRepositoryState(); if (!state.CanCommit()) { throw new WrongRepositoryStateException(MessageFormat.Format(JGitText.Get().cannotCommitOnARepoWithState , state.Name())); } ProcessOptions(state); try { if (all && !repo.IsBare && repo.WorkTree != null) { Git git = new Git(repo); try { git.Add().AddFilepattern(".").SetUpdate(true).Call(); } catch (NoFilepatternException e) { // should really not happen throw new JGitInternalException(e.Message, e); } } Ref head = repo.GetRef(Constants.HEAD); if (head == null) { throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported ); } // determine the current HEAD and the commit it is referring to ObjectId headId = repo.Resolve(Constants.HEAD + "^{commit}"); if (headId == null && amend) { throw new WrongRepositoryStateException(JGitText.Get().commitAmendOnInitialNotPossible ); } if (headId != null) { if (amend) { RevCommit previousCommit = new RevWalk(repo).ParseCommit(headId); RevCommit[] p = previousCommit.Parents; for (int i = 0; i < p.Length; i++) { parents.Add(0, p[i].Id); } if (author == null) { author = previousCommit.GetAuthorIdent(); } } else { parents.Add(0, headId); } } // lock the index DirCache index = repo.LockDirCache(); try { if (!only.IsEmpty()) { index = CreateTemporaryIndex(headId, index); } ObjectInserter odi = repo.NewObjectInserter(); try { // Write the index as tree to the object database. This may // fail for example when the index contains unmerged paths // (unresolved conflicts) ObjectId indexTreeId = index.WriteTree(odi); if (insertChangeId) { InsertChangeId(indexTreeId); } // Create a Commit object, populate it and write it NGit.CommitBuilder commit = new NGit.CommitBuilder(); commit.Committer = committer; commit.Author = author; commit.Message = message; commit.SetParentIds(parents); commit.TreeId = indexTreeId; ObjectId commitId = odi.Insert(commit); odi.Flush(); RevWalk revWalk = new RevWalk(repo); try { RevCommit revCommit = revWalk.ParseCommit(commitId); RefUpdate ru = repo.UpdateRef(Constants.HEAD); ru.SetNewObjectId(commitId); if (reflogComment != null) { ru.SetRefLogMessage(reflogComment, false); } else { string prefix = amend ? "commit (amend): " : "commit: "; ru.SetRefLogMessage(prefix + revCommit.GetShortMessage(), false); } if (headId != null) { ru.SetExpectedOldObjectId(headId); } else { ru.SetExpectedOldObjectId(ObjectId.ZeroId); } RefUpdate.Result rc = ru.ForceUpdate(); switch (rc) { case RefUpdate.Result.NEW: case RefUpdate.Result.FORCED: case RefUpdate.Result.FAST_FORWARD: { SetCallable(false); if (state == RepositoryState.MERGING_RESOLVED) { // Commit was successful. Now delete the files // used for merge commits repo.WriteMergeCommitMsg(null); repo.WriteMergeHeads(null); } else { if (state == RepositoryState.CHERRY_PICKING_RESOLVED) { repo.WriteMergeCommitMsg(null); repo.WriteCherryPickHead(null); } } return(revCommit); } case RefUpdate.Result.REJECTED: case RefUpdate.Result.LOCK_FAILURE: { throw new ConcurrentRefUpdateException(JGitText.Get().couldNotLockHEAD, ru.GetRef (), rc); } default: { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().updatingRefFailed , Constants.HEAD, commitId.ToString(), rc)); } } } finally { revWalk.Release(); } } finally { odi.Release(); } } finally { index.Unlock(); } } catch (UnmergedPathException e) { throw new UnmergedPathsException(e); } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfCommitCommand , e); } }