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(); } }
/// <summary> /// Executes the /// <code>Add</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 DirCache after Add</returns> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> /// <exception cref="NGit.Api.Errors.NoFilepatternException"></exception> public override DirCache Call() { if (filepatterns.IsEmpty()) { throw new NoFilepatternException(JGitText.Get().atLeastOnePatternIsRequired); } CheckCallable(); DirCache dc = null; bool addAll = false; if (filepatterns.Contains(".")) { addAll = true; } ObjectInserter inserter = repo.NewObjectInserter(); try { dc = repo.LockDirCache(); DirCacheIterator c; DirCacheBuilder builder = dc.Builder(); TreeWalk tw = new TreeWalk(repo); tw.AddTree(new DirCacheBuildIterator(builder)); if (workingTreeIterator == null) { workingTreeIterator = new FileTreeIterator(repo); } tw.AddTree(workingTreeIterator); tw.Recursive = true; if (!addAll) { tw.Filter = PathFilterGroup.CreateFromStrings(filepatterns); } string lastAddedFile = null; while (tw.Next()) { string path = tw.PathString; WorkingTreeIterator f = tw.GetTree <WorkingTreeIterator>(1); if (tw.GetTree <DirCacheIterator>(0) == null && f != null && f.IsEntryIgnored()) { } else { // file is not in index but is ignored, do nothing // In case of an existing merge conflict the // DirCacheBuildIterator iterates over all stages of // this path, we however want to add only one // new DirCacheEntry per path. if (!(path.Equals(lastAddedFile))) { if (!(update && tw.GetTree <DirCacheIterator>(0) == null)) { c = tw.GetTree <DirCacheIterator>(0); if (f != null) { // the file exists long sz = f.GetEntryLength(); DirCacheEntry entry = new DirCacheEntry(path); if (c == null || c.GetDirCacheEntry() == null || !c.GetDirCacheEntry().IsAssumeValid) { FileMode mode = f.GetIndexFileMode(c); entry.FileMode = mode; if (FileMode.GITLINK != mode) { entry.SetLength(sz); entry.LastModified = f.GetEntryLastModified(); long contentSize = f.GetEntryContentLength(); InputStream @in = f.OpenEntryStream(); try { entry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, contentSize, @in)); } finally { @in.Close(); } } else { entry.SetObjectId(f.EntryObjectId); } builder.Add(entry); lastAddedFile = path; } else { builder.Add(c.GetDirCacheEntry()); } } else { if (c != null && (!update || FileMode.GITLINK == c.EntryFileMode)) { builder.Add(c.GetDirCacheEntry()); } } } } } } inserter.Flush(); builder.Commit(); SetCallable(false); } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfAddCommand , e); } finally { inserter.Release(); if (dc != null) { dc.Unlock(); } } return(dc); }
/// <exception cref="System.IO.IOException"></exception> public override long Size(string path, ObjectId id) { Seek(path); return(ptr.GetEntryLength()); }
/// <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(); } }