Rebased all commits, v0.0.1
added a new file First major commit Successful POST of new comment 🚀 Updated README Updated README 📕 Added more infrastructure Creating async job More setup Getting arguments from Neovim -> Lua -> Golang Moved commands Added getProjectInfo command Adding make comment command Setting up arguments for MakeComment command Removed extraneous comments Setup basic function for adding comments Lint fixes Handling bad requests correctly Better formatting Printing success message Adding utility table print Set comment from popup UI Added mappings for closing and sending text Moved popup into separate file Added comment Cleaned up code and added approve command Initialize project information Removed extraneous import Don't initialize project in non-gitlab directories Setup approve command Set up revoke and approve commands correctly Cleaned up redundant code Moved get current branch command Reorganization of the code First attempt to add step installing Go binary Adjusted path to binary Added install bin check Do Lua method Fixed install step Tweaked binPath + bin Added basic readme information 📗 Removed .luarc.json file Adding diffview command Added string_starts function Made base branch configurable Added note to readme Fixed readme Added diffview dep to readme Update README.md Update README.md Update README.md Update README.md Renamed files Set up developer workflow Updated README Removed dev note Refactor and moving around files Fixed ft/after mappings Setup read command Added read summary command Got rid of filetype bindings and set up commands Set correct filetype for comment buffer Added read() command to README Updated review -> summary Fixed issue with diffview buffers Added command for getting and showing all comments (out of order) Better error message Adding more code to handle showing comments Added ability to jump from comment to specific changed buffer line Initial refactor Added simple comment action Fixed error message More cleanup Fixed bug with M.PROJECT_ID Leaving comment refactor Fixed comment Cleaned up old code Added missing exit command Check gitlab repo status before initialization Better help strings Added ListDiscussions command Added Go code Darkened metadata, filtered out non-real discussions Removed dummy log Sort the discussions by most recent activity Grab hash of current discussion Wired up reply action in Lua code Moved to NUI Table Adding basic jump-to-file ability More tweaks Allow jump anywhere in the tree Ability to reply directly in the buffer window Jump to location in file Don't jump if no refresh is set Cleaned up mappings + other code Get rid of gitlab CLI dependency Fixed discussions bug Don't initialize client on main/master branches Moved comment into separate module Moved lua modules into separate files Modularized library and state Slightly better error/exception handling Added license file Updated readme Moved into todo.md file Added todo file Standardized naming conventions (snake_case in Lua, camelCase in Go) Moved common popup state into utils folder Cleaned up keymapping functions Note on install Changing bin path Updated README Chnaged from success to info Redirect output to /dev/null on build Checking install code Removed print statement Slight reorganization Setting up delete comment Set up confirmation modal Passing in node ID to delete_comment Functioning comment deletion Added delete_comment command Updated README Furhter modularized discussion code Cleaned up and refactored reply code Update README.md Added ability to edit comments Updated todos Fixed main/master base branch issue Set up keybinding rules Updated todo.md Removed diffview dependency Slight cleanup 🧹 Trying something out... Trying something for the binary... Trying again Fixed install for non-lazy users Update README.md Update README.md Update README.md Update README.md Update README.md
This commit is contained in:
18
cmd/approve.go
Normal file
18
cmd/approve.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *Client) Approve() error {
|
||||
|
||||
_, _, err := c.git.MergeRequestApprovals.ApproveMergeRequest(c.projectId, c.mergeId, nil, nil)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Approving MR failed: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Success! Approved MR.")
|
||||
|
||||
return nil
|
||||
}
|
||||
68
cmd/client.go
Normal file
68
cmd/client.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
command string
|
||||
projectId string
|
||||
mergeId int
|
||||
git *gitlab.Client
|
||||
}
|
||||
|
||||
/* This will initialize the client with the token and check for the basic project ID and command arguments */
|
||||
func (c *Client) Init(branchName string) error {
|
||||
|
||||
if len(os.Args) < 3 {
|
||||
return errors.New("Must provide command and projectId")
|
||||
}
|
||||
|
||||
command, projectId := os.Args[1], os.Args[2]
|
||||
c.command = command
|
||||
c.projectId = projectId
|
||||
|
||||
if projectId == "" {
|
||||
return errors.New("Must provide projectId")
|
||||
}
|
||||
|
||||
git, err := gitlab.NewClient(os.Getenv("GITLAB_TOKEN"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to create client: %v", err)
|
||||
}
|
||||
|
||||
options := gitlab.ListMergeRequestsOptions{
|
||||
State: gitlab.String("opened"),
|
||||
SourceBranch: &branchName,
|
||||
}
|
||||
|
||||
mergeRequests, _, err := git.MergeRequests.ListMergeRequests(&options)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to list merge requests: %w", err)
|
||||
}
|
||||
|
||||
if len(mergeRequests) == 0 {
|
||||
return errors.New("No merge requests found")
|
||||
}
|
||||
|
||||
mergeId := strconv.Itoa(mergeRequests[0].IID)
|
||||
mergeIdInt, err := strconv.Atoi(mergeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.mergeId = mergeIdInt
|
||||
c.git = git
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Usage(command string) {
|
||||
fmt.Printf("Usage: gitlab-nvim %s <project-id> ...args", command)
|
||||
os.Exit(1)
|
||||
}
|
||||
116
cmd/comment.go
Normal file
116
cmd/comment.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
const mrVersionsUrl = "https://gitlab.com/api/v4/projects/%s/merge_requests/%d/versions"
|
||||
|
||||
type MRVersion struct {
|
||||
ID int `json:"id"`
|
||||
HeadCommitSHA string `json:"head_commit_sha"`
|
||||
BaseCommitSHA string `json:"base_commit_sha"`
|
||||
StartCommitSHA string `json:"start_commit_sha"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
MergeRequestID int `json:"merge_request_id"`
|
||||
State string `json:"state"`
|
||||
RealSize string `json:"real_size"`
|
||||
}
|
||||
|
||||
func (c *Client) Comment() error {
|
||||
if len(os.Args) < 6 {
|
||||
c.Usage("comment")
|
||||
}
|
||||
|
||||
lineNumber, fileName, comment := os.Args[3], os.Args[4], os.Args[5]
|
||||
if lineNumber == "" || fileName == "" || comment == "" {
|
||||
c.Usage("comment")
|
||||
}
|
||||
|
||||
lineNumberInt, err := strconv.Atoi(lineNumber)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Not a valid line number: %w", err)
|
||||
}
|
||||
|
||||
err, response := getMRVersions(c.projectId, c.mergeId)
|
||||
if err != nil {
|
||||
log.Fatalf("Error making diff thread: %s", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
|
||||
var diffVersionInfo []MRVersion
|
||||
err = json.Unmarshal(body, &diffVersionInfo)
|
||||
|
||||
time := time.Now()
|
||||
|
||||
options := gitlab.CreateMergeRequestDiscussionOptions{
|
||||
Body: &comment,
|
||||
CreatedAt: &time,
|
||||
Position: &gitlab.NotePosition{
|
||||
PositionType: "text",
|
||||
BaseSHA: diffVersionInfo[0].BaseCommitSHA,
|
||||
HeadSHA: diffVersionInfo[0].HeadCommitSHA,
|
||||
StartSHA: diffVersionInfo[0].StartCommitSHA,
|
||||
NewPath: fileName,
|
||||
OldPath: fileName,
|
||||
NewLine: lineNumberInt,
|
||||
},
|
||||
}
|
||||
|
||||
_, _, err = c.git.Discussions.CreateMergeRequestDiscussion(c.projectId, c.mergeId, &options)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not leave comment: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Left Comment: " + comment[0:min(len(comment), 25)] + "...")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func min(a int, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
/* Gets the latest merge request revision data */
|
||||
func getMRVersions(projectId string, mergeId int) (e error, response *http.Response) {
|
||||
|
||||
gitlabToken := os.Getenv("GITLAB_TOKEN")
|
||||
url := fmt.Sprintf(mrVersionsUrl, projectId, mergeId)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
|
||||
req.Header.Add("PRIVATE-TOKEN", gitlabToken)
|
||||
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
response, err = client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
||||
if response.StatusCode != 200 {
|
||||
return errors.New("Non-200 status code: " + response.Status), nil
|
||||
}
|
||||
|
||||
return nil, response
|
||||
}
|
||||
29
cmd/delete_comment.go
Normal file
29
cmd/delete_comment.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (c *Client) DeleteComment() error {
|
||||
discussionId, noteId := os.Args[3], os.Args[4]
|
||||
if discussionId == "" || noteId == "" {
|
||||
c.Usage("deleteComment")
|
||||
}
|
||||
|
||||
noteIdInt, err := strconv.Atoi(noteId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not convert noteId to int: %w", err)
|
||||
}
|
||||
|
||||
_, err = c.git.Discussions.DeleteMergeRequestDiscussionNote(c.projectId, c.mergeId, discussionId, noteIdInt)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not delete comment: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Deleted comment")
|
||||
|
||||
return nil
|
||||
}
|
||||
46
cmd/edit_comment.go
Normal file
46
cmd/edit_comment.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
func (c *Client) EditComment() error {
|
||||
if len(os.Args) < 6 {
|
||||
return errors.New("Must provide commentId, noteId, and edited text")
|
||||
}
|
||||
|
||||
discussionId, noteId, newCommentText := os.Args[3], os.Args[4], os.Args[5]
|
||||
if discussionId == "" || newCommentText == "" {
|
||||
return errors.New("Must provide commentId, noteId, and edited text")
|
||||
}
|
||||
|
||||
options := gitlab.UpdateMergeRequestDiscussionNoteOptions{
|
||||
Body: gitlab.String(newCommentText),
|
||||
}
|
||||
|
||||
noteIdInt, err := strconv.Atoi(noteId)
|
||||
if err != nil {
|
||||
return errors.New("Not a valid noteId")
|
||||
}
|
||||
|
||||
gitlabNote, _, err := c.git.Discussions.UpdateMergeRequestDiscussionNote(c.projectId, c.mergeId, discussionId, noteIdInt, &options)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to edit comment: %w", err)
|
||||
}
|
||||
|
||||
note, err := json.Marshal(gitlabNote)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to marshal note: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println(string(note))
|
||||
|
||||
return nil
|
||||
}
|
||||
46
cmd/info.go
Normal file
46
cmd/info.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
const mrUrl = "https://gitlab.com/api/v4/projects/%s/merge_requests/%d"
|
||||
|
||||
func (c *Client) Info() error {
|
||||
|
||||
url := fmt.Sprintf(mrUrl, c.projectId, c.mergeId)
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to build read request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("PRIVATE-TOKEN", os.Getenv("GITLAB_TOKEN"))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to make info request: %w", err)
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode < 200 || res.StatusCode >= 300 {
|
||||
return errors.New(fmt.Sprintf("Recieved non-200 response: %d", res.StatusCode))
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse read response: %w", err)
|
||||
}
|
||||
|
||||
/* This response is parsed into a table in our Lua code */
|
||||
fmt.Println(string(body))
|
||||
|
||||
return nil
|
||||
}
|
||||
60
cmd/list_discussions.go
Normal file
60
cmd/list_discussions.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"encoding/json"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
type SortableDiscussions []*gitlab.Discussion
|
||||
|
||||
func (n SortableDiscussions) Len() int {
|
||||
return len(n)
|
||||
}
|
||||
|
||||
func (d SortableDiscussions) Less(i int, j int) bool {
|
||||
iTime := d[i].Notes[len(d[i].Notes)-1].CreatedAt
|
||||
jTime := d[j].Notes[len(d[j].Notes)-1].CreatedAt
|
||||
return iTime.After(*jTime)
|
||||
|
||||
}
|
||||
|
||||
func (n SortableDiscussions) Swap(i, j int) {
|
||||
n[i], n[j] = n[j], n[i]
|
||||
}
|
||||
|
||||
func (c *Client) ListDiscussions() error {
|
||||
|
||||
mergeRequestDiscussionOptions := gitlab.ListMergeRequestDiscussionsOptions{
|
||||
Page: 1,
|
||||
PerPage: 250,
|
||||
}
|
||||
discussions, _, err := c.git.Discussions.ListMergeRequestDiscussions(c.projectId, c.mergeId, &mergeRequestDiscussionOptions, nil)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Listing discussions failed: %w", err)
|
||||
}
|
||||
|
||||
var realDiscussions []*gitlab.Discussion
|
||||
for i := 0; i < len(discussions); i++ {
|
||||
notes := discussions[i].Notes
|
||||
for j := 0; j < len(notes); j++ {
|
||||
if notes[j].Type == gitlab.NoteTypeValue("DiffNote") {
|
||||
realDiscussions = append(realDiscussions, discussions[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortedDiscussions := SortableDiscussions(realDiscussions)
|
||||
sort.Sort(sortedDiscussions)
|
||||
|
||||
discussionsOutput, err := json.Marshal(sortedDiscussions)
|
||||
|
||||
fmt.Println(string(discussionsOutput))
|
||||
|
||||
return nil
|
||||
}
|
||||
76
cmd/main.go
Normal file
76
cmd/main.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
star = "star"
|
||||
info = "info"
|
||||
approve = "approve"
|
||||
revoke = "revoke"
|
||||
comment = "comment"
|
||||
deleteComment = "deleteComment"
|
||||
editComment = "editComment"
|
||||
reply = "reply"
|
||||
listDiscussions = "listDiscussions"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
branchName, err := getCurrentBranch()
|
||||
errCheck(err)
|
||||
if branchName == "main" || branchName == "master" {
|
||||
return
|
||||
}
|
||||
|
||||
var c Client
|
||||
errCheck(c.Init(branchName))
|
||||
|
||||
switch c.command {
|
||||
case star:
|
||||
errCheck(c.Star())
|
||||
case approve:
|
||||
errCheck(c.Approve())
|
||||
case revoke:
|
||||
errCheck(c.Revoke())
|
||||
case comment:
|
||||
errCheck(c.Comment())
|
||||
case deleteComment:
|
||||
errCheck(c.DeleteComment())
|
||||
case editComment:
|
||||
errCheck(c.EditComment())
|
||||
case info:
|
||||
errCheck(c.Info())
|
||||
case reply:
|
||||
errCheck(c.Reply())
|
||||
case listDiscussions:
|
||||
errCheck(c.ListDiscussions())
|
||||
default:
|
||||
c.Usage("command")
|
||||
}
|
||||
}
|
||||
|
||||
func errCheck(err error) {
|
||||
if err != nil {
|
||||
log.Fatalf("Failure: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
/* Gets the current branch */
|
||||
func getCurrentBranch() (res string, e error) {
|
||||
gitCmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
|
||||
output, err := gitCmd.Output()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error running git rev-parse: %w", err)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(output)), nil
|
||||
|
||||
}
|
||||
41
cmd/reply.go
Normal file
41
cmd/reply.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
func (c *Client) Reply() error {
|
||||
|
||||
if len(os.Args) < 5 {
|
||||
return errors.New("Must provide discussionId and reply text")
|
||||
}
|
||||
|
||||
discussionId, reply := os.Args[3], os.Args[4]
|
||||
|
||||
now := time.Now()
|
||||
options := gitlab.AddMergeRequestDiscussionNoteOptions{
|
||||
Body: gitlab.String(reply),
|
||||
CreatedAt: &now,
|
||||
}
|
||||
|
||||
gitlabNote, _, err := c.git.Discussions.AddMergeRequestDiscussionNote(c.projectId, c.mergeId, discussionId, &options)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not leave reply: %w", err)
|
||||
}
|
||||
|
||||
output, err := json.Marshal(gitlabNote)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not marshal note: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println(string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
18
cmd/revoke.go
Normal file
18
cmd/revoke.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *Client) Revoke() error {
|
||||
|
||||
_, err := c.git.MergeRequestApprovals.UnapproveMergeRequest(c.projectId, c.mergeId, nil, nil)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Revoking approval failed: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Success! Revoked MR approval.")
|
||||
|
||||
return nil
|
||||
}
|
||||
17
cmd/star.go
Normal file
17
cmd/star.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func (c *Client) Star() error {
|
||||
project, _, err := c.git.Projects.StarProject(c.projectId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Starring project failed: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Success! Starred project: %s", project.Name)
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user