Comments on deleted lines

This commit is contained in:
Harrison Cramer
2023-04-23 17:21:13 -04:00
parent b0cdc5dd88
commit 182575d95a
4 changed files with 157 additions and 50 deletions

View File

@@ -1,14 +1,17 @@
package main package main
import ( import (
"bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"mime/multipart"
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
"strings"
"sync" "sync"
"time" "time"
@@ -16,6 +19,7 @@ import (
) )
const mrVersionsUrl = "https://gitlab.com/api/v4/projects/%s/merge_requests/%d/versions" const mrVersionsUrl = "https://gitlab.com/api/v4/projects/%s/merge_requests/%d/versions"
const commentUrl = "https://gitlab.com/api/v4/projects/%s/repository/commits/%s/comments"
type MRVersion struct { type MRVersion struct {
ID int `json:"id"` ID int `json:"id"`
@@ -29,11 +33,11 @@ type MRVersion struct {
} }
func (c *Client) Comment() error { func (c *Client) Comment() error {
if len(os.Args) < 6 { if len(os.Args) < 7 {
c.Usage("comment") c.Usage("comment")
} }
lineNumber, fileName, comment := os.Args[3], os.Args[4], os.Args[5] lineNumber, fileName, comment, sha := os.Args[3], os.Args[4], os.Args[5], os.Args[6]
if lineNumber == "" || fileName == "" || comment == "" { if lineNumber == "" || fileName == "" || comment == "" {
c.Usage("comment") c.Usage("comment")
} }
@@ -53,18 +57,22 @@ func (c *Client) Comment() error {
var diffVersionInfo []MRVersion var diffVersionInfo []MRVersion
err = json.Unmarshal(body, &diffVersionInfo) err = json.Unmarshal(body, &diffVersionInfo)
if err != nil {
return fmt.Errorf("Error unmarshalling version info JSON: %w", err)
}
time := time.Now() time := time.Now()
if sha == "" {
/* This is necessary since we do not know whether the comment is on a line that /* This is necessary since we do not know whether the comment is on a line that
has been changed or not. Making all three of these API calls will let us leave has been changed or not. Making all three of these API calls will let us leave
the comment regardless. See the Gitlab documentation: https://docs.gitlab.com/ee/api/discussions.html#create-a-new-thread-in-the-merge-request-diff */ the comment regardless. See the Gitlab documentation: https://docs.gitlab.com/ee/api/discussions.html#create-a-new-thread-in-the-merge-request-diff */
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(3) wg.Add(2)
resultChannel := make(chan *gitlab.Discussion, 3) resultChannel := make(chan *gitlab.Discussion, 2)
for i := 0; i < 3; i++ { for i := 0; i < 2; i++ {
ii := i ii := i
go func() { go func() {
defer wg.Done() defer wg.Done()
@@ -83,8 +91,6 @@ func (c *Client) Comment() error {
if ii == 0 { if ii == 0 {
options.Position.NewLine = lineNumberInt options.Position.NewLine = lineNumberInt
} else if ii == 1 {
options.Position.OldLine = lineNumberInt
} else { } else {
options.Position.NewLine = lineNumberInt options.Position.NewLine = lineNumberInt
options.Position.OldLine = lineNumberInt options.Position.OldLine = lineNumberInt
@@ -111,9 +117,37 @@ func (c *Client) Comment() error {
if createdDiscussion == nil { if createdDiscussion == nil {
return fmt.Errorf("Could not leave comment") return fmt.Errorf("Could not leave comment")
} }
} else {
payload := &bytes.Buffer{}
writer := multipart.NewWriter(payload)
_ = writer.WriteField("note", comment)
_ = writer.WriteField("path", "README.md")
_ = writer.WriteField("line", "3")
_ = writer.WriteField("line_type", "old")
err := writer.Close()
if err != nil {
return fmt.Errorf("Error making form data: %w", err)
}
url := fmt.Sprintf(commentUrl, c.projectId, strings.TrimSpace(sha))
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, url, payload)
if err != nil {
return fmt.Errorf("Error building request: %w", err)
}
req.Header.Add("PRIVATE-TOKEN", os.Getenv("GITLAB_TOKEN"))
req.Header.Set("Content-Type", writer.FormDataContentType())
res, err := client.Do(req)
if err != nil {
return fmt.Errorf("Error making request: %w", err)
}
defer res.Body.Close()
}
fmt.Println("Left Comment: " + comment[0:min(len(comment), 25)] + "...") fmt.Println("Left Comment: " + comment[0:min(len(comment), 25)] + "...")
return nil return nil
} }
@@ -151,3 +185,29 @@ func getMRVersions(projectId string, mergeId int) (e error, response *http.Respo
return nil, response return nil, response
} }
func (c *Client) OverviewComment() error {
lineNumber, fileName, comment, sha := os.Args[3], os.Args[4], os.Args[5], os.Args[6]
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)
}
postCommitCommentOptions := gitlab.PostCommitCommentOptions{
Note: gitlab.String(comment),
Path: gitlab.String(fileName),
Line: &lineNumberInt,
LineType: gitlab.String("old"),
}
_, _, err = c.git.Commits.PostCommitComment(c.projectId, sha, &postCommitCommentOptions)
if err != nil {
return fmt.Errorf("Error leaving overview comment: %w", err)
}
fmt.Println("Left Overview Comment: " + comment[0:min(len(comment), 25)] + "...")
return nil
}

View File

@@ -14,6 +14,7 @@ const (
approve = "approve" approve = "approve"
revoke = "revoke" revoke = "revoke"
comment = "comment" comment = "comment"
overviewComment = "overviewComment"
deleteComment = "deleteComment" deleteComment = "deleteComment"
editComment = "editComment" editComment = "editComment"
reply = "reply" reply = "reply"
@@ -44,6 +45,8 @@ func main() {
errCheck(c.DeleteComment()) errCheck(c.DeleteComment())
case editComment: case editComment:
errCheck(c.EditComment()) errCheck(c.EditComment())
case overviewComment:
errCheck(c.OverviewComment())
case info: case info:
errCheck(c.Info()) errCheck(c.Info())
case reply: case reply:

View File

@@ -19,11 +19,43 @@ M.create_comment = function()
keymaps.set_popup_keymaps(commentPopup, M.confirm_create_comment) keymaps.set_popup_keymaps(commentPopup, M.confirm_create_comment)
end end
M.find_deletion_commit = function(file)
local current_line = vim.api.nvim_get_current_line()
local command = string.format("git log -S '%s' %s", current_line, file)
local handle = io.popen(command)
local output = handle:read("*line")
if output == nil then
notify("Error reading SHA of deletion commit", "error")
return ""
end
handle:close()
local words = {}
for word in output:gmatch("%S+") do
table.insert(words, word)
end
return words[2]
end
-- Sends the comment to Gitlab -- Sends the comment to Gitlab
M.confirm_create_comment = function(text) M.confirm_create_comment = function(text)
if u.base_invalid() then return end if u.base_invalid() then return end
local relative_file_path = u.get_relative_file_path() local relative_file_path = u.get_relative_file_path()
local current_line_number = u.get_current_line_number() local current_line_number = u.get_current_line_number()
if relative_file_path == nil then return end
-- If leaving a comment on a deleted line, get hash value + proper filename
local sha = ""
local is_base_file = relative_file_path:find(".git")
if is_base_file then -- We are looking at a deletion.
local _, path = u.split_diff_view_filename(relative_file_path)
sha = M.find_deletion_commit(path)
if sha == "" then
return
end
end
Job:new({ Job:new({
command = state.BIN, command = state.BIN,
args = { args = {
@@ -32,6 +64,7 @@ M.confirm_create_comment = function(text)
current_line_number, current_line_number,
relative_file_path, relative_file_path,
text, text,
sha
}, },
-- TODO: Render the tree after comment creation. Refresh? -- TODO: Render the tree after comment creation. Refresh?
on_stdout = u.print_success, on_stdout = u.print_success,

View File

@@ -215,6 +215,16 @@ local read_file = function(file_path)
return file_contents return file_contents
end end
local split_diff_view_filename = function(filename)
local hash, path = filename:match("://%.git/(/?[0-9a-f]+)(/.*)$")
if hash and path then
path = path:gsub("%.git/", ""):gsub("^/", "")
hash = hash:gsub("^/", "")
end
return hash, path
end
M.get_relative_file_path = get_relative_file_path M.get_relative_file_path = get_relative_file_path
M.get_current_line_number = get_current_line_number M.get_current_line_number = get_current_line_number
M.get_buffer_text = get_buffer_text M.get_buffer_text = get_buffer_text
@@ -233,5 +243,6 @@ M.print_error = print_error
M.create_popup_state = create_popup_state M.create_popup_state = create_popup_state
M.exit = exit M.exit = exit
M.read_file = read_file M.read_file = read_file
M.split_diff_view_filename = split_diff_view_filename
M.P = P M.P = P
return M return M