/// <exception cref="System.IO.IOException"></exception> private void BreakModifies(ContentSource.Pair reader, ProgressMonitor pm) { AList <DiffEntry> newEntries = new AList <DiffEntry>(entries.Count); pm.BeginTask(JGitText.Get().renamesBreakingModifies, entries.Count); for (int i = 0; i < entries.Count; i++) { DiffEntry e = entries[i]; if (e.GetChangeType() == DiffEntry.ChangeType.MODIFY) { int score = CalculateModifyScore(reader, e); if (score < breakScore) { IList <DiffEntry> tmp = DiffEntry.BreakModify(e); DiffEntry del = tmp[0]; del.score = score; deleted.AddItem(del); added.AddItem(tmp[1]); } else { newEntries.AddItem(e); } } else { newEntries.AddItem(e); } pm.Update(1); } entries = newEntries; }
/// <summary>Detect renames in the current file set.</summary> /// <remarks>Detect renames in the current file set.</remarks> /// <param name="reader">reader to obtain objects from the repository with.</param> /// <param name="pm">report progress during the detection phases.</param> /// <returns> /// an unmodifiable list of /// <see cref="DiffEntry">DiffEntry</see> /// s representing all files /// that have been changed. /// </returns> /// <exception cref="System.IO.IOException">file contents cannot be read from the repository. /// </exception> public virtual IList <DiffEntry> Compute(ContentSource.Pair reader, ProgressMonitor pm) { if (!done) { done = true; if (pm == null) { pm = NullProgressMonitor.INSTANCE; } if (0 < breakScore) { BreakModifies(reader, pm); } if (!added.IsEmpty() && !deleted.IsEmpty()) { FindExactRenames(pm); } if (!added.IsEmpty() && !deleted.IsEmpty()) { FindContentRenames(reader, pm); } if (0 < breakScore && !added.IsEmpty() && !deleted.IsEmpty()) { RejoinModifies(pm); } Sharpen.Collections.AddAll(entries, added); added = null; Sharpen.Collections.AddAll(entries, deleted); deleted = null; entries.Sort(DIFF_COMPARATOR); } return(Sharpen.Collections.UnmodifiableList(entries)); }
internal SimilarityRenameDetector(ContentSource.Pair reader, IList <DiffEntry> srcs , IList <DiffEntry> dsts) { this.reader = reader; this.srcs = srcs; this.dsts = dsts; }
/// <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 FindContentRenames(ContentSource.Pair reader, ProgressMonitor pm) { int cnt = Math.Max(added.Count, deleted.Count); if (GetRenameLimit() == 0 || cnt <= GetRenameLimit()) { SimilarityRenameDetector d; d = new SimilarityRenameDetector(reader, deleted, added); d.SetRenameScore(GetRenameScore()); d.Compute(pm); overRenameLimit |= d.IsTableOverflow(); deleted = d.GetLeftOverSources(); added = d.GetLeftOverDestinations(); Sharpen.Collections.AddAll(entries, d.GetMatches()); } else { overRenameLimit = true; } }
/// <exception cref="System.IO.IOException"></exception> private int CalculateModifyScore(ContentSource.Pair reader, DiffEntry d) { try { SimilarityIndex src = new SimilarityIndex(); src.Hash(reader.Open(DiffEntry.Side.OLD, d)); src.Sort(); SimilarityIndex dst = new SimilarityIndex(); dst.Hash(reader.Open(DiffEntry.Side.NEW, d)); dst.Sort(); return(src.Score(dst, 100)); } catch (SimilarityIndex.TableFullException) { // If either table overflowed while being constructed, don't allow // the pair to be broken. Returning 1 higher than breakScore will // ensure its not similar, but not quite dissimilar enough to break. // overRenameLimit = true; return(breakScore + 1); } }
/// <summary>Set the repository the formatter can load object contents from.</summary> /// <remarks> /// Set the repository the formatter can load object contents from. /// Once a repository has been set, the formatter must be released to ensure /// the internal ObjectReader is able to release its resources. /// </remarks> /// <param name="repository">source repository holding referenced objects.</param> public virtual void SetRepository(Repository repository) { if (reader != null) { reader.Release(); } db = repository; reader = db.NewObjectReader(); ContentSource cs = ContentSource.Create(reader); source = new ContentSource.Pair(cs, cs); DiffConfig dc = db.GetConfig().Get(DiffConfig.KEY); if (dc.IsNoPrefix()) { SetOldPrefix(string.Empty); SetNewPrefix(string.Empty); } SetDetectRenames(dc.IsRenameDetectionEnabled()); diffAlgorithm = DiffAlgorithm.GetAlgorithm(db.GetConfig().GetEnum(ConfigConstants .CONFIG_DIFF_SECTION, null, ConfigConstants.CONFIG_KEY_ALGORITHM, DiffAlgorithm.SupportedAlgorithm .HISTOGRAM)); }
internal SimilarityRenameDetector(ContentSource.Pair reader, IList<DiffEntry> srcs , IList<DiffEntry> dsts) { this.reader = reader; this.srcs = srcs; this.dsts = dsts; }