github.com/friedemannf/reviewdog@v0.14.0/service/gitlab/gitlab_mr_diff.go (about) 1 package gitlab 2 3 import ( 4 "context" 5 "fmt" 6 "os/exec" 7 "strings" 8 9 "github.com/xanzy/go-gitlab" 10 11 "github.com/friedemannf/reviewdog" 12 "github.com/friedemannf/reviewdog/service/serviceutil" 13 ) 14 15 var _ reviewdog.DiffService = &MergeRequestDiff{} 16 17 // MergeRequestDiff is a diff service for GitLab MergeRequest. 18 type MergeRequestDiff struct { 19 cli *gitlab.Client 20 pr int 21 sha string 22 projects string 23 24 // wd is working directory relative to root of repository. 25 wd string 26 } 27 28 // NewGitLabMergeRequestDiff returns a new MergeRequestDiff service. 29 // itLabMergeRequestDiff service needs git command in $PATH. 30 func NewGitLabMergeRequestDiff(cli *gitlab.Client, owner, repo string, pr int, sha string) (*MergeRequestDiff, error) { 31 workDir, err := serviceutil.GitRelWorkdir() 32 if err != nil { 33 return nil, fmt.Errorf("MergeRequestCommitCommenter needs 'git' command: %w", err) 34 } 35 return &MergeRequestDiff{ 36 cli: cli, 37 pr: pr, 38 sha: sha, 39 projects: owner + "/" + repo, 40 wd: workDir, 41 }, nil 42 } 43 44 // Diff returns a diff of MergeRequest. It runs `git diff` locally instead of 45 // diff_url of GitLab Merge Request because diff of diff_url is not suited for 46 // comment API in a sense that diff of diff_url is equivalent to 47 // `git diff --no-renames`, we want diff which is equivalent to 48 // `git diff --find-renames`. 49 func (g *MergeRequestDiff) Diff(ctx context.Context) ([]byte, error) { 50 mr, _, err := g.cli.MergeRequests.GetMergeRequest(g.projects, g.pr, nil) 51 if err != nil { 52 return nil, err 53 } 54 targetBranch, _, err := g.cli.Branches.GetBranch(mr.TargetProjectID, mr.TargetBranch, nil) 55 if err != nil { 56 return nil, err 57 } 58 return g.gitDiff(ctx, g.sha, targetBranch.Commit.ID) 59 } 60 61 func (g *MergeRequestDiff) gitDiff(_ context.Context, baseSha, targetSha string) ([]byte, error) { 62 b, err := exec.Command("git", "merge-base", targetSha, baseSha).Output() 63 if err != nil { 64 return nil, fmt.Errorf("failed to get merge-base commit: %w", err) 65 } 66 mergeBase := strings.Trim(string(b), "\n") 67 bytes, err := exec.Command("git", "diff", "--find-renames", mergeBase, baseSha).Output() 68 if err != nil { 69 return nil, fmt.Errorf("failed to run git diff: %w", err) 70 } 71 return bytes, nil 72 } 73 74 // Strip returns 1 as a strip of git diff. 75 func (g *MergeRequestDiff) Strip() int { 76 return 1 77 }