public virtual void TestCreateFileHeader_Modify() { ObjectId adId = Blob("a\nd\n"); ObjectId abcdId = Blob("a\nb\nc\nd\n"); string diffHeader = MakeDiffHeader(PATH_A, PATH_A, adId, abcdId); DiffEntry ad = DiffEntry.Delete(PATH_A, adId); DiffEntry abcd = DiffEntry.Add(PATH_A, abcdId); DiffEntry mod = DiffEntry.Pair(DiffEntry.ChangeType.MODIFY, ad, abcd, 0); FileHeader fh = df.ToFileHeader(mod); NUnit.Framework.Assert.AreEqual(diffHeader, RawParseUtils.Decode(fh.GetBuffer())); NUnit.Framework.Assert.AreEqual(0, fh.GetStartOffset()); NUnit.Framework.Assert.AreEqual(fh.GetBuffer().Length, fh.GetEndOffset()); NUnit.Framework.Assert.AreEqual(FileHeader.PatchType.UNIFIED, fh.GetPatchType()); NUnit.Framework.Assert.AreEqual(1, fh.GetHunks().Count); HunkHeader hh = fh.GetHunks()[0]; NUnit.Framework.Assert.AreEqual(1, hh.ToEditList().Count); EditList el = hh.ToEditList(); NUnit.Framework.Assert.AreEqual(1, el.Count); Edit e = el[0]; NUnit.Framework.Assert.AreEqual(1, e.GetBeginA()); NUnit.Framework.Assert.AreEqual(1, e.GetEndA()); NUnit.Framework.Assert.AreEqual(1, e.GetBeginB()); NUnit.Framework.Assert.AreEqual(3, e.GetEndB()); NUnit.Framework.Assert.AreEqual(Edit.Type.INSERT, e.GetType()); }
/// <exception cref="System.IO.IOException"></exception> internal virtual void Compute(ProgressMonitor pm) { if (pm == null) { pm = NullProgressMonitor.INSTANCE; } pm.BeginTask(JGitText.Get().renamesFindingByContent, 2 * srcs.Count * dsts.Count); // int mNext = BuildMatrix(pm); @out = new AList <DiffEntry>(Math.Min(mNext, dsts.Count)); // Match rename pairs on a first come, first serve basis until // we have looked at everything that is above our minimum score. // for (--mNext; mNext >= 0; mNext--) { long ent = matrix[mNext]; int sIdx = SrcFile(ent); int dIdx = DstFile(ent); DiffEntry s = srcs[sIdx]; DiffEntry d = dsts[dIdx]; if (d == null) { pm.Update(1); continue; } // was already matched earlier DiffEntry.ChangeType type; if (s.changeType == DiffEntry.ChangeType.DELETE) { // First use of this source file. Tag it as a rename so we // later know it is already been used as a rename, other // matches (if any) will claim themselves as copies instead. // s.changeType = DiffEntry.ChangeType.RENAME; type = DiffEntry.ChangeType.RENAME; } else { type = DiffEntry.ChangeType.COPY; } @out.AddItem(DiffEntry.Pair(type, s, d, Score(ent))); dsts.Set(dIdx, null); // Claim the destination was matched. pm.Update(1); } srcs = CompactSrcList(srcs); dsts = CompactDstList(dsts); pm.EndTask(); }
public virtual void TestCreateFileHeader_Binary() { ObjectId adId = Blob("a\nd\n"); ObjectId binId = Blob("a\nb\nc\n\x0\x0\x0\x0d\n"); string diffHeader = MakeDiffHeader(PATH_A, PATH_B, adId, binId) + "Binary files differ\n"; DiffEntry ad = DiffEntry.Delete(PATH_A, adId); DiffEntry abcd = DiffEntry.Add(PATH_B, binId); DiffEntry mod = DiffEntry.Pair(DiffEntry.ChangeType.MODIFY, ad, abcd, 0); FileHeader fh = df.ToFileHeader(mod); NUnit.Framework.Assert.AreEqual(diffHeader, RawParseUtils.Decode(fh.GetBuffer())); NUnit.Framework.Assert.AreEqual(FileHeader.PatchType.BINARY, fh.GetPatchType()); NUnit.Framework.Assert.AreEqual(1, fh.GetHunks().Count); HunkHeader hh = fh.GetHunks()[0]; NUnit.Framework.Assert.AreEqual(0, hh.ToEditList().Count); }
public virtual void TestCreateFileHeader_GitLink() { ObjectId aId = Blob("a\n"); ObjectId bId = Blob("b\n"); string diffHeader = MakeDiffHeaderModeChange(PATH_A, PATH_A, aId, bId, GITLINK, REGULAR_FILE ) + "-Subproject commit " + aId.Name + "\n"; DiffEntry ad = DiffEntry.Delete(PATH_A, aId); ad.oldMode = FileMode.GITLINK; DiffEntry abcd = DiffEntry.Add(PATH_A, bId); DiffEntry mod = DiffEntry.Pair(DiffEntry.ChangeType.MODIFY, ad, abcd, 0); FileHeader fh = df.ToFileHeader(mod); NUnit.Framework.Assert.AreEqual(diffHeader, RawParseUtils.Decode(fh.GetBuffer())); NUnit.Framework.Assert.AreEqual(1, fh.GetHunks().Count); HunkHeader hh = fh.GetHunks()[0]; NUnit.Framework.Assert.AreEqual(0, hh.ToEditList().Count); }
private void RejoinModifies(ProgressMonitor pm) { Dictionary <string, DiffEntry> nameMap = new Dictionary <string, DiffEntry>(); AList <DiffEntry> newAdded = new AList <DiffEntry>(added.Count); pm.BeginTask(JGitText.Get().renamesRejoiningModifies, added.Count + deleted.Count ); foreach (DiffEntry src in deleted) { nameMap.Put(src.oldPath, src); pm.Update(1); } foreach (DiffEntry dst in added) { DiffEntry src_1 = Sharpen.Collections.Remove(nameMap, dst.newPath); if (src_1 != null) { if (SameType(src_1.oldMode, dst.newMode)) { entries.AddItem(DiffEntry.Pair(DiffEntry.ChangeType.MODIFY, src_1, dst, src_1.score )); } else { nameMap.Put(src_1.oldPath, src_1); newAdded.AddItem(dst); } } else { newAdded.AddItem(dst); } pm.Update(1); } added = newAdded; deleted = new AList <DiffEntry>(nameMap.Values); }
private static DiffEntry ExactCopy(DiffEntry src, DiffEntry dst) { return(DiffEntry.Pair(DiffEntry.ChangeType.COPY, src, dst, EXACT_RENAME_SCORE)); }
private static DiffEntry ExactRename(DiffEntry src, DiffEntry dst) { return(DiffEntry.Pair(DiffEntry.ChangeType.RENAME, src, dst, EXACT_RENAME_SCORE)); }
private void FindExactRenames(ProgressMonitor pm) { pm.BeginTask(JGitText.Get().renamesFindingExact, added.Count + added.Count + deleted .Count + added.Count * deleted.Count); // Dictionary <AbbreviatedObjectId, object> deletedMap = PopulateMap(deleted, pm); Dictionary <AbbreviatedObjectId, object> addedMap = PopulateMap(added, pm); AList <DiffEntry> uniqueAdds = new AList <DiffEntry>(added.Count); AList <IList <DiffEntry> > nonUniqueAdds = new AList <IList <DiffEntry> >(); foreach (object o in addedMap.Values) { if (o is DiffEntry) { uniqueAdds.AddItem((DiffEntry)o); } else { nonUniqueAdds.AddItem((IList <DiffEntry>)o); } } AList <DiffEntry> left = new AList <DiffEntry>(added.Count); foreach (DiffEntry a in uniqueAdds) { object del = deletedMap.Get(a.newId); if (del is DiffEntry) { // We have one add to one delete: pair them if they are the same // type DiffEntry e = (DiffEntry)del; if (SameType(e.oldMode, a.newMode)) { e.changeType = DiffEntry.ChangeType.RENAME; entries.AddItem(ExactRename(e, a)); } else { left.AddItem(a); } } else { if (del != null) { // We have one add to many deletes: find the delete with the // same type and closest name to the add, then pair them IList <DiffEntry> list = (IList <DiffEntry>)del; DiffEntry best = BestPathMatch(a, list); if (best != null) { best.changeType = DiffEntry.ChangeType.RENAME; entries.AddItem(ExactRename(best, a)); } else { left.AddItem(a); } } else { left.AddItem(a); } } pm.Update(1); } foreach (IList <DiffEntry> adds in nonUniqueAdds) { object o_1 = deletedMap.Get(adds[0].newId); if (o_1 is DiffEntry) { // We have many adds to one delete: find the add with the same // type and closest name to the delete, then pair them. Mark the // rest as copies of the delete. DiffEntry d = (DiffEntry)o_1; DiffEntry best = BestPathMatch(d, adds); if (best != null) { d.changeType = DiffEntry.ChangeType.RENAME; entries.AddItem(ExactRename(d, best)); foreach (DiffEntry a_1 in adds) { if (a_1 != best) { if (SameType(d.oldMode, a_1.newMode)) { entries.AddItem(ExactCopy(d, a_1)); } else { left.AddItem(a_1); } } } } else { Sharpen.Collections.AddAll(left, adds); } } else { if (o_1 != null) { // We have many adds to many deletes: score all the adds against // all the deletes by path name, take the best matches, pair // them as renames, then call the rest copies IList <DiffEntry> dels = (IList <DiffEntry>)o_1; long[] matrix = new long[dels.Count * adds.Count]; int mNext = 0; for (int delIdx = 0; delIdx < dels.Count; delIdx++) { string deletedName = dels[delIdx].oldPath; for (int addIdx = 0; addIdx < adds.Count; addIdx++) { string addedName = adds[addIdx].newPath; int score = SimilarityRenameDetector.NameScore(addedName, deletedName); matrix[mNext] = SimilarityRenameDetector.Encode(score, delIdx, addIdx); mNext++; } } Arrays.Sort(matrix); for (--mNext; mNext >= 0; mNext--) { long ent = matrix[mNext]; int delIdx_1 = SimilarityRenameDetector.SrcFile(ent); int addIdx = SimilarityRenameDetector.DstFile(ent); DiffEntry d = dels[delIdx_1]; DiffEntry a_1 = adds[addIdx]; if (a_1 == null) { pm.Update(1); continue; } // was already matched earlier DiffEntry.ChangeType type; if (d.changeType == DiffEntry.ChangeType.DELETE) { // First use of this source file. Tag it as a rename so we // later know it is already been used as a rename, other // matches (if any) will claim themselves as copies instead. // d.changeType = DiffEntry.ChangeType.RENAME; type = DiffEntry.ChangeType.RENAME; } else { type = DiffEntry.ChangeType.COPY; } entries.AddItem(DiffEntry.Pair(type, d, a_1, 100)); adds.Set(addIdx, null); // Claim the destination was matched. pm.Update(1); } } else { Sharpen.Collections.AddAll(left, adds); } } } added = left; deleted = new AList <DiffEntry>(deletedMap.Count); foreach (object o_2 in deletedMap.Values) { if (o_2 is DiffEntry) { DiffEntry e = (DiffEntry)o_2; if (e.changeType == DiffEntry.ChangeType.DELETE) { deleted.AddItem(e); } } else { IList <DiffEntry> list = (IList <DiffEntry>)o_2; foreach (DiffEntry e in list) { if (e.changeType == DiffEntry.ChangeType.DELETE) { deleted.AddItem(e); } } } } pm.EndTask(); }