/// <exception cref="System.InvalidOperationException"></exception> /// <exception cref="System.IO.IOException"></exception> private void CheckoutCommit(RevCommit commit) { RevWalk walk = new RevWalk(db); RevCommit head = walk.ParseCommit(db.Resolve(Constants.HEAD)); DirCacheCheckout dco = new DirCacheCheckout(db, head.Tree, db.LockDirCache(), commit .Tree); dco.SetFailOnConflict(true); dco.Checkout(); walk.Release(); // update the HEAD RefUpdate refUpdate = db.UpdateRef(Constants.HEAD, true); refUpdate.SetNewObjectId(commit); refUpdate.ForceUpdate(); }
/// <exception cref="System.NotSupportedException"></exception> /// <exception cref="NGit.Errors.TransportException"></exception> private void ExecuteImp(ProgressMonitor monitor, FetchResult result) { conn = transport.OpenFetch(); try { result.SetAdvertisedRefs(transport.GetURI(), conn.GetRefsMap()); ICollection <Ref> matched = new HashSet <Ref>(); foreach (RefSpec spec in toFetch) { if (spec.GetSource() == null) { throw new TransportException(MessageFormat.Format(JGitText.Get().sourceRefNotSpecifiedForRefspec , spec)); } if (spec.IsWildcard()) { ExpandWildcard(spec, matched); } else { ExpandSingle(spec, matched); } } ICollection <Ref> additionalTags = Sharpen.Collections.EmptyList <Ref>(); TagOpt tagopt = transport.GetTagOpt(); if (tagopt == TagOpt.AUTO_FOLLOW) { additionalTags = ExpandAutoFollowTags(); } else { if (tagopt == TagOpt.FETCH_TAGS) { ExpandFetchTags(); } } bool includedTags; if (!askFor.IsEmpty() && !AskForIsComplete()) { FetchObjects(monitor); includedTags = conn.DidFetchIncludeTags(); // Connection was used for object transfer. If we // do another fetch we must open a new connection. // CloseConnection(result); } else { includedTags = false; } if (tagopt == TagOpt.AUTO_FOLLOW && !additionalTags.IsEmpty()) { // There are more tags that we want to follow, but // not all were asked for on the initial request. // Sharpen.Collections.AddAll(have, askFor.Keys); askFor.Clear(); foreach (Ref r in additionalTags) { ObjectId id = r.GetPeeledObjectId(); if (id == null) { id = r.GetObjectId(); } if (transport.local.HasObject(id)) { WantTag(r); } } if (!askFor.IsEmpty() && (!includedTags || !AskForIsComplete())) { ReopenConnection(); if (!askFor.IsEmpty()) { FetchObjects(monitor); } } } } finally { CloseConnection(result); } RevWalk walk = new RevWalk(transport.local); try { if (transport.IsRemoveDeletedRefs()) { DeleteStaleTrackingRefs(result, walk); } foreach (TrackingRefUpdate u in localUpdates) { try { u.Update(walk); result.Add(u); } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingTrackingRef , u.GetLocalName(), err.Message), err); } } } finally { walk.Release(); } if (!fetchHeadUpdates.IsEmpty()) { try { UpdateFETCH_HEAD(result); } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingFETCH_HEAD , err.Message), err); } } }
/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> private RevTag ParseTag(AnyObjectId id) { RevWalk rw = new RevWalk(db); try { return rw.ParseTag(id); } finally { rw.Release(); } }
public static MergeCommandResult MergeTrees (NGit.Repository repo, RevCommit srcBase, RevCommit srcCommit, string sourceDisplayName, bool commitResult) { RevCommit newHead = null; 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()); ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger (repo)); // CherryPick command sets the working tree, but this should not be necessary, and when setting it // untracked files are deleted during the merge // merger.SetWorkingTreeIterator(new FileTreeIterator(repo)); merger.SetBase(srcBase); bool noProblems; IDictionary<string, MergeResult<NGit.Diff.Sequence>> lowLevelResults = null; IDictionary<string, ResolveMerger.MergeFailureReason> failingPaths = null; IList<string> modifiedFiles = null; ResolveMerger resolveMerger = (ResolveMerger)merger; resolveMerger.SetCommitNames(new string[] { "BASE", "HEAD", sourceDisplayName }); noProblems = merger.Merge(headCommit, srcCommit); lowLevelResults = resolveMerger.GetMergeResults(); modifiedFiles = resolveMerger.GetModifiedFiles(); failingPaths = resolveMerger.GetFailingPaths(); if (noProblems) { if (modifiedFiles != null && modifiedFiles.Count == 0) { return new MergeCommandResult(headCommit, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, MergeStatus.ALREADY_UP_TO_DATE, MergeStrategy.RESOLVE, null, null); } DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache (), merger.GetResultTreeId()); dco.SetFailOnConflict(true); dco.Checkout(); if (commitResult) { newHead = new NGit.Api.Git(repo).Commit().SetMessage(srcCommit.GetFullMessage() ).SetAuthor(srcCommit.GetAuthorIdent()).Call(); return new MergeCommandResult(newHead.Id, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, MergeStatus.MERGED, MergeStrategy.RESOLVE, null, null); } else { return new MergeCommandResult(headCommit, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, MergeStatus.MERGED, MergeStrategy.RESOLVE, null, null); } } else { if (failingPaths != null) { return new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.FAILED, MergeStrategy.RESOLVE, lowLevelResults , null); } else { return new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.CONFLICTING, MergeStrategy.RESOLVE, lowLevelResults , null); } } } finally { revWalk.Release(); } }
/// <summary>Delete the ref.</summary> /// <remarks> /// Delete the ref. /// <p> /// This is the same as: /// <pre> /// return delete(new RevWalk(getRepository())); /// </pre> /// </remarks> /// <returns>the result status of the delete.</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public virtual RefUpdate.Result Delete() { RevWalk rw = new RevWalk(GetRepository()); try { return Delete(rw); } finally { rw.Release(); } }
/// <exception cref="System.InvalidOperationException"></exception> /// <exception cref="System.IO.IOException"></exception> private void CheckoutBranch(string branchName) { RevWalk walk = new RevWalk(db); RevCommit head = walk.ParseCommit(db.Resolve(Constants.HEAD)); RevCommit branch = walk.ParseCommit(db.Resolve(branchName)); DirCacheCheckout dco = new DirCacheCheckout(db, head.Tree, db.LockDirCache(), branch .Tree); dco.SetFailOnConflict(true); NUnit.Framework.Assert.IsTrue(dco.Checkout()); walk.Release(); // update the HEAD RefUpdate refUpdate = db.UpdateRef(Constants.HEAD); NUnit.Framework.Assert.AreEqual(RefUpdate.Result.FORCED, refUpdate.Link(branchName )); }
private RevCommit ParseCommit(Repository repo, ObjectId id) { RevWalk rw = new RevWalk(repo); var head = rw.ParseCommit(id); rw.MarkStart(head); RevCommit commit = null; try { commit = rw.Next(); while( commit != null ) { if (commit.Id.Name == id.Name) { return commit; } commit = rw.Next(); } } finally { rw.Release(); } return commit; }
/// <exception cref="NGit.Errors.TransportException"></exception> private void VerifyPrerequisites() { if (prereqs.IsEmpty()) { return; } RevWalk rw = new RevWalk(transport.local); try { RevFlag PREREQ = rw.NewFlag("PREREQ"); RevFlag SEEN = rw.NewFlag("SEEN"); IDictionary<ObjectId, string> missing = new Dictionary<ObjectId, string>(); IList<RevObject> commits = new AList<RevObject>(); foreach (KeyValuePair<ObjectId, string> e in prereqs.EntrySet()) { ObjectId p = e.Key; try { RevCommit c = rw.ParseCommit(p); if (!c.Has(PREREQ)) { c.Add(PREREQ); commits.AddItem(c); } } catch (MissingObjectException) { missing.Put(p, e.Value); } catch (IOException err) { throw new TransportException(transport.uri, MessageFormat.Format(JGitText.Get().cannotReadCommit , p.Name), err); } } if (!missing.IsEmpty()) { throw new MissingBundlePrerequisiteException(transport.uri, missing); } foreach (Ref r in transport.local.GetAllRefs().Values) { try { rw.MarkStart(rw.ParseCommit(r.GetObjectId())); } catch (IOException) { } } // If we cannot read the value of the ref skip it. int remaining = commits.Count; try { RevCommit c; while ((c = rw.Next()) != null) { if (c.Has(PREREQ)) { c.Add(SEEN); if (--remaining == 0) { break; } } } } catch (IOException err) { throw new TransportException(transport.uri, JGitText.Get().cannotReadObject, err); } if (remaining > 0) { foreach (RevObject o in commits) { if (!o.Has(SEEN)) { missing.Put(o, prereqs.Get(o)); } } throw new MissingBundlePrerequisiteException(transport.uri, missing); } } finally { rw.Release(); } }
/// <summary> /// Executes the /// <code>tag</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.RevTag">NGit.Revwalk.RevTag</see> /// object representing the successful tag /// </returns> /// <exception cref="NGit.Api.Errors.NoHeadException">when called on a git repo without a HEAD reference /// </exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"> /// a low-level exception of JGit has occurred. The original /// exception can be retrieved by calling /// <see cref="System.Exception.InnerException()">System.Exception.InnerException()</see> /// . Expect only /// <code>IOException's</code> /// to be wrapped. /// </exception> /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException"></exception> /// <exception cref="NGit.Api.Errors.InvalidTagNameException"></exception> public override RevTag Call() { CheckCallable(); RepositoryState state = repo.GetRepositoryState(); ProcessOptions(state); try { // create the tag object TagBuilder newTag = new TagBuilder(); newTag.SetTag(name); newTag.SetMessage(message); newTag.SetTagger(tagger); // if no id is set, we should attempt to use HEAD if (id == null) { ObjectId objectId = repo.Resolve(Constants.HEAD + "^{commit}"); if (objectId == null) { throw new NoHeadException(JGitText.Get().tagOnRepoWithoutHEADCurrentlyNotSupported ); } newTag.SetObjectId(objectId, Constants.OBJ_COMMIT); } else { newTag.SetObjectId(id); } // write the tag object ObjectInserter inserter = repo.NewObjectInserter(); try { ObjectId tagId = inserter.Insert(newTag); inserter.Flush(); RevWalk revWalk = new RevWalk(repo); try { RevTag revTag = revWalk.ParseTag(tagId); string refName = Constants.R_TAGS + newTag.GetTag(); RefUpdate tagRef = repo.UpdateRef(refName); tagRef.SetNewObjectId(tagId); tagRef.SetForceUpdate(forceUpdate); tagRef.SetRefLogMessage("tagged " + name, false); RefUpdate.Result updateResult = tagRef.Update(revWalk); switch (updateResult) { case RefUpdate.Result.NEW: case RefUpdate.Result.FORCED: { return(revTag); } case RefUpdate.Result.LOCK_FAILURE: { throw new ConcurrentRefUpdateException(JGitText.Get().couldNotLockHEAD, tagRef.GetRef (), updateResult); } default: { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().updatingRefFailed , refName, newTag.ToString(), updateResult)); } } } finally { revWalk.Release(); } } finally { inserter.Release(); } } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfTagCommand , e); } }
/// <summary>Core validation to be performed on all stashed commits</summary> /// <param name="commit"></param> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> private void ValidateStashedCommit(RevCommit commit) { NUnit.Framework.Assert.IsNotNull(commit); Ref stashRef = db.GetRef(Constants.R_STASH); NUnit.Framework.Assert.IsNotNull(stashRef); NUnit.Framework.Assert.AreEqual(commit, stashRef.GetObjectId()); NUnit.Framework.Assert.IsNotNull(commit.GetAuthorIdent()); NUnit.Framework.Assert.AreEqual(commit.GetAuthorIdent(), commit.GetCommitterIdent ()); NUnit.Framework.Assert.AreEqual(2, commit.ParentCount); // Load parents RevWalk walk = new RevWalk(db); try { foreach (RevCommit parent in commit.Parents) { walk.ParseBody(parent); } } finally { walk.Release(); } NUnit.Framework.Assert.AreEqual(1, commit.GetParent(1).ParentCount); NUnit.Framework.Assert.AreEqual(head, commit.GetParent(1).GetParent(0)); NUnit.Framework.Assert.IsFalse(commit.Tree.Equals(head.Tree), "Head tree matches stashed commit tree" ); NUnit.Framework.Assert.AreEqual(head, commit.GetParent(0)); NUnit.Framework.Assert.IsFalse(commit.GetFullMessage().Equals(commit.GetParent(1) .GetFullMessage())); }
public override void Commit (ChangeSet changeSet, IProgressMonitor monitor) { PersonIdent author = new PersonIdent (repo); PersonIdent committer = new PersonIdent (repo); string message = changeSet.GlobalComment; if (string.IsNullOrEmpty (message)) throw new ArgumentException ("Commit message must not be null or empty!", "message"); if (string.IsNullOrEmpty (author.GetName ())) throw new ArgumentException ("Author name must not be null or empty!", "author"); RepositoryState state = repo.GetRepositoryState (); if (!state.CanCommit ()) { throw new WrongRepositoryStateException ("Cannot commit with repository in state: " + state); } try { Ref head = repo.GetRef (Constants.HEAD); if (head == null) throw new InvalidOperationException ("No HEAD"); List<ObjectId> parents = new List<ObjectId>(); // determine the current HEAD and the commit it is referring to ObjectId headId = repo.Resolve (Constants.HEAD + "^{commit}"); if (headId != null) parents.Insert (0, headId); ObjectInserter odi = repo.NewObjectInserter (); try { List<string> filePaths = GetFilesInPaths (changeSet.Items.Select (i => i.LocalPath)); ObjectId indexTreeId = CreateCommitTree (filePaths); ObjectId commitId = GitUtil.CreateCommit (repo, message, parents, indexTreeId, author, committer); RevWalk revWalk = new RevWalk (repo); try { RevCommit revCommit = revWalk.ParseCommit (commitId); RefUpdate ru = repo.UpdateRef (Constants.HEAD); ru.SetNewObjectId (commitId); ru.SetRefLogMessage ("commit : " + revCommit.GetShortMessage (), false); ru.SetExpectedOldObjectId (headId); RefUpdate.Result rc = ru.Update (); switch (rc) { case RefUpdate.Result.NEW: case RefUpdate.Result.FAST_FORWARD: { Unstage (filePaths); if (state == RepositoryState.MERGING_RESOLVED) { // Commit was successful. Now delete the files // used for merge commits repo.WriteMergeCommitMsg (null); repo.WriteMergeHeads (null); } return; } case RefUpdate.Result.REJECTED: case RefUpdate.Result.LOCK_FAILURE: throw new ConcurrentRefUpdateException (JGitText.Get ().couldNotLockHEAD, ru.GetRef (), rc); default: throw new JGitInternalException ("Reference update failed"); } } finally { revWalk.Release (); } } finally { odi.Release (); } } catch (UnmergedPathException) { // since UnmergedPathException is a subclass of IOException // which should not be wrapped by a JGitInternalException we // have to catch and re-throw it here throw; } catch (IOException e) { throw new JGitInternalException (JGitText.Get ().exceptionCaughtDuringExecutionOfCommitCommand, e); } }
/// <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> /// on success the /// <see cref="NGit.Revwalk.RevCommit">NGit.Revwalk.RevCommit</see> /// pointed to by the new HEAD is /// returned. If a failure occurred during cherry-pick /// <code>null</code> is returned. The list of successfully /// cherry-picked /// <see cref="NGit.Ref">NGit.Ref</see> /// 's can be obtained by calling /// <see cref="GetCherryPickedRefs()">GetCherryPickedRefs()</see> /// </returns> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override RevCommit Call() { RevCommit newHead = null; 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(JGitText.Get().canOnlyCherryPickCommitsWithOneParent ); } RevCommit srcParent = srcCommit.GetParent(0); revWalk.ParseHeaders(srcParent); ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger (repo)); merger.SetWorkingTreeIterator(new FileTreeIterator(repo)); merger.SetBase(srcParent.Tree); 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() ).SetAuthor(srcCommit.GetAuthorIdent()).Call(); cherryPickedRefs.AddItem(src); } else { return(null); } } } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionCaughtDuringExecutionOfCherryPickCommand , e), e); } finally { revWalk.Release(); } return(newHead); }
/// <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.Errors.UnmergedPathException">when the current index contained unmerged paths (conflicts) /// </exception> /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">when repository is not in the right state for committing /// </exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"> /// a low-level exception of JGit has occurred. The original /// exception can be retrieved by calling /// <see cref="System.Exception.InnerException()">System.Exception.InnerException()</see> /// . Expect only /// <code>IOException's</code> /// to be wrapped. Subclasses of /// <see cref="System.IO.IOException">System.IO.IOException</see> /// (e.g. /// <see cref="NGit.Errors.UnmergedPathException">NGit.Errors.UnmergedPathException</see> /// ) are /// typically not wrapped here but thrown as original exception /// </exception> /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException"></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) { 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); } } else { parents.Add(0, headId); } } // lock the index DirCache index = repo.LockDirCache(); try { 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); // 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); ru.SetRefLogMessage("commit : " + revCommit.GetShortMessage(), false); ru.SetExpectedOldObjectId(headId); 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); } 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) { // since UnmergedPathException is a subclass of IOException // which should not be wrapped by a JGitInternalException we // have to catch and re-throw it here throw; } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfCommitCommand , e); } }
/// <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>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 { string mergeMessage = new MergeMessageFormatter().Format(commits, head); repo.WriteMergeCommitMsg(mergeMessage); 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; IList <string> unmergedPaths = null; if (merger is ResolveMerger) { ResolveMerger resolveMerger = (ResolveMerger)merger; resolveMerger.SetCommitNames(new string[] { "BASE", "HEAD", @ref.GetName() }); resolveMerger.SetWorkingTreeIterator(new FileTreeIterator(repo)); noProblems = merger.Merge(headCommit, srcCommit); lowLevelResults = resolveMerger.GetMergeResults(); failingPaths = resolveMerger.GetFailingPaths(); unmergedPaths = resolveMerger.GetUnmergedPaths(); } else { noProblems = merger.Merge(headCommit, srcCommit); } 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 , failingPaths, null)); } else { string mergeMessageWithConflicts = new MergeMessageFormatter().FormatWithConflicts (mergeMessage, unmergedPaths); repo.WriteMergeCommitMsg(mergeMessageWithConflicts); return(new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.CONFLICTING, mergeStrategy, lowLevelResults , null)); } } } } } catch (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(); } }
/// <exception cref="System.NotSupportedException"></exception> /// <exception cref="NGit.Errors.TransportException"></exception> private void ExecuteImp(ProgressMonitor monitor, FetchResult result) { conn = transport.OpenFetch(); try { result.SetAdvertisedRefs(transport.GetURI(), conn.GetRefsMap()); ICollection<Ref> matched = new HashSet<Ref>(); foreach (RefSpec spec in toFetch) { if (spec.GetSource() == null) { throw new TransportException(MessageFormat.Format(JGitText.Get().sourceRefNotSpecifiedForRefspec , spec)); } if (spec.IsWildcard()) { ExpandWildcard(spec, matched); } else { ExpandSingle(spec, matched); } } ICollection<Ref> additionalTags = Sharpen.Collections.EmptyList<Ref>(); TagOpt tagopt = transport.GetTagOpt(); if (tagopt == TagOpt.AUTO_FOLLOW) { additionalTags = ExpandAutoFollowTags(); } else { if (tagopt == TagOpt.FETCH_TAGS) { ExpandFetchTags(); } } bool includedTags; if (!askFor.IsEmpty() && !AskForIsComplete()) { FetchObjects(monitor); includedTags = conn.DidFetchIncludeTags(); // Connection was used for object transfer. If we // do another fetch we must open a new connection. // CloseConnection(result); } else { includedTags = false; } if (tagopt == TagOpt.AUTO_FOLLOW && !additionalTags.IsEmpty()) { // There are more tags that we want to follow, but // not all were asked for on the initial request. // Sharpen.Collections.AddAll(have, askFor.Keys); askFor.Clear(); foreach (Ref r in additionalTags) { ObjectId id = r.GetPeeledObjectId(); if (id == null) { id = r.GetObjectId(); } if (transport.local.HasObject(id)) { WantTag(r); } } if (!askFor.IsEmpty() && (!includedTags || !AskForIsComplete())) { ReopenConnection(); if (!askFor.IsEmpty()) { FetchObjects(monitor); } } } } finally { CloseConnection(result); } RevWalk walk = new RevWalk(transport.local); try { if (monitor is BatchingProgressMonitor) { ((BatchingProgressMonitor)monitor).SetDelayStart(250, TimeUnit.MILLISECONDS); } monitor.BeginTask(JGitText.Get().updatingReferences, localUpdates.Count); if (transport.IsRemoveDeletedRefs()) { DeleteStaleTrackingRefs(result, walk); } foreach (TrackingRefUpdate u in localUpdates) { try { monitor.Update(1); u.Update(walk); result.Add(u); } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingTrackingRef , u.GetLocalName(), err.Message), err); } } monitor.EndTask(); } finally { walk.Release(); } if (!fetchHeadUpdates.IsEmpty()) { try { UpdateFETCH_HEAD(result); } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingFETCH_HEAD , err.Message), err); } } }
// TODO not implemented yet // TODO not implemented yet /// <summary> /// Executes the /// <code>Reset</code> /// command. 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 Ref after reset</returns> /// <exception cref="System.IO.IOException"></exception> public override Ref Call() { CheckCallable(); Ref r; RevCommit commit; try { bool merging = false; if (repo.GetRepositoryState().Equals(RepositoryState.MERGING) || repo.GetRepositoryState ().Equals(RepositoryState.MERGING_RESOLVED)) { merging = true; } // resolve the ref to a commit ObjectId commitId; try { commitId = repo.Resolve(@ref); } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().cannotRead, @ref ), e); } RevWalk rw = new RevWalk(repo); try { commit = rw.ParseCommit(commitId); } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().cannotReadCommit , commitId.ToString()), e); } finally { rw.Release(); } // write the ref RefUpdate ru = repo.UpdateRef(Constants.HEAD); ru.SetNewObjectId(commitId); string refName = Repository.ShortenRefName(@ref); string message = "reset --" + mode.ToString().ToLower() + " " + refName; //$NON-NLS-1$ //$NON-NLS-1$ ru.SetRefLogMessage(message, false); if (ru.ForceUpdate() == RefUpdate.Result.LOCK_FAILURE) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().cannotLock, ru .GetName())); } switch (mode) { case ResetCommand.ResetType.HARD: { CheckoutIndex(commit); break; } case ResetCommand.ResetType.MIXED: { ResetIndex(commit); break; } case ResetCommand.ResetType.SOFT: { // do nothing, only the ref was changed break; } case ResetCommand.ResetType.KEEP: case ResetCommand.ResetType.MERGE: { // TODO // TODO throw new NotSupportedException(); } } if (mode != ResetCommand.ResetType.SOFT && merging) { ResetMerge(); } SetCallable(false); r = ru.GetRef(); } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfResetCommand , e); } return(r); }
public static MergeCommandResult CherryPick (NGit.Repository repo, RevCommit srcCommit) { RevCommit newHead = null; 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()); // get the parent of the commit to cherry-pick if (srcCommit.ParentCount != 1) { throw new MultipleParentsNotAllowedException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent ); } RevCommit srcParent = srcCommit.GetParent(0); revWalk.ParseHeaders(srcParent); return MergeTrees (repo, srcParent, srcCommit, srcCommit.Name, true); } catch (IOException e) { throw new Exception ("Commit failed", e); } finally { revWalk.Release(); } }
public static MergeCommandResult MergeTrees(NGit.ProgressMonitor monitor, NGit.Repository repo, RevCommit srcBase, RevCommit srcCommit, string sourceDisplayName, bool commitResult) { RevCommit newHead = null; 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()); ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger (repo)); merger.SetWorkingTreeIterator(new FileTreeIterator(repo)); merger.SetBase(srcBase); bool noProblems; IDictionary <string, MergeResult <NGit.Diff.Sequence> > lowLevelResults = null; IDictionary <string, ResolveMerger.MergeFailureReason> failingPaths = null; IList <string> modifiedFiles = null; ResolveMerger resolveMerger = (ResolveMerger)merger; resolveMerger.SetCommitNames(new string[] { "BASE", "HEAD", sourceDisplayName }); noProblems = merger.Merge(headCommit, srcCommit); lowLevelResults = resolveMerger.GetMergeResults(); modifiedFiles = resolveMerger.GetModifiedFiles(); failingPaths = resolveMerger.GetFailingPaths(); if (monitor != null) { monitor.Update(50); } if (noProblems) { if (modifiedFiles != null && modifiedFiles.Count == 0) { return(new MergeCommandResult(headCommit, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, MergeStatus.ALREADY_UP_TO_DATE, MergeStrategy.RESOLVE, null, null)); } DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache (), merger.GetResultTreeId()); dco.SetFailOnConflict(true); dco.Checkout(); if (commitResult) { newHead = new NGit.Api.Git(repo).Commit().SetMessage(srcCommit.GetFullMessage() ).SetAuthor(srcCommit.GetAuthorIdent()).Call(); return(new MergeCommandResult(newHead.Id, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, MergeStatus.MERGED, MergeStrategy.RESOLVE, null, null)); } else { return(new MergeCommandResult(headCommit, null, new ObjectId[] { headCommit.Id, srcCommit .Id }, MergeStatus.MERGED, MergeStrategy.RESOLVE, null, null)); } } else { if (failingPaths != null) { return(new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.FAILED, MergeStrategy.RESOLVE, lowLevelResults , failingPaths, null)); } else { return(new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { headCommit.Id, srcCommit.Id }, MergeStatus.CONFLICTING, MergeStrategy.RESOLVE, lowLevelResults , null)); } } } finally { revWalk.Release(); } }
private RevTree ParseTree(Repository repo, ObjectId id) { RevWalk rw = new RevWalk(repo); RevTree tree; try { tree = rw.LookupTree(id); } finally { rw.Release(); } return tree; }
/// <exception cref="System.NotSupportedException"></exception> /// <exception cref="NGit.Errors.TransportException"></exception> private void ExecuteImp(ProgressMonitor monitor, FetchResult result) { conn = transport.OpenFetch(); try { result.SetAdvertisedRefs(transport.GetURI(), conn.GetRefsMap()); ICollection<Ref> matched = new HashSet<Ref>(); foreach (RefSpec spec in toFetch) { if (spec.GetSource() == null) { throw new TransportException(MessageFormat.Format(JGitText.Get().sourceRefNotSpecifiedForRefspec , spec)); } if (spec.IsWildcard()) { ExpandWildcard(spec, matched); } else { ExpandSingle(spec, matched); } } ICollection<Ref> additionalTags = Sharpen.Collections.EmptyList<Ref>(); TagOpt tagopt = transport.GetTagOpt(); if (tagopt == TagOpt.AUTO_FOLLOW) { additionalTags = ExpandAutoFollowTags(); } else { if (tagopt == TagOpt.FETCH_TAGS) { ExpandFetchTags(); } } bool includedTags; if (!askFor.IsEmpty() && !AskForIsComplete()) { FetchObjects(monitor); includedTags = conn.DidFetchIncludeTags(); // Connection was used for object transfer. If we // do another fetch we must open a new connection. // CloseConnection(result); } else { includedTags = false; } if (tagopt == TagOpt.AUTO_FOLLOW && !additionalTags.IsEmpty()) { // There are more tags that we want to follow, but // not all were asked for on the initial request. // Sharpen.Collections.AddAll(have, askFor.Keys); askFor.Clear(); foreach (Ref r in additionalTags) { ObjectId id = r.GetPeeledObjectId(); if (id == null) { id = r.GetObjectId(); } if (transport.local.HasObject(id)) { WantTag(r); } } if (!askFor.IsEmpty() && (!includedTags || !AskForIsComplete())) { ReopenConnection(); if (!askFor.IsEmpty()) { FetchObjects(monitor); } } } } finally { CloseConnection(result); } BatchRefUpdate batch = transport.local.RefDatabase.NewBatchUpdate().SetAllowNonFastForwards (true).SetRefLogMessage("fetch", true); RevWalk walk = new RevWalk(transport.local); try { if (monitor is BatchingProgressMonitor) { ((BatchingProgressMonitor)monitor).SetDelayStart(250, TimeUnit.MILLISECONDS); } if (transport.IsRemoveDeletedRefs()) { DeleteStaleTrackingRefs(result, batch); } foreach (TrackingRefUpdate u in localUpdates) { result.Add(u); batch.AddCommand(u.AsReceiveCommand()); } foreach (ReceiveCommand cmd in batch.GetCommands()) { cmd.UpdateType(walk); if (cmd.GetType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD && cmd is TrackingRefUpdate.Command && !((TrackingRefUpdate.Command)cmd).CanForceUpdate()) { cmd.SetResult(ReceiveCommand.Result.REJECTED_NONFASTFORWARD); } } if (transport.IsDryRun()) { foreach (ReceiveCommand cmd_1 in batch.GetCommands()) { if (cmd_1.GetResult() == ReceiveCommand.Result.NOT_ATTEMPTED) { cmd_1.SetResult(ReceiveCommand.Result.OK); } } } else { batch.Execute(walk, monitor); } } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingTrackingRef , GetFirstFailedRefName(batch), err.Message), err); } finally { walk.Release(); } if (!fetchHeadUpdates.IsEmpty()) { try { UpdateFETCH_HEAD(result); } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingFETCH_HEAD , err.Message), err); } } }
/// <summary>Checks if a file with the given path exists in the HEAD tree</summary> /// <param name="path"></param> /// <returns>true if the file exists</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> private bool InHead(string path) { ObjectId headId = db.Resolve(Constants.HEAD); RevWalk rw = new RevWalk(db); TreeWalk tw = null; try { tw = TreeWalk.ForPath(db, path, rw.ParseTree(headId)); return tw != null; } finally { rw.Release(); rw.Dispose(); if (tw != null) { tw.Release(); } } }
// TODO not implemented yet // TODO not implemented yet /// <summary> /// Executes the /// <code>Reset</code> /// command. 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 Ref after reset</returns> /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException /// </exception> /// <exception cref="NGit.Api.Errors.CheckoutConflictException"></exception> public override Ref Call() { CheckCallable(); Ref r; RevCommit commit; try { RepositoryState state = repo.GetRepositoryState(); bool merging = state.Equals(RepositoryState.MERGING) || state.Equals(RepositoryState .MERGING_RESOLVED); bool cherryPicking = state.Equals(RepositoryState.CHERRY_PICKING) || state.Equals (RepositoryState.CHERRY_PICKING_RESOLVED); // resolve the ref to a commit ObjectId commitId; try { commitId = repo.Resolve(@ref + "^{commit}"); if (commitId == null) { // @TODO throw an InvalidRefNameException. We can't do that // now because this would break the API throw new JGitInternalException("Invalid ref " + @ref + " specified"); } } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().cannotRead, @ref ), e); } RevWalk rw = new RevWalk(repo); try { commit = rw.ParseCommit(commitId); } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().cannotReadCommit , commitId.ToString()), e); } finally { rw.Release(); } if (!filepaths.IsEmpty()) { // reset [commit] -- paths ResetIndexForPaths(commit); SetCallable(false); return(repo.GetRef(Constants.HEAD)); } // write the ref RefUpdate ru = repo.UpdateRef(Constants.HEAD); ru.SetNewObjectId(commitId); string refName = Repository.ShortenRefName(@ref); string message = refName + ": updating " + Constants.HEAD; //$NON-NLS-1$ ru.SetRefLogMessage(message, false); if (ru.ForceUpdate() == RefUpdate.Result.LOCK_FAILURE) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().cannotLock, ru .GetName())); } ObjectId origHead = ru.GetOldObjectId(); if (origHead != null) { repo.WriteOrigHead(origHead); } switch (mode) { case ResetCommand.ResetType.HARD: { CheckoutIndex(commit); break; } case ResetCommand.ResetType.MIXED: { ResetIndex(commit); break; } case ResetCommand.ResetType.SOFT: { // do nothing, only the ref was changed break; } case ResetCommand.ResetType.KEEP: case ResetCommand.ResetType.MERGE: { // TODO // TODO throw new NotSupportedException(); } } if (mode != ResetCommand.ResetType.SOFT) { if (merging) { ResetMerge(); } else { if (cherryPicking) { ResetCherryPick(); } else { if (repo.ReadSquashCommitMsg() != null) { repo.WriteSquashCommitMsg(null); } } } } SetCallable(false); r = ru.GetRef(); } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfResetCommand , e); } return(r); }
/// <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)); }
/// <exception cref="System.IO.IOException"></exception> private RebaseResult Abort(RebaseResult result) { try { string commitId = ReadFile(repo.Directory, Constants.ORIG_HEAD); monitor.BeginTask(MessageFormat.Format(JGitText.Get().abortingRebase, commitId), ProgressMonitor.UNKNOWN); DirCacheCheckout dco; RevCommit commit = walk.ParseCommit(repo.Resolve(commitId)); if (result.GetStatus().Equals(RebaseResult.Status.FAILED)) { RevCommit head = walk.ParseCommit(repo.Resolve(Constants.HEAD)); dco = new DirCacheCheckout(repo, head.Tree, repo.LockDirCache(), commit.Tree); } else { dco = new DirCacheCheckout(repo, repo.LockDirCache(), commit.Tree); } dco.SetFailOnConflict(false); dco.Checkout(); walk.Release(); } finally { monitor.EndTask(); } try { string headName = ReadFile(rebaseDir, HEAD_NAME); if (headName.StartsWith(Constants.R_REFS)) { monitor.BeginTask(MessageFormat.Format(JGitText.Get().resettingHead, headName), ProgressMonitor .UNKNOWN); // update the HEAD RefUpdate refUpdate = repo.UpdateRef(Constants.HEAD, false); RefUpdate.Result res = refUpdate.Link(headName); switch (res) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { throw new JGitInternalException(JGitText.Get().abortingRebaseFailed); } } } // cleanup the files FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE); repo.WriteCherryPickHead(null); return(result); } finally { monitor.EndTask(); } }
/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> private RevCommit ParseCommit(AnyObjectId id) { RevWalk rw = new RevWalk(db); try { return rw.ParseCommit(id); } finally { rw.Release(); } }
/// <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().refAlreadyExists , 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.Split("/", 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(); } }
/// <exception cref="System.InvalidOperationException"></exception> /// <exception cref="System.IO.IOException"></exception> protected internal virtual void CheckoutBranch(string branchName) { RevWalk walk = new RevWalk(db); RevCommit head = walk.ParseCommit(db.Resolve(Constants.HEAD)); RevCommit branch = walk.ParseCommit(db.Resolve(branchName)); DirCacheCheckout dco = new DirCacheCheckout(db, head.Tree.Id, db.LockDirCache(), branch.Tree.Id); dco.SetFailOnConflict(true); dco.Checkout(); walk.Release(); // update the HEAD RefUpdate refUpdate = db.UpdateRef(Constants.HEAD); refUpdate.Link(branchName); }
/// <exception cref="System.NotSupportedException"></exception> /// <exception cref="NGit.Errors.TransportException"></exception> private void ExecuteImp(ProgressMonitor monitor, FetchResult result) { conn = transport.OpenFetch(); try { result.SetAdvertisedRefs(transport.GetURI(), conn.GetRefsMap()); ICollection <Ref> matched = new HashSet <Ref>(); foreach (RefSpec spec in toFetch) { if (spec.GetSource() == null) { throw new TransportException(MessageFormat.Format(JGitText.Get().sourceRefNotSpecifiedForRefspec , spec)); } if (spec.IsWildcard()) { ExpandWildcard(spec, matched); } else { ExpandSingle(spec, matched); } } ICollection <Ref> additionalTags = Sharpen.Collections.EmptyList <Ref>(); TagOpt tagopt = transport.GetTagOpt(); if (tagopt == TagOpt.AUTO_FOLLOW) { additionalTags = ExpandAutoFollowTags(); } else { if (tagopt == TagOpt.FETCH_TAGS) { ExpandFetchTags(); } } bool includedTags; if (!askFor.IsEmpty() && !AskForIsComplete()) { FetchObjects(monitor); includedTags = conn.DidFetchIncludeTags(); // Connection was used for object transfer. If we // do another fetch we must open a new connection. // CloseConnection(result); } else { includedTags = false; } if (tagopt == TagOpt.AUTO_FOLLOW && !additionalTags.IsEmpty()) { // There are more tags that we want to follow, but // not all were asked for on the initial request. // Sharpen.Collections.AddAll(have, askFor.Keys); askFor.Clear(); foreach (Ref r in additionalTags) { ObjectId id = r.GetPeeledObjectId(); if (id == null) { id = r.GetObjectId(); } if (transport.local.HasObject(id)) { WantTag(r); } } if (!askFor.IsEmpty() && (!includedTags || !AskForIsComplete())) { ReopenConnection(); if (!askFor.IsEmpty()) { FetchObjects(monitor); } } } } finally { CloseConnection(result); } BatchRefUpdate batch = transport.local.RefDatabase.NewBatchUpdate().SetAllowNonFastForwards (true).SetRefLogMessage("fetch", true); RevWalk walk = new RevWalk(transport.local); try { if (monitor is BatchingProgressMonitor) { ((BatchingProgressMonitor)monitor).SetDelayStart(250, TimeUnit.MILLISECONDS); } if (transport.IsRemoveDeletedRefs()) { DeleteStaleTrackingRefs(result, batch); } foreach (TrackingRefUpdate u in localUpdates) { result.Add(u); batch.AddCommand(u.AsReceiveCommand()); } foreach (ReceiveCommand cmd in batch.GetCommands()) { cmd.UpdateType(walk); if (cmd.GetType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD && cmd is TrackingRefUpdate.Command && !((TrackingRefUpdate.Command)cmd).CanForceUpdate()) { cmd.SetResult(ReceiveCommand.Result.REJECTED_NONFASTFORWARD); } } if (transport.IsDryRun()) { foreach (ReceiveCommand cmd_1 in batch.GetCommands()) { if (cmd_1.GetResult() == ReceiveCommand.Result.NOT_ATTEMPTED) { cmd_1.SetResult(ReceiveCommand.Result.OK); } } } else { batch.Execute(walk, monitor); } } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingTrackingRef , GetFirstFailedRefName(batch), err.Message), err); } finally { walk.Release(); } if (!fetchHeadUpdates.IsEmpty()) { try { UpdateFETCH_HEAD(result); } catch (IOException err) { throw new TransportException(MessageFormat.Format(JGitText.Get().failureUpdatingFETCH_HEAD , err.Message), err); } } }