github.com/mattbailey/reviewdog@v0.10.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/reviewdog/reviewdog" 12 "github.com/reviewdog/reviewdog/service/serviceutil" 13 ) 14 15 var _ reviewdog.DiffService = &GitLabMergeRequestDiff{} 16 17 // GitLabMergeRequestDiff is a diff service for GitLab MergeRequest. 18 type GitLabMergeRequestDiff 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 GitLabMergeRequestDiff service. 29 // itLabMergeRequestDiff service needs git command in $PATH. 30 func NewGitLabMergeRequestDiff(cli *gitlab.Client, owner, repo string, pr int, sha string) (*GitLabMergeRequestDiff, error) { 31 workDir, err := serviceutil.GitRelWorkdir() 32 if err != nil { 33 return nil, fmt.Errorf("GitLabMergeRequestCommitCommenter needs 'git' command: %v", err) 34 } 35 return &GitLabMergeRequestDiff{ 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 *GitLabMergeRequestDiff) 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 *GitLabMergeRequestDiff) 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: %v", err) 65 } 66 mergeBase := strings.Trim(string(b), "\n") 67 relArg := fmt.Sprintf("--relative=%s", g.wd) 68 bytes, err := exec.Command("git", "diff", relArg, "--find-renames", mergeBase, baseSha).Output() 69 if err != nil { 70 return nil, fmt.Errorf("failed to run git diff: %v", err) 71 } 72 return bytes, nil 73 } 74 75 // Strip returns 1 as a strip of git diff. 76 func (g *GitLabMergeRequestDiff) Strip() int { 77 return 1 78 }