private bool CheckLinesContent(IRepository repository, IScmData scmData, string testRevision, ProjectFile file, bool resultOnly) { IBlame fileBlame = null; try { fileBlame = scmData.Blame(testRevision, file.Path); } catch { } if (fileBlame == null) { if (! resultOnly) { Console.WriteLine("File {0} does not exist.", file.Path); } return false; } double currentLOC = repository.SelectionDSL() .Commits().TillRevision(testRevision) .Files().IdIs(file.ID) .Modifications().InCommits().InFiles() .CodeBlocks().InModifications() .CalculateLOC(); bool correct = currentLOC == fileBlame.Count; if (! correct) { if (! resultOnly) { Console.WriteLine("Incorrect number of lines in file {0}. {1} should be {2}", file.Path, currentLOC, fileBlame.Count ); } else { return false; } } SmartDictionary<string, int> linesByRevision = new SmartDictionary<string, int>(x => 0); foreach (var line in fileBlame) { linesByRevision[line.Value]++; } var codeBySourceRevision = ( from f in repository.Queryable<ProjectFile>() join m in repository.Queryable<Modification>() on f.ID equals m.FileID join cb in repository.Queryable<CodeBlock>() on m.ID equals cb.ModificationID join c in repository.Queryable<Commit>() on m.CommitID equals c.ID let addedCodeBlock = repository.Queryable<CodeBlock>() .Single(x => x.ID == (cb.Size < 0 ? cb.TargetCodeBlockID : cb.ID)) let codeAddedInitiallyInRevision = repository.Queryable<Commit>() .Single(x => x.ID == addedCodeBlock.AddedInitiallyInCommitID) .Revision let testRevisionNumber = repository.Queryable<Commit>() .Single(x => x.Revision == testRevision) .OrderedNumber where f.ID == file.ID && c.OrderedNumber <= testRevisionNumber group cb.Size by codeAddedInitiallyInRevision into g select new { FromRevision = g.Key, CodeSize = g.Sum() } ).Where(x => x.CodeSize != 0).ToList(); var errorCode = ( from codeFromRevision in codeBySourceRevision where codeFromRevision.CodeSize != linesByRevision[codeFromRevision.FromRevision] select new { SourceRevision = codeFromRevision.FromRevision, CodeSize = codeFromRevision.CodeSize, RealCodeSize = linesByRevision[codeFromRevision.FromRevision] } ).ToList(); correct = correct && codeBySourceRevision.Count() == linesByRevision.Count && errorCode.Count == 0; if (! resultOnly) { if (codeBySourceRevision.Count() != linesByRevision.Count) { Console.WriteLine("Number of revisions file {0} contains code from is incorrect. {1} should be {2}", file.Path, codeBySourceRevision.Count(), linesByRevision.Count ); } foreach (var error in errorCode) { Console.WriteLine("Incorrect number of lines in file {0} from revision {1}. {2} should be {3}", file.Path, error.SourceRevision, error.CodeSize, error.RealCodeSize ); } if ((! correct) && (errorCode.Count > 0)) { string latestCodeRevision = repository.LastRevision(errorCode.Select(x => x.SourceRevision)); var commitsFileTouchedIn = repository.SelectionDSL() .Files().IdIs(file.ID) .Commits().FromRevision(latestCodeRevision).TouchFiles() .OrderBy(c => c.OrderedNumber); foreach (var commit in commitsFileTouchedIn) { if (!CheckLinesContent(repository, scmData, commit.Revision, file, true)) { Console.WriteLine("{0} - incorrectly mapped commit.", commit.Revision); if ((automaticallyFixDiffErrors) && (errorCode.Sum(x => x.CodeSize - x.RealCodeSize) == 0)) { var incorrectDeleteCodeBlocks = from cb in repository.SelectionDSL() .Commits().RevisionIs(commit.Revision) .Files().PathIs(file.Path) .Modifications().InCommits().InFiles() .CodeBlocks().InModifications().Deleted() join tcb in repository.Queryable<CodeBlock>() on cb.TargetCodeBlockID equals tcb.ID join m in repository.Queryable<Modification>() on tcb.ModificationID equals m.ID join c in repository.Queryable<Commit>() on m.CommitID equals c.ID where errorCode.Select(x => x.SourceRevision).Contains(c.Revision) select new { Code = cb, TargetRevision = c.Revision }; foreach (var error in errorCode) { var incorrectDeleteCodeBlock = incorrectDeleteCodeBlocks.SingleOrDefault(x => x.TargetRevision == error.SourceRevision); var codeBlock = incorrectDeleteCodeBlock == null ? null : incorrectDeleteCodeBlock.Code; double difference = error.CodeSize - error.RealCodeSize; if (codeBlock == null) { codeBlock = new CodeBlock() { Size = 0, Modification = repository.SelectionDSL() .Commits().RevisionIs(commit.Revision) .Files().PathIs(file.Path) .Modifications().InCommits().InFiles().Single(), }; repository.Add(codeBlock); } Console.WriteLine("Fix code block size for file {0} in revision {1}:", file.Path, commit.Revision); Console.Write("Was {0}", codeBlock.Size); codeBlock.Size -= difference; if (codeBlock.Size == 0) { repository.Delete(codeBlock); } else if ((codeBlock.Size > 0) && (codeBlock.AddedInitiallyInCommitID == null)) { codeBlock.AddedInitiallyInCommit = commit; } else if ((codeBlock.Size < 0) && (codeBlock.TargetCodeBlockID == null)) { codeBlock.TargetCodeBlock = repository.SelectionDSL() .Commits().RevisionIs(error.SourceRevision) .Files().PathIs(file.Path) .Modifications().InFiles() .CodeBlocks().InModifications().AddedInitiallyInCommits().Single(); } Console.WriteLine(", now {0}", codeBlock.Size); } } break; } } } } return correct; }
public override IDictionary<string, object> BuildData(IRepository repository) { Dictionary<string,object> result = new Dictionary<string,object>(); double totalLoc = repository.SelectionDSL() .Files().InDirectory(TargetDir) .Modifications().InFiles() .CodeBlocks().InModifications().CalculateLOC(); List<object> releaseObjects = new List<object>(); var releases = repository.AllReleases(); releases.Add(repository.LastRevision(), "upcoming"); DateTime statFrom = repository.Queryable<Commit>().Min(x => x.Date); string prevRelease = null; foreach (var release in releases) { var releaseCommits = repository.SelectionDSL() .Commits() .AfterRevision(prevRelease) .TillRevision(release.Key) .Fixed(); var releaseCode = releaseCommits .Files() .InDirectory(TargetDir) .Modifications() .InCommits() .InFiles() .CodeBlocks() .InModifications() .Fixed(); var totalReleaseCommits = repository.SelectionDSL() .Commits() .TillRevision(release.Key) .Fixed(); var totalReleaseCode = totalReleaseCommits .Files() .InDirectory(TargetDir) .Modifications() .InCommits() .InFiles() .CodeBlocks() .InModifications() .Fixed(); DateTime releaseStatFrom = releaseCommits.Min(x => x.Date); DateTime releaseStatTo = releaseCommits.Max(x => x.Date); int releaseCommitsCount = releaseCommits.Count(); int releaseAuthorsCount = releaseCommits.Select(c => c.Author).Distinct().Count(); int releaseFixesCount = releaseCommits.AreBugFixes().Count(); int releaseFilesCount = repository.SelectionDSL() .Files().ExistInRevision(release.Key).Count(); int releaseTouchedFilesCount = releaseCommits .Files() .ExistInRevision(release.Key) .TouchedInCommits() .Count(); int releaseDefectiveFilesCount = releaseCode .DefectiveFiles(prevRelease, null) .ExistInRevision(release.Key) .Count(); int totalReleaseCommitsCount = totalReleaseCommits.Count(); int totalReleaseAuthorsCount = totalReleaseCommits.Select(c => c.Author).Distinct().Count(); int totalReleaseFixesCount = totalReleaseCommits.AreBugFixes().Count(); var totalReleaseLoc = totalReleaseCode.CalculateLOC(); var releaseRemainLoc = releaseCode.Added().CalculateLOC() + releaseCode.ModifiedBy().CalculateLOC(); var totalReleaseAddedLoc = totalReleaseCode.Added().CalculateLOC(); var releaseAddedLoc = releaseCode.Added().CalculateLOC(); double releaseDD = releaseCode.CalculateDefectDensity(); double totalReleaseDD = totalReleaseCode.CalculateDefectDensity(); double postReleaseDD = releaseDD - releaseCode.CalculateDefectDensity(release.Key); releaseObjects.Add(new { tag = release.Value, commits = string.Format("{0} ({1})", releaseCommitsCount, totalReleaseCommitsCount ), days = string.Format("{0} ({1})", (releaseStatTo - releaseStatFrom).Days, (releaseStatTo - statFrom).Days ), authors = string.Format("{0} ({1})", releaseAuthorsCount, totalReleaseAuthorsCount ), files = releaseFilesCount, files_changed = string.Format( "{0} ({1}%)", releaseTouchedFilesCount, (((double)releaseTouchedFilesCount / releaseFilesCount) * 100).ToString("F02") ), files_defective = string.Format( "{0} ({1}%)", releaseDefectiveFilesCount, (((double)releaseDefectiveFilesCount / releaseFilesCount) * 100).ToString("F02") ), dd = string.Format("{0} ({1})", releaseDD.ToString("F03"), totalReleaseDD.ToString("F03") ), post_release_dd = string.Format( "{0} ({1}%)", postReleaseDD.ToString("F02"), ((releaseDD > 0 ? postReleaseDD / releaseDD : 0) * 100).ToString("F02") ), fixed_defects = string.Format("{0} ({1})", releaseFixesCount, totalReleaseFixesCount ), added_loc = string.Format("{0} ({1})", releaseAddedLoc, totalReleaseAddedLoc ), removed_loc = string.Format("{0} ({1})", - releaseCode.Deleted().CalculateLOC(), - totalReleaseCode.Deleted().CalculateLOC() ), loc = totalReleaseLoc, remain_loc = releaseRemainLoc, contribution = ((releaseRemainLoc / totalLoc) * 100).ToString("F02") + "%", demand_for_code = (releaseAddedLoc > 0 ? ((releaseRemainLoc / releaseAddedLoc) * 100) : 0).ToString("F02") + "%" }); prevRelease = release.Key; } result.Add("releases", releaseObjects); return result; }
private bool CheckLinesContent(IRepository repository, IScmData scmData, string testRevision, ProjectFile file, bool resultOnly) { IBlame fileBlame = null; try { fileBlame = scmData.Blame(testRevision, file.Path); } catch { } if (fileBlame == null) { if (!resultOnly) { Console.WriteLine("File {0} does not exist.", file.Path); } return(false); } double currentLOC = repository.SelectionDSL() .Commits().TillRevision(testRevision) .Files().IdIs(file.ID) .Modifications().InCommits().InFiles() .CodeBlocks().InModifications() .CalculateLOC(); bool correct = currentLOC == fileBlame.Count; if (!correct) { if (!resultOnly) { Console.WriteLine("Incorrect number of lines in file {0}. {1} should be {2}", file.Path, currentLOC, fileBlame.Count ); } else { return(false); } } SmartDictionary <string, int> linesByRevision = new SmartDictionary <string, int>(x => 0); foreach (var line in fileBlame) { linesByRevision[line.Value]++; } var codeBySourceRevision = ( from f in repository.Queryable <ProjectFile>() join m in repository.Queryable <Modification>() on f.ID equals m.FileID join cb in repository.Queryable <CodeBlock>() on m.ID equals cb.ModificationID join c in repository.Queryable <Commit>() on m.CommitID equals c.ID let addedCodeBlock = repository.Queryable <CodeBlock>() .Single(x => x.ID == (cb.Size < 0 ? cb.TargetCodeBlockID : cb.ID)) let codeAddedInitiallyInRevision = repository.Queryable <Commit>() .Single(x => x.ID == addedCodeBlock.AddedInitiallyInCommitID) .Revision let testRevisionNumber = repository.Queryable <Commit>() .Single(x => x.Revision == testRevision) .OrderedNumber where f.ID == file.ID && c.OrderedNumber <= testRevisionNumber group cb.Size by codeAddedInitiallyInRevision into g select new { FromRevision = g.Key, CodeSize = g.Sum() } ).Where(x => x.CodeSize != 0).ToList(); var errorCode = ( from codeFromRevision in codeBySourceRevision where codeFromRevision.CodeSize != linesByRevision[codeFromRevision.FromRevision] select new { SourceRevision = codeFromRevision.FromRevision, CodeSize = codeFromRevision.CodeSize, RealCodeSize = linesByRevision[codeFromRevision.FromRevision] } ).ToList(); correct = correct && codeBySourceRevision.Count() == linesByRevision.Count && errorCode.Count == 0; if (!resultOnly) { if (codeBySourceRevision.Count() != linesByRevision.Count) { Console.WriteLine("Number of revisions file {0} contains code from is incorrect. {1} should be {2}", file.Path, codeBySourceRevision.Count(), linesByRevision.Count ); } foreach (var error in errorCode) { Console.WriteLine("Incorrect number of lines in file {0} from revision {1}. {2} should be {3}", file.Path, error.SourceRevision, error.CodeSize, error.RealCodeSize ); } if ((!correct) && (errorCode.Count > 0)) { string latestCodeRevision = repository.LastRevision(errorCode.Select(x => x.SourceRevision)); var commitsFileTouchedIn = repository.SelectionDSL() .Files().IdIs(file.ID) .Commits().FromRevision(latestCodeRevision).TouchFiles() .OrderBy(c => c.OrderedNumber); foreach (var commit in commitsFileTouchedIn) { if (!CheckLinesContent(repository, scmData, commit.Revision, file, true)) { Console.WriteLine("{0} - incorrectly mapped commit.", commit.Revision); if ((automaticallyFixDiffErrors) && (errorCode.Sum(x => x.CodeSize - x.RealCodeSize) == 0)) { var incorrectDeleteCodeBlocks = from cb in repository.SelectionDSL() .Commits().RevisionIs(commit.Revision) .Files().PathIs(file.Path) .Modifications().InCommits().InFiles() .CodeBlocks().InModifications().Deleted() join tcb in repository.Queryable <CodeBlock>() on cb.TargetCodeBlockID equals tcb.ID join m in repository.Queryable <Modification>() on tcb.ModificationID equals m.ID join c in repository.Queryable <Commit>() on m.CommitID equals c.ID where errorCode.Select(x => x.SourceRevision).Contains(c.Revision) select new { Code = cb, TargetRevision = c.Revision }; foreach (var error in errorCode) { var incorrectDeleteCodeBlock = incorrectDeleteCodeBlocks.SingleOrDefault(x => x.TargetRevision == error.SourceRevision); var codeBlock = incorrectDeleteCodeBlock == null ? null : incorrectDeleteCodeBlock.Code; double difference = error.CodeSize - error.RealCodeSize; if (codeBlock == null) { codeBlock = new CodeBlock() { Size = 0, Modification = repository.SelectionDSL() .Commits().RevisionIs(commit.Revision) .Files().PathIs(file.Path) .Modifications().InCommits().InFiles().Single(), }; repository.Add(codeBlock); } Console.WriteLine("Fix code block size for file {0} in revision {1}:", file.Path, commit.Revision); Console.Write("Was {0}", codeBlock.Size); codeBlock.Size -= difference; if (codeBlock.Size == 0) { repository.Delete(codeBlock); } else if ((codeBlock.Size > 0) && (codeBlock.AddedInitiallyInCommitID == null)) { codeBlock.AddedInitiallyInCommit = commit; } else if ((codeBlock.Size < 0) && (codeBlock.TargetCodeBlockID == null)) { codeBlock.TargetCodeBlock = repository.SelectionDSL() .Commits().RevisionIs(error.SourceRevision) .Files().PathIs(file.Path) .Modifications().InFiles() .CodeBlocks().InModifications().AddedInitiallyInCommits().Single(); } Console.WriteLine(", now {0}", codeBlock.Size); } } break; } } } } return(correct); }
public override IDictionary <string, object> BuildData(IRepository repository) { Dictionary <string, object> result = new Dictionary <string, object>(); double totalLoc = repository.SelectionDSL() .Files().InDirectory(TargetDir) .Modifications().InFiles() .CodeBlocks().InModifications().CalculateLOC(); List <object> releaseObjects = new List <object>(); var releases = repository.AllReleases(); releases.Add(repository.LastRevision(), "upcoming"); DateTime statFrom = repository.Queryable <Commit>().Min(x => x.Date); string prevRelease = null; foreach (var release in releases) { var releaseCommits = repository.SelectionDSL() .Commits() .AfterRevision(prevRelease) .TillRevision(release.Key) .Fixed(); var releaseCode = releaseCommits .Files() .InDirectory(TargetDir) .Modifications() .InCommits() .InFiles() .CodeBlocks() .InModifications() .Fixed(); var totalReleaseCommits = repository.SelectionDSL() .Commits() .TillRevision(release.Key) .Fixed(); var totalReleaseCode = totalReleaseCommits .Files() .InDirectory(TargetDir) .Modifications() .InCommits() .InFiles() .CodeBlocks() .InModifications() .Fixed(); DateTime releaseStatFrom = releaseCommits.Min(x => x.Date); DateTime releaseStatTo = releaseCommits.Max(x => x.Date); int releaseCommitsCount = releaseCommits.Count(); int releaseAuthorsCount = releaseCommits.Select(c => c.Author).Distinct().Count(); int releaseFixesCount = releaseCommits.AreBugFixes().Count(); int releaseFilesCount = repository.SelectionDSL() .Files().ExistInRevision(release.Key).Count(); int releaseTouchedFilesCount = releaseCommits .Files() .ExistInRevision(release.Key) .TouchedInCommits() .Count(); int releaseDefectiveFilesCount = releaseCode .DefectiveFiles(prevRelease, null) .ExistInRevision(release.Key) .Count(); int totalReleaseCommitsCount = totalReleaseCommits.Count(); int totalReleaseAuthorsCount = totalReleaseCommits.Select(c => c.Author).Distinct().Count(); int totalReleaseFixesCount = totalReleaseCommits.AreBugFixes().Count(); var totalReleaseLoc = totalReleaseCode.CalculateLOC(); var releaseRemainLoc = releaseCode.Added().CalculateLOC() + releaseCode.ModifiedBy().CalculateLOC(); var totalReleaseAddedLoc = totalReleaseCode.Added().CalculateLOC(); var releaseAddedLoc = releaseCode.Added().CalculateLOC(); double releaseDD = releaseCode.CalculateDefectDensity(); double totalReleaseDD = totalReleaseCode.CalculateDefectDensity(); double postReleaseDD = releaseDD - releaseCode.CalculateDefectDensity(release.Key); releaseObjects.Add(new { tag = release.Value, commits = string.Format("{0} ({1})", releaseCommitsCount, totalReleaseCommitsCount ), days = string.Format("{0} ({1})", (releaseStatTo - releaseStatFrom).Days, (releaseStatTo - statFrom).Days ), authors = string.Format("{0} ({1})", releaseAuthorsCount, totalReleaseAuthorsCount ), files = releaseFilesCount, files_changed = string.Format( "{0} ({1}%)", releaseTouchedFilesCount, (((double)releaseTouchedFilesCount / releaseFilesCount) * 100).ToString("F02") ), files_defective = string.Format( "{0} ({1}%)", releaseDefectiveFilesCount, (((double)releaseDefectiveFilesCount / releaseFilesCount) * 100).ToString("F02") ), dd = string.Format("{0} ({1})", releaseDD.ToString("F03"), totalReleaseDD.ToString("F03") ), post_release_dd = string.Format( "{0} ({1}%)", postReleaseDD.ToString("F02"), ((releaseDD > 0 ? postReleaseDD / releaseDD : 0) * 100).ToString("F02") ), fixed_defects = string.Format("{0} ({1})", releaseFixesCount, totalReleaseFixesCount ), added_loc = string.Format("{0} ({1})", releaseAddedLoc, totalReleaseAddedLoc ), removed_loc = string.Format("{0} ({1})", -releaseCode.Deleted().CalculateLOC(), -totalReleaseCode.Deleted().CalculateLOC() ), loc = totalReleaseLoc, remain_loc = releaseRemainLoc, contribution = ((releaseRemainLoc / totalLoc) * 100).ToString("F02") + "%", demand_for_code = (releaseAddedLoc > 0 ? ((releaseRemainLoc / releaseAddedLoc) * 100) : 0).ToString("F02") + "%" }); prevRelease = release.Key; } result.Add("releases", releaseObjects); return(result); }