From 3044fca1d292f1b40bb12dfbdd2580fdf467d9e6 Mon Sep 17 00:00:00 2001 From: ChanochShayner <57212002+ChanochShayner@users.noreply.github.com> Date: Sun, 27 Aug 2023 10:27:02 +0300 Subject: [PATCH] Tag resource with remove changes (#409) * Tag resource with remove changes * Some UT fixes * golangci * naming * CR * golangci --- src/common/gitservice/blame.go | 46 ++++++++++++++++++++++++++-- src/common/gitservice/git_service.go | 40 +++++++++++++++--------- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/common/gitservice/blame.go b/src/common/gitservice/blame.go index 1f2f926dd..7391655d8 100644 --- a/src/common/gitservice/blame.go +++ b/src/common/gitservice/blame.go @@ -5,6 +5,8 @@ import ( "strings" "time" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/bridgecrewio/yor/src/common/logger" "github.com/bridgecrewio/yor/src/common/structure" @@ -19,16 +21,54 @@ type GitBlame struct { GitUserEmail string } -func NewGitBlame(filePath string, lines structure.Lines, blameResult *git.BlameResult, gitOrg string, gitRepository string, userEmail string) *GitBlame { - gitBlame := GitBlame{GitOrg: gitOrg, GitRepository: gitRepository, BlamesByLine: map[int]*git.Line{}, FilePath: filePath, GitUserEmail: userEmail} +func GetPreviousBlameResult(gitSvc *GitService, filePath string) (*git.BlameResult, *object.Commit) { + if gitSvc.repository == nil { + return nil, nil + } + ref, err := gitSvc.repository.Head() + if err != nil { + return nil, nil + } + commit, err := gitSvc.repository.CommitObject(ref.Hash()) + if err != nil { + return nil, nil + } + parentIter := commit.Parents() + previousCommit, err := parentIter.Next() + if err != nil { + return nil, nil + } + + var previousBlameResult *git.BlameResult + result, ok := gitSvc.PreviousBlameByFile.Load(filePath) + if !ok { + return nil, nil + } + + previousBlameResult = result.(*git.BlameResult) + return previousBlameResult, previousCommit +} + +func NewGitBlame(relativeFilePath string, filePath string, lines structure.Lines, blameResult *git.BlameResult, gitSvc *GitService) *GitBlame { + gitBlame := GitBlame{GitOrg: gitSvc.organization, GitRepository: gitSvc.repoName, BlamesByLine: map[int]*git.Line{}, FilePath: relativeFilePath, GitUserEmail: gitSvc.currentUserEmail} startLine := lines.Start - 1 // the lines in blameResult.Lines start from zero while the lines range start from 1 endLine := lines.End - 1 + previousBlameResult, previousCommit := GetPreviousBlameResult(gitSvc, filePath) + for line := startLine; line <= endLine; line++ { if line >= len(blameResult.Lines) { - logger.Warning(fmt.Sprintf("Index out of bound on parsed file %s", filePath)) + logger.Warning(fmt.Sprintf("Index out of bound on parsed file %s", relativeFilePath)) return &gitBlame } gitBlame.BlamesByLine[line+1] = blameResult.Lines[line] + + // Check if the line has been removed in the current state of the file + if previousBlameResult != nil && len(previousBlameResult.Lines) > len(blameResult.Lines) { + if previousBlameResult.Lines[line].Text != blameResult.Lines[line].Text { + // The line has been removed, so update the git commit id + gitBlame.BlamesByLine[line+1].Hash = previousCommit.Hash + } + } } return &gitBlame diff --git a/src/common/gitservice/git_service.go b/src/common/gitservice/git_service.go index 11d73f423..1bcff72bf 100644 --- a/src/common/gitservice/git_service.go +++ b/src/common/gitservice/git_service.go @@ -18,14 +18,15 @@ import ( ) type GitService struct { - gitRootDir string - scanPathFromRoot string - repository *git.Repository - remoteURL string - organization string - repoName string - BlameByFile *sync.Map - currentUserEmail string + gitRootDir string + scanPathFromRoot string + repository *git.Repository + remoteURL string + organization string + repoName string + BlameByFile *sync.Map + PreviousBlameByFile *sync.Map + currentUserEmail string } var gitGraphLock sync.Mutex @@ -53,10 +54,11 @@ func NewGitService(rootDir string) (*GitService, error) { scanPathFromRoot, _ := filepath.Rel(rootDirIter, scanAbsDir) gitService := GitService{ - gitRootDir: rootDir, - scanPathFromRoot: scanPathFromRoot, - repository: repository, - BlameByFile: &sync.Map{}, + gitRootDir: rootDir, + scanPathFromRoot: scanPathFromRoot, + repository: repository, + BlameByFile: &sync.Map{}, + PreviousBlameByFile: &sync.Map{}, } err = gitService.setOrgAndName() gitService.currentUserEmail = GetGitUserEmail() @@ -115,7 +117,7 @@ func (g *GitService) GetBlameForFileLines(filePath string, lines structure.Lines relativeFilePath := g.ComputeRelativeFilePath(filePath) blame, ok := g.BlameByFile.Load(filePath) if ok { - return NewGitBlame(relativeFilePath, lines, blame.(*git.BlameResult), g.organization, g.repoName, g.currentUserEmail), nil + return NewGitBlame(relativeFilePath, filePath, lines, blame.(*git.BlameResult), g), nil } var err error @@ -126,7 +128,7 @@ func (g *GitService) GetBlameForFileLines(filePath string, lines structure.Lines g.BlameByFile.Store(filePath, blame) - return NewGitBlame(relativeFilePath, lines, blame.(*git.BlameResult), g.organization, g.repoName, g.currentUserEmail), nil + return NewGitBlame(relativeFilePath, filePath, lines, blame.(*git.BlameResult), g), nil } func (g *GitService) GetOrganization() string { @@ -157,11 +159,21 @@ func (g *GitService) GetFileBlame(filePath string) (*git.BlameResult, error) { return nil, fmt.Errorf("failed to find commit %s ", head.Hash().String()) } + parentIter := selectedCommit.Parents() + previousCommit, err := parentIter.Next() + if err != nil { + return nil, fmt.Errorf("failed to get previous commit: %s", err) + } blame, err = git.Blame(selectedCommit, relativeFilePath) if err != nil { return nil, fmt.Errorf("failed to get blame for latest commit of file %s because of error %s", filePath, err) } + previousBlame, err := git.Blame(previousCommit, relativeFilePath) + if err != nil { + return nil, fmt.Errorf("failed to get blame for latest commit of file %s because of error %s", filePath, err) + } g.BlameByFile.Store(filePath, blame) + g.PreviousBlameByFile.Store(filePath, previousBlame) return blame.(*git.BlameResult), nil }