github.com/khulnasoft/codebase@v0.0.0-20231214144635-a707781cbb24/service/gerrit/change_review.go (about)

     1  package gerrit
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path/filepath"
     7  	"sync"
     8  
     9  	"golang.org/x/build/gerrit"
    10  
    11  	"github.com/khulnasoft/codebase"
    12  	"github.com/khulnasoft/codebase/service/serviceutil"
    13  )
    14  
    15  var _ codebase.CommentService = &ChangeReviewCommenter{}
    16  
    17  // ChangeReviewCommenter is a comment service for Gerrit Change Review
    18  // API:
    19  //
    20  //	https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#set-review
    21  //	POST /changes/{change-id}/revisions/{revision-id}/review
    22  type ChangeReviewCommenter struct {
    23  	cli        *gerrit.Client
    24  	changeID   string
    25  	revisionID string
    26  
    27  	muComments   sync.Mutex
    28  	postComments []*codebase.Comment
    29  
    30  	// wd is working directory relative to root of repository.
    31  	wd string
    32  }
    33  
    34  // NewChangeReviewCommenter returns a new NewChangeReviewCommenter service.
    35  // ChangeReviewCommenter service needs git command in $PATH.
    36  func NewChangeReviewCommenter(cli *gerrit.Client, changeID, revisionID string) (*ChangeReviewCommenter, error) {
    37  	workDir, err := serviceutil.GitRelWorkdir()
    38  	if err != nil {
    39  		return nil, fmt.Errorf("ChangeReviewCommenter needs 'git' command: %w", err)
    40  	}
    41  
    42  	return &ChangeReviewCommenter{
    43  		cli:          cli,
    44  		changeID:     changeID,
    45  		revisionID:   revisionID,
    46  		postComments: []*codebase.Comment{},
    47  		wd:           workDir,
    48  	}, nil
    49  }
    50  
    51  // Post accepts a comment and holds it. Flush method actually posts comments to Gerrit
    52  func (g *ChangeReviewCommenter) Post(_ context.Context, c *codebase.Comment) error {
    53  	c.Result.Diagnostic.GetLocation().Path = filepath.Join(g.wd, c.Result.Diagnostic.GetLocation().GetPath())
    54  	g.muComments.Lock()
    55  	defer g.muComments.Unlock()
    56  	g.postComments = append(g.postComments, c)
    57  	return nil
    58  }
    59  
    60  // Flush posts comments which has not been posted yet.
    61  func (g *ChangeReviewCommenter) Flush(ctx context.Context) error {
    62  	g.muComments.Lock()
    63  	defer g.muComments.Unlock()
    64  
    65  	return g.postAllComments(ctx)
    66  }
    67  
    68  func (g *ChangeReviewCommenter) postAllComments(ctx context.Context) error {
    69  	review := gerrit.ReviewInput{
    70  		Comments: map[string][]gerrit.CommentInput{},
    71  	}
    72  	for _, c := range g.postComments {
    73  		if !c.Result.InDiffFile {
    74  			continue
    75  		}
    76  		loc := c.Result.Diagnostic.GetLocation()
    77  		path := loc.GetPath()
    78  		review.Comments[path] = append(review.Comments[path], gerrit.CommentInput{
    79  			Line:    int(loc.GetRange().GetStart().GetLine()),
    80  			Message: c.Result.Diagnostic.GetMessage(),
    81  		})
    82  	}
    83  
    84  	return g.cli.SetReview(ctx, g.changeID, g.revisionID, review)
    85  }