public virtual void TestTreeIteratorWithGitmodules() { ObjectId subId = ObjectId.FromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); string path = "sub"; Config gitmodules = new Config(); gitmodules.SetString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, ConfigConstants .CONFIG_KEY_PATH, "sub"); gitmodules.SetString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, ConfigConstants .CONFIG_KEY_URL, "git://example.com/sub"); RevCommit commit = testDb.GetRevWalk().ParseCommit(testDb.Commit().NoParents().Add (Constants.DOT_GIT_MODULES, gitmodules.ToText()).Edit(new _PathEdit_397(subId, path )).Create()); CanonicalTreeParser p = new CanonicalTreeParser(); p.Reset(testDb.GetRevWalk().GetObjectReader(), commit.Tree); SubmoduleWalk gen = SubmoduleWalk.ForPath(db, p, "sub"); NUnit.Framework.Assert.AreEqual(path, gen.GetPath()); NUnit.Framework.Assert.AreEqual(subId, gen.GetObjectId()); NUnit.Framework.Assert.AreEqual(new FilePath(db.WorkTree, path), gen.GetDirectory ()); NUnit.Framework.Assert.IsNull(gen.GetConfigUpdate()); NUnit.Framework.Assert.IsNull(gen.GetConfigUrl()); NUnit.Framework.Assert.AreEqual("sub", gen.GetModulesPath()); NUnit.Framework.Assert.IsNull(gen.GetModulesUpdate()); NUnit.Framework.Assert.AreEqual("git://example.com/sub", gen.GetModulesUrl()); NUnit.Framework.Assert.IsNull(gen.GetRepository()); NUnit.Framework.Assert.IsFalse(gen.Next()); }
public override void Dispose() { base.Dispose(); _pendingObjects = new BlockObjQueue(); _treeWalk = new CanonicalTreeParser(); _currentTree = null; last = null; }
internal override void reset(int retainFlags) { base.reset(retainFlags); _pendingObjects = new BlockObjQueue(); _treeWalk = new CanonicalTreeParser(); _currentTree = null; last = null; }
/// <summary> /// Set the tree used by this walk for finding /// <code>.gitmodules</code> /// . /// <p> /// The root tree is not read until the first submodule is encountered by the /// walk. /// <p> /// This method need only be called if constructing a walk manually instead of /// with one of the static factory methods above. /// </summary> /// <param name="id">ID of a tree containing .gitmodules</param> /// <returns>this generator</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public virtual NGit.Submodule.SubmoduleWalk SetRootTree(AnyObjectId id) { CanonicalTreeParser p = new CanonicalTreeParser(); p.Reset(walk.ObjectReader, id); rootTree = p; modulesConfig = null; return(this); }
/// <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(RevTree a, RevTree b) { AssertHaveRepository(); CanonicalTreeParser aParser = new CanonicalTreeParser(); CanonicalTreeParser bParser = new CanonicalTreeParser(); aParser.Reset(reader, a); bParser.Reset(reader, b); return(Scan(aParser, bParser)); }
/// <summary>adds a new path with the specified stage to the index builder</summary> /// <param name="path"></param> /// <param name="p"></param> /// <param name="stage"></param> /// <returns>the entry which was added to the index</returns> private DirCacheEntry Add(byte[] path, CanonicalTreeParser p, int stage) { if (p != null && !p.EntryFileMode.Equals(FileMode.TREE)) { DirCacheEntry e = new DirCacheEntry(path, stage); e.FileMode = p.EntryFileMode; e.SetObjectId(p.EntryObjectId); builder.Add(e); return(e); } return(null); }
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>Does the content merge.</summary> /// <remarks> /// Does the content merge. The three texts base, ours and theirs are /// specified with /// <see cref="NGit.Treewalk.CanonicalTreeParser">NGit.Treewalk.CanonicalTreeParser</see> /// . If any of the parsers is /// specified as <code>null</code> then an empty text will be used instead. /// </remarks> /// <param name="base"></param> /// <param name="ours"></param> /// <param name="theirs"></param> /// <returns>the result of the content merge</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> private MergeResult <RawText> ContentMerge(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser theirs) { RawText baseText = @base == null ? RawText.EMPTY_TEXT : GetRawText(@base.EntryObjectId , db); RawText ourText = ours == null ? RawText.EMPTY_TEXT : GetRawText(ours.EntryObjectId , db); RawText theirsText = theirs == null ? RawText.EMPTY_TEXT : GetRawText(theirs.EntryObjectId , db); return(mergeAlgorithm.Merge(RawTextComparator.DEFAULT, baseText, ourText, theirsText )); }
private CanonicalTreeParser enter(RevObject tree) { CanonicalTreeParser p = _treeWalk.createSubtreeIterator0(Repository, tree, WindowCursor); if (p.eof()) { // We can't tolerate the subtree being an empty tree, as // that will break us out early before we visit all names. // If it is, advance to the parent's next record. // return(_treeWalk.next()); } return(p); }
internal BaseSearch(ProgressMonitor countingMonitor, ICollection <RevTree> bases, ObjectIdSubclassMap <ObjectToPack> objects, IList <ObjectToPack> edges, ObjectReader or) { progress = countingMonitor; reader = or; baseTrees = Sharpen.Collections.ToArray(bases, new ObjectId[bases.Count]); objectsMap = objects; edgeObjects = edges; alreadyProcessed = new IntSet(); treeCache = new ObjectIdSubclassMap <BaseSearch.TreeWithData>(); parser = new CanonicalTreeParser(); idBuf = new MutableObjectId(); }
private void ResetIndexForPaths(RevCommit commit) { DirCache dc = null; DirCacheEditor edit; try { dc = repo.LockDirCache(); edit = dc.Editor(); TreeWalk tw = new TreeWalk(repo); tw.AddTree(new DirCacheIterator(dc)); tw.AddTree(commit.Tree); tw.Filter = PathFilterGroup.CreateFromStrings(filepaths); tw.Recursive = true; while (tw.Next()) { string path = tw.PathString; // DirCacheIterator dci = tw.getTree(0, DirCacheIterator.class); CanonicalTreeParser tree = tw.GetTree <CanonicalTreeParser>(1); if (tree == null) { // file is not in the commit, remove from index edit.Add(new DirCacheEditor.DeletePath(path)); } else { // revert index to commit // it seams that there is concurrent access to tree // variable, therefore we need to keep references to // entryFileMode and entryObjectId in local // variables FileMode entryFileMode = tree.EntryFileMode; ObjectId entryObjectId = tree.EntryObjectId; edit.Add(new _PathEdit_305(entryFileMode, entryObjectId, path)); } } edit.Commit(); } catch (IOException e) { throw new RuntimeException(e); } finally { if (dc != null) { dc.Unlock(); } } }
/// <exception cref="System.IO.IOException"></exception> private CanonicalTreeParser Enter(RevObject tree) { CanonicalTreeParser p = treeWalk.CreateSubtreeIterator0(reader, tree); if (p.Eof) { // We can't tolerate the subtree being an empty tree, as // that will break us out early before we visit all names. // If it is, advance to the parent's next record. // return(treeWalk.Next()); } return(p); }
protected internal override void Reset(int retainFlags) { base.Reset(retainFlags); foreach (RevObject obj in rootObjects) { obj.flags &= ~IN_PENDING; } rootObjects = new AList <RevObject>(); pendingObjects = new BlockObjQueue(); treeWalk = new CanonicalTreeParser(); currentTree = null; last = null; firstCommit = null; lastCommit = null; }
/// <exception cref="NGit.Errors.MissingObjectException"></exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception> /// <exception cref="System.IO.IOException"></exception> private void MarkTreeUninteresting(RevTree tree) { if ((tree.flags & UNINTERESTING) != 0) { return; } tree.flags |= UNINTERESTING; treeWalk = treeWalk.ResetRoot(reader, tree); while (!treeWalk.Eof) { FileMode mode = treeWalk.EntryFileMode; int sType = mode.GetObjectType(); switch (sType) { case Constants.OBJ_BLOB: { treeWalk.GetEntryObjectId(idBuffer); LookupBlob(idBuffer).flags |= UNINTERESTING; break; } case Constants.OBJ_TREE: { treeWalk.GetEntryObjectId(idBuffer); RevTree t = LookupTree(idBuffer); if ((t.flags & UNINTERESTING) == 0) { t.flags |= UNINTERESTING; treeWalk = treeWalk.CreateSubtreeIterator0(reader, t); continue; } break; } default: { if (FileMode.GITLINK.Equals(mode)) { break; } treeWalk.GetEntryObjectId(idBuffer); throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().corruptObjectInvalidMode3 , mode, idBuffer.Name, treeWalk.EntryPathString, tree)); } } treeWalk = treeWalk.Next(); } }
private void MarkTreeUninteresting(RevObject tree) { if ((tree.Flags & UNINTERESTING) != 0) { return; } tree.Flags |= UNINTERESTING; _treeWalk = _treeWalk.resetRoot(Repository, tree, WindowCursor); while (!_treeWalk.eof()) { FileMode mode = _treeWalk.EntryFileMode; var sType = (int)mode.ObjectType; switch (sType) { case Constants.OBJ_BLOB: _treeWalk.getEntryObjectId(IdBuffer); lookupBlob(IdBuffer).Flags |= UNINTERESTING; break; case Constants.OBJ_TREE: _treeWalk.getEntryObjectId(IdBuffer); RevTree t = lookupTree(IdBuffer); if ((t.Flags & UNINTERESTING) == 0) { t.Flags |= UNINTERESTING; _treeWalk = _treeWalk.createSubtreeIterator0(Repository, t, WindowCursor); continue; } break; default: if (FileMode.GitLink == FileMode.FromBits(mode.Bits)) { break; } _treeWalk.getEntryObjectId(IdBuffer); throw new CorruptObjectException("Invalid mode " + mode + " for " + IdBuffer + " " + _treeWalk.EntryPathString + " in " + tree + "."); } _treeWalk = _treeWalk.next(); } }
public static IEnumerable <DiffEntry> CompareCommits(NGit.Repository repo, AnyObjectId reference, ObjectId compared) { var diff = new MyersDiff(repo); if (reference != ObjectId.ZeroId) { var firstTree = new CanonicalTreeParser(); firstTree.Reset(repo.NewObjectReader(), new RevWalk(repo).ParseTree(reference)); diff.SetOldTree(firstTree); } var secondTree = new CanonicalTreeParser(); secondTree.Reset(repo.NewObjectReader(), new RevWalk(repo).ParseTree(compared)); diff.SetNewTree(secondTree); return(diff.Call()); }
private void ResetIndexForPaths(RevCommit commit) { DirCache dc = null; DirCacheEditor edit; try { dc = repo.LockDirCache(); edit = dc.Editor(); TreeWalk tw = new TreeWalk(repo); tw.AddTree(new DirCacheIterator(dc)); tw.AddTree(commit.Tree); tw.Filter = PathFilterGroup.CreateFromStrings(filepaths); while (tw.Next()) { string path = tw.PathString; // DirCacheIterator dci = tw.getTree(0, DirCacheIterator.class); CanonicalTreeParser tree = tw.GetTree <CanonicalTreeParser>(1); if (tree == null) { // file is not in the commit, remove from index edit.Add(new DirCacheEditor.DeletePath(path)); } else { // revert index to commit edit.Add(new _PathEdit_281(tree, path)); } } edit.Commit(); } catch (IOException e) { throw new RuntimeException(e); } finally { if (dc != null) { dc.Unlock(); } } }
/// <summary>Updates the index after a content merge has happened.</summary> /// <remarks> /// Updates the index after a content merge has happened. If no conflict has /// occurred this includes persisting the merged content to the object /// database. In case of conflicts this method takes care to write the /// correct stages to the index. /// </remarks> /// <param name="base"></param> /// <param name="ours"></param> /// <param name="theirs"></param> /// <param name="result"></param> /// <param name="of"></param> /// <exception cref="System.IO.FileNotFoundException">System.IO.FileNotFoundException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> private void UpdateIndex(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser theirs, MergeResult <RawText> result, FilePath of) { if (result.ContainsConflicts()) { // a conflict occurred, the file will contain conflict markers // the index will be populated with the three stages and only the // workdir (if used) contains the halfways merged content Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0); Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0); Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0); mergeResults.Put(tw.PathString, result.Upcast()); } else { // no conflict occurred, the file will contain fully merged content. // the index will be populated with the new merged version DirCacheEntry dce = new DirCacheEntry(tw.PathString); int newMode = MergeFileModes(tw.GetRawMode(0), tw.GetRawMode(1), tw.GetRawMode(2) ); // set the mode for the new content. Fall back to REGULAR_FILE if // you can't merge modes of OURS and THEIRS dce.FileMode = (newMode == FileMode.MISSING.GetBits()) ? FileMode.REGULAR_FILE : FileMode.FromBits(newMode); dce.LastModified = of.LastModified(); dce.SetLength((int)of.Length()); InputStream @is = new FileInputStream(of); try { dce.SetObjectId(GetObjectInserter().Insert(Constants.OBJ_BLOB, of.Length(), @is)); } finally { @is.Close(); if (inCore) { FileUtils.Delete(of); } } builder.Add(dce); } }
/// <exception cref="System.IO.IOException"></exception> private AbstractTreeIterator GetTreeIterator(string name) { ObjectId id = db.Resolve(name); if (id == null) { throw new ArgumentException(name); } CanonicalTreeParser p = new CanonicalTreeParser(); ObjectReader or = db.NewObjectReader(); try { p.Reset(or, new RevWalk(db).ParseTree(id)); return(p); } finally { or.Release(); } }
private void ResetIndexForPaths(RevCommit commit) { DirCache dc = null; try { dc = repo.LockDirCache(); DirCacheBuilder builder = dc.Builder(); TreeWalk tw = new TreeWalk(repo); tw.AddTree(new DirCacheBuildIterator(builder)); tw.AddTree(commit.Tree); tw.Filter = PathFilterGroup.CreateFromStrings(filepaths); tw.Recursive = true; while (tw.Next()) { CanonicalTreeParser tree = tw.GetTree <CanonicalTreeParser>(1); // only keep file in index if it's in the commit if (tree != null) { // revert index to commit DirCacheEntry entry = new DirCacheEntry(tw.RawPath); entry.FileMode = tree.EntryFileMode; entry.SetObjectId(tree.EntryObjectId); builder.Add(entry); } } builder.Commit(); } catch (IOException e) { throw new RuntimeException(e); } finally { if (dc != null) { dc.Unlock(); } } }
public override string ToString() { byte[] raw = ToByteArray(); CanonicalTreeParser p = new CanonicalTreeParser(); p.Reset(raw); StringBuilder r = new StringBuilder(); r.Append("Tree={"); if (!p.Eof) { r.Append('\n'); try { new ObjectChecker().CheckTree(raw); } catch (CorruptObjectException error) { r.Append("*** ERROR: ").Append(error.Message).Append("\n"); r.Append('\n'); } } while (!p.Eof) { FileMode mode = p.EntryFileMode; r.Append(mode); r.Append(' '); r.Append(Constants.TypeString(mode.GetObjectType())); r.Append(' '); r.Append(p.EntryObjectId.Name); r.Append(' '); r.Append(p.EntryPathString); r.Append('\n'); p.Next(); } r.Append("}"); return(r.ToString()); }
/// <exception cref="System.IO.IOException"></exception> private DirCache CreateTemporaryIndex(ObjectId headId, DirCache index) { ObjectInserter inserter = null; // get DirCacheEditor to modify the index if required DirCacheEditor dcEditor = index.Editor(); // get DirCacheBuilder for newly created in-core index to build a // temporary index for this commit DirCache inCoreIndex = DirCache.NewInCore(); DirCacheBuilder dcBuilder = inCoreIndex.Builder(); onlyProcessed = new bool[only.Count]; bool emptyCommit = true; TreeWalk treeWalk = new TreeWalk(repo); int dcIdx = treeWalk.AddTree(new DirCacheIterator(index)); int fIdx = treeWalk.AddTree(new FileTreeIterator(repo)); int hIdx = -1; if (headId != null) { hIdx = treeWalk.AddTree(new RevWalk(repo).ParseTree(headId)); } treeWalk.Recursive = true; while (treeWalk.Next()) { string path = treeWalk.PathString; // check if current entry's path matches a specified path int pos = LookupOnly(path); CanonicalTreeParser hTree = null; if (hIdx != -1) { hTree = treeWalk.GetTree <CanonicalTreeParser>(hIdx); } if (pos >= 0) { // include entry in commit DirCacheIterator dcTree = treeWalk.GetTree <DirCacheIterator>(dcIdx); FileTreeIterator fTree = treeWalk.GetTree <FileTreeIterator>(fIdx); // check if entry refers to a tracked file bool tracked = dcTree != null || hTree != null; if (!tracked) { break; } if (fTree != null) { // create a new DirCacheEntry with data retrieved from disk DirCacheEntry dcEntry = new DirCacheEntry(path); long entryLength = fTree.GetEntryLength(); dcEntry.SetLength(entryLength); dcEntry.LastModified = fTree.GetEntryLastModified(); dcEntry.FileMode = fTree.GetIndexFileMode(dcTree); bool objectExists = (dcTree != null && fTree.IdEqual(dcTree)) || (hTree != null && fTree.IdEqual(hTree)); if (objectExists) { dcEntry.SetObjectId(fTree.EntryObjectId); } else { if (FileMode.GITLINK.Equals(dcEntry.FileMode)) { dcEntry.SetObjectId(fTree.EntryObjectId); } else { // insert object if (inserter == null) { inserter = repo.NewObjectInserter(); } long contentLength = fTree.GetEntryContentLength(); InputStream inputStream = fTree.OpenEntryStream(); try { dcEntry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, contentLength, inputStream )); } finally { inputStream.Close(); } } } // update index dcEditor.Add(new _PathEdit_375(dcEntry, path)); // add to temporary in-core index dcBuilder.Add(dcEntry); if (emptyCommit && (hTree == null || !hTree.IdEqual(fTree) || hTree.EntryRawMode != fTree.EntryRawMode)) { // this is a change emptyCommit = false; } } else { // if no file exists on disk, remove entry from index and // don't add it to temporary in-core index dcEditor.Add(new DirCacheEditor.DeletePath(path)); if (emptyCommit && hTree != null) { // this is a change emptyCommit = false; } } // keep track of processed path onlyProcessed[pos] = true; } else { // add entries from HEAD for all other paths if (hTree != null) { // create a new DirCacheEntry with data retrieved from HEAD DirCacheEntry dcEntry = new DirCacheEntry(path); dcEntry.SetObjectId(hTree.EntryObjectId); dcEntry.FileMode = hTree.EntryFileMode; // add to temporary in-core index dcBuilder.Add(dcEntry); } } } // there must be no unprocessed paths left at this point; otherwise an // untracked or unknown path has been specified for (int i = 0; i < onlyProcessed.Length; i++) { if (!onlyProcessed[i]) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().entryNotFoundByPath , only[i])); } } // there must be at least one change if (emptyCommit) { throw new JGitInternalException(JGitText.Get().emptyCommit); } // update index dcEditor.Commit(); // finish temporary in-core index used for this commit dcBuilder.Finish(); return(inCoreIndex); }
} // 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
/// <exception cref="System.IO.FileNotFoundException"></exception> /// <exception cref="System.InvalidOperationException"></exception> /// <exception cref="System.IO.IOException"></exception> private bool ContentMerge(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser theirs) { MergeFormatter fmt = new MergeFormatter(); RawText baseText = @base == null ? RawText.EMPTY_TEXT : GetRawText(@base.EntryObjectId , db); // do the merge MergeResult <RawText> result = mergeAlgorithm.Merge(RawTextComparator.DEFAULT, baseText , GetRawText(ours.EntryObjectId, db), GetRawText(theirs.EntryObjectId, db)); FilePath of = null; FileOutputStream fos; if (!inCore) { FilePath workTree = db.WorkTree; if (workTree == null) { // TODO: This should be handled by WorkingTreeIterators which // support write operations throw new NotSupportedException(); } of = new FilePath(workTree, tw.PathString); fos = new FileOutputStream(of); try { fmt.FormatMerge(fos, result, Arrays.AsList(commitNames), Constants.CHARACTER_ENCODING ); } finally { fos.Close(); } } else { if (!result.ContainsConflicts()) { // When working inCore, only trivial merges can be handled, // so we generate objects only in conflict free cases of = FilePath.CreateTempFile("merge_", "_temp", null); fos = new FileOutputStream(of); try { fmt.FormatMerge(fos, result, Arrays.AsList(commitNames), Constants.CHARACTER_ENCODING ); } finally { fos.Close(); } } } if (result.ContainsConflicts()) { // a conflict occurred, the file will contain conflict markers // the index will be populated with the three stages and only the // workdir (if used) contains the halfways merged content Add(tw.RawPath, @base, DirCacheEntry.STAGE_1); Add(tw.RawPath, ours, DirCacheEntry.STAGE_2); Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3); mergeResults.Put(tw.PathString, result.Upcast()); return(false); } else { // no conflict occurred, the file will contain fully merged content. // the index will be populated with the new merged version DirCacheEntry dce = new DirCacheEntry(tw.PathString); dce.FileMode = tw.GetFileMode(0); dce.LastModified = of.LastModified(); dce.SetLength((int)of.Length()); InputStream @is = new FileInputStream(of); try { dce.SetObjectId(oi.Insert(Constants.OBJ_BLOB, of.Length(), @is)); } finally { @is.Close(); if (inCore) { FileUtils.Delete(of); } } builder.Add(dce); return(true); } }
/// <summary>Processes one path and tries to merge.</summary> /// <remarks> /// Processes one path and tries to merge. This method will do all do all /// trivial (not content) merges and will also detect if a merge will fail. /// The merge will fail when one of the following is true /// <ul> /// <li>the index entry does not match the entry in ours. When merging one /// branch into the current HEAD, ours will point to HEAD and theirs will /// point to the other branch. It is assumed that the index matches the HEAD /// because it will only not match HEAD if it was populated before the merge /// operation. But the merge commit should not accidentally contain /// modifications done before the merge. Check the <a href= /// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge" /// >git read-tree</a> documentation for further explanations.</li> /// <li>A conflict was detected and the working-tree file is dirty. When a /// conflict is detected the content-merge algorithm will try to write a /// merged version into the working-tree. If the file is dirty we would /// override unsaved data.</li> /// </remarks> /// <param name="base">the common base for ours and theirs</param> /// <param name="ours"> /// the ours side of the merge. When merging a branch into the /// HEAD ours will point to HEAD /// </param> /// <param name="theirs"> /// the theirs side of the merge. When merging a branch into the /// current HEAD theirs will point to the branch which is merged /// into HEAD. /// </param> /// <param name="index">the index entry</param> /// <param name="work">the file in the working tree</param> /// <returns> /// <code>false</code> if the merge will fail because the index entry /// didn't match ours or the working-dir file was dirty and a /// conflict occurred /// </returns> /// <exception cref="NGit.Errors.MissingObjectException">NGit.Errors.MissingObjectException /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">NGit.Errors.IncorrectObjectTypeException /// </exception> /// <exception cref="NGit.Errors.CorruptObjectException">NGit.Errors.CorruptObjectException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser theirs, DirCacheBuildIterator index, WorkingTreeIterator work) { enterSubtree = true; int modeO = tw.GetRawMode(T_OURS); int modeT = tw.GetRawMode(T_THEIRS); int modeB = tw.GetRawMode(T_BASE); if (modeO == 0 && modeT == 0 && modeB == 0) { // File is either untracked or new, staged but uncommitted return(true); } if (IsIndexDirty()) { return(false); } if (NonTree(modeO) && modeO == modeT && tw.IdEqual(T_OURS, T_THEIRS)) { // OURS and THEIRS are equal: it doesn't matter which one we choose. // OURS is chosen. Add(tw.RawPath, ours, DirCacheEntry.STAGE_0); // no checkout needed! return(true); } if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS)) { // THEIRS was not changed compared to BASE. All changes must be in // OURS. OURS is chosen. Add(tw.RawPath, ours, DirCacheEntry.STAGE_0); // no checkout needed! return(true); } if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS)) { // OURS was not changed compared to BASE. All changes must be in // THEIRS. THEIRS is chosen. // Check worktree before checking out THEIRS if (IsWorktreeDirty()) { return(false); } if (NonTree(modeT)) { DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0); if (e != null) { toBeCheckedOut.Put(tw.PathString, e); } return(true); } else { if (modeT == 0 && modeB != 0) { // we want THEIRS ... but THEIRS contains the deletion of the // file toBeCheckedOut.Put(tw.PathString, null); return(true); } } } if (tw.IsSubtree) { // file/folder conflicts: here I want to detect only file/folder // conflict between ours and theirs. file/folder conflicts between // base/index/workingTree and something else are not relevant or // detected later if (NonTree(modeO) && !NonTree(modeT)) { if (NonTree(modeB)) { Add(tw.RawPath, @base, DirCacheEntry.STAGE_1); } Add(tw.RawPath, ours, DirCacheEntry.STAGE_2); unmergedPaths.AddItem(tw.PathString); enterSubtree = false; return(true); } if (NonTree(modeT) && !NonTree(modeO)) { if (NonTree(modeB)) { Add(tw.RawPath, @base, DirCacheEntry.STAGE_1); } Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3); unmergedPaths.AddItem(tw.PathString); enterSubtree = false; return(true); } // ours and theirs are both folders or both files (and treewalk // tells us we are in a subtree because of index or working-dir). // If they are both folders no content-merge is required - we can // return here. if (!NonTree(modeO)) { return(true); } } // ours and theirs are both files, just fall out of the if block // and do the content merge if (NonTree(modeO) && NonTree(modeT)) { // Check worktree before modifying files if (IsWorktreeDirty()) { return(false); } if (!ContentMerge(@base, ours, theirs)) { unmergedPaths.AddItem(tw.PathString); } modifiedFiles.AddItem(tw.PathString); } return(true); }
/// <summary> /// Create a new revision and object walker for a given repository. /// </summary> /// <param name="repo"> /// The repository the walker will obtain data from. /// </param> public ObjectWalk(Repository repo) : base(repo) { _pendingObjects = new BlockObjQueue(); _treeWalk = new CanonicalTreeParser(); }
/// <summary>Processes one path and tries to merge.</summary> /// <remarks> /// Processes one path and tries to merge. This method will do all do all /// trivial (not content) merges and will also detect if a merge will fail. /// The merge will fail when one of the following is true /// <ul> /// <li>the index entry does not match the entry in ours. When merging one /// branch into the current HEAD, ours will point to HEAD and theirs will /// point to the other branch. It is assumed that the index matches the HEAD /// because it will only not match HEAD if it was populated before the merge /// operation. But the merge commit should not accidentally contain /// modifications done before the merge. Check the <a href= /// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge" /// >git read-tree</a> documentation for further explanations.</li> /// <li>A conflict was detected and the working-tree file is dirty. When a /// conflict is detected the content-merge algorithm will try to write a /// merged version into the working-tree. If the file is dirty we would /// override unsaved data.</li> /// </remarks> /// <param name="base">the common base for ours and theirs</param> /// <param name="ours"> /// the ours side of the merge. When merging a branch into the /// HEAD ours will point to HEAD /// </param> /// <param name="theirs"> /// the theirs side of the merge. When merging a branch into the /// current HEAD theirs will point to the branch which is merged /// into HEAD. /// </param> /// <param name="index">the index entry</param> /// <param name="work">the file in the working tree</param> /// <returns> /// <code>false</code> if the merge will fail because the index entry /// didn't match ours or the working-dir file was dirty and a /// conflict occurred /// </returns> /// <exception cref="NGit.Errors.MissingObjectException">NGit.Errors.MissingObjectException /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">NGit.Errors.IncorrectObjectTypeException /// </exception> /// <exception cref="NGit.Errors.CorruptObjectException">NGit.Errors.CorruptObjectException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser theirs, DirCacheBuildIterator index, WorkingTreeIterator work) { enterSubtree = true; int modeO = tw.GetRawMode(T_OURS); int modeT = tw.GetRawMode(T_THEIRS); int modeB = tw.GetRawMode(T_BASE); if (modeO == 0 && modeT == 0 && modeB == 0) { // File is either untracked or new, staged but uncommitted return(true); } if (IsIndexDirty()) { return(false); } DirCacheEntry ourDce = null; if (index == null || index.GetDirCacheEntry() == null) { // create a fake DCE, but only if ours is valid. ours is kept only // in case it is valid, so a null ourDce is ok in all other cases. if (NonTree(modeO)) { ourDce = new DirCacheEntry(tw.RawPath); ourDce.SetObjectId(tw.GetObjectId(T_OURS)); ourDce.FileMode = tw.GetFileMode(T_OURS); } } else { ourDce = index.GetDirCacheEntry(); } if (NonTree(modeO) && NonTree(modeT) && tw.IdEqual(T_OURS, T_THEIRS)) { // OURS and THEIRS have equal content. Check the file mode if (modeO == modeT) { // content and mode of OURS and THEIRS are equal: it doesn't // matter which one we choose. OURS is chosen. Since the index // is clean (the index matches already OURS) we can keep the existing one Keep(ourDce); // no checkout needed! return(true); } else { // same content but different mode on OURS and THEIRS. // Try to merge the mode and report an error if this is // not possible. int newMode = MergeFileModes(modeB, modeO, modeT); if (newMode != FileMode.MISSING.GetBits()) { if (newMode == modeO) { // ours version is preferred Keep(ourDce); } else { // the preferred version THEIRS has a different mode // than ours. Check it out! if (IsWorktreeDirty(work)) { return(false); } // we know about length and lastMod only after we have written the new content. // This will happen later. Set these values to 0 for know. DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0, 0, 0); toBeCheckedOut.Put(tw.PathString, e); } return(true); } else { // FileModes are not mergeable. We found a conflict on modes. // For conflicting entries we don't know lastModified and length. Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0); Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0); Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0); unmergedPaths.AddItem(tw.PathString); mergeResults.Put(tw.PathString, new MergeResult <RawText>(Sharpen.Collections.EmptyList <RawText>()).Upcast()); } return(true); } } if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS)) { // THEIRS was not changed compared to BASE. All changes must be in // OURS. OURS is chosen. We can keep the existing entry. Keep(ourDce); // no checkout needed! return(true); } if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS)) { // OURS was not changed compared to BASE. All changes must be in // THEIRS. THEIRS is chosen. // Check worktree before checking out THEIRS if (IsWorktreeDirty(work)) { return(false); } if (NonTree(modeT)) { // we know about length and lastMod only after we have written // the new content. // This will happen later. Set these values to 0 for know. DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0, 0, 0); if (e != null) { toBeCheckedOut.Put(tw.PathString, e); } return(true); } else { if (modeT == 0 && modeB != 0) { // we want THEIRS ... but THEIRS contains the deletion of the // file toBeDeleted.AddItem(tw.PathString); return(true); } } } if (tw.IsSubtree) { // file/folder conflicts: here I want to detect only file/folder // conflict between ours and theirs. file/folder conflicts between // base/index/workingTree and something else are not relevant or // detected later if (NonTree(modeO) && !NonTree(modeT)) { if (NonTree(modeB)) { Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0); } Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0); unmergedPaths.AddItem(tw.PathString); enterSubtree = false; return(true); } if (NonTree(modeT) && !NonTree(modeO)) { if (NonTree(modeB)) { Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0); } Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0); unmergedPaths.AddItem(tw.PathString); enterSubtree = false; return(true); } // ours and theirs are both folders or both files (and treewalk // tells us we are in a subtree because of index or working-dir). // If they are both folders no content-merge is required - we can // return here. if (!NonTree(modeO)) { return(true); } } // ours and theirs are both files, just fall out of the if block // and do the content merge if (NonTree(modeO) && NonTree(modeT)) { // Check worktree before modifying files if (IsWorktreeDirty(work)) { return(false); } // Don't attempt to resolve submodule link conflicts if (IsGitLink(modeO) || IsGitLink(modeT)) { Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0); Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0); Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0); unmergedPaths.AddItem(tw.PathString); return(true); } MergeResult <RawText> result = ContentMerge(@base, ours, theirs); FilePath of = WriteMergedFile(result); UpdateIndex(@base, ours, theirs, result, of); if (result.ContainsConflicts()) { unmergedPaths.AddItem(tw.PathString); } modifiedFiles.AddItem(tw.PathString); } else { if (modeO != modeT) { // OURS or THEIRS has been deleted if (((modeO != 0 && !tw.IdEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw.IdEqual(T_BASE , T_THEIRS)))) { Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0); Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0); DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0); // OURS was deleted checkout THEIRS if (modeO == 0) { // Check worktree before checking out THEIRS if (IsWorktreeDirty(work)) { return(false); } if (NonTree(modeT)) { if (e != null) { toBeCheckedOut.Put(tw.PathString, e); } } } unmergedPaths.AddItem(tw.PathString); // generate a MergeResult for the deleted file mergeResults.Put(tw.PathString, ContentMerge(@base, ours, theirs).Upcast()); } } } return(true); }
/// <summary> /// Pop the next most recent object. /// </summary> /// <returns>next most recent object; null if traversal is over.</returns> /// <exception cref="MissingObjectException"> /// One or or more of the next objects are not available from the /// object database, but were thought to be candidates for /// traversal. This usually indicates a broken link. /// </exception> /// <exception cref="IncorrectObjectTypeException"> /// One or or more of the objects in a tree do not match the type indicated. /// </exception> /// <exception cref="Exception"> /// A pack file or loose object could not be Read. /// </exception> public RevObject nextObject() { _fromTreeWalk = false; if (_nextSubtree != null) { _treeWalk = _treeWalk.createSubtreeIterator0(Repository, _nextSubtree, WindowCursor); _nextSubtree = null; } while (!_treeWalk.eof()) { FileMode mode = _treeWalk.EntryFileMode; var sType = (int)mode.ObjectType; switch (sType) { case Constants.OBJ_BLOB: _treeWalk.getEntryObjectId(IdBuffer); RevBlob blob = lookupBlob(IdBuffer); if ((blob.Flags & SEEN) != 0) { break; } blob.Flags |= SEEN; if (ShouldSkipObject(blob)) { break; } _fromTreeWalk = true; return(blob); case Constants.OBJ_TREE: _treeWalk.getEntryObjectId(IdBuffer); RevTree tree = lookupTree(IdBuffer); if ((tree.Flags & SEEN) != 0) { break; } tree.Flags |= SEEN; if (ShouldSkipObject(tree)) { break; } _nextSubtree = tree; _fromTreeWalk = true; return(tree); default: if (FileMode.GitLink.Equals(mode.Bits)) { break; } _treeWalk.getEntryObjectId(IdBuffer); throw new CorruptObjectException("Invalid mode " + mode + " for " + IdBuffer + " " + _treeWalk.EntryPathString + " in " + _currentTree + "."); } _treeWalk = _treeWalk.next(); } while (true) { RevObject obj = _pendingObjects.next(); if (obj == null) { return(null); } if ((obj.Flags & SEEN) != 0) { continue; } obj.Flags |= SEEN; if (ShouldSkipObject(obj)) { continue; } RevTree oTree = (obj as RevTree); if (oTree != null) { _currentTree = oTree; _treeWalk = _treeWalk.resetRoot(Repository, _currentTree, WindowCursor); } return(obj); } }
public _PathEdit_281(CanonicalTreeParser tree, string baseArg1) : base(baseArg1) { this.tree = tree; }
/// <summary> /// Executes the /// <code>Diff</code> /// command with all the options and parameters /// collected by the setter methods (e.g. /// <see cref="SetCached(bool)">SetCached(bool)</see> /// of this /// class. Each instance of this class should only be used for one invocation /// of the command. Don't call this method twice on an instance. /// </summary> /// <returns>a DiffEntry for each path which is different</returns> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override IList <DiffEntry> Call() { DiffFormatter diffFmt; if (@out != null && !showNameAndStatusOnly) { diffFmt = new DiffFormatter(new BufferedOutputStream(@out)); } else { diffFmt = new DiffFormatter(NullOutputStream.INSTANCE); } diffFmt.SetRepository(repo); diffFmt.SetProgressMonitor(monitor); try { if (cached) { if (oldTree == null) { ObjectId head = repo.Resolve(Constants.HEAD + "^{tree}"); if (head == null) { throw new NoHeadException(JGitText.Get().cannotReadTree); } CanonicalTreeParser p = new CanonicalTreeParser(); ObjectReader reader = repo.NewObjectReader(); try { p.Reset(reader, head); } finally { reader.Release(); } oldTree = p; } newTree = new DirCacheIterator(repo.ReadDirCache()); } else { if (oldTree == null) { oldTree = new DirCacheIterator(repo.ReadDirCache()); } if (newTree == null) { newTree = new FileTreeIterator(repo); } } diffFmt.SetPathFilter(pathFilter); IList <DiffEntry> result = diffFmt.Scan(oldTree, newTree); if (showNameAndStatusOnly) { return(result); } else { if (contextLines >= 0) { diffFmt.SetContext(contextLines); } if (destinationPrefix != null) { diffFmt.SetNewPrefix(destinationPrefix); } if (sourcePrefix != null) { diffFmt.SetOldPrefix(sourcePrefix); } diffFmt.Format(result); diffFmt.Flush(); return(result); } } catch (IOException e) { throw new JGitInternalException(e.Message, e); } finally { diffFmt.Release(); } }