示例#1
0
        public void FindDiffError(int startRevision, string path)
        {
            int    revisionNumber = startRevision;
            string revision       = scmDataWithoutCache.RevisionByNumber(revisionNumber);

            do
            {
                Console.WriteLine("Searching for diff errors in commit {0}({1})...", revision, revisionNumber);

                List <string> fileErrors = new List <string>();
                foreach (var file in scmDataWithoutCache.Log(revision).TouchedFiles.Select(x => x.Path))
                {
                    if ((path != null) && (path != file))
                    {
                        continue;
                    }
                    var diff = scmDataWithoutCache.Diff(revision, file);
                    if (diff.AddedLines.Count() > 0)
                    {
                        var blame = scmDataWithoutCache.Blame(revision, file);

                        foreach (var line in diff.AddedLines)
                        {
                            if (blame[line] != revision)
                            {
                                fileErrors.Add(string.Format(
                                                   "Line {0}: added in diff, but blame say otherwise.", line
                                                   ));
                            }
                        }
                        foreach (var line in blame.Where(x => x.Value == revision).Select(x => x.Key))
                        {
                            if (!diff.AddedLines.Contains(line))
                            {
                                fileErrors.Add(string.Format(
                                                   "Line {0}: not added in diff, but blame say otherwise.", line
                                                   ));
                            }
                        }
                    }
                    if (fileErrors.Count > 0)
                    {
                        Console.WriteLine("Diff error in revision {0} in file {1}.", revision, file);
                        foreach (var error in fileErrors)
                        {
                            Console.WriteLine(error);
                        }
                        return;
                    }
                }

                revisionNumber++;
                revision = scmDataWithoutCache.RevisionByNumber(revisionNumber);
            } while (revision != null);

            Console.WriteLine("No diff errors.");
        }
示例#2
0
        public IBlame Blame(string revision, string filePath)
        {
            string key = revision + filePath;

            if (!blames.ContainsKey(key))
            {
                blames.Add(key, innerScmData.Blame(revision, filePath));
            }
            return(blames[key]);
        }
示例#3
0
        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;
        }
示例#4
0
        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);
        }