/// <summary>Enable or disable rename detection.</summary> /// <remarks> /// Enable or disable rename detection. /// Before enabling rename detection the repository must be set with /// <see cref="SetRepository(NGit.Repository)">SetRepository(NGit.Repository)</see> /// . Once enabled the detector can be /// configured away from its defaults by obtaining the instance directly from /// <see cref="GetRenameDetector()">GetRenameDetector()</see> /// and invoking configuration. /// </remarks> /// <param name="on">if rename detection should be enabled.</param> public virtual void SetDetectRenames(bool on) { if (on && renameDetector == null) { AssertHaveRepository(); renameDetector = new RenameDetector(db); } else { if (!on) { renameDetector = null; } } }
// 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> public static IList <NGit.Diff.DiffEntry> Scan(TreeWalk walk) { IList <NGit.Diff.DiffEntry> r = new AList <NGit.Diff.DiffEntry>(); MutableObjectId idBuf = new MutableObjectId(); while (walk.Next()) { NGit.Diff.DiffEntry entry = new NGit.Diff.DiffEntry(); walk.GetObjectId(idBuf, 0); entry.oldId = AbbreviatedObjectId.FromObjectId(idBuf); walk.GetObjectId(idBuf, 1); entry.newId = AbbreviatedObjectId.FromObjectId(idBuf); entry.oldMode = walk.GetFileMode(0); entry.newMode = walk.GetFileMode(1); entry.newPath = entry.oldPath = walk.PathString; if (entry.oldMode == FileMode.MISSING) { entry.oldPath = NGit.Diff.DiffEntry.DEV_NULL; entry.changeType = DiffEntry.ChangeType.ADD; r.AddItem(entry); } else { if (entry.newMode == FileMode.MISSING) { entry.newPath = NGit.Diff.DiffEntry.DEV_NULL; entry.changeType = DiffEntry.ChangeType.DELETE; r.AddItem(entry); } else { entry.changeType = DiffEntry.ChangeType.MODIFY; if (RenameDetector.SameType(entry.oldMode, entry.newMode)) { r.AddItem(entry); } else { Sharpen.Collections.AddAll(r, BreakModify(entry)); } } } } return(r); }
/// <summary> /// Convert the TreeWalk into DiffEntry headers, depending on /// <code>includeTrees</code> /// it will add tree objects into result or not. /// </summary> /// <param name="walk"> /// the TreeWalk to walk through. Must have exactly two trees and /// when /// <code>includeTrees</code> /// parameter is /// <code>true</code> /// it can't /// be recursive. /// </param> /// <param name="includeTrees">include tree object's.</param> /// <returns>headers describing the changed files.</returns> /// <exception cref="System.IO.IOException">the repository cannot be accessed.</exception> /// <exception cref="System.ArgumentException"> /// when /// <code>includeTrees</code> /// is true and given TreeWalk is /// recursive. Or when given TreeWalk doesn't have exactly two /// trees /// </exception> public static IList <NGit.Diff.DiffEntry> Scan(TreeWalk walk, bool includeTrees) { if (walk.TreeCount != 2) { throw new ArgumentException(JGitText.Get().treeWalkMustHaveExactlyTwoTrees); } if (includeTrees && walk.Recursive) { throw new ArgumentException(JGitText.Get().cannotBeRecursiveWhenTreesAreIncluded); } IList <NGit.Diff.DiffEntry> r = new AList <NGit.Diff.DiffEntry>(); MutableObjectId idBuf = new MutableObjectId(); while (walk.Next()) { NGit.Diff.DiffEntry entry = new NGit.Diff.DiffEntry(); walk.GetObjectId(idBuf, 0); entry.oldId = AbbreviatedObjectId.FromObjectId(idBuf); walk.GetObjectId(idBuf, 1); entry.newId = AbbreviatedObjectId.FromObjectId(idBuf); entry.oldMode = walk.GetFileMode(0); entry.newMode = walk.GetFileMode(1); entry.newPath = entry.oldPath = walk.PathString; if (entry.oldMode == FileMode.MISSING) { entry.oldPath = NGit.Diff.DiffEntry.DEV_NULL; entry.changeType = DiffEntry.ChangeType.ADD; r.AddItem(entry); } else { if (entry.newMode == FileMode.MISSING) { entry.newPath = NGit.Diff.DiffEntry.DEV_NULL; entry.changeType = DiffEntry.ChangeType.DELETE; r.AddItem(entry); } else { if (!entry.oldId.Equals(entry.newId)) { entry.changeType = DiffEntry.ChangeType.MODIFY; if (RenameDetector.SameType(entry.oldMode, entry.newMode)) { r.AddItem(entry); } else { Sharpen.Collections.AddAll(r, BreakModify(entry)); } } else { if (entry.oldMode != entry.newMode) { entry.changeType = DiffEntry.ChangeType.MODIFY; r.AddItem(entry); } } } } if (includeTrees && walk.IsSubtree) { walk.EnterSubtree(); } } return(r); }
/// <exception cref="System.IO.IOException"></exception> private int BuildMatrix(ProgressMonitor pm) { // Allocate for the worst-case scenario where every pair has a // score that we need to consider. We might not need that many. // matrix = new long[srcs.Count * dsts.Count]; long[] srcSizes = new long[srcs.Count]; long[] dstSizes = new long[dsts.Count]; BitSet dstTooLarge = null; // Consider each pair of files, if the score is above the minimum // threshold we need record that scoring in the matrix so we can // later find the best matches. // int mNext = 0; for (int srcIdx = 0; srcIdx < srcs.Count; srcIdx++) { DiffEntry srcEnt = srcs[srcIdx]; if (!IsFile(srcEnt.oldMode)) { pm.Update(dsts.Count); continue; } SimilarityIndex s = null; for (int dstIdx = 0; dstIdx < dsts.Count; dstIdx++) { DiffEntry dstEnt = dsts[dstIdx]; if (!IsFile(dstEnt.newMode)) { pm.Update(1); continue; } if (!RenameDetector.SameType(srcEnt.oldMode, dstEnt.newMode)) { pm.Update(1); continue; } if (dstTooLarge != null && dstTooLarge.Get(dstIdx)) { pm.Update(1); continue; } long srcSize = srcSizes[srcIdx]; if (srcSize == 0) { srcSize = Size(DiffEntry.Side.OLD, srcEnt) + 1; srcSizes[srcIdx] = srcSize; } long dstSize = dstSizes[dstIdx]; if (dstSize == 0) { dstSize = Size(DiffEntry.Side.NEW, dstEnt) + 1; dstSizes[dstIdx] = dstSize; } long max = Math.Max(srcSize, dstSize); long min = Math.Min(srcSize, dstSize); if (min * 100 / max < renameScore) { // Cannot possibly match, as the file sizes are so different pm.Update(1); continue; } if (s == null) { try { s = Hash(DiffEntry.Side.OLD, srcEnt); } catch (SimilarityIndex.TableFullException) { tableOverflow = true; goto SRC_continue; } } SimilarityIndex d; try { d = Hash(DiffEntry.Side.NEW, dstEnt); } catch (SimilarityIndex.TableFullException) { if (dstTooLarge == null) { dstTooLarge = new BitSet(dsts.Count); } dstTooLarge.Set(dstIdx); tableOverflow = true; pm.Update(1); continue; } int contentScore = s.Score(d, 10000); // nameScore returns a value between 0 and 100, but we want it // to be in the same range as the content score. This allows it // to be dropped into the pretty formula for the final score. int nameScore = NameScore(srcEnt.oldPath, dstEnt.newPath) * 100; int score = (contentScore * 99 + nameScore * 1) / 10000; if (score < renameScore) { pm.Update(1); continue; } matrix[mNext++] = Encode(score, srcIdx, dstIdx); pm.Update(1); } SRC_continue :; } SRC_break :; // Sort everything in the range we populated, which might be the // entire matrix, or just a smaller slice if we had some bad low // scoring pairs. // Arrays.Sort(matrix, 0, mNext); return(mNext); }
public override void SetUp() { base.SetUp(); testDb = new TestRepository <FileRepository>(db); rd = new RenameDetector(db); }