github.com/mistwind/reviewdog@v0.0.0-20230322024206-9cfa11856d58/service/gitlab/gitlab_push_commits_diff.go (about)

     1  package gitlab
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"os/exec"
     8  
     9  	"github.com/xanzy/go-gitlab"
    10  
    11  	"github.com/mistwind/reviewdog"
    12  	"github.com/mistwind/reviewdog/service/serviceutil"
    13  )
    14  
    15  var _ reviewdog.DiffService = &PushCommitsDiff{}
    16  
    17  // PushCommitsDiff is a diff service for GitLab Push Commits.
    18  type PushCommitsDiff struct {
    19  	cli       *gitlab.Client
    20  	sha       string
    21  	beforeSHA string
    22  	projects  string
    23  
    24  	// wd is working directory relative to root of repository.
    25  	wd string
    26  }
    27  
    28  // NewGitLabPushCommitsDiff returns a new PushCommitsDiff service.
    29  // itLabPushCommitsDiff service needs git command in $PATH.
    30  func NewGitLabPushCommitsDiff(cli *gitlab.Client, owner, repo string, sha string, beforeSHA string) (*PushCommitsDiff, error) {
    31  	workDir, err := serviceutil.GitRelWorkdir()
    32  	if err != nil {
    33  		return nil, fmt.Errorf("PushCommitsDiff needs 'git' command: %w", err)
    34  	}
    35  	return &PushCommitsDiff{
    36  		cli:       cli,
    37  		sha:       sha,
    38  		beforeSHA: beforeSHA,
    39  		projects:  owner + "/" + repo,
    40  		wd:        workDir,
    41  	}, nil
    42  }
    43  
    44  // NewGitLabPushCommitsDiffWithProjectID returns a new PushCommitsDiff service.
    45  // itLabPushCommitsDiff service needs git command in $PATH.
    46  func NewGitLabPushCommitsDiffWithProjectID(cli *gitlab.Client, projectID string, sha string, beforeSHA string) (*PushCommitsDiff, error) {
    47  	workDir, err := serviceutil.GitRelWorkdir()
    48  	if err != nil {
    49  		return nil, fmt.Errorf("PushCommitsDiff needs 'git' command: %w", err)
    50  	}
    51  	return &PushCommitsDiff{
    52  		cli:       cli,
    53  		sha:       sha,
    54  		beforeSHA: beforeSHA,
    55  		projects:  projectID,
    56  		wd:        workDir,
    57  	}, nil
    58  }
    59  
    60  // Diff returns a diff of PushCommits. It runs `git diff` locally instead of
    61  // diff_url of GitLab Merge Request because diff of diff_url is not suited for
    62  // comment API in a sense that diff of diff_url is equivalent to
    63  // `git diff --no-renames`, we want diff which is equivalent to
    64  // `git diff --find-renames`.
    65  // git diff old new
    66  func (g *PushCommitsDiff) Diff(ctx context.Context) ([]byte, error) {
    67  	b, err := g.gitDiff(ctx, g.beforeSHA, g.sha)
    68  	log.Printf("reviewdog: [gitlab-push-commit-report] PushCommitsDiff: %s\n", string(b))
    69  	return b, err
    70  }
    71  
    72  func (g *PushCommitsDiff) gitDiff(_ context.Context, baseSha, targetSha string) ([]byte, error) {
    73  	bytes, err := exec.Command("git", "diff", "--find-renames", baseSha, targetSha).Output()
    74  	if err != nil {
    75  		return nil, fmt.Errorf("failed to run git diff: %w", err)
    76  	}
    77  	return bytes, nil
    78  }
    79  
    80  // Strip returns 1 as a strip of git diff.
    81  func (g *PushCommitsDiff) Strip() int {
    82  	return 1
    83  }