ObjectId WriteWorkingDirectoryTree(RevTree headTree, DirCache index) { DirCache dc = DirCache.NewInCore(); DirCacheBuilder cb = dc.Builder(); ObjectInserter oi = _repo.NewObjectInserter(); try { TreeWalk tw = new TreeWalk(_repo); tw.Reset(); tw.AddTree(new FileTreeIterator(_repo)); tw.AddTree(headTree); tw.AddTree(new DirCacheIterator(index)); while (tw.Next()) { // Ignore untracked files if (tw.IsSubtree) { tw.EnterSubtree(); } else if (tw.GetFileMode(0) != NGit.FileMode.MISSING && (tw.GetFileMode(1) != NGit.FileMode.MISSING || tw.GetFileMode(2) != NGit.FileMode.MISSING)) { WorkingTreeIterator f = tw.GetTree <WorkingTreeIterator>(0); DirCacheIterator dcIter = tw.GetTree <DirCacheIterator>(2); DirCacheEntry currentEntry = dcIter.GetDirCacheEntry(); DirCacheEntry ce = new DirCacheEntry(tw.PathString); if (!f.IsModified(currentEntry, true)) { ce.SetLength(currentEntry.Length); ce.LastModified = currentEntry.LastModified; ce.FileMode = currentEntry.FileMode; ce.SetObjectId(currentEntry.GetObjectId()); } else { long sz = f.GetEntryLength(); ce.SetLength(sz); ce.LastModified = f.GetEntryLastModified(); ce.FileMode = f.EntryFileMode; var data = f.OpenEntryStream(); try { ce.SetObjectId(oi.Insert(Constants.OBJ_BLOB, sz, data)); } finally { data.Close(); } } cb.Add(ce); } } cb.Finish(); return(dc.WriteTree(oi)); } finally { oi.Release(); } }
public Stash Create(string message) { UserConfig config = _repo.GetConfig().Get(UserConfig.KEY); RevWalk rw = new RevWalk(_repo); ObjectId headId = _repo.Resolve(Constants.HEAD); var parent = rw.ParseCommit(headId); PersonIdent author = new PersonIdent(config.GetAuthorName() ?? "unknown", config.GetAuthorEmail() ?? "unknown@(none)."); if (string.IsNullOrEmpty(message)) { // Use the commit summary as message message = parent.Abbreviate(7).ToString() + " " + parent.GetShortMessage(); int i = message.IndexOfAny(new char[] { '\r', '\n' }); if (i != -1) { message = message.Substring(0, i); } } // Create the index tree commit ObjectInserter inserter = _repo.NewObjectInserter(); DirCache dc = _repo.ReadDirCache(); var tree_id = dc.WriteTree(inserter); inserter.Release(); string commitMsg = "index on " + _repo.GetBranch() + ": " + message; ObjectId indexCommit = GitUtil.CreateCommit(_repo, commitMsg + "\n", new ObjectId[] { headId }, tree_id, author, author); // Create the working dir commit tree_id = WriteWorkingDirectoryTree(parent.Tree, dc); commitMsg = "WIP on " + _repo.GetBranch() + ": " + message; var wipCommit = GitUtil.CreateCommit(_repo, commitMsg + "\n", new ObjectId[] { headId, indexCommit }, tree_id, author, author); string prevCommit = null; FileInfo sf = StashRefFile; if (sf.Exists) { prevCommit = File.ReadAllText(sf.FullName).Trim(' ', '\t', '\r', '\n'); } Stash s = new Stash(prevCommit, wipCommit.Name, author, commitMsg); FileInfo stashLog = StashLogFile; File.AppendAllText(stashLog.FullName, s.FullLine + "\n"); File.WriteAllText(sf.FullName, s.CommitId + "\n"); // Wipe all local changes GitUtil.HardReset(_repo, Constants.HEAD); s.StashCollection = this; return(s); }
public virtual void TestRecursiveFiltering() { ObjectInserter odi = db.NewObjectInserter(); ObjectId aSth = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString( "a.sth")); ObjectId aTxt = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString( "a.txt")); ObjectId bSth = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString( "b.sth")); ObjectId bTxt = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString( "b.txt")); DirCache dc = db.ReadDirCache(); DirCacheBuilder builder = dc.Builder(); DirCacheEntry aSthEntry = new DirCacheEntry("a.sth"); aSthEntry.FileMode = FileMode.REGULAR_FILE; aSthEntry.SetObjectId(aSth); DirCacheEntry aTxtEntry = new DirCacheEntry("a.txt"); aTxtEntry.FileMode = FileMode.REGULAR_FILE; aTxtEntry.SetObjectId(aTxt); builder.Add(aSthEntry); builder.Add(aTxtEntry); DirCacheEntry bSthEntry = new DirCacheEntry("sub/b.sth"); bSthEntry.FileMode = FileMode.REGULAR_FILE; bSthEntry.SetObjectId(bSth); DirCacheEntry bTxtEntry = new DirCacheEntry("sub/b.txt"); bTxtEntry.FileMode = FileMode.REGULAR_FILE; bTxtEntry.SetObjectId(bTxt); builder.Add(bSthEntry); builder.Add(bTxtEntry); builder.Finish(); ObjectId treeId = dc.WriteTree(odi); odi.Flush(); TreeWalk tw = new TreeWalk(db); tw.Recursive = true; tw.Filter = PathSuffixFilter.Create(".txt"); tw.AddTree(treeId); IList <string> paths = new List <string>(); while (tw.Next()) { paths.AddItem(tw.PathString); } IList <string> expected = new List <string>(); expected.AddItem("a.txt"); expected.AddItem("sub/b.txt"); NUnit.Framework.Assert.AreEqual(expected, paths); }
/// <exception cref="System.Exception"></exception> private ObjectId Commit(ObjectInserter odi, DirCache treeB, ObjectId[] parentIds) { NGit.CommitBuilder c = new NGit.CommitBuilder(); c.TreeId = treeB.WriteTree(odi); c.Author = new PersonIdent("A U Thor", "a.u.thor", 1L, 0); c.Committer = c.Author; c.SetParentIds(parentIds); c.Message = "Tree " + c.TreeId.Name; ObjectId id = odi.Insert(c); odi.Flush(); return(id); }
/// <exception cref="System.IO.IOException"></exception> private ObjectId BuildTree(Dictionary <string, string> headEntries) { DirCache lockDirCache = DirCache.NewInCore(); // assertTrue(lockDirCache.lock()); DirCacheEditor editor = lockDirCache.Editor(); if (headEntries != null) { foreach (KeyValuePair <string, string> e in headEntries.EntrySet()) { DirCacheCheckoutTest.AddEdit addEdit = new DirCacheCheckoutTest.AddEdit(e.Key, GenSha1 (e.Value), e.Value.Length); editor.Add(addEdit); } } editor.Finish(); return(lockDirCache.WriteTree(db.NewObjectInserter())); }
/// <exception cref="System.IO.IOException"></exception> protected internal override bool MergeImpl() { tw.AddTree(MergeBase()); tw.AddTree(sourceTrees[0]); tw.AddTree(sourceTrees[1]); bool hasConflict = false; builder = cache.Builder(); while (tw.Next()) { int modeO = tw.GetRawMode(T_OURS); int modeT = tw.GetRawMode(T_THEIRS); if (modeO == modeT && tw.IdEqual(T_OURS, T_THEIRS)) { Add(T_OURS, DirCacheEntry.STAGE_0); continue; } int modeB = tw.GetRawMode(T_BASE); if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS)) { Add(T_THEIRS, DirCacheEntry.STAGE_0); } else { if (modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS)) { Add(T_OURS, DirCacheEntry.STAGE_0); } else { if (NonTree(modeB)) { Add(T_BASE, DirCacheEntry.STAGE_1); hasConflict = true; } if (NonTree(modeO)) { Add(T_OURS, DirCacheEntry.STAGE_2); hasConflict = true; } if (NonTree(modeT)) { Add(T_THEIRS, DirCacheEntry.STAGE_3); hasConflict = true; } if (tw.IsSubtree) { tw.EnterSubtree(); } } } } builder.Finish(); builder = null; if (hasConflict) { return(false); } try { ObjectInserter odi = GetObjectInserter(); resultTree = cache.WriteTree(odi); odi.Flush(); return(true); } catch (UnmergedPathException) { resultTree = null; return(false); } }
/// <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); } }
/// <exception cref="System.IO.IOException"></exception> protected internal override bool MergeImpl() { bool implicitDirCache = false; if (dircache == null) { dircache = GetRepository().LockDirCache(); implicitDirCache = true; } try { builder = dircache.Builder(); DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder); tw = new NameConflictTreeWalk(db); tw.AddTree(MergeBase()); tw.AddTree(sourceTrees[0]); tw.AddTree(sourceTrees[1]); tw.AddTree(buildIt); if (workingTreeIterator != null) { tw.AddTree(workingTreeIterator); } while (tw.Next()) { if (!ProcessEntry(tw.GetTree <CanonicalTreeParser>(T_BASE), tw.GetTree <CanonicalTreeParser >(T_OURS), tw.GetTree <CanonicalTreeParser>(T_THEIRS), tw.GetTree <DirCacheBuildIterator >(T_INDEX), (workingTreeIterator == null) ? null : tw.GetTree <WorkingTreeIterator >(T_FILE))) { CleanUp(); return(false); } if (tw.IsSubtree && enterSubtree) { tw.EnterSubtree(); } } if (!inCore) { // All content-merges are successfully done. If we can now write the // new index we are on quite safe ground. Even if the checkout of // files coming from "theirs" fails the user can work around such // failures by checking out the index again. if (!builder.Commit()) { CleanUp(); throw new IndexWriteException(); } builder = null; // No problem found. The only thing left to be done is to checkout // all files from "theirs" which have been selected to go into the // new index. Checkout(); } else { builder.Finish(); builder = null; } if (GetUnmergedPaths().IsEmpty()) { resultTree = dircache.WriteTree(oi); return(true); } else { resultTree = null; return(false); } } finally { if (implicitDirCache) { dircache.Unlock(); } } }
/// <exception cref="System.Exception"></exception> private ObjectId Commit(ObjectInserter odi, DirCache treeB, ObjectId[] parentIds) { NGit.CommitBuilder c = new NGit.CommitBuilder(); c.TreeId = treeB.WriteTree(odi); c.Author = new PersonIdent("A U Thor", "a.u.thor", 1L, 0); c.Committer = c.Author; c.SetParentIds(parentIds); c.Message = "Tree " + c.TreeId.Name; ObjectId id = odi.Insert(c); odi.Flush(); return id; }
/// <summary> /// Stash the contents on the working directory and index in separate commits /// and reset to the current HEAD commit. /// </summary> /// <remarks> /// Stash the contents on the working directory and index in separate commits /// and reset to the current HEAD commit. /// </remarks> /// <returns>stashed commit or null if no changes to stash</returns> /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException /// </exception> public override RevCommit Call() { CheckCallable(); Ref head = GetHead(); ObjectReader reader = repo.NewObjectReader(); try { RevCommit headCommit = ParseCommit(reader, head.GetObjectId()); DirCache cache = repo.LockDirCache(); ObjectInserter inserter = repo.NewObjectInserter(); ObjectId commitId; try { TreeWalk treeWalk = new TreeWalk(reader); treeWalk.Recursive = true; treeWalk.AddTree(headCommit.Tree); treeWalk.AddTree(new DirCacheIterator(cache)); treeWalk.AddTree(new FileTreeIterator(repo)); treeWalk.Filter = AndTreeFilter.Create(new SkipWorkTreeFilter(1), new IndexDiffFilter (1, 2)); // Return null if no local changes to stash if (!treeWalk.Next()) { return(null); } MutableObjectId id = new MutableObjectId(); IList <DirCacheEditor.PathEdit> wtEdits = new AList <DirCacheEditor.PathEdit>(); IList <string> wtDeletes = new AList <string>(); do { AbstractTreeIterator headIter = treeWalk.GetTree <AbstractTreeIterator>(0); DirCacheIterator indexIter = treeWalk.GetTree <DirCacheIterator>(1); WorkingTreeIterator wtIter = treeWalk.GetTree <WorkingTreeIterator>(2); if (headIter != null && indexIter != null && wtIter != null) { if (!indexIter.GetDirCacheEntry().IsMerged()) { throw new UnmergedPathsException(new UnmergedPathException(indexIter.GetDirCacheEntry ())); } if (wtIter.IdEqual(indexIter) || wtIter.IdEqual(headIter)) { continue; } treeWalk.GetObjectId(id, 0); DirCacheEntry entry = new DirCacheEntry(treeWalk.RawPath); entry.SetLength(wtIter.GetEntryLength()); entry.LastModified = wtIter.GetEntryLastModified(); entry.FileMode = wtIter.EntryFileMode; long contentLength = wtIter.GetEntryContentLength(); InputStream @in = wtIter.OpenEntryStream(); try { entry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, contentLength, @in)); } finally { @in.Close(); } wtEdits.AddItem(new _PathEdit_273(entry, entry)); } else { if (indexIter == null) { wtDeletes.AddItem(treeWalk.PathString); } else { if (wtIter == null && headIter != null) { wtDeletes.AddItem(treeWalk.PathString); } } } }while (treeWalk.Next()); string branch = Repository.ShortenRefName(head.GetTarget().GetName()); // Commit index changes NGit.CommitBuilder builder = CreateBuilder(headCommit); builder.TreeId = cache.WriteTree(inserter); builder.Message = MessageFormat.Format(indexMessage, branch, headCommit.Abbreviate (7).Name, headCommit.GetShortMessage()); ObjectId indexCommit = inserter.Insert(builder); // Commit working tree changes if (!wtEdits.IsEmpty() || !wtDeletes.IsEmpty()) { DirCacheEditor editor = cache.Editor(); foreach (DirCacheEditor.PathEdit edit in wtEdits) { editor.Add(edit); } foreach (string path in wtDeletes) { editor.Add(new DirCacheEditor.DeletePath(path)); } editor.Finish(); } builder.AddParentId(indexCommit); builder.Message = MessageFormat.Format(workingDirectoryMessage, branch, headCommit .Abbreviate(7).Name, headCommit.GetShortMessage()); builder.TreeId = cache.WriteTree(inserter); commitId = inserter.Insert(builder); inserter.Flush(); UpdateStashRef(commitId, builder.Author, builder.Message); } finally { inserter.Release(); cache.Unlock(); } // Hard reset to HEAD new ResetCommand(repo).SetMode(ResetCommand.ResetType.HARD).Call(); // Return stashed commit return(ParseCommit(reader, commitId)); } catch (IOException e) { throw new JGitInternalException(JGitText.Get().stashFailed, e); } finally { reader.Release(); } }
public virtual void TestFindObjects() { DirCache tree0 = DirCache.NewInCore(); DirCacheBuilder b0 = tree0.Builder(); ObjectReader or = db.NewObjectReader(); ObjectInserter oi = db.NewObjectInserter(); DirCacheEntry aDotB = MakeEntry("a.b", EXECUTABLE_FILE); b0.Add(aDotB); DirCacheEntry aSlashB = MakeEntry("a/b", REGULAR_FILE); b0.Add(aSlashB); DirCacheEntry aSlashCSlashD = MakeEntry("a/c/d", REGULAR_FILE); b0.Add(aSlashCSlashD); DirCacheEntry aZeroB = MakeEntry("a0b", SYMLINK); b0.Add(aZeroB); b0.Finish(); NUnit.Framework.Assert.AreEqual(4, tree0.GetEntryCount()); ObjectId tree = tree0.WriteTree(oi); // Find the directories that were implicitly created above. TreeWalk tw = new TreeWalk(or); tw.AddTree(tree); ObjectId a = null; ObjectId aSlashC = null; while (tw.Next()) { if (tw.PathString.Equals("a")) { a = tw.GetObjectId(0); tw.EnterSubtree(); while (tw.Next()) { if (tw.PathString.Equals("a/c")) { aSlashC = tw.GetObjectId(0); break; } } break; } } NUnit.Framework.Assert.AreEqual(a, TreeWalk.ForPath(or, "a", tree).GetObjectId(0) ); NUnit.Framework.Assert.AreEqual(a, TreeWalk.ForPath(or, "a/", tree).GetObjectId(0 )); NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a", tree)); NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a/", tree)); NUnit.Framework.Assert.AreEqual(aDotB.GetObjectId(), TreeWalk.ForPath(or, "a.b", tree).GetObjectId(0)); NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a.b", tree)); NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a.b/", tree)); NUnit.Framework.Assert.AreEqual(aDotB.GetObjectId(), TreeWalk.ForPath(or, "a.b/", tree).GetObjectId(0)); NUnit.Framework.Assert.AreEqual(aZeroB.GetObjectId(), TreeWalk.ForPath(or, "a0b", tree).GetObjectId(0)); NUnit.Framework.Assert.AreEqual(aSlashB.GetObjectId(), TreeWalk.ForPath(or, "a/b" , tree).GetObjectId(0)); NUnit.Framework.Assert.AreEqual(aSlashB.GetObjectId(), TreeWalk.ForPath(or, "b", a).GetObjectId(0)); NUnit.Framework.Assert.AreEqual(aSlashC, TreeWalk.ForPath(or, "a/c", tree).GetObjectId (0)); NUnit.Framework.Assert.AreEqual(aSlashC, TreeWalk.ForPath(or, "c", a).GetObjectId (0)); NUnit.Framework.Assert.AreEqual(aSlashCSlashD.GetObjectId(), TreeWalk.ForPath(or, "a/c/d", tree).GetObjectId(0)); NUnit.Framework.Assert.AreEqual(aSlashCSlashD.GetObjectId(), TreeWalk.ForPath(or, "c/d", a).GetObjectId(0)); or.Release(); oi.Release(); }