/// <summary> /// finds out the path and revision of all diffs needed for this search /// </summary> /// <param name="filesOfInterest"></param> /// <param name="searchOptions"></param> /// <param name="diffInfoFileRelations"></param> /// <returns></returns> public IList <DiffInfo> GetDiffInfos(ICollection <string> filesOfInterest, SearchOptions searchOptions, out IDictionary <DiffInfo, IList <string> > diffInfoFileRelations) { diffInfoFileRelations = new Dictionary <DiffInfo, IList <string> >(); if (this.Disposed) { Progress.DebugLog("GetDiffInfos called on closed SubversionSearcher"); return(null); } long?startRevisionNumber = null; long?endRevisionNumber = null; if (searchOptions.SearchFromRevision.RevisionType == SvnRevisionType.Number) { startRevisionNumber = searchOptions.SearchFromRevision.Revision; } else if (searchOptions.SearchFromRevision.RevisionType == SvnRevisionType.Time) { for (int i = 0; i < Revisions.Count; i++) { if (Revisions[i].Time >= searchOptions.SearchFromRevision.Time) { startRevisionNumber = Revisions[i].Revision; break; } } } if (searchOptions.SearchToRevision.RevisionType == SvnRevisionType.Number) { endRevisionNumber = searchOptions.SearchToRevision.Revision; } else if (searchOptions.SearchToRevision.RevisionType == SvnRevisionType.Time) { for (int i = Revisions.Count - 1; i >= 0; i--) { if (Revisions[i].Time <= searchOptions.SearchToRevision.Time) { endRevisionNumber = Revisions[i].Revision; break; } } } else if (searchOptions.SearchToRevision.RevisionType == SvnRevisionType.Head) { endRevisionNumber = HeadRevision; } if (!startRevisionNumber.HasValue || !endRevisionNumber.HasValue) { Progress.DebugLog("startRevision or endRevision number is null"); Progress.Log("something failed"); return(null); } HashSet <long> ignoreRevisions = new HashSet <long>(); HashSet <string> authors = new HashSet <string>(from a in searchOptions.Authors where !String.IsNullOrWhiteSpace(a) select a.ToUpper()); if (authors.Count != 0) { foreach (CommitInfo r in Revisions.Values) { if (!((r.Author != null && searchOptions.Authors.Contains(r.Author)) ^ searchOptions.ExcludeAuthors)) { ignoreRevisions.Add(r.Revision); } } } // adding the files that were selected in the checkbox tree foreach (string fname in filesOfInterest) { foreach (DiffInfo di in GetFileHistory(fname, startRevisionNumber.Value, endRevisionNumber.Value, ignoreRevisions, searchOptions.StopOnCopy)) { if (diffInfoFileRelations.TryGetValue(di, out IList <string> li) == false) { diffInfoFileRelations[di] = li = new List <string>(); } li.Add(fname); } } // add files that contain substring in name if (!String.IsNullOrEmpty(searchOptions.FilenameSubstring)) { foreach (KeyValuePair <string, IList <NodeAtTime> > kv in nodes) { if (searchOptions.HeadNodePath != "" && !kv.Key.StartsWith(searchOptions.HeadNodePath + '/')) { continue; } var stringInFname = searchOptions.FilenameSubstring.ToUpperInvariant(); if ((searchOptions.FilenameSubstring == "*" && !FiletypeBlacklist.Contains(Path.GetExtension(kv.Key).ToLower())) || kv.Key.ToUpperInvariant().Contains(stringInFname)) { foreach (NodeAtTime n in kv.Value) { foreach (DiffInfo di in GetFileHistory(n, startRevisionNumber.Value, endRevisionNumber.Value, ignoreRevisions, true)) { IList <string> li; if (diffInfoFileRelations.TryGetValue(di, out li) == false) { diffInfoFileRelations[di] = li = new List <string>(); } if (!li.Contains(kv.Key)) { li.Add(kv.Key); } } } } } } Utils.Vardump <DiffInfo>("relevantDiffs.txt", diffInfoFileRelations.Keys, (di) => { string result = String.Format("r{0,5} {1}", di.RevB, di.Path); return(result); }); return(diffInfoFileRelations.Keys.ToList()); }
// -- private void BuildRepositoryStructure(IList <CommitInfo> revs, IList <SimplifiedSvnChangeItem> changeItems) { Revisions = new Dictionary <long, CommitInfo>(); nodes = new Dictionary <string, IList <NodeAtTime> >(); equalAdds = new Dictionary <NodeAtTime, ISet <NodeAtTime> >(); table = new Table(this); nodes.Add("", new List <NodeAtTime> { new NodeAtTime("", 0) }); foreach (var e in revs) { Revisions.Add(e.Revision, e); } if (revs.Count > 0) { HeadRevision = revs[revs.Count - 1].Revision; } Stopwatch sw = Stopwatch.StartNew(); long currentRevsion = 0; ISet <string> filesCopiedThisRevision = new HashSet <string>(); foreach (var changeItem in changeItems) { if (changeItem.Revision != currentRevsion) { currentRevsion = changeItem.Revision; if (changeItem.Revision == revs.Count - 1 || changeItem.Revision % 17 == 0) { Progress.Log("Building repository structure ({0} of {1})", changeItem.Revision, revs.Count - 1); } filesCopiedThisRevision = new HashSet <string>(); } string nodePath = changeItem.Path.Substring(1); if (changeItem.Action == SvnChangeAction.Modify) { AddModification(nodePath, currentRevsion, filesCopiedThisRevision.Contains(nodePath)); } else if (changeItem.Action == SvnChangeAction.Add) { AddAddition(nodePath, changeItem, currentRevsion, ref filesCopiedThisRevision); // add to same files } else if (changeItem.Action == SvnChangeAction.Delete) { AddDeletion(nodePath, changeItem, currentRevsion); } else if (changeItem.Action == SvnChangeAction.Replace) { // investigate replace without copying AddDeletion(nodePath, changeItem, currentRevsion); AddAddition(nodePath, changeItem, currentRevsion, ref filesCopiedThisRevision); // add to same files } else { Progress.DebugLog("{0} occured at {1}@{2}", changeItem.Action, nodePath, currentRevsion); } } { IList <string> listsToRemove = new List <string>(); // remove nodes with deleteRevision == addRevision, remove nodesPaths with no nodes, add to table foreach (var kv in nodes) { IList <NodeAtTime> natsToRemove = null; foreach (var nat in kv.Value) { if (nat.DeleteRevision.HasValue && nat.DeleteRevision == nat.AddRevision) { // happens when replaces happen if (natsToRemove == null) { natsToRemove = new List <NodeAtTime>(); } natsToRemove.Add(nat); continue; } if (nat.IsFolder) { continue; } else if (NodesTaggedAsFolder.Count > 0 && NodesTaggedAsFolder.Contains(new Tuple <string, long>(nat.Path, nat.AddRevision))) { nat.SetIsFolder(); } else { bool isBinary = FiletypeBlacklist.Contains(Path.GetExtension(nat.Path)); for (int i = nat.Actions.Count - 1; i > 0; i--) { table.AddToDict(nat.Actions[i].Revision, kv.Key, isBinary); } if (nat.Actions[0].Modified) { table.AddToDict(nat.Actions[0].Revision, kv.Key, isBinary); } else { table.AddToDict(nat.Actions[0].Revision, kv.Key, isBinary); } if (nat.DeleteRevision.HasValue) { table.AddToDict(nat.DeleteRevision.Value, kv.Key, isBinary); } } } if (natsToRemove != null) { foreach (var n in natsToRemove) { kv.Value.Remove(n); } } if (kv.Value.Count == 0) { listsToRemove.Add(kv.Key); } } foreach (var v in listsToRemove) { nodes.Remove(v); } } { IList <NodeAtTime> toRemove = new List <NodeAtTime>(); // clear all the equalsAdds entries who's Set contain only one entry foreach (var kv in equalAdds) { if (kv.Value.Count <= 1) { toRemove.Add(kv.Key); } else { foreach (var s in kv.Value) { if (s.IsFolder) { // if one is a folder, all of them are toRemove.Add(kv.Key); break; } } } } foreach (var v in toRemove) { equalAdds.Remove(v); } } sw.Stop(); Progress.DebugLog("repository structure building time: {0}ms", sw.Elapsed.TotalMilliseconds); }