public virtual void SubmoduleWithNoHead() { Git git = new Git(db); WriteTrashFile("file.txt", "content"); git.Add().AddFilepattern("file.txt").Call(); RevCommit id = git.Commit().SetMessage("create file").Call(); string path = "sub"; DirCache cache = db.LockDirCache(); DirCacheEditor editor = cache.Editor(); editor.Add(new _PathEdit_345(id, path)); editor.Commit(); NUnit.Framework.Assert.IsNotNull(Git.Init().SetDirectory(new FilePath(db.WorkTree , path)).Call().GetRepository()); TreeWalk walk = new TreeWalk(db); DirCacheIterator indexIter = new DirCacheIterator(db.ReadDirCache()); FileTreeIterator workTreeIter = new FileTreeIterator(db); walk.AddTree(indexIter); walk.AddTree(workTreeIter); walk.Filter = PathFilter.Create(path); NUnit.Framework.Assert.IsTrue(walk.Next()); NUnit.Framework.Assert.IsFalse(indexIter.IdEqual(workTreeIter)); NUnit.Framework.Assert.AreEqual(ObjectId.ZeroId, workTreeIter.EntryObjectId); }
public virtual void SubmoduleNestedWithHeadMatchingIndex() { Git git = new Git(db); WriteTrashFile("file.txt", "content"); git.Add().AddFilepattern("file.txt").Call(); RevCommit id = git.Commit().SetMessage("create file").Call(); string path = "sub/dir1/dir2"; DirCache cache = db.LockDirCache(); DirCacheEditor editor = cache.Editor(); editor.Add(new _PathEdit_412(id, path)); editor.Commit(); Git.CloneRepository().SetURI(db.Directory.ToURI().ToString()).SetDirectory(new FilePath (db.WorkTree, path)).Call().GetRepository().Close(); TreeWalk walk = new TreeWalk(db); DirCacheIterator indexIter = new DirCacheIterator(db.ReadDirCache()); FileTreeIterator workTreeIter = new FileTreeIterator(db); walk.AddTree(indexIter); walk.AddTree(workTreeIter); walk.Filter = PathFilter.Create(path); NUnit.Framework.Assert.IsTrue(walk.Next()); NUnit.Framework.Assert.IsTrue(indexIter.IdEqual(workTreeIter)); }
public void testNoSubtree_NoTreeWalk() { DirCache dc = DirCache.read(db); string[] paths = { "a.", "a0b" }; var ents = new DirCacheEntry[paths.Length]; for (int i = 0; i < paths.Length; i++) { ents[i] = new DirCacheEntry(paths[i]); ents[i].setFileMode(FileMode.RegularFile); } DirCacheBuilder b = dc.builder(); for (int i = 0; i < ents.Length; i++) { b.add(ents[i]); } b.finish(); var iter = new DirCacheIterator(dc); int pathIdx = 0; for (; !iter.eof(); iter.next(1)) { Assert.AreEqual(pathIdx, iter.Pointer); Assert.AreSame(ents[pathIdx], iter.getDirCacheEntry()); pathIdx++; } Assert.AreEqual(paths.Length, pathIdx); }
public virtual void TestDirCacheMatchingId() { FilePath f = WriteTrashFile("file", "content"); Git git = new Git(db); WriteTrashFile("file", "content"); FsTick(f); git.Add().AddFilepattern("file").Call(); DirCacheEntry dce = db.ReadDirCache().GetEntry("file"); TreeWalk tw = new TreeWalk(db); FileTreeIterator fti = new FileTreeIterator(trash, db.FileSystem, ((FileBasedConfig )db.GetConfig()).Get(WorkingTreeOptions.KEY)); tw.AddTree(fti); DirCacheIterator dci = new DirCacheIterator(db.ReadDirCache()); tw.AddTree(dci); fti.SetDirCacheIterator(tw, 1); while (tw.Next() && !tw.PathString.Equals("file")) { } // NUnit.Framework.Assert.AreEqual(WorkingTreeIterator.MetadataDiff.EQUAL, fti.CompareMetadata (dce)); ObjectId fromRaw = ObjectId.FromRaw(fti.IdBuffer, fti.IdOffset); NUnit.Framework.Assert.AreEqual("6b584e8ece562ebffc15d38808cd6b98fc3d97ea", fromRaw .GetName()); NUnit.Framework.Assert.IsFalse(fti.IsModified(dce, false)); }
public virtual void TestDiff() { Write(new FilePath(db.Directory.GetParent(), "test.txt"), "test"); FilePath folder = new FilePath(db.Directory.GetParent(), "folder"); folder.Mkdir(); Write(new FilePath(folder, "folder.txt"), "folder"); Git git = new Git(db); git.Add().AddFilepattern(".").Call(); git.Commit().SetMessage("Initial commit").Call(); Write(new FilePath(folder, "folder.txt"), "folder change"); ByteArrayOutputStream os = new ByteArrayOutputStream(); DiffFormatter df = new DiffFormatter(new SafeBufferedOutputStream(os)); df.SetRepository(db); df.SetPathFilter(PathFilter.Create("folder")); DirCacheIterator oldTree = new DirCacheIterator(db.ReadDirCache()); FileTreeIterator newTree = new FileTreeIterator(db); df.Format(oldTree, newTree); df.Flush(); string actual = System.Text.Encoding.UTF8.GetString(os.ToByteArray()); string expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n" + "index 0119635..95c4c65 100644\n" + "--- a/folder/folder.txt\n" + "+++ b/folder/folder.txt\n" + "@@ -1 +1 @@\n" + "-folder\n" + "\\ No newline at end of file\n" + "+folder change\n" + "\\ No newline at end of file\n"; NUnit.Framework.Assert.AreEqual(expected.ToString(), actual); }
public virtual void IdOffset() { Git git = new Git(db); WriteTrashFile("fileAinfsonly", "A"); FilePath fileBinindex = WriteTrashFile("fileBinindex", "B"); FsTick(fileBinindex); git.Add().AddFilepattern("fileBinindex").Call(); WriteTrashFile("fileCinfsonly", "C"); TreeWalk tw = new TreeWalk(db); DirCacheIterator indexIter = new DirCacheIterator(db.ReadDirCache()); FileTreeIterator workTreeIter = new FileTreeIterator(db); tw.AddTree(indexIter); tw.AddTree(workTreeIter); workTreeIter.SetDirCacheIterator(tw, 0); AssertEntry("d46c305e85b630558ee19cc47e73d2e5c8c64cdc", "a,", tw); AssertEntry("58ee403f98538ec02409538b3f80adf610accdec", "a,b", tw); AssertEntry("0000000000000000000000000000000000000000", "a", tw); AssertEntry("b8d30ff397626f0f1d3538d66067edf865e201d6", "a0b", tw); // The reason for adding this test. Check that the id is correct for // mixed AssertEntry("8c7e5a667f1b771847fe88c01c3de34413a1b220", "fileAinfsonly", tw); AssertEntry("7371f47a6f8bd23a8fa1a8b2a9479cdd76380e54", "fileBinindex", tw); AssertEntry("96d80cd6c4e7158dbebd0849f4fb7ce513e5828c", "fileCinfsonly", tw); NUnit.Framework.Assert.IsFalse(tw.Next()); }
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 void testEmptyTree_NoTreeWalk() { DirCache dc = DirCache.read(db); Assert.AreEqual(0, dc.getEntryCount()); var i = new DirCacheIterator(dc); Assert.IsTrue(i.eof()); }
public void testSingleSubtree_NoRecursion() { DirCache dc = DirCache.read(db); string[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; var ents = new DirCacheEntry[paths.Length]; for (int i = 0; i < paths.Length; i++) { ents[i] = new DirCacheEntry(paths[i]); ents[i].setFileMode(FileMode.RegularFile); } DirCacheBuilder b = dc.builder(); for (int i = 0; i < ents.Length; i++) { b.add(ents[i]); } b.finish(); string[] expPaths = { "a.", "a", "a0b" }; FileMode[] expModes = { FileMode.RegularFile, FileMode.Tree, FileMode.RegularFile }; var expPos = new[] { 0, -1, 4 }; var iter = new DirCacheIterator(dc); var tw = new TreeWalk(db); tw.reset(); tw.addTree(iter); tw.Recursive = false; int pathIdx = 0; while (tw.next()) { Assert.AreSame(iter, tw.getTree <DirCacheIterator>(0, typeof(DirCacheIterator))); Assert.AreEqual(expModes[pathIdx].Bits, tw.getRawMode(0)); Assert.AreSame(expModes[pathIdx], tw.getFileMode(0)); Assert.AreEqual(expPaths[pathIdx], tw.getPathString()); if (expPos[pathIdx] >= 0) { Assert.AreEqual(expPos[pathIdx], iter.Pointer); Assert.AreSame(ents[expPos[pathIdx]], iter.getDirCacheEntry()); } else { Assert.AreSame(FileMode.Tree, tw.getFileMode(0)); } pathIdx++; } Assert.AreEqual(expPaths.Length, pathIdx); }
public override bool Include(TreeWalk walker) { DirCacheIterator i = walker.GetTree <DirCacheIterator>(treeIdx); if (i == null) { return(true); } DirCacheEntry e = i.GetDirCacheEntry(); return(e == null || !e.IsSkipWorkTree); }
public void testSingleSubtree_Recursive() { DirCache dc = DirCache.read(db); FileMode mode = FileMode.RegularFile; string[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; var ents = new DirCacheEntry[paths.Length]; for (int i = 0; i < paths.Length; i++) { ents[i] = new DirCacheEntry(paths[i]); ents[i].setFileMode(mode); } DirCacheBuilder b = dc.builder(); for (int i = 0; i < ents.Length; i++) { b.add(ents[i]); } b.finish(); var iter = new DirCacheIterator(dc); var tw = new TreeWalk(db); tw.reset(); tw.addTree(iter); tw.Recursive = true; int pathIdx = 0; while (tw.next()) { var c = tw.getTree <DirCacheIterator>(0, typeof(DirCacheIterator)); Assert.IsNotNull(c); Assert.AreEqual(pathIdx, c.Pointer); Assert.AreSame(ents[pathIdx], c.getDirCacheEntry()); Assert.AreEqual(paths[pathIdx], tw.getPathString()); Assert.AreEqual(mode.Bits, tw.getRawMode(0)); Assert.AreSame(mode, tw.getFileMode(0)); pathIdx++; } Assert.AreEqual(paths.Length, pathIdx); }
/// <exception cref="System.IO.IOException"></exception> private void ResetIndex(RevCommit commit) { DirCache dc = repo.LockDirCache(); TreeWalk walk = null; try { DirCacheEditor editor = dc.Editor(); walk = new TreeWalk(repo); walk.AddTree(commit.Tree); walk.AddTree(new DirCacheIterator(dc)); walk.Recursive = true; while (walk.Next()) { AbstractTreeIterator cIter = walk.GetTree <AbstractTreeIterator>(0); if (cIter == null) { editor.Add(new DirCacheEditor.DeletePath(walk.PathString)); continue; } DirCacheEntry entry = new DirCacheEntry(walk.RawPath); entry.FileMode = cIter.EntryFileMode; entry.SetObjectIdFromRaw(cIter.IdBuffer, cIter.IdOffset); DirCacheIterator dcIter = walk.GetTree <DirCacheIterator>(1); if (dcIter != null && dcIter.IdEqual(cIter)) { DirCacheEntry indexEntry = dcIter.GetDirCacheEntry(); entry.LastModified = indexEntry.LastModified; entry.SetLength(indexEntry.Length); } editor.Add(new _PathEdit_356(entry, entry)); } editor.Commit(); } finally { dc.Unlock(); if (walk != null) { walk.Release(); } } }
public void testNoSubtree_WithTreeWalk() { DirCache dc = DirCache.read(db); string[] paths = { "a.", "a0b" }; FileMode[] modes = { FileMode.ExecutableFile, FileMode.GitLink }; var ents = new DirCacheEntry[paths.Length]; for (int i = 0; i < paths.Length; i++) { ents[i] = new DirCacheEntry(paths[i]); ents[i].setFileMode(modes[i]); } DirCacheBuilder b = dc.builder(); for (int i = 0; i < ents.Length; i++) { b.add(ents[i]); } b.finish(); var iter = new DirCacheIterator(dc); var tw = new TreeWalk(db); tw.reset(); tw.addTree(iter); int pathIdx = 0; while (tw.next()) { Assert.AreSame(iter, tw.getTree <DirCacheIterator>(0, typeof(DirCacheIterator))); Assert.AreEqual(pathIdx, iter.Pointer); Assert.AreSame(ents[pathIdx], iter.getDirCacheEntry()); Assert.AreEqual(paths[pathIdx], tw.getPathString()); Assert.AreEqual(modes[pathIdx].Bits, tw.getRawMode(0)); Assert.AreSame(modes[pathIdx], tw.getFileMode(0)); pathIdx++; } Assert.AreEqual(paths.Length, pathIdx); }
public static List <string> GetConflictedFiles(NGit.Repository repo) { List <string> list = new List <string> (); TreeWalk treeWalk = new TreeWalk(repo); treeWalk.Reset(); treeWalk.Recursive = true; DirCache dc = repo.ReadDirCache(); treeWalk.AddTree(new DirCacheIterator(dc)); while (treeWalk.Next()) { DirCacheIterator dirCacheIterator = treeWalk.GetTree <DirCacheIterator>(0); var ce = dirCacheIterator.GetDirCacheEntry(); if (ce != null && ce.Stage == 1) { list.Add(ce.PathString); } } return(list); }
public virtual void TestSameDiff() { Write(new FilePath(db.Directory.GetParent(), "test.txt"), "test"); FilePath folder = new FilePath(db.Directory.GetParent(), "folder"); folder.Mkdir(); Write(new FilePath(folder, "folder.txt"), "\n\n\n\nfolder"); Git git = new Git(db); git.Add().AddFilepattern(".").Call(); git.Commit().SetMessage("Initial commit").Call(); Write(new FilePath(folder, "folder.txt"), "\n\n\n\nfolder change"); PatchIdDiffFormatter df = new PatchIdDiffFormatter(); df.SetRepository(db); df.SetPathFilter(PathFilter.Create("folder")); DirCacheIterator oldTree = new DirCacheIterator(db.ReadDirCache()); FileTreeIterator newTree = new FileTreeIterator(db); df.Format(oldTree, newTree); df.Flush(); NUnit.Framework.Assert.AreEqual("08fca5ac531383eb1da8bf6b6f7cf44411281407", df.GetCalulatedPatchId ().Name); Write(new FilePath(folder, "folder.txt"), "a\n\n\n\nfolder"); git.Add().AddFilepattern(".").Call(); git.Commit().SetMessage("Initial commit").Call(); Write(new FilePath(folder, "folder.txt"), "a\n\n\n\nfolder change"); df = new PatchIdDiffFormatter(); df.SetRepository(db); df.SetPathFilter(PathFilter.Create("folder")); oldTree = new DirCacheIterator(db.ReadDirCache()); newTree = new FileTreeIterator(db); df.Format(oldTree, newTree); df.Flush(); NUnit.Framework.Assert.AreEqual("08fca5ac531383eb1da8bf6b6f7cf44411281407", df.GetCalulatedPatchId ().Name); }
public virtual void TestDiff() { Write(new FilePath(db.Directory.GetParent(), "test.txt"), "test"); FilePath folder = new FilePath(db.Directory.GetParent(), "folder"); folder.Mkdir(); Write(new FilePath(folder, "folder.txt"), "folder"); Git git = new Git(db); git.Add().AddFilepattern(".").Call(); git.Commit().SetMessage("Initial commit").Call(); Write(new FilePath(folder, "folder.txt"), "folder change"); PatchIdDiffFormatter df = new PatchIdDiffFormatter(); df.SetRepository(db); df.SetPathFilter(PathFilter.Create("folder")); DirCacheIterator oldTree = new DirCacheIterator(db.ReadDirCache()); FileTreeIterator newTree = new FileTreeIterator(db); df.Format(oldTree, newTree); df.Flush(); NUnit.Framework.Assert.AreEqual("1ff64e0f9333e9b81967c3e8d7a81362b14d5441", df.GetCalulatedPatchId ().Name); }
/// <exception cref="System.IO.IOException"></exception> private DirCache CreateTemporaryIndex(ObjectId headId, DirCache index) { ObjectInserter inserter = null; // get DirCacheEditor to modify the index if required DirCacheEditor dcEditor = index.Editor(); // get DirCacheBuilder for newly created in-core index to build a // temporary index for this commit DirCache inCoreIndex = DirCache.NewInCore(); DirCacheBuilder dcBuilder = inCoreIndex.Builder(); onlyProcessed = new bool[only.Count]; bool emptyCommit = true; TreeWalk treeWalk = new TreeWalk(repo); int dcIdx = treeWalk.AddTree(new DirCacheIterator(index)); int fIdx = treeWalk.AddTree(new FileTreeIterator(repo)); int hIdx = -1; if (headId != null) { hIdx = treeWalk.AddTree(new RevWalk(repo).ParseTree(headId)); } treeWalk.Recursive = true; while (treeWalk.Next()) { string path = treeWalk.PathString; // check if current entry's path matches a specified path int pos = LookupOnly(path); CanonicalTreeParser hTree = null; if (hIdx != -1) { hTree = treeWalk.GetTree <CanonicalTreeParser>(hIdx); } if (pos >= 0) { // include entry in commit DirCacheIterator dcTree = treeWalk.GetTree <DirCacheIterator>(dcIdx); FileTreeIterator fTree = treeWalk.GetTree <FileTreeIterator>(fIdx); // check if entry refers to a tracked file bool tracked = dcTree != null || hTree != null; if (!tracked) { break; } if (fTree != null) { // create a new DirCacheEntry with data retrieved from disk DirCacheEntry dcEntry = new DirCacheEntry(path); long entryLength = fTree.GetEntryLength(); dcEntry.SetLength(entryLength); dcEntry.LastModified = fTree.GetEntryLastModified(); dcEntry.FileMode = fTree.GetIndexFileMode(dcTree); bool objectExists = (dcTree != null && fTree.IdEqual(dcTree)) || (hTree != null && fTree.IdEqual(hTree)); if (objectExists) { dcEntry.SetObjectId(fTree.EntryObjectId); } else { if (FileMode.GITLINK.Equals(dcEntry.FileMode)) { dcEntry.SetObjectId(fTree.EntryObjectId); } else { // insert object if (inserter == null) { inserter = repo.NewObjectInserter(); } long contentLength = fTree.GetEntryContentLength(); InputStream inputStream = fTree.OpenEntryStream(); try { dcEntry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, contentLength, inputStream )); } finally { inputStream.Close(); } } } // update index dcEditor.Add(new _PathEdit_375(dcEntry, path)); // add to temporary in-core index dcBuilder.Add(dcEntry); if (emptyCommit && (hTree == null || !hTree.IdEqual(fTree) || hTree.EntryRawMode != fTree.EntryRawMode)) { // this is a change emptyCommit = false; } } else { // if no file exists on disk, remove entry from index and // don't add it to temporary in-core index dcEditor.Add(new DirCacheEditor.DeletePath(path)); if (emptyCommit && hTree != null) { // this is a change emptyCommit = false; } } // keep track of processed path onlyProcessed[pos] = true; } else { // add entries from HEAD for all other paths if (hTree != null) { // create a new DirCacheEntry with data retrieved from HEAD DirCacheEntry dcEntry = new DirCacheEntry(path); dcEntry.SetObjectId(hTree.EntryObjectId); dcEntry.FileMode = hTree.EntryFileMode; // add to temporary in-core index dcBuilder.Add(dcEntry); } } } // there must be no unprocessed paths left at this point; otherwise an // untracked or unknown path has been specified for (int i = 0; i < onlyProcessed.Length; i++) { if (!onlyProcessed[i]) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().entryNotFoundByPath , only[i])); } } // there must be at least one change if (emptyCommit) { throw new JGitInternalException(JGitText.Get().emptyCommit); } // update index dcEditor.Commit(); // finish temporary in-core index used for this commit dcBuilder.Finish(); return(inCoreIndex); }
/// <summary> /// Run the diff operation. Until this is called, all lists will be empty /// </summary> /// <returns>true if anything is different between index, tree, and workdir</returns> private void UpdateDirectory(IEnumerable <string> paths, bool recursive) { RevWalk rw = new RevWalk(Repository); ObjectId id = Repository.Resolve(Constants.HEAD); var commit = id != null?rw.ParseCommit(id) : null; TreeWalk treeWalk = new TreeWalk(Repository); treeWalk.Reset(); treeWalk.Recursive = false; if (commit != null) { treeWalk.AddTree(commit.Tree); } else { treeWalk.AddTree(new EmptyTreeIterator()); } DirCache dc = Repository.ReadDirCache(); treeWalk.AddTree(new DirCacheIterator(dc)); FileTreeIterator workTree = new FileTreeIterator(Repository.WorkTree, Repository.FileSystem, WorkingTreeOptions.KEY.Parse(Repository.GetConfig())); treeWalk.AddTree(workTree); List <TreeFilter> filters = new List <TreeFilter> (); filters.Add(new SkipWorkTreeFilter(1)); var pathFilters = paths.Where(p => p != ".").Select(p => PathFilter.Create(p)).ToArray(); if (pathFilters.Length > 1) { filters.Add(OrTreeFilter.Create(pathFilters)); // Use an OR to join all path filters } else if (pathFilters.Length == 1) { filters.Add(pathFilters[0]); } if (filters.Count > 1) { treeWalk.Filter = AndTreeFilter.Create(filters); } else { treeWalk.Filter = filters[0]; } while (treeWalk.Next()) { AbstractTreeIterator treeIterator = treeWalk.GetTree <AbstractTreeIterator>(0); DirCacheIterator dirCacheIterator = treeWalk.GetTree <DirCacheIterator>(1); WorkingTreeIterator workingTreeIterator = treeWalk.GetTree <WorkingTreeIterator>(2); NGit.FileMode fileModeTree = treeWalk.GetFileMode(0); if (treeWalk.IsSubtree) { treeWalk.EnterSubtree(); continue; } int stage = dirCacheIterator != null?dirCacheIterator.GetDirCacheEntry().Stage : 0; if (stage > 1) { continue; } else if (stage == 1) { MergeConflict.Add(dirCacheIterator.EntryPathString); changesExist = true; continue; } if (treeIterator != null) { if (dirCacheIterator != null) { if (!treeIterator.EntryObjectId.Equals(dirCacheIterator.EntryObjectId)) { // in repo, in index, content diff => changed Modified.Add(dirCacheIterator.EntryPathString); changesExist = true; } } else { // in repo, not in index => removed if (!fileModeTree.Equals(NGit.FileMode.TYPE_TREE)) { Removed.Add(treeIterator.EntryPathString); changesExist = true; } } } else { if (dirCacheIterator != null) { // not in repo, in index => added Added.Add(dirCacheIterator.EntryPathString); changesExist = true; } else { // not in repo, not in index => untracked if (workingTreeIterator != null && !workingTreeIterator.IsEntryIgnored()) { Untracked.Add(workingTreeIterator.EntryPathString); changesExist = true; } } } if (dirCacheIterator != null) { if (workingTreeIterator == null) { // in index, not in workdir => missing Missing.Add(dirCacheIterator.EntryPathString); changesExist = true; } else { // Workaround to file time resolution issues long itime = dirCacheIterator.GetDirCacheEntry().LastModified; long ftime = workingTreeIterator.GetEntryLastModified(); if (itime / 1000 != ftime / 1000) { if (!dirCacheIterator.IdEqual(workingTreeIterator)) { // in index, in workdir, content differs => modified Modified.Add(dirCacheIterator.EntryPathString); changesExist = true; } } } } } }
/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> public override bool Include(TreeWalk tw) { // If the working tree file doesn't exist, it does exist for at least // one other so include this difference. int wm = tw.GetRawMode(workingTree); if (wm == 0) { return(true); } // If the path does not appear in the DirCache and its ignored // we can avoid returning a result here, but only if its not in any // other tree. int cnt = tw.TreeCount; int dm = tw.GetRawMode(dirCache); if (dm == 0) { if (honorIgnores && WorkingTree(tw).IsEntryIgnored()) { int i = 0; for (; i < cnt; i++) { if (i == dirCache || i == workingTree) { continue; } if (tw.GetRawMode(i) != 0) { break; } } // If i is cnt then the path does not appear in any other tree, // and this working tree entry can be safely ignored. return(i == cnt ? false : true); } else { // In working tree and not ignored, and not in DirCache. return(true); } } // Always include subtrees as WorkingTreeIterator cannot provide // efficient elimination of unmodified subtrees. if (tw.IsSubtree) { return(true); } // Try the inexpensive comparisons between index and all real trees // first. Only if we don't find a diff here we have to bother with // the working tree for (int i_1 = 0; i_1 < cnt; i_1++) { if (i_1 == dirCache || i_1 == workingTree) { continue; } if (tw.GetRawMode(i_1) != dm || !tw.IdEqual(i_1, dirCache)) { return(true); } } // Only one chance left to detect a diff: between index and working // tree. Make use of the WorkingTreeIterator#isModified() method to // avoid computing SHA1 on filesystem content if not really needed. WorkingTreeIterator wi = WorkingTree(tw); DirCacheIterator di = tw.GetTree <DirCacheIterator>(dirCache); return(wi.IsModified(di.GetDirCacheEntry(), true)); }
/// <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(); } }
/// <summary>Run the diff operation.</summary> /// <remarks> /// Run the diff operation. Until this is called, all lists will be empty. /// <p> /// The operation may be aborted by the progress monitor. In that event it /// will report what was found before the cancel operation was detected. /// Callers should ignore the result if monitor.isCancelled() is true. If a /// progress monitor is not needed, callers should use /// <see cref="Diff()">Diff()</see> /// instead. Progress reporting is crude and approximate and only intended /// for informing the user. /// </remarks> /// <param name="monitor">for reporting progress, may be null</param> /// <param name="estWorkTreeSize">number or estimated files in the working tree</param> /// <param name="estIndexSize">number of estimated entries in the cache</param> /// <param name="title"></param> /// <returns>if anything is different between index, tree, and workdir</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public virtual bool Diff(ProgressMonitor monitor, int estWorkTreeSize, int estIndexSize , string title) { dirCache = repository.ReadDirCache(); TreeWalk treeWalk = new TreeWalk(repository); treeWalk.Recursive = true; // add the trees (tree, dirchache, workdir) if (tree != null) { treeWalk.AddTree(tree); } else { treeWalk.AddTree(new EmptyTreeIterator()); } treeWalk.AddTree(new DirCacheIterator(dirCache)); treeWalk.AddTree(initialWorkingTreeIterator); ICollection <TreeFilter> filters = new AList <TreeFilter>(4); if (monitor != null) { // Get the maximum size of the work tree and index // and add some (quite arbitrary) if (estIndexSize == 0) { estIndexSize = dirCache.GetEntryCount(); } int total = Math.Max(estIndexSize * 10 / 9, estWorkTreeSize * 10 / 9); monitor.BeginTask(title, total); filters.AddItem(new IndexDiff.ProgressReportingFilter(monitor, total)); } if (filter != null) { filters.AddItem(filter); } filters.AddItem(new SkipWorkTreeFilter(INDEX)); filters.AddItem(new IndexDiffFilter(INDEX, WORKDIR)); treeWalk.Filter = AndTreeFilter.Create(filters); while (treeWalk.Next()) { AbstractTreeIterator treeIterator = treeWalk.GetTree <AbstractTreeIterator>(TREE); DirCacheIterator dirCacheIterator = treeWalk.GetTree <DirCacheIterator>(INDEX); WorkingTreeIterator workingTreeIterator = treeWalk.GetTree <WorkingTreeIterator>(WORKDIR ); if (dirCacheIterator != null) { DirCacheEntry dirCacheEntry = dirCacheIterator.GetDirCacheEntry(); if (dirCacheEntry != null && dirCacheEntry.Stage > 0) { conflicts.AddItem(treeWalk.PathString); continue; } } if (treeIterator != null) { if (dirCacheIterator != null) { if (!treeIterator.IdEqual(dirCacheIterator) || treeIterator.EntryRawMode != dirCacheIterator .EntryRawMode) { // in repo, in index, content diff => changed changed.AddItem(treeWalk.PathString); } } else { // in repo, not in index => removed removed.AddItem(treeWalk.PathString); if (workingTreeIterator != null) { untracked.AddItem(treeWalk.PathString); } } } else { if (dirCacheIterator != null) { // not in repo, in index => added added.AddItem(treeWalk.PathString); } else { // not in repo, not in index => untracked if (workingTreeIterator != null && !workingTreeIterator.IsEntryIgnored()) { untracked.AddItem(treeWalk.PathString); } } } if (dirCacheIterator != null) { if (workingTreeIterator == null) { // in index, not in workdir => missing missing.AddItem(treeWalk.PathString); } else { if (workingTreeIterator.IsModified(dirCacheIterator.GetDirCacheEntry(), true)) { // in index, in workdir, content differs => modified modified.AddItem(treeWalk.PathString); } } } } // consume the remaining work if (monitor != null) { monitor.EndTask(); } if (added.IsEmpty() && changed.IsEmpty() && removed.IsEmpty() && missing.IsEmpty( ) && modified.IsEmpty() && untracked.IsEmpty()) { return(false); } else { return(true); } }
/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> public override bool Include(TreeWalk tw) { int cnt = tw.TreeCount; int wm = tw.GetRawMode(workingTree); string path = tw.PathString; if (!tw.PostOrderTraversal) { // detect untracked Folders // Whenever we enter a folder in the workingtree assume it will // contain only untracked files and add it to // untrackedParentFolders. If we later find tracked files we will // remove it from this list if (FileMode.TREE.Equals(wm)) { // Clean untrackedParentFolders. This potentially moves entries // from untrackedParentFolders to untrackedFolders CopyUntrackedFolders(path); // add the folder we just entered to untrackedParentFolders untrackedParentFolders.AddFirst(path); } // detect untracked Folders // Whenever we see a tracked file we know that all of its parent // folders do not belong into untrackedParentFolders anymore. Clean // it. for (int i = 0; i < cnt; i++) { int rmode = tw.GetRawMode(i); if (i != workingTree && rmode != 0 && FileMode.TREE.Equals(rmode)) { untrackedParentFolders.Clear(); break; } } } // If the working tree file doesn't exist, it does exist for at least // one other so include this difference. if (wm == 0) { return(true); } // If the path does not appear in the DirCache and its ignored // we can avoid returning a result here, but only if its not in any // other tree. int dm = tw.GetRawMode(dirCache); WorkingTreeIterator wi = WorkingTree(tw); if (dm == 0) { if (honorIgnores && wi.IsEntryIgnored()) { ignoredPaths.AddItem(wi.EntryPathString); int i = 0; for (; i < cnt; i++) { if (i == dirCache || i == workingTree) { continue; } if (tw.GetRawMode(i) != 0) { break; } } // If i is cnt then the path does not appear in any other tree, // and this working tree entry can be safely ignored. return(i == cnt ? false : true); } else { // In working tree and not ignored, and not in DirCache. return(true); } } // Always include subtrees as WorkingTreeIterator cannot provide // efficient elimination of unmodified subtrees. if (tw.IsSubtree) { return(true); } // Try the inexpensive comparisons between index and all real trees // first. Only if we don't find a diff here we have to bother with // the working tree for (int i_1 = 0; i_1 < cnt; i_1++) { if (i_1 == dirCache || i_1 == workingTree) { continue; } if (tw.GetRawMode(i_1) != dm || !tw.IdEqual(i_1, dirCache)) { return(true); } } // Only one chance left to detect a diff: between index and working // tree. Make use of the WorkingTreeIterator#isModified() method to // avoid computing SHA1 on filesystem content if not really needed. DirCacheIterator di = tw.GetTree <DirCacheIterator>(dirCache); return(wi.IsModified(di.GetDirCacheEntry(), true)); }
private GitFileStatus GetFileStatus(TreeWalk treeWalk) { AbstractTreeIterator treeIterator = treeWalk.GetTree <AbstractTreeIterator>(TREE); DirCacheIterator dirCacheIterator = treeWalk.GetTree <DirCacheIterator>(INDEX); WorkingTreeIterator workingTreeIterator = treeWalk.GetTree <WorkingTreeIterator>(WORKDIR); if (dirCacheIterator != null) { DirCacheEntry dirCacheEntry = dirCacheIterator.GetDirCacheEntry(); if (dirCacheEntry != null && dirCacheEntry.Stage > 0) { return(GitFileStatus.Conflict); } if (workingTreeIterator == null) { // in index, not in workdir => missing return(GitFileStatus.Deleted); } else { if (workingTreeIterator.IsModified(dirCacheIterator.GetDirCacheEntry(), true)) { // in index, in workdir, content differs => modified return(GitFileStatus.Modified); } } } if (treeIterator != null) { if (dirCacheIterator != null) { if (!treeIterator.IdEqual(dirCacheIterator) || treeIterator.EntryRawMode != dirCacheIterator.EntryRawMode) { // in repo, in index, content diff => changed return(GitFileStatus.Staged); } } else { return(GitFileStatus.Removed); } } else { if (dirCacheIterator != null) { // not in repo, in index => added return(GitFileStatus.Added); } else { // not in repo, not in index => untracked if (workingTreeIterator != null) { return(!workingTreeIterator.IsEntryIgnored() ? GitFileStatus.New : GitFileStatus.Ignored); } } } return(GitFileStatus.NotControlled); }
/// <summary>Apply the changes in a stashed commit to the working directory and index /// </summary> /// <returns>id of stashed commit that was applied</returns> /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException /// </exception> /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">NGit.Api.Errors.WrongRepositoryStateException /// </exception> public override ObjectId Call() { CheckCallable(); if (repo.GetRepositoryState() != RepositoryState.SAFE) { throw new WrongRepositoryStateException(MessageFormat.Format(JGitText.Get().stashApplyOnUnsafeRepository , repo.GetRepositoryState())); } ObjectId headTree = GetHeadTree(); ObjectId stashId = GetStashId(); ObjectReader reader = repo.NewObjectReader(); try { RevWalk revWalk = new RevWalk(reader); RevCommit stashCommit = revWalk.ParseCommit(stashId); if (stashCommit.ParentCount != 2) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().stashCommitMissingTwoParents , stashId.Name)); } RevTree stashWorkingTree = stashCommit.Tree; RevTree stashIndexTree = revWalk.ParseCommit(stashCommit.GetParent(1)).Tree; RevTree stashHeadTree = revWalk.ParseCommit(stashCommit.GetParent(0)).Tree; CanonicalTreeParser stashWorkingIter = new CanonicalTreeParser(); stashWorkingIter.Reset(reader, stashWorkingTree); CanonicalTreeParser stashIndexIter = new CanonicalTreeParser(); stashIndexIter.Reset(reader, stashIndexTree); CanonicalTreeParser stashHeadIter = new CanonicalTreeParser(); stashHeadIter.Reset(reader, stashHeadTree); CanonicalTreeParser headIter = new CanonicalTreeParser(); headIter.Reset(reader, headTree); DirCache cache = repo.LockDirCache(); DirCacheEditor editor = cache.Editor(); try { DirCacheIterator indexIter = new DirCacheIterator(cache); FileTreeIterator workingIter = new FileTreeIterator(repo); TreeWalk treeWalk = new TreeWalk(reader); treeWalk.Recursive = true; treeWalk.Filter = new StashApplyCommand.StashDiffFilter(); treeWalk.AddTree(stashHeadIter); treeWalk.AddTree(stashIndexIter); treeWalk.AddTree(stashWorkingIter); treeWalk.AddTree(headIter); treeWalk.AddTree(indexIter); treeWalk.AddTree(workingIter); ScanForConflicts(treeWalk); // Reset trees and walk treeWalk.Reset(); stashWorkingIter.Reset(reader, stashWorkingTree); stashIndexIter.Reset(reader, stashIndexTree); stashHeadIter.Reset(reader, stashHeadTree); treeWalk.AddTree(stashHeadIter); treeWalk.AddTree(stashIndexIter); treeWalk.AddTree(stashWorkingIter); ApplyChanges(treeWalk, cache, editor); } finally { editor.Commit(); cache.Unlock(); } } catch (JGitInternalException e) { throw; } catch (IOException e) { throw new JGitInternalException(JGitText.Get().stashApplyFailed, e); } finally { reader.Release(); } return(stashId); }