private static IEnumerable<DiffEntry> GetDiffEntries(this RevCommit commit, Repository repository) { var tw = new TreeWalk(repository) { Recursive = true }; if (commit.ParentCount > 0) { if (commit.Parents.First().Tree != null) { tw.AddTree(commit.Parents.First().Tree); } else { tw.AddTree(new EmptyTreeIterator()); } } else { tw.AddTree(new EmptyTreeIterator()); } tw.Filter = TreeFilter.ANY_DIFF; tw.AddTree(commit.Tree); return DiffEntry.Scan(tw); }
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()); }
public virtual void TestNonRecursiveFiltering() { 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")); 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); builder.Finish(); ObjectId treeId = dc.WriteTree(odi); odi.Flush(); TreeWalk tw = new TreeWalk(db); 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"); NUnit.Framework.Assert.AreEqual(expected, paths); }
/// <summary>Create submodule generator</summary> /// <param name="repository"></param> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public SubmoduleWalk(Repository repository) { this.repository = repository; repoConfig = repository.GetConfig(); walk = new TreeWalk(repository); walk.Recursive = true; }
public virtual void TestNoDF_NoGap() { DirCache tree0 = db.ReadDirCache(); DirCache tree1 = db.ReadDirCache(); { DirCacheBuilder b0 = tree0.Builder(); DirCacheBuilder b1 = tree1.Builder(); b0.Add(MakeEntry("a", REGULAR_FILE)); b0.Add(MakeEntry("a.b", EXECUTABLE_FILE)); b1.Add(MakeEntry("a/b", REGULAR_FILE)); b0.Add(MakeEntry("a0b", SYMLINK)); b0.Finish(); b1.Finish(); NUnit.Framework.Assert.AreEqual(3, tree0.GetEntryCount()); NUnit.Framework.Assert.AreEqual(1, tree1.GetEntryCount()); } TreeWalk tw = new TreeWalk(db); tw.AddTree(new DirCacheIterator(tree0)); tw.AddTree(new DirCacheIterator(tree1)); AssertModes("a", REGULAR_FILE, MISSING, tw); AssertModes("a.b", EXECUTABLE_FILE, MISSING, tw); AssertModes("a", MISSING, TREE, tw); tw.EnterSubtree(); AssertModes("a/b", MISSING, REGULAR_FILE, tw); AssertModes("a0b", SYMLINK, MISSING, tw); }
public virtual void TestEmptyTree_WithTreeWalk() { DirCache dc = DirCache.NewInCore(); NUnit.Framework.Assert.AreEqual(0, dc.GetEntryCount()); TreeWalk tw = new TreeWalk(db); tw.AddTree(new DirCacheIterator(dc)); NUnit.Framework.Assert.IsFalse(tw.Next()); }
public virtual void TestInitialize_TogglePostOrder() { TreeWalk tw = new TreeWalk(db); NUnit.Framework.Assert.IsFalse(tw.PostOrderTraversal); tw.PostOrderTraversal = true; NUnit.Framework.Assert.IsTrue(tw.PostOrderTraversal); tw.PostOrderTraversal = false; NUnit.Framework.Assert.IsFalse(tw.PostOrderTraversal); }
public virtual void TestWrap() { TreeWalk tw = new TreeWalk(db); TreeFilter a = TreeFilter.ALL; TreeFilter n = NotTreeFilter.Create(a); NUnit.Framework.Assert.IsNotNull(n); NUnit.Framework.Assert.IsTrue(a.Include(tw)); NUnit.Framework.Assert.IsFalse(n.Include(tw)); }
public void testEmptyTree_WithTreeWalk() { DirCache dc = DirCache.read(db); Assert.AreEqual(0, dc.getEntryCount()); var tw = new TreeWalk(db); tw.reset(); tw.addTree(new DirCacheIterator(dc)); Assert.IsFalse(tw.next()); }
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; }
/// <summary> /// Returns a list of files that have changed in a commit /// </summary> public static IEnumerable<Change> GetCommitChanges (NGit.Repository repo, RevCommit commit) { var treeIds = new[] { commit.Tree.Id }.Concat (commit.Parents.Select (c => c.Tree.Id)).ToArray (); var walk = new TreeWalk (repo); walk.Reset (treeIds); walk.Recursive = true; walk.Filter = AndTreeFilter.Create (AndTreeFilter.ANY_DIFF, AndTreeFilter.ALL); return CalculateCommitDiff (repo, walk, new[] { commit }.Concat (commit.Parents).ToArray ()); }
public virtual void TestResetDoesNotAffectPostOrder() { TreeWalk tw = new TreeWalk(db); tw.PostOrderTraversal = true; NUnit.Framework.Assert.IsTrue(tw.PostOrderTraversal); tw.Reset(); NUnit.Framework.Assert.IsTrue(tw.PostOrderTraversal); tw.PostOrderTraversal = false; NUnit.Framework.Assert.IsFalse(tw.PostOrderTraversal); tw.Reset(); NUnit.Framework.Assert.IsFalse(tw.PostOrderTraversal); }
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; }
/// <summary> /// Compares two commits and returns a list of files that have changed /// </summary> public static IEnumerable<Change> CompareCommits (NGit.Repository repo, RevCommit reference, RevCommit compared) { var changes = new List<Change>(); if (reference == null && compared == null) return changes; ObjectId refTree = (reference != null ? reference.Tree.Id : ObjectId.ZeroId); ObjectId comparedTree = (compared != null ? compared.Tree.Id : ObjectId.ZeroId); var walk = new TreeWalk (repo); if (reference == null || compared == null) walk.Reset ((reference ?? compared).Tree.Id); else walk.Reset (new AnyObjectId[] {refTree, comparedTree}); walk.Recursive = true; walk.Filter = AndTreeFilter.Create(TreeFilter.ANY_DIFF, TreeFilter.ALL); return CalculateCommitDiff (repo, walk, new[] { reference, compared }); }
public virtual void TestPathFilterGroup_DoesNotSkipTail() { DirCache dc = db.ReadDirCache(); FileMode mode = FileMode.REGULAR_FILE; string[] paths = new string[] { "a.", "a/b", "a/c", "a/d", "a0b" }; DirCacheEntry[] ents = new DirCacheEntry[paths.Length]; for (int i = 0; i < paths.Length; i++) { ents[i] = new DirCacheEntry(paths[i]); ents[i].FileMode = mode; } { DirCacheBuilder b = dc.Builder(); for (int i_1 = 0; i_1 < ents.Length; i_1++) { b.Add(ents[i_1]); } b.Finish(); } int expIdx = 2; DirCacheBuilder b_1 = dc.Builder(); TreeWalk tw = new TreeWalk(db); tw.AddTree(new DirCacheBuildIterator(b_1)); tw.Recursive = true; tw.Filter = PathFilterGroup.CreateFromStrings(Collections.Singleton(paths[expIdx] )); NUnit.Framework.Assert.IsTrue(tw.Next(), "found " + paths[expIdx]); DirCacheIterator c = tw.GetTree<DirCacheIterator>(0); NUnit.Framework.Assert.IsNotNull(c); NUnit.Framework.Assert.AreEqual(expIdx, c.ptr); NUnit.Framework.Assert.AreSame(ents[expIdx], c.GetDirCacheEntry()); NUnit.Framework.Assert.AreEqual(paths[expIdx], tw.PathString); NUnit.Framework.Assert.AreEqual(mode.GetBits(), tw.GetRawMode(0)); NUnit.Framework.Assert.AreSame(mode, tw.GetFileMode(0)); b_1.Add(c.GetDirCacheEntry()); NUnit.Framework.Assert.IsFalse(tw.Next(), "no more entries"); b_1.Finish(); NUnit.Framework.Assert.AreEqual(ents.Length, dc.GetEntryCount()); for (int i_2 = 0; i_2 < ents.Length; i_2++) { NUnit.Framework.Assert.AreSame(ents[i_2], dc.GetEntry(i_2)); } }
public IEnumerable<FileDiff> GetFileDiffs(string newHash, string oldHash) { NGit.Repository repo = this.git.GetRepository(); ObjectId newCommit = repo.Resolve(newHash + "^{tree}"); ObjectId oldCommit = repo.Resolve(oldHash + "^{tree}"); var walk = new TreeWalk(repo) { Recursive = true }; walk.AddTree(oldCommit); walk.AddTree(newCommit); IEnumerable<DiffEntry> entries = DiffEntry.Scan(walk); var diffs = entries.Where(diff => diff.GetNewId().Name != diff.GetOldId().Name); return from diffEntry in diffs let diffType = ToDiffType(diffEntry.GetChangeType()) let path = diffType == DiffType.Delete ? diffEntry.GetOldPath() : diffEntry.GetNewPath() select new FileDiff(path, diffType); }
public virtual void ShouldListAddedFileInInitialCommit() { // given WriteTrashFile("a.txt", "content"); Git git = new Git(db); git.Add().AddFilepattern("a.txt").Call(); RevCommit c = git.Commit().SetMessage("initial commit").Call(); // when TreeWalk walk = new TreeWalk(db); walk.AddTree(new EmptyTreeIterator()); walk.AddTree(c.Tree); IList<DiffEntry> result = DiffEntry.Scan(walk); // then Assert.IsNotNull (result); Assert.AreEqual(1, result.Count); DiffEntry entry = result[0]; Assert.AreEqual(entry.GetChangeType(), DiffEntry.ChangeType.ADD); Assert.AreEqual(entry.GetNewPath(), "a.txt"); Assert.AreEqual(entry.GetOldPath(), DiffEntry.DEV_NULL); }
public static string GetFileContent(this RevCommit commit, string path, Repository repository) { var treeWalk = new TreeWalk(repository) {Recursive = true, Filter = PathFilter.Create(path)}; treeWalk.AddTree(commit.Tree); if (!treeWalk.Next()) { return string.Empty; } var objectId = treeWalk.GetObjectId(0); var loader = repository.Open(objectId); using (var stream = loader.OpenStream()) { using (var reader = new StreamReader(stream)) { return reader.ReadToEnd(); } } }
public void testTreeWalk_LsFiles() { global::GitSharp.Core.Repository db = createBareRepository(); List<CGitIndexRecord> ls = ReadLsFiles(); var dc = new DirCache(_index); Assert.AreEqual(0, dc.getEntryCount()); dc.read(); Assert.AreEqual(ls.Count, dc.getEntryCount()); var rItr = ls.GetEnumerator(); var tw = new TreeWalk(db); tw.reset(); tw.Recursive = true; tw.addTree(new DirCacheIterator(dc)); while (rItr.MoveNext()) { Assert.IsTrue(tw.next()); var dcItr = tw.getTree<DirCacheIterator>(0, typeof(DirCacheIterator)); Assert.IsNotNull(dcItr); AssertAreEqual(rItr.Current, dcItr.getDirCacheEntry()); } }
/// <exception cref="NGit.Errors.CorruptObjectException"></exception> /// <exception cref="System.IO.IOException"></exception> public virtual void AssertWorkDir(Dictionary<string, string> i) { TreeWalk walk = new TreeWalk(db); walk.Recursive = true; walk.AddTree(new FileTreeIterator(db)); string expectedValue; string path; int nrFiles = 0; FileTreeIterator ft; while (walk.Next()) { ft = walk.GetTree<FileTreeIterator>(0); path = ft.EntryPathString; expectedValue = i.Get(path); NUnit.Framework.Assert.IsNotNull(expectedValue, "found unexpected file for path " + path + " in workdir"); FilePath file = new FilePath(db.WorkTree, path); NUnit.Framework.Assert.IsTrue(file.Exists()); if (file.IsFile()) { FileInputStream @is = new FileInputStream(file); byte[] buffer = new byte[(int)file.Length()]; int offset = 0; int numRead = 0; while (offset < buffer.Length && (numRead = @is.Read(buffer, offset, buffer.Length - offset)) >= 0) { offset += numRead; } @is.Close(); CollectionAssert.AreEqual (buffer, Sharpen.Runtime.GetBytesForString(i.Get(path)), "unexpected content for path " + path + " in workDir. "); nrFiles++; } } NUnit.Framework.Assert.AreEqual(i.Count, nrFiles, "WorkDir has not the right size." ); }
public static API_NGit files(this API_NGit nGit,string commitId, Action<TreeWalk> onTreeWalk) { try { var headCommit = nGit.Repository.Resolve(commitId); if (commitId.notNull()) { var revWalk = new RevWalk(nGit.Repository); var commit = revWalk.ParseCommit(headCommit); var treeWalk = new TreeWalk(nGit.Repository); var tree = commit.Tree; treeWalk.AddTree(tree); treeWalk.Recursive = true; while (treeWalk.Next()) onTreeWalk(treeWalk); } } catch (Exception ex) { ex.log("[API_NGit][getRepoFiles]"); } return nGit ; }
public override bool Include(TreeWalk walker) { 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 walker) { return(path.Include(walker) && ANY_DIFF.Include(walker)); }
internal WorkingTreeSource(WorkingTreeIterator iterator) { this.tw = new TreeWalk((ObjectReader)null); this.iterator = iterator; }
/// <param name="walker">The walk to check against.</param> /// <returns> /// /// <code>true</code> /// if the path length of this filter matches the length /// of the current path of the supplied TreeWalk. /// </returns> public virtual bool IsDone(TreeWalk walker) { return(pathRaw.Length == walker.GetPathLength()); }
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); }
public virtual void CommitSubmoduleUpdate() { Git git = new Git(db); WriteTrashFile("file.txt", "content"); git.Add().AddFilepattern("file.txt").Call(); RevCommit commit = git.Commit().SetMessage("create file").Call(); WriteTrashFile("file.txt", "content2"); git.Add().AddFilepattern("file.txt").Call(); RevCommit commit2 = git.Commit().SetMessage("edit file").Call(); SubmoduleAddCommand command = new SubmoduleAddCommand(db); string path = "sub"; command.SetPath(path); string uri = db.Directory.ToURI().ToString(); command.SetURI(uri); Repository repo = command.Call(); NUnit.Framework.Assert.IsNotNull(repo); AddRepoToClose(repo); SubmoduleWalk generator = SubmoduleWalk.ForIndex(db); NUnit.Framework.Assert.IsTrue(generator.Next()); NUnit.Framework.Assert.AreEqual(path, generator.GetPath()); NUnit.Framework.Assert.AreEqual(commit2, generator.GetObjectId()); NUnit.Framework.Assert.AreEqual(uri, generator.GetModulesUrl()); NUnit.Framework.Assert.AreEqual(path, generator.GetModulesPath()); NUnit.Framework.Assert.AreEqual(uri, generator.GetConfigUrl()); Repository subModRepo = generator.GetRepository(); AddRepoToClose(subModRepo); NUnit.Framework.Assert.IsNotNull(subModRepo); NUnit.Framework.Assert.AreEqual(commit2, repo.Resolve(Constants.HEAD)); RevCommit submoduleAddCommit = git.Commit().SetMessage("submodule add").SetOnly(path ).Call(); NUnit.Framework.Assert.IsNotNull(submoduleAddCommit); RefUpdate update = repo.UpdateRef(Constants.HEAD); update.SetNewObjectId(commit); NUnit.Framework.Assert.AreEqual(RefUpdate.Result.FORCED, update.ForceUpdate()); RevCommit submoduleEditCommit = git.Commit().SetMessage("submodule add").SetOnly( path).Call(); NUnit.Framework.Assert.IsNotNull(submoduleEditCommit); TreeWalk walk = new TreeWalk(db); walk.AddTree(submoduleAddCommit.Tree); walk.AddTree(submoduleEditCommit.Tree); walk.Filter = TreeFilter.ANY_DIFF; IList <DiffEntry> diffs = DiffEntry.Scan(walk); NUnit.Framework.Assert.AreEqual(1, diffs.Count); DiffEntry subDiff = diffs[0]; NUnit.Framework.Assert.AreEqual(FileMode.GITLINK, subDiff.GetOldMode()); NUnit.Framework.Assert.AreEqual(FileMode.GITLINK, subDiff.GetNewMode()); NUnit.Framework.Assert.AreEqual(commit2, subDiff.GetOldId().ToObjectId()); NUnit.Framework.Assert.AreEqual(commit, subDiff.GetNewId().ToObjectId()); NUnit.Framework.Assert.AreEqual(path, subDiff.GetNewPath()); NUnit.Framework.Assert.AreEqual(path, subDiff.GetOldPath()); }
/// <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)); indexDiffFilter = new IndexDiffFilter(INDEX, WORKDIR); filters.AddItem(indexDiffFilter); 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(); } ignored = indexDiffFilter.GetIgnoredPaths(); if (added.IsEmpty() && changed.IsEmpty() && removed.IsEmpty() && missing.IsEmpty( ) && modified.IsEmpty() && untracked.IsEmpty()) { return(false); } else { return(true); } }
/// <summary> /// Return a list of those objects in the index which differ from whats in /// HEAD /// </summary> /// <returns>a set of ObjectIds of changed objects in the index</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> /// <exception cref="NGit.Errors.CorruptObjectException">NGit.Errors.CorruptObjectException /// </exception> /// <exception cref="NGit.Errors.NoWorkTreeException">NGit.Errors.NoWorkTreeException /// </exception> private ICollection <ObjectId> ListNonHEADIndexObjects() { RevWalk revWalk = null; try { if (repo.GetIndexFile() == null) { return(Sharpen.Collections.EmptySet <ObjectId>()); } } catch (NoWorkTreeException) { return(Sharpen.Collections.EmptySet <ObjectId>()); } TreeWalk treeWalk = new TreeWalk(repo); try { treeWalk.AddTree(new DirCacheIterator(repo.ReadDirCache())); ObjectId headID = repo.Resolve(Constants.HEAD); if (headID != null) { revWalk = new RevWalk(repo); treeWalk.AddTree(revWalk.ParseTree(headID)); revWalk.Dispose(); revWalk = null; } treeWalk.Filter = TreeFilter.ANY_DIFF; treeWalk.Recursive = true; ICollection <ObjectId> ret = new HashSet <ObjectId>(); while (treeWalk.Next()) { ObjectId objectId = treeWalk.GetObjectId(0); switch (treeWalk.GetRawMode(0) & FileMode.TYPE_MASK) { case FileMode.TYPE_MISSING: case FileMode.TYPE_GITLINK: { continue; goto case FileMode.TYPE_TREE; } case FileMode.TYPE_TREE: case FileMode.TYPE_FILE: case FileMode.TYPE_SYMLINK: { ret.AddItem(objectId); continue; goto default; } default: { throw new IOException(MessageFormat.Format(JGitText.Get().corruptObjectInvalidMode3 , string.Format("%o", Sharpen.Extensions.ValueOf(treeWalk.GetRawMode(0)), (objectId == null) ? "null" : objectId.Name, treeWalk.PathString, repo.GetIndexFile()))); } } } return(ret); } finally { if (revWalk != null) { revWalk.Dispose(); } treeWalk.Release(); } }
/// <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) { if (dirCacheIterator != null || treeIterator != null) { 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; } } } } } }
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(); } }
// Modified version of GitSharp's Commit class private Change[] GetChanges(Repository repository, ObjectId id1, ObjectId id2) { var list = new List <Change>(); TreeWalk walk = new TreeWalk(repository); walk.Reset(id1, id2); walk.Recursive = true; walk.Filter = TreeFilter.ANY_DIFF; while (walk.Next()) { int m0 = walk.GetRawMode(0); if (walk.TreeCount == 2) { int m1 = walk.GetRawMode(1); var change = new Change { Name = walk.PathString, }; if (m0 != 0 && m1 == 0) { change.ChangeType = ChangeType.Added; } else if (m0 == 0 && m1 != 0) { change.ChangeType = ChangeType.Deleted; } else if (m0 != m1 && walk.IdEqual(0, 1)) { change.ChangeType = ChangeType.TypeChanged; } else { change.ChangeType = ChangeType.Modified; } list.Add(change); } else { var raw_modes = new int[walk.TreeCount - 1]; for (int i = 0; i < walk.TreeCount - 1; i++) { raw_modes[i] = walk.GetRawMode(i + 1); } var change = new Change { Name = walk.PathString, }; if (m0 != 0 && raw_modes.All(m1 => m1 == 0)) { change.ChangeType = ChangeType.Added; list.Add(change); } else if (m0 == 0 && raw_modes.Any(m1 => m1 != 0)) { change.ChangeType = ChangeType.Deleted; list.Add(change); } else if (raw_modes.Select((m1, i) => new { Mode = m1, Index = i + 1 }).All(x => !walk.IdEqual(0, x.Index))) // TODO: not sure if this condition suffices in some special cases. { change.ChangeType = ChangeType.Modified; list.Add(change); } else if (raw_modes.Select((m1, i) => new { Mode = m1, Index = i + 1 }).Any(x => m0 != x.Mode && walk.IdEqual(0, x.Index))) { change.ChangeType = ChangeType.TypeChanged; list.Add(change); } } } return(list.ToArray()); }
private void AssertCorrectId(DirCache treeT, TreeWalk tw) { NUnit.Framework.Assert.AreEqual(treeT.GetEntry(tw.PathString).GetObjectId(), tw.GetObjectId (0)); }
/// <summary> /// compare the given commits and return the changes. /// </summary> /// <param name="repo"></param> /// <param name="walk"></param> /// <param name="commits">first commit in the array is the commit that is compared against the others which are his ancestors (i.e. from different branches)</param> /// <returns></returns> private static IEnumerable <Change> CalculateCommitDiff(Repository repo, TreeWalk walk, Commit[] commits) { while (walk.next()) { int m0 = walk.getRawMode(0); if (walk.getTreeCount() == 2) { int m1 = walk.getRawMode(1); var change = new Change { ReferenceCommit = commits[0], ComparedCommit = commits[1], ReferencePermissions = walk.getFileMode(0).Bits, ComparedPermissions = walk.getFileMode(1).Bits, Name = walk.getNameString(), Path = walk.getPathString(), }; if (m0 != 0 && m1 == 0) { change.ChangeType = ChangeType.Added; change.ComparedObject = Wrap(repo, walk.getObjectId(0)); } else if (m0 == 0 && m1 != 0) { change.ChangeType = ChangeType.Deleted; change.ReferenceObject = Wrap(repo, walk.getObjectId(0)); } else if (m0 != m1 && walk.idEqual(0, 1)) { change.ChangeType = ChangeType.TypeChanged; change.ReferenceObject = Wrap(repo, walk.getObjectId(0)); change.ComparedObject = Wrap(repo, walk.getObjectId(1)); } else { change.ChangeType = ChangeType.Modified; change.ReferenceObject = Wrap(repo, walk.getObjectId(0)); change.ComparedObject = Wrap(repo, walk.getObjectId(1)); } yield return(change); } else { var raw_modes = new int[walk.getTreeCount() - 1]; for (int i = 0; i < walk.getTreeCount() - 1; i++) { raw_modes[i] = walk.getRawMode(i + 1); } var change = new Change { ReferenceCommit = commits[0], //ComparedCommit = compared, Name = walk.getNameString(), Path = walk.getPathString(), }; if (m0 != 0 && raw_modes.All(m1 => m1 == 0)) { change.ChangeType = ChangeType.Added; change.ComparedObject = Wrap(repo, walk.getObjectId(0)); yield return(change); } else if (m0 == 0 && raw_modes.Any(m1 => m1 != 0)) { change.ChangeType = ChangeType.Deleted; yield return(change); } else if (raw_modes.Select((m1, i) => new { Mode = m1, Index = i + 1 }).All(x => !walk.idEqual(0, x.Index))) // TODO: not sure if this condition suffices in some special cases. { change.ChangeType = ChangeType.Modified; change.ReferenceObject = Wrap(repo, walk.getObjectId(0)); yield return(change); } else if (raw_modes.Select((m1, i) => new { Mode = m1, Index = i + 1 }).Any(x => m0 != x.Mode && walk.idEqual(0, x.Index))) { change.ChangeType = ChangeType.TypeChanged; change.ReferenceObject = Wrap(repo, walk.getObjectId(0)); yield return(change); } } } }
/// <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>Determine if the current entry is interesting to report.</summary> /// <remarks> /// Determine if the current entry is interesting to report. /// <p> /// This method is consulted for subtree entries even if /// <see cref="NGit.Treewalk.TreeWalk.Recursive()">NGit.Treewalk.TreeWalk.Recursive() /// </see> /// is enabled. The consultation allows the /// filter to bypass subtree recursion on a case-by-case basis, even when /// recursion is enabled at the application level. /// </remarks> /// <param name="walker">the walker the filter needs to examine.</param> /// <returns> /// true if the current entry should be seen by the application; /// false to hide the entry. /// </returns> /// <exception cref="NGit.Errors.MissingObjectException"> /// an object the filter needs to consult to determine its answer /// does not exist in the Git repository the walker is operating /// on. Filtering this current walker entry is impossible without /// the object. /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"> /// an object the filter needed to consult was not of the /// expected object type. This usually indicates a corrupt /// repository, as an object link is referencing the wrong type. /// </exception> /// <exception cref="System.IO.IOException"> /// a loose object or pack file could not be read to obtain data /// necessary for the filter to make its decision. /// </exception> public abstract bool Include(TreeWalk walker);
/// <exception cref="NGit.Errors.StopWalkException"></exception> /// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> public override bool Include(RevWalk walker, RevCommit c) { // Reset the tree filter to scan this commit and parents. // RevCommit[] pList = c.parents; int nParents = pList.Length; TreeWalk tw = pathFilter; ObjectId[] trees = new ObjectId[nParents + 1]; for (int i = 0; i < nParents; i++) { RevCommit p = c.parents[i]; if ((p.flags & PARSED) == 0) { p.ParseHeaders(walker); } trees[i] = p.Tree; } trees[nParents] = c.Tree; tw.Reset(trees); if (nParents == 1) { // We have exactly one parent. This is a very common case. // int chgs = 0; int adds = 0; while (tw.Next()) { chgs++; if (tw.GetRawMode(0) == 0 && tw.GetRawMode(1) != 0) { adds++; } else { break; } } // no point in looking at this further. if (chgs == 0) { // No changes, so our tree is effectively the same as // our parent tree. We pass the buck to our parent. // c.flags |= REWRITE; return(false); } else { // We have interesting items, but neither of the special // cases denoted above. // if (adds > 0 && tw.Filter is FollowFilter) { // One of the paths we care about was added in this // commit. We need to update our filter to its older // name, if we can discover it. Find out what that is. // UpdateFollowFilter(trees); } return(true); } } else { if (nParents == 0) { // We have no parents to compare against. Consider us to be // REWRITE only if we have no paths matching our filter. // if (tw.Next()) { return(true); } c.flags |= REWRITE; return(false); } } // We are a merge commit. We can only be REWRITE if we are same // to _all_ parents. We may also be able to eliminate a parent if // it does not contribute changes to us. Such a parent may be an // uninteresting side branch. // int[] chgs_1 = new int[nParents]; int[] adds_1 = new int[nParents]; while (tw.Next()) { int myMode = tw.GetRawMode(nParents); for (int i_1 = 0; i_1 < nParents; i_1++) { int pMode = tw.GetRawMode(i_1); if (myMode == pMode && tw.IdEqual(i_1, nParents)) { continue; } chgs_1[i_1]++; if (pMode == 0 && myMode != 0) { adds_1[i_1]++; } } } bool same = false; bool diff = false; for (int i_2 = 0; i_2 < nParents; i_2++) { if (chgs_1[i_2] == 0) { // No changes, so our tree is effectively the same as // this parent tree. We pass the buck to only this one // parent commit. // RevCommit p = pList[i_2]; if ((p.flags & UNINTERESTING) != 0) { // This parent was marked as not interesting by the // application. We should look for another parent // that is interesting. // same = true; continue; } c.flags |= REWRITE; c.parents = new RevCommit[] { p }; return(false); } if (chgs_1[i_2] == adds_1[i_2]) { // All of the differences from this parent were because we // added files that they did not have. This parent is our // "empty tree root" and thus their history is not relevant. // Cut our grandparents to be an empty list. // pList[i_2].parents = RevCommit.NO_PARENTS; } // We have an interesting difference relative to this parent. // diff = true; } if (diff && !same) { // We did not abort above, so we are different in at least one // way from all of our parents. We have to take the blame for // that difference. // return(true); } // We are the same as all of our parents. We must keep them // as they are and allow those parents to flow into pending // for further scanning. // c.flags |= REWRITE; return(false); }
public override bool include(TreeWalk walker) { if (walker == null) throw new ArgumentNullException ("walker"); int n = paths.Length; for (int i = 0; ; ) { byte[] r = paths[i].pathRaw; int cmp = walker.isPathPrefix(r, r.Length); if (cmp == 0) return true; if (++i < n) continue; if (cmp > 0) throw StopWalkException.INSTANCE; return false; } }
public override bool include(TreeWalk walker) { return(a.include(walker) && b.include(walker)); }
public override bool include(TreeWalk walker) { return walker.isPathPrefix(pathRaw, pathRaw.Length) == 0; }
/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> public override bool Include(TreeWalk walker) { return(a.Include(walker) || b.Include(walker)); }
public static RevCommit[] Blame(NGit.Repository repo, RevCommit commit, string file) { string localFile = ToGitPath(repo, file); TreeWalk tw = TreeWalk.ForPath(repo, localFile, commit.Tree); if (tw == null) { return(new RevCommit [0]); } int totalLines = GetFileLineCount(repo, tw); int lineCount = totalLines; RevCommit[] lines = new RevCommit [lineCount]; RevWalk revWalker = new RevWalk(repo); revWalker.MarkStart(commit); List <RevCommit> commitHistory = new List <RevCommit>(); FilePath localCpath = FromGitPath(repo, localFile); foreach (RevCommit ancestorCommit in revWalker) { foreach (Change change in GetCommitChanges(repo, ancestorCommit)) { FilePath cpath = FromGitPath(repo, change.Path); if (change.ChangeType != ChangeType.Deleted && (localCpath == cpath || cpath.IsChildPathOf(localCpath))) { commitHistory.Add(ancestorCommit); break; } } } int historySize = commitHistory.Count; if (historySize > 1) { RevCommit recentCommit = commitHistory[0]; RawText latestRawText = GetRawText(repo, localFile, recentCommit); for (int i = 1; i < historySize; i++) { RevCommit ancestorCommit = commitHistory[i]; RawText ancestorRawText = GetRawText(repo, localFile, ancestorCommit); lineCount -= SetBlameLines(repo, lines, recentCommit, latestRawText, ancestorRawText); recentCommit = ancestorCommit; if (lineCount <= 0) { break; } } if (lineCount > 0) { RevCommit firstCommit = commitHistory[historySize - 1]; for (int i = 0; i < totalLines; i++) { if (lines[i] == null) { lines[i] = firstCommit; } } } } else if (historySize == 1) { RevCommit firstCommit = commitHistory[0]; for (int i = 0; i < totalLines; i++) { lines[i] = firstCommit; } } return(lines); }
/** * Determine if the current entry is interesting to report. * <p> * This method is consulted for subtree entries even if * {@link TreeWalk#isRecursive()} is enabled. The consultation allows the * filter to bypass subtree recursion on a case-by-case basis, even when * recursion is enabled at the application level. * * @param walker * the walker the filter needs to examine. * @return true if the current entry should be seen by the application; * false to hide the entry. * @throws MissingObjectException * an object the filter needs to consult to determine its answer * does not exist in the Git repository the walker is operating * on. Filtering this current walker entry is impossible without * the object. * @throws IncorrectObjectTypeException * an object the filter needed to consult was not of the * expected object type. This usually indicates a corrupt * repository, as an object link is referencing the wrong type. * @throws IOException * a loose object or pack file could not be read to obtain data * necessary for the filter to make its decision. */ public abstract bool include(TreeWalk walker);
/// <exception cref="NGit.Errors.CorruptObjectException"></exception> private void BeginWalk() { walk = new TreeWalk(db); walk.AddTree(new FileTreeIterator(db)); }
public override bool include(TreeWalk walker) { int n = walker.getTreeCount(); if (n == 1) // Assume they meant difference to empty tree. return true; int m = walker.getRawMode(baseTree); for (int i = 1; i < n; i++) if (walker.getRawMode(i) != m || !walker.idEqual(i, baseTree)) return true; return false; }
public override bool Include(TreeWalk walker) { return(walker.IsPathPrefix(pathRaw, pathRaw.Length) == 0); }
/// <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 WorkingTreeIterator WorkingTree(TreeWalk tw) { return(tw.GetTree <WorkingTreeIterator>(workingTree)); }
private DirCacheEntry ToEntry(int stage, TreeWalk tw) { DirCacheEntry e = new DirCacheEntry(tw.RawPath, stage); AbstractTreeIterator i; i = tw.GetTree<AbstractTreeIterator>(0); e.FileMode = tw.GetFileMode(0); e.SetObjectIdFromRaw(i.IdBuffer, i.IdOffset); return e; }
/// <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); }
public static List<GitData_File> gitData_Files(this API_NGit nGit, int max_FilesToShow, string commitSha1) { var gitData_Files = new List<GitData_File>(); try { var headCommit = nGit.Repository.Resolve(commitSha1); if (commitSha1.notNull()) { var revWalk = new RevWalk(nGit.Repository); var commit = revWalk.ParseCommit(headCommit); var treeWalk = new TreeWalk(nGit.Repository); var tree = commit.Tree; treeWalk.AddTree(tree); treeWalk.Recursive = true; while (treeWalk.Next() && (max_FilesToShow == -1) || gitData_Files.size() < max_FilesToShow) gitData_Files.add_File(treeWalk); //repoFiles.Add(treeWalk.PathString); } } catch(Exception ex) { ex.log("[API_NGit][gitData_Files]"); } return gitData_Files; }
// reduce the visibility of the default constructor /// <summary>Convert the TreeWalk into DiffEntry headers.</summary> /// <remarks>Convert the TreeWalk into DiffEntry headers.</remarks> /// <param name="walk">the TreeWalk to walk through. Must have exactly two trees.</param> /// <returns>headers describing the changed files.</returns> /// <exception cref="System.IO.IOException">the repository cannot be accessed.</exception> /// <exception cref="System.ArgumentException">When given TreeWalk doesn't have exactly two trees. /// </exception> public static IList <NGit.Diff.DiffEntry> Scan(TreeWalk walk) { return(Scan(walk, false)); }
public override bool include(TreeWalk walker) { if (walker == null) throw new ArgumentNullException ("walker"); int cmp = walker.isPathPrefix(raw, raw.Length); if (cmp > 0) throw StopWalkException.INSTANCE; return cmp == 0; }
/// <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.EntryFileMode; bool objectExists = (dcTree != null && fTree.IdEqual(dcTree)) || (hTree != null && fTree.IdEqual(hTree)); if (objectExists) { dcEntry.SetObjectId(fTree.EntryObjectId); } else { // insert object if (inserter == null) { inserter = repo.NewObjectInserter(); } InputStream inputStream = fTree.OpenEntryStream(); try { dcEntry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, entryLength, inputStream) ); } finally { inputStream.Close(); } } // update index dcEditor.Add(new _PathEdit_359(dcEntry, path)); // add to temporary in-core index dcBuilder.Add(dcEntry); if (emptyCommit && (hTree == null || !hTree.IdEqual(fTree))) { // 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); }
public override bool include(TreeWalk walker) { return true; }
} // End Function GetDiff // https://stackoverflow.com/questions/13537734/how-to-use-jgit-to-get-list-of-changed-files // https://github.com/centic9/jgit-cookbook/blob/master/src/main/java/org/dstadler/jgit/porcelain/ShowChangedFilesBetweenCommits.java public static void GetChanges(Git git, Repository repo, RevCommit oldCommit, RevCommit newCommit) { System.Console.WriteLine("Printing diff between commit: " + oldCommit.ToString() + " and " + newCommit.ToString()); ObjectReader reader = repo.NewObjectReader(); // prepare the two iterators to compute the diff between CanonicalTreeParser oldTreeIter = new CanonicalTreeParser(); oldTreeIter.Reset(reader, oldCommit.Tree.Id); CanonicalTreeParser newTreeIter = new CanonicalTreeParser(); newTreeIter.Reset(reader, newCommit.Tree.Id); // DiffStatFormatter df = new DiffStatFormatter(newCommit.Name, repo); using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { DiffFormatter diffFormatter = new DiffFormatter(ms); diffFormatter.SetRepository(repo); int entryCount = 0; foreach (DiffEntry entry in diffFormatter.Scan(oldCommit, newCommit)) { string pathToUse = null; TreeWalk treeWalk = new TreeWalk(repo); treeWalk.Recursive = true; if (entry.GetChangeType() == DiffEntry.ChangeType.DELETE) { treeWalk.AddTree(oldCommit.Tree); pathToUse = entry.GetOldPath(); } else { treeWalk.AddTree(newCommit.Tree); pathToUse = entry.GetNewPath(); } treeWalk.Filter = PathFilter.Create(pathToUse); if (!treeWalk.Next()) { throw new System.Exception("Did not find expected file '" + pathToUse + "'"); } ObjectId objectId = treeWalk.GetObjectId(0); ObjectLoader loader = repo.Open(objectId); string strModifiedFile = ReadFile(loader); System.Console.WriteLine(strModifiedFile); ////////////// // https://stackoverflow.com/questions/27361538/how-to-show-changes-between-commits-with-jgit diffFormatter.Format(diffFormatter.ToFileHeader(entry)); string diff = GetDiff(repo, entry); System.Console.WriteLine(diff); entryCount++; } // Next entry System.Console.WriteLine(entryCount); ms.Position = 0; using (System.IO.StreamReader sr = new System.IO.StreamReader(ms)) { string strAllDiffs = sr.ReadToEnd(); System.Console.WriteLine(strAllDiffs); } // End Using sr } // End Using ms System.Collections.Generic.IList<DiffEntry> diffs = git.Diff() .SetNewTree(newTreeIter) .SetOldTree(oldTreeIter) .Call(); foreach (DiffEntry entry in diffs) { System.Console.WriteLine("Entry: " + entry); System.Console.WriteLine("Entry: " + entry.GetChangeType()); } // Next entry System.Console.WriteLine("Done"); } // End Sub GetChanges
/// <summary>Recursively add an entire tree into this builder.</summary> /// <remarks> /// Recursively add an entire tree into this builder. /// <p> /// If pathPrefix is "a/b" and the tree contains file "c" then the resulting /// DirCacheEntry will have the path "a/b/c". /// <p> /// All entries are inserted at stage 0, therefore assuming that the /// application will not insert any other paths with the same pathPrefix. /// </remarks> /// <param name="pathPrefix"> /// UTF-8 encoded prefix to mount the tree's entries at. If the /// path does not end with '/' one will be automatically inserted /// as necessary. /// </param> /// <param name="stage">stage of the entries when adding them.</param> /// <param name="reader"> /// reader the tree(s) will be read from during recursive /// traversal. This must be the same repository that the resulting /// DirCache would be written out to (or used in) otherwise the /// caller is simply asking for deferred MissingObjectExceptions. /// Caller is responsible for releasing this reader when done. /// </param> /// <param name="tree"> /// the tree to recursively add. This tree's contents will appear /// under <code>pathPrefix</code>. The ObjectId must be that of a /// tree; the caller is responsible for dereferencing a tag or /// commit (if necessary). /// </param> /// <exception cref="System.IO.IOException">a tree cannot be read to iterate through its entries. /// </exception> public virtual void AddTree(byte[] pathPrefix, int stage, ObjectReader reader, AnyObjectId tree) { TreeWalk tw = new TreeWalk(reader); tw.AddTree(new CanonicalTreeParser(pathPrefix, reader, tree.ToObjectId())); tw.Recursive = true; if (tw.Next()) { DirCacheEntry newEntry = ToEntry(stage, tw); BeforeAdd(newEntry); FastAdd(newEntry); while (tw.Next()) { FastAdd(ToEntry(stage, tw)); } } }
/// <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)); }
public virtual void TestFindObjects() { DirCache tree0 = DirCache.NewInCore(); DirCacheBuilder b0 = tree0.Builder(); ObjectReader or = db.NewObjectReader(); ObjectInserter oi = db.NewObjectInserter(); DirCacheEntry aDotB = CreateEntry("a.b", EXECUTABLE_FILE); b0.Add(aDotB); DirCacheEntry aSlashB = CreateEntry("a/b", REGULAR_FILE); b0.Add(aSlashB); DirCacheEntry aSlashCSlashD = CreateEntry("a/c/d", REGULAR_FILE); b0.Add(aSlashCSlashD); DirCacheEntry aZeroB = CreateEntry("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(); }
public BinarySearchTree(BinaryTreeNode <T> rootNode, TreeWalk walk) : this(rootNode) { this.TreeWalk = walk; }