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 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 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 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)); }
/// <exception cref="NGit.Errors.CorruptObjectException"></exception> /// <exception cref="System.IO.IOException"></exception> private bool IsModified(string path) { NameConflictTreeWalk tw = new NameConflictTreeWalk(repo); tw.AddTree(new DirCacheIterator(dc)); tw.AddTree(new FileTreeIterator(repo)); tw.Recursive = true; tw.Filter = PathFilter.Create(path); DirCacheIterator dcIt; WorkingTreeIterator wtIt; while (tw.Next()) { dcIt = tw.GetTree <DirCacheIterator>(0); wtIt = tw.GetTree <WorkingTreeIterator>(1); if (dcIt == null || wtIt == null) { return(true); } if (wtIt.IsModified(dcIt.GetDirCacheEntry(), true)) { return(true); } } return(false); }
/// <summary> /// Create a generator and advance it to the submodule entry at the given /// path /// </summary> /// <param name="repository"></param> /// <param name="treeId"> /// the root of a tree containing both a submodule at the given path /// and .gitmodules at the root. /// </param> /// <param name="path"></param> /// <returns>generator at given path, null if no submodule at given path</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public static NGit.Submodule.SubmoduleWalk ForPath(Repository repository, AnyObjectId treeId, string path) { NGit.Submodule.SubmoduleWalk generator = new NGit.Submodule.SubmoduleWalk(repository ); try { generator.SetTree(treeId); PathFilter filter = PathFilter.Create(path); generator.SetFilter(filter); generator.SetRootTree(treeId); while (generator.Next()) { if (filter.IsDone(generator.walk)) { return(generator); } } } catch (IOException e) { generator.Release(); throw; } generator.Release(); return(null); }
/// <summary>Open a tree walk and filter to exactly one path.</summary> /// <remarks> /// Open a tree walk and filter to exactly one path. /// <p> /// The returned tree walk is already positioned on the requested path, so /// the caller should not need to invoke /// <see cref="Next()">Next()</see> /// unless they are /// looking for a possible directory/file name conflict. /// </remarks> /// <param name="reader">the reader the walker will obtain tree data from.</param> /// <param name="path">single path to advance the tree walk instance into.</param> /// <param name="trees">one or more trees to walk through, all with the same root.</param> /// <returns> /// a new tree walk configured for exactly this one path; null if no /// path was found in any of the trees. /// </returns> /// <exception cref="System.IO.IOException">reading a pack file or loose object failed. /// </exception> /// <exception cref="NGit.Errors.CorruptObjectException"> /// an tree object could not be read as its data stream did not /// appear to be a tree, or could not be inflated. /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">an object we expected to be a tree was not a tree. /// </exception> /// <exception cref="NGit.Errors.MissingObjectException">a tree object was not found. /// </exception> public static NGit.Treewalk.TreeWalk ForPath(NGit.ObjectReader reader, string path , params AnyObjectId[] trees) { NGit.Treewalk.TreeWalk tw = new NGit.Treewalk.TreeWalk(reader); PathFilter f = PathFilter.Create(path); tw.Filter = f; tw.Reset(trees); tw.Recursive = false; while (tw.Next()) { if (f.IsDone(tw)) { return(tw); } else { if (tw.IsSubtree) { tw.EnterSubtree(); } } } return(null); }
/// <summary>Create a blame generator for the repository and path</summary> /// <param name="repository">repository to access revision data from.</param> /// <param name="path">initial path of the file to start scanning.</param> public BlameGenerator(Repository repository, string path) { this.repository = repository; this.resultPath = PathFilter.Create(path); idBuf = new MutableObjectId(); SetFollowFileRenames(true); InitRevPool(false); remaining = -1; }
public GitFileStatus GetFileStatusNoCache(string fileName) { if (Directory.Exists(fileName)) { return(GitFileStatus.Ignored); } var fileNameRel = GetRelativeFileNameForGit(fileName); TreeWalk treeWalk = new TreeWalk(this.repository) { Recursive = true }; RevTree revTree = head == null ? null : new RevWalk(repository).ParseTree(head); if (revTree != null) { treeWalk.AddTree(revTree); } else { treeWalk.AddTree(new EmptyTreeIterator()); } treeWalk.AddTree(new DirCacheIterator(dirCache)); treeWalk.AddTree(new FileTreeIterator(this.repository)); var filters = new TreeFilter[] { PathFilter.Create(fileNameRel), new SkipWorkTreeFilter(INDEX), new IndexDiffFilter(INDEX, WORKDIR) }; treeWalk.Filter = AndTreeFilter.Create(filters); var status = GitFileStatus.NotControlled; if (treeWalk.Next()) { status = GetFileStatus(treeWalk); } if (status == GitFileStatus.NotControlled) { var dirCacheEntry2 = dirCache.GetEntry(fileNameRel); if (dirCacheEntry2 != null) { var treeEntry2 = TreeWalk.ForPath(repository, fileNameRel, revTree); if (treeEntry2 != null && treeEntry2.GetObjectId(0).Equals(dirCacheEntry2.GetObjectId())) { return(GitFileStatus.Tracked); } } } return(GitFileStatus.NotControlled); }
/// <exception cref="System.IO.IOException"></exception> private bool ProcessOne(Candidate n) { RevCommit parent = n.GetParent(0); if (parent == null) { return(Split(n.GetNextCandidate(0), n)); } if (parent.Has(SEEN)) { return(false); } revPool.ParseHeaders(parent); if (Find(parent, n.sourcePath)) { if (idBuf.Equals(n.sourceBlob)) { // The common case of the file not being modified in // a simple string-of-pearls history. Blame parent. n.sourceCommit = parent; Push(n); return(false); } Candidate next = n.Create(parent, n.sourcePath); next.sourceBlob = idBuf.ToObjectId(); next.LoadText(reader); return(Split(next, n)); } if (n.sourceCommit == null) { return(Result(n)); } DiffEntry r = FindRename(parent, n.sourceCommit, n.sourcePath); if (r == null) { return(Result(n)); } if (0 == r.GetOldId().PrefixCompare(n.sourceBlob)) { // A 100% rename without any content change can also // skip directly to the parent. n.sourceCommit = parent; n.sourcePath = PathFilter.Create(r.GetOldPath()); Push(n); return(false); } Candidate next_1 = n.Create(parent, PathFilter.Create(r.GetOldPath())); next_1.sourceBlob = r.GetOldId().ToObjectId(); next_1.renameScore = r.GetScore(); next_1.LoadText(reader); return(Split(next_1, n)); }
private static string GetCommitDiff(Repository repository, Git git, RevCommit rev, String file) { //Fetch diffrence of commit OutputStream @out = new ByteArrayOutputStream(); DiffCommand diff1 = git.Diff().SetPathFilter(PathFilter.Create(file)).SetOldTree(GetTreeIterator(rev.GetParent(0).Tree.Name, repository)).SetNewTree(GetTreeIterator(rev.Tree.Name, repository)).SetOutputStream(@out); IList <DiffEntry> entries = diff1.Call(); string data = @out.ToString(); data = System.Text.RegularExpressions.Regex.Replace(data, "[^a-zA-Z.]+", " ");//[^0-9a-zA-Z.] data = RemoveStopWords(data); return(data); }
public const string BaseFileForDependency = "CatalogController.cs";// "defaultResources.nopres.xml"; public static string GetCommitDiff(Repository repository, Git git, RevCommit rev, String file) { string snapshotN = GetSnapshot(repository, git, rev.GetParent(0).Tree, file); string snapshotNPlusOne = GetSnapshot(repository, git, rev.Tree, file); //Fetch diffrence of commit OutputStream @out = new ByteArrayOutputStream(); DiffCommand diff = git.Diff().SetPathFilter(PathFilter.Create(file)).SetOldTree(GetTreeIterator(rev.GetParent(0).Tree.Name, repository)).SetNewTree(GetTreeIterator(rev.Tree.Name, repository)).SetOutputStream(@out); IList <DiffEntry> entries = diff.Call(); return(@out.ToString()); }
/// <summary> /// Load the config for this walk from /// <code>.gitmodules</code> /// . /// <p> /// Uses the root tree if /// <see cref="SetRootTree(NGit.Treewalk.AbstractTreeIterator)">SetRootTree(NGit.Treewalk.AbstractTreeIterator) /// </see> /// was /// previously called, otherwise uses the working tree. /// <p> /// If no submodule config is found, loads an empty config. /// </summary> /// <returns>this generator</returns> /// <exception cref="System.IO.IOException">if an error occurred, or if the repository is bare /// </exception> /// <exception cref="NGit.Errors.ConfigInvalidException">NGit.Errors.ConfigInvalidException /// </exception> public virtual NGit.Submodule.SubmoduleWalk LoadModulesConfig() { if (rootTree == null) { FilePath modulesFile = new FilePath(repository.WorkTree, Constants.DOT_GIT_MODULES ); FileBasedConfig config = new FileBasedConfig(modulesFile, repository.FileSystem); config.Load(); modulesConfig = config; } else { TreeWalk configWalk = new TreeWalk(repository); try { configWalk.AddTree(rootTree); // The root tree may be part of the submodule walk, so we need to revert // it after this walk. int idx; for (idx = 0; !rootTree.First; idx++) { rootTree.Back(1); } try { configWalk.Recursive = false; PathFilter filter = PathFilter.Create(Constants.DOT_GIT_MODULES); configWalk.Filter = filter; while (configWalk.Next()) { if (filter.IsDone(configWalk)) { modulesConfig = new BlobBasedConfig(null, repository, configWalk.GetObjectId(0)); return(this); } } modulesConfig = new Config(); } finally { if (idx > 0) { rootTree.Next(idx); } } } finally { configWalk.Release(); } } return(this); }
public ActionResult FileDiff(string path, string fromSha1, string toSha1) { var nGit = TM_UserData_Git.Current.NGit; Func <Repository, string, string, string, string> getDiff = (gitRepo, repoPath, fromCommitId, toCommitId) => { var fromCommit = gitRepo.Resolve(fromCommitId); var toCommit = gitRepo.Resolve(toCommitId); var outputStream = "Sharpen.dll".assembly().type("ByteArrayOutputStream").ctor(new object[0]).cast <OutputStream>(); //return "diffing from {0} to {1}".format(fromCommit, toCommit); var diffFormater = new DiffFormatter(outputStream); var pathFilter = PathFilter.Create(repoPath); diffFormater.SetRepository(gitRepo); diffFormater.SetPathFilter(pathFilter); //diffFormater.Format(refLog.GetNewId(), refLog.GetOldId()); diffFormater.Format(fromCommit, toCommit); return("result: " + outputStream.str()); }; Func <Repository, string, string, string> getFistValue = (gitRepo, commitSha1, repoPath) => { var revCommit = nGit.commit(commitSha1); var outputStream = "Sharpen.dll".assembly().type("ByteArrayOutputStream").ctor(new object[0]).cast <OutputStream>(); var diffFormater = new DiffFormatter(outputStream); var pathFilter = PathFilter.Create(repoPath); diffFormater.SetRepository(gitRepo); diffFormater.SetPathFilter(pathFilter); var revWalk = new RevWalk(gitRepo); var canonicalTreeParser = new CanonicalTreeParser(null, revWalk.GetObjectReader(), revCommit.Tree); diffFormater.Format(new EmptyTreeIterator(), canonicalTreeParser); return(outputStream.str().fix_CRLF()); }; var rawDiff = fromSha1 == NGit_Consts.EMPTY_SHA1 ? getFistValue(nGit.repository(), fromSha1, path) : getDiff(nGit.repository(), path, fromSha1, toSha1); var viewFile = new View_GitFileDiff() { FilePath = path, FromSha1 = fromSha1, ToSha1 = toSha1, Diff = rawDiff }; return(View(viewFile)); }
/// <summary>Determine the differences between two trees.</summary> /// <remarks> /// Determine the differences between two trees. /// No output is created, instead only the file paths that are different are /// returned. Callers may choose to format these paths themselves, or convert /// them into /// <see cref="NGit.Patch.FileHeader">NGit.Patch.FileHeader</see> /// instances with a complete edit list by /// calling /// <see cref="ToFileHeader(DiffEntry)">ToFileHeader(DiffEntry)</see> /// . /// </remarks> /// <param name="a">the old (or previous) side.</param> /// <param name="b">the new (or updated) side.</param> /// <returns>the paths that are different.</returns> /// <exception cref="System.IO.IOException">trees cannot be read or file contents cannot be read. /// </exception> public virtual IList <DiffEntry> Scan(AbstractTreeIterator a, AbstractTreeIterator b) { AssertHaveRepository(); TreeWalk walk = new TreeWalk(reader); walk.AddTree(a); walk.AddTree(b); walk.Recursive = true; TreeFilter filter = GetDiffTreeFilterFor(a, b); if (pathFilter is FollowFilter) { walk.Filter = AndTreeFilter.Create(PathFilter.Create(((FollowFilter)pathFilter).GetPath ()), filter); } else { walk.Filter = AndTreeFilter.Create(pathFilter, filter); } source = new ContentSource.Pair(Source(a), Source(b)); IList <DiffEntry> files = DiffEntry.Scan(walk); if (pathFilter is FollowFilter && IsAdd(files)) { // The file we are following was added here, find where it // came from so we can properly show the rename or copy, // then continue digging backwards. // a.Reset(); b.Reset(); walk.Reset(); walk.AddTree(a); walk.AddTree(b); walk.Filter = filter; if (renameDetector == null) { SetDetectRenames(true); } files = UpdateFollowFilter(DetectRenames(DiffEntry.Scan(walk))); } else { if (renameDetector != null) { files = DetectRenames(files); } } return(files); }
/// <exception cref="System.IO.IOException"></exception> private void Seek(string path) { if (!path.Equals(current)) { iterator.Reset(); tw.Reset(); tw.AddTree(iterator); tw.Filter = PathFilter.Create(path); current = path; if (!tw.Next()) { throw new FileNotFoundException(path); } ptr = tw.GetTree <WorkingTreeIterator>(0); if (ptr == null) { throw new FileNotFoundException(path); } } }
public virtual void GeneratorFilteredToOneOfTwoSubmodules() { ObjectId id1 = ObjectId.FromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); string path1 = "sub1"; ObjectId id2 = ObjectId.FromString("abcd1234abcd1234abcd1234abcd1234abcd1235"); string path2 = "sub2"; DirCache cache = db.LockDirCache(); DirCacheEditor editor = cache.Editor(); editor.Add(new _PathEdit_271(id1, path1)); editor.Add(new _PathEdit_278(id2, path2)); editor.Commit(); SubmoduleWalk gen = SubmoduleWalk.ForIndex(db); gen.SetFilter(PathFilter.Create(path1)); NUnit.Framework.Assert.IsTrue(gen.Next()); NUnit.Framework.Assert.AreEqual(path1, gen.GetPath()); NUnit.Framework.Assert.AreEqual(id1, gen.GetObjectId()); NUnit.Framework.Assert.IsFalse(gen.Next()); }
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); }
/// <summary>Is the configured already a submodule in the index?</summary> /// <returns>true if submodule exists in index, false otherwise</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> protected internal virtual bool SubmoduleExists() { TreeFilter filter = PathFilter.Create(path); return(SubmoduleWalk.ForIndex(repo).SetFilter(filter).Next()); }
/// <summary>Create a new tree filter for a user supplied path.</summary> /// <remarks> /// Create a new tree filter for a user supplied path. /// <p> /// Path strings are relative to the root of the repository. If the user's /// input should be assumed relative to a subdirectory of the repository the /// caller must prepend the subdirectory's path prior to creating the filter. /// <p> /// Path strings use '/' to delimit directories on all platforms. /// </remarks> /// <param name="path"> /// the path to filter on. Must not be the empty string. All /// trailing '/' characters will be trimmed before string's length /// is checked or is used as part of the constructed filter. /// </param> /// <returns>a new filter for the requested path.</returns> /// <exception cref="System.ArgumentException">the path supplied was the empty string. /// </exception> public static NGit.Revwalk.FollowFilter Create(string path) { return(new NGit.Revwalk.FollowFilter(PathFilter.Create(path))); }
public virtual void TestDiffTwoCommits() { Write(new FilePath(db.WorkTree, "test.txt"), "test"); FilePath folder = new FilePath(db.WorkTree, "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"); git.Add().AddFilepattern(".").Call(); git.Commit().SetMessage("second commit").Call(); Write(new FilePath(folder, "folder.txt"), "second folder change"); git.Add().AddFilepattern(".").Call(); git.Commit().SetMessage("third commit").Call(); // bad filter DiffCommand diff = git.Diff().SetShowNameAndStatusOnly(true).SetPathFilter(PathFilter .Create("test.txt")).SetOldTree(GetTreeIterator("HEAD^^")).SetNewTree(GetTreeIterator ("HEAD^")); IList <DiffEntry> entries = diff.Call(); NUnit.Framework.Assert.AreEqual(0, entries.Count); // no filter, two commits OutputStream @out = new ByteArrayOutputStream(); diff = git.Diff().SetOutputStream(@out).SetOldTree(GetTreeIterator("HEAD^^")).SetNewTree (GetTreeIterator("HEAD^")); entries = diff.Call(); NUnit.Framework.Assert.AreEqual(1, entries.Count); NUnit.Framework.Assert.AreEqual(DiffEntry.ChangeType.MODIFY, entries[0].GetChangeType ()); NUnit.Framework.Assert.AreEqual("folder/folder.txt", entries[0].GetOldPath()); NUnit.Framework.Assert.AreEqual("folder/folder.txt", entries[0].GetNewPath()); string actual = @out.ToString(); 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); }
/// <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; } } } } } }
/// <summary>Show only commits that affect any of the specified paths.</summary> /// <remarks> /// Show only commits that affect any of the specified paths. The path must /// either name a file or a directory exactly. Note that regex expressions or /// wildcards are not supported. /// </remarks> /// <param name="path">a path is relative to the top level of the repository</param> /// <returns> /// /// <code>this</code> /// </returns> public virtual NGit.Api.LogCommand AddPath(string path) { CheckCallable(); pathFilters.AddItem(PathFilter.Create(path)); return(this); }
} // 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
public static void MergeTest(EngineContext engineContext) { // TODO: Currently hardcoded var db = new FileRepository(new FilePath(@"C:\DEV\hotei_scene", Constants.DOT_GIT)); var git = new Git(db); var tree1Ref = db.GetRef("test"); var tree2Ref = db.GetRef(Constants.HEAD); var tree1CommitId = tree1Ref.GetObjectId(); var tree2CommitId = tree2Ref.GetObjectId(); // Merge tree1 into current tree var mergeResult = git.Merge().Include(tree1CommitId).Call(); if (mergeResult.GetMergeStatus() == MergeStatus.CONFLICTING) { foreach (var conflict in mergeResult.GetConflicts()) { if (conflict.Key.EndsWith(".hotei")) { // Search base tree (common ancestor), if any var walk = new RevWalk(db); walk.SetRevFilter(RevFilter.MERGE_BASE); walk.MarkStart(walk.ParseCommit(tree1CommitId)); walk.MarkStart(walk.ParseCommit(tree2CommitId)); var baseTree = walk.Next(); var tw = new NameConflictTreeWalk(db); tw.AddTree(new RevWalk(db).ParseTree(tree1CommitId).ToObjectId()); tw.AddTree(new RevWalk(db).ParseTree(tree2CommitId).ToObjectId()); if (baseTree != null) { tw.AddTree(new RevWalk(db).ParseTree(baseTree.ToObjectId()).ToObjectId()); } tw.Filter = PathFilter.Create(conflict.Key); // Should be only one iteration while (tw.Next()) { var tree0 = baseTree != null?tw.GetTree <AbstractTreeIterator>(2) : null; var tree1 = tw.GetTree <AbstractTreeIterator>(0); var tree2 = tw.GetTree <AbstractTreeIterator>(1); // Get contents of every versions for the 3-way merge var data0 = baseTree != null?LoadEntities(new MemoryStream(tw.ObjectReader.Open(tree0.EntryObjectId).GetBytes())) : null; var data1 = LoadEntities(new MemoryStream(tw.ObjectReader.Open(tree1.EntryObjectId).GetBytes())); var data2 = LoadEntities(new MemoryStream(tw.ObjectReader.Open(tree2.EntryObjectId).GetBytes())); // Perform 3-way merge var entities = new List <EntityDefinition>(); ThreeWayMergeOrdered.Merge(entities, data0, data1, data2, x => x.Guid, (x, y) => x == y, ResolveEntityConflicts); // Save new merged file var fileStream = new FileStream(new FilePath(db.WorkTree, conflict.Key), FileMode.Create, FileAccess.Write); var stream = new BinarySerializationWriter(fileStream); stream.Context.Serializer = Serializer; stream.SerializeClass(null, ref entities, ArchiveMode.Serialize); fileStream.Close(); // TODO: Check if all conflicts are really resolved // Add resolved file for merge commit git.Add().AddFilepattern(conflict.Key).Call(); } } } } }
/// <exception cref="System.IO.IOException"></exception> private bool ProcessMerge(Candidate n) { int pCnt = n.GetParentCount(); for (int pIdx = 0; pIdx < pCnt; pIdx++) { RevCommit parent = n.GetParent(pIdx); if (parent.Has(SEEN)) { continue; } revPool.ParseHeaders(parent); } // If any single parent exactly matches the merge, follow only // that one parent through history. ObjectId[] ids = null; for (int pIdx_1 = 0; pIdx_1 < pCnt; pIdx_1++) { RevCommit parent = n.GetParent(pIdx_1); if (parent.Has(SEEN)) { continue; } if (!Find(parent, n.sourcePath)) { continue; } if (!(n is Candidate.ReverseCandidate) && idBuf.Equals(n.sourceBlob)) { n.sourceCommit = parent; Push(n); return(false); } if (ids == null) { ids = new ObjectId[pCnt]; } ids[pIdx_1] = idBuf.ToObjectId(); } // If rename detection is enabled, search for any relevant names. DiffEntry[] renames = null; if (renameDetector != null) { renames = new DiffEntry[pCnt]; for (int pIdx_2 = 0; pIdx_2 < pCnt; pIdx_2++) { RevCommit parent = n.GetParent(pIdx_2); if (parent.Has(SEEN)) { continue; } if (ids != null && ids[pIdx_2] != null) { continue; } DiffEntry r = FindRename(parent, n.sourceCommit, n.sourcePath); if (r == null) { continue; } if (n is Candidate.ReverseCandidate) { if (ids == null) { ids = new ObjectId[pCnt]; } ids[pCnt] = r.GetOldId().ToObjectId(); } else { if (0 == r.GetOldId().PrefixCompare(n.sourceBlob)) { // A 100% rename without any content change can also // skip directly to the parent. Note this bypasses an // earlier parent that had the path (above) but did not // have an exact content match. For performance reasons // we choose to follow the one parent over trying to do // possibly both parents. n.sourceCommit = parent; n.sourcePath = PathFilter.Create(r.GetOldPath()); Push(n); return(false); } } renames[pIdx_2] = r; } } // Construct the candidate for each parent. Candidate[] parents = new Candidate[pCnt]; for (int pIdx_3 = 0; pIdx_3 < pCnt; pIdx_3++) { RevCommit parent = n.GetParent(pIdx_3); if (parent.Has(SEEN)) { continue; } Candidate p; if (renames != null && renames[pIdx_3] != null) { p = n.Create(parent, PathFilter.Create(renames[pIdx_3].GetOldPath())); p.renameScore = renames[pIdx_3].GetScore(); p.sourceBlob = renames[pIdx_3].GetOldId().ToObjectId(); } else { if (ids != null && ids[pIdx_3] != null) { p = n.Create(parent, n.sourcePath); p.sourceBlob = ids[pIdx_3]; } else { continue; } } EditList editList; if (n is Candidate.ReverseCandidate && p.sourceBlob.Equals(n.sourceBlob)) { // This special case happens on ReverseCandidate forks. p.sourceText = n.sourceText; editList = new EditList(0); } else { p.LoadText(reader); editList = diffAlgorithm.Diff(textComparator, p.sourceText, n.sourceText); } if (editList.IsEmpty()) { // Ignoring whitespace (or some other special comparator) can // cause non-identical blobs to have an empty edit list. In // a case like this push the parent alone. if (n is Candidate.ReverseCandidate) { parents[pIdx_3] = p; continue; } p.regionList = n.regionList; Push(p); return(false); } p.TakeBlame(editList, n); // Only remember this parent candidate if there is at least // one region that was blamed on the parent. if (p.regionList != null) { // Reverse blame requires inverting the regions. This puts // the regions the parent deleted from us into the parent, // and retains the common regions to look at other parents // for deletions. if (n is Candidate.ReverseCandidate) { Region r = p.regionList; p.regionList = n.regionList; n.regionList = r; } parents[pIdx_3] = p; } } if (n is Candidate.ReverseCandidate) { // On a reverse blame report all deletions found in the children, // and pass on to them a copy of our region list. Candidate resultHead = null; Candidate resultTail = null; for (int pIdx_2 = 0; pIdx_2 < pCnt; pIdx_2++) { Candidate p = parents[pIdx_2]; if (p == null) { continue; } if (p.regionList != null) { Candidate r = p.Copy(p.sourceCommit); if (resultTail != null) { resultTail.queueNext = r; resultTail = r; } else { resultHead = r; resultTail = r; } } if (n.regionList != null) { p.regionList = n.regionList.DeepCopy(); Push(p); } } if (resultHead != null) { return(Result(resultHead)); } return(false); } // Push any parents that are still candidates. for (int pIdx_4 = 0; pIdx_4 < pCnt; pIdx_4++) { if (parents[pIdx_4] != null) { Push(parents[pIdx_4]); } } if (n.regionList != null) { return(Result(n)); } return(false); }