Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
e3d7dfe
trim trailing slash from custom URLs
harrisoncramer Feb 26, 2024
438d126
Updated .github/CONTRIBUTING.md
harrisoncramer Feb 26, 2024
d29bd0b
Updated .github/ISSUE_TEMPLATE/bug_report.md
harrisoncramer Feb 26, 2024
a6401d9
Feat: Improve discussion tree toggling (#192)
jakubbortlik Feb 27, 2024
d985d71
Fix Multi Line Issues (Large Refactor) (#197)
harrisoncramer Feb 27, 2024
8859c47
Fix: location provider (#198)
harrisoncramer Feb 28, 2024
00e3e24
fix: add nil check for diffview performance issue (#199)
harrisoncramer Feb 28, 2024
8937783
Fix: Switch Tabs During Comment Creation (#200)
harrisoncramer Feb 28, 2024
7a3e761
Fix: Check if file is modified (#201)
harrisoncramer Feb 28, 2024
4c4f4b5
Fix: Off by 1 Error in Old Sha (#202)
harrisoncramer Feb 28, 2024
2010c24
Fix: Rebuild Diagnostics + Signs (#203)
harrisoncramer Mar 2, 2024
f6ada57
Fixes Off-By-One Issue w/ New SHA (#205)
harrisoncramer Mar 2, 2024
949e076
Fix: Reviewer Jump (#206)
harrisoncramer Mar 3, 2024
816338f
Merge branch 'main' into develop
harrisoncramer Mar 3, 2024
e6cc34c
Fix Typo In Settings Check (#209)
harrisoncramer Mar 3, 2024
d5ad0ea
fix: Calculate new line in ranged comment after all hunks correctly (…
harrisoncramer Mar 4, 2024
ca35faa
fix: range in new SHA (#212)
harrisoncramer Mar 4, 2024
6288ab5
Merge branch 'main' into develop
harrisoncramer Mar 4, 2024
1bf75e2
fix: address mIssing get_lines function (#224)
harrisoncramer Mar 26, 2024
6016624
fix: diagnostic creation for comments on deleted lines (#226)
harrisoncramer Mar 28, 2024
3e9b155
feat: Allow insecure https connection to Gitlab (#229)
harrisoncramer Mar 29, 2024
6b4fba3
Merge branch 'main' into develop
harrisoncramer Apr 3, 2024
f55852f
Merge branch 'main' into develop
harrisoncramer Apr 3, 2024
8b4ccaf
fix: remove esc keybinding (#240)
harrisoncramer Apr 4, 2024
61291a3
Removes backup register option (#242)
harrisoncramer Apr 4, 2024
09d5c55
fix: update go-gitlab and fix label code (#243)
harrisoncramer Apr 6, 2024
081ad8f
feat: enable pipeline command on main/master (#244)
harrisoncramer Apr 7, 2024
b00b168
Expose Gitlab Data via API (#235)
harrisoncramer Apr 8, 2024
db90a36
fix: line code fix (#245)
harrisoncramer Apr 8, 2024
3852084
Merge branch 'main' into develop
harrisoncramer Apr 8, 2024
bce50d0
feat: add squash and remove source branch (#230)
jakubbortlik Apr 8, 2024
50cded6
Fix: Treat INFO.labels as a table not as a string (#250)
jakubbortlik Apr 8, 2024
330c012
merged main
harrisoncramer Apr 8, 2024
77a6d92
feat: ssh remote url can have custom port (#248)
sunfuze Apr 9, 2024
2d59ac6
feat: Allow saving popup contents to temp_registers when quitting (#238)
jakubbortlik Apr 9, 2024
cc689a1
fix: Autocommand causes exit() to be called twice (#252)
jakubbortlik Apr 10, 2024
6d15f23
feat: Add keymap to copy node URL to clipboard (#253)
jakubbortlik Apr 10, 2024
77c64ae
merged main
harrisoncramer Apr 10, 2024
48a03c6
fix: do not colorize output if no info is provided (#255)
harrisoncramer Apr 10, 2024
d92bc09
Merge branch 'main' into develop
harrisoncramer Apr 10, 2024
9bdd077
feat: Copy web url of MR to clipboard (#258)
jakubbortlik Apr 11, 2024
9ab1a7a
Merge branch 'main' into develop
harrisoncramer Apr 12, 2024
7d76187
fix: Jumping to wrong buffer (#261)
harrisoncramer Apr 12, 2024
540986a
Fix: Go to last line and show warning when diagnostic is past the end…
jakubbortlik Apr 14, 2024
5df7bb3
fix: Get recent pipeline through other means (#266)
harrisoncramer Apr 14, 2024
15a02cb
feat: Add keymaps and linewise actions to layouts (#265)
jakubbortlik Apr 15, 2024
a2c79c3
ix: File comments don't have line number information (#268)
jakubbortlik Apr 16, 2024
442dea1
feat: add authentication provider setting (#270)
patrickpichler Apr 19, 2024
7aba653
Merge branch 'main' into develop
harrisoncramer Apr 19, 2024
f604c94
feat: Create and Manage Reviews (Draft Notes) (#264)
harrisoncramer Apr 19, 2024
e71e848
feat: 272 feature allow mr selection within neovim (#273)
harrisoncramer Apr 20, 2024
adc20bf
Fixes no draft notes, winbar issue (#275)
harrisoncramer Apr 20, 2024
1ecbf35
Merge branch 'main' into develop
harrisoncramer Apr 20, 2024
2c2d0eb
Fix: Restore focus (#277)
harrisoncramer Apr 20, 2024
9ec134d
fix: draft note edits + reply keybinding (#279)
harrisoncramer Apr 21, 2024
681c29e
Feat: Check feature branch is up-to-date on remote (#278)
jakubbortlik Apr 21, 2024
fa16905
feat: wrap CLI commands, toggle draft/live mode (#280)
harrisoncramer Apr 22, 2024
8affee7
fix: Update readme w/ correct packer installation (#285)
harrisoncramer Apr 22, 2024
9c22fd1
fix: non-existent buffer comments (#284)
harrisoncramer Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 47 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ To view these help docs and to get more detailed help information, please run `:

1. Install Go
2. Add configuration (see Installation section)
3. Checkout your feature branch: `git checkout feature-branch`
4. Open Neovim
5. Run `:lua require("gitlab").review()` to open the reviewer pane
5. Run `:lua require("gitlab").choose_merge_request()`

This will checkout the branch locally, and open the plugin's reviewer pane.

For more detailed information about the Lua APIs please run `:h gitlab.nvim.api`

Expand Down Expand Up @@ -56,20 +56,25 @@ return {
And with Packer:

```lua
use {
'harrisoncramer/gitlab.nvim',
requires = {
"MunifTanjim/nui.nvim",
"nvim-lua/plenary.nvim",
"sindrets/diffview.nvim",
"stevearc/dressing.nvim", -- Recommended but not required. Better UI for pickers.
"nvim-tree/nvim-web-devicons", -- Recommended but not required. Icons in discussion tree.
},
run = function() require("gitlab.server").build(true) end,
config = function()
require("gitlab").setup()
end,
}
use {
"harrisoncramer/gitlab.nvim",
requires = {
"MunifTanjim/nui.nvim",
"nvim-lua/plenary.nvim",
"sindrets/diffview.nvim"
"stevearc/dressing.nvim", -- Recommended but not required. Better UI for pickers.
"nvim-tree/nvim-web-devicons", -- Recommended but not required. Icons in discussion tree.
},
build = function()
require("gitlab.server").build()
end,
branch = "develop",
config = function()
require("diffview") -- We require some global state from diffview
local gitlab = require("gitlab")
gitlab.setup()
end,
}
```

## Connecting to Gitlab
Expand All @@ -92,6 +97,18 @@ gitlab_url=https://my-personal-gitlab-instance.com/

The plugin will look for the `.gitlab.nvim` file in the root of the current project by default. However, you may provide a custom path to the configuration file via the `config_path` option. This must be an absolute path to the directory that holds your `.gitlab.nvim` file.

In case even more control over the auth config is needed, there is the possibility to override the `auth_provider` settings field. It should be
a function that returns the `token` as well as the `gitlab_url` value, and a nilable error. If the `gitlab_url` is `nil`, `https://gitlab.com` is used as default.

Here an example how to use a custom `auth_provider`:
```lua
require("gitlab").setup({
auth_provider = function()
return "my_token", "https://custom.gitlab.instance.url", nil
end,
}
```

For more settings, please see `:h gitlab.nvim.connecting-to-gitlab`

## Configuring the Plugin
Expand All @@ -103,7 +120,10 @@ require("gitlab").setup({
port = nil, -- The port of the Go server, which runs in the background, if omitted or `nil` the port will be chosen automatically
log_path = vim.fn.stdpath("cache") .. "/gitlab.nvim.log", -- Log path for the Go server
config_path = nil, -- Custom path for `.gitlab.nvim` file, please read the "Connecting to Gitlab" section
debug = { go_request = false, go_response = false }, -- Which values to log
debug = {
go_request = false,
go_response = false,
},
attachment_dir = nil, -- The local directory for files (see the "summary" section)
reviewer_settings = {
diffview = {
Expand Down Expand Up @@ -150,6 +170,7 @@ require("gitlab").setup({
toggle_resolved_discussions = "R", -- Open or close all resolved discussions
toggle_unresolved_discussions = "U", -- Open or close all unresolved discussions
keep_current_open = false, -- If true, current discussion stays open even if it should otherwise be closed when toggling
publish_draft = "P", -- Publishes the currently focused note/comment
toggle_resolved = "p" -- Toggles the resolved status of the whole discussion
position = "left", -- "top", "right", "bottom" or "left"
open_in_browser = "b" -- Jump to the URL of the current note/discussion
Expand All @@ -160,9 +181,14 @@ require("gitlab").setup({
unresolved = '-', -- Symbol to show next to unresolved discussions
tree_type = "simple", -- Type of discussion tree - "simple" means just list of discussions, "by_file_name" means file tree with discussions under file
toggle_tree_type = "i", -- Toggle type of discussion tree - "simple", or "by_file_name"
draft_mode = false, -- Whether comments are posted as drafts as part of a review
toggle_draft_mode = "D" -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
winbar = nil -- Custom function to return winbar title, should return a string. Provided with WinbarTable (defined in annotations.lua)
-- If using lualine, please add "gitlab" to disabled file types, otherwise you will not see the winbar.
},
choose_merge_request = {
open_reviewer = true, -- Open the reviewer window automatically after switching merge requests
},
info = { -- Show additional fields in the summary view
enabled = true,
horizontal = false, -- Display metadata to the left of the summary rather than underneath
Expand Down Expand Up @@ -246,6 +272,7 @@ you need to set them up yourself. Here's what I'm using:
```lua
local gitlab = require("gitlab")
local gitlab_server = require("gitlab.server")
vim.keymap.set("n", "glb", gitlab.choose_merge_request)
vim.keymap.set("n", "glr", gitlab.review)
vim.keymap.set("n", "gls", gitlab.summary)
vim.keymap.set("n", "glA", gitlab.approve)
Expand All @@ -266,6 +293,8 @@ vim.keymap.set("n", "glrd", gitlab.delete_reviewer)
vim.keymap.set("n", "glp", gitlab.pipeline)
vim.keymap.set("n", "glo", gitlab.open_in_browser)
vim.keymap.set("n", "glM", gitlab.merge)
vim.keymap.set("n", "glu", gitlab.copy_mr_url)
vim.keymap.set("n", "glP", gitlab.publish_all_drafts)
```

For more information about each of these commands, and about the APIs in general, run `:h gitlab.nvim.api`
2 changes: 2 additions & 0 deletions after/syntax/gitlab.vim
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ syntax match ChevronDown ""
syntax match ChevronRight ""
syntax match Resolved /\s✓\s\?/
syntax match Unresolved /\s-\s\?/
syntax match Pencil //

highlight link Username GitlabUsername
highlight link Date GitlabDate
highlight link ChevronDown GitlabChevron
highlight link ChevronRight GitlabChevron
highlight link Resolved GitlabResolved
highlight link Unresolved GitlabUnresolved
highlight link Pencil GitlabDraft

let b:current_syntax = "gitlab"
8 changes: 4 additions & 4 deletions cmd/assignee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ func updateAssigneesErr(pid interface{}, mergeRequest int, opt *gitlab.UpdateMer
func TestAssigneeHandler(t *testing.T) {
t.Run("Updates assignees", func(t *testing.T) {
request := makeRequest(t, http.MethodPut, "/mr/assignee", AssigneeUpdateRequest{Ids: []int{1, 2}})
server, _ := createRouterAndApi(fakeClient{updateMergeRequestFn: updateAssignees})
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssignees})
data := serveRequest(t, server, request, AssigneeUpdateResponse{})
assert(t, data.SuccessResponse.Message, "Assignees updated")
assert(t, data.SuccessResponse.Status, http.StatusOK)
})

t.Run("Disallows non-PUT method", func(t *testing.T) {
request := makeRequest(t, http.MethodPost, "/mr/assignee", nil)
server, _ := createRouterAndApi(fakeClient{updateMergeRequestFn: updateAssignees})
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssignees})
data := serveRequest(t, server, request, ErrorResponse{})
assert(t, data.Status, http.StatusMethodNotAllowed)
assert(t, data.Details, "Invalid request type")
Expand All @@ -40,7 +40,7 @@ func TestAssigneeHandler(t *testing.T) {

t.Run("Handles errors from Gitlab client", func(t *testing.T) {
request := makeRequest(t, http.MethodPut, "/mr/assignee", AssigneeUpdateRequest{Ids: []int{1, 2}})
server, _ := createRouterAndApi(fakeClient{updateMergeRequestFn: updateAssigneesErr})
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssigneesErr})
data := serveRequest(t, server, request, ErrorResponse{})
assert(t, data.Status, http.StatusInternalServerError)
assert(t, data.Message, "Could not modify merge request assignees")
Expand All @@ -49,7 +49,7 @@ func TestAssigneeHandler(t *testing.T) {

t.Run("Handles non-200s from Gitlab client", func(t *testing.T) {
request := makeRequest(t, http.MethodPut, "/mr/assignee", AssigneeUpdateRequest{Ids: []int{1, 2}})
server, _ := createRouterAndApi(fakeClient{updateMergeRequestFn: updateAssigneesNon200})
server, _ := createRouterAndApi(fakeClient{updateMergeRequest: updateAssigneesNon200})
data := serveRequest(t, server, request, ErrorResponse{})
assert(t, data.Status, http.StatusSeeOther)
assert(t, data.Message, "Could not modify merge request assignees")
Expand Down
2 changes: 2 additions & 0 deletions cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type Client struct {
*gitlab.LabelsService
*gitlab.AwardEmojiService
*gitlab.UsersService
*gitlab.DraftNotesService
}

/* initGitlabClient parses and validates the project settings and initializes the Gitlab client. */
Expand Down Expand Up @@ -116,6 +117,7 @@ func initGitlabClient() (error, *Client) {
LabelsService: client.Labels,
AwardEmojiService: client.AwardEmoji,
UsersService: client.Users,
DraftNotesService: client.DraftNotes,
}
}

Expand Down
78 changes: 15 additions & 63 deletions cmd/comment.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"crypto/sha1"
"encoding/json"
"fmt"
"io"
Expand All @@ -11,28 +10,8 @@ import (
)

type PostCommentRequest struct {
Comment string `json:"comment"`
FileName string `json:"file_name"`
NewLine *int `json:"new_line,omitempty"`
OldLine *int `json:"old_line,omitempty"`
HeadCommitSHA string `json:"head_commit_sha"`
BaseCommitSHA string `json:"base_commit_sha"`
StartCommitSHA string `json:"start_commit_sha"`
Type string `json:"type"`
LineRange *LineRange `json:"line_range,omitempty"`
}

/* LineRange represents the range of a note. */
type LineRange struct {
StartRange *LinePosition `json:"start"`
EndRange *LinePosition `json:"end"`
}

/* LinePosition represents a position in a line range. Unlike the Gitlab struct, this does not contain LineCode with a sha1 of the filename */
type LinePosition struct {
Type string `json:"type"`
OldLine int `json:"old_line"`
NewLine int `json:"new_line"`
Comment string `json:"comment"`
PositionData
}

type DeleteCommentRequest struct {
Expand All @@ -53,6 +32,15 @@ type CommentResponse struct {
Discussion *gitlab.Discussion `json:"discussion"`
}

/* CommentWithPosition is a comment with an (optional) position data value embedded in it. The position data will be non-nil for range-based comments. */
type CommentWithPosition struct {
PositionData PositionData
}

func (comment CommentWithPosition) GetPositionData() PositionData {
return comment.PositionData
}

/* commentHandler creates, edits, and deletes discussions (comments, multi-line comments) */
func (a *api) commentHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
Expand Down Expand Up @@ -133,46 +121,10 @@ func (a *api) postComment(w http.ResponseWriter, r *http.Request) {

/* If we are leaving a comment on a line, leave position. Otherwise,
we are leaving a note (unlinked comment) */
var friendlyName = "Note"

if postCommentRequest.FileName != "" {
friendlyName = "Comment"
opt.Position = &gitlab.PositionOptions{
PositionType: &postCommentRequest.Type,
StartSHA: &postCommentRequest.StartCommitSHA,
HeadSHA: &postCommentRequest.HeadCommitSHA,
BaseSHA: &postCommentRequest.BaseCommitSHA,
NewPath: &postCommentRequest.FileName,
OldPath: &postCommentRequest.FileName,
NewLine: postCommentRequest.NewLine,
OldLine: postCommentRequest.OldLine,
}

if postCommentRequest.LineRange != nil {
friendlyName = "Multiline Comment"
shaFormat := "%x_%d_%d"
startFilenameSha := fmt.Sprintf(
shaFormat,
sha1.Sum([]byte(postCommentRequest.FileName)),
postCommentRequest.LineRange.StartRange.OldLine,
postCommentRequest.LineRange.StartRange.NewLine,
)
endFilenameSha := fmt.Sprintf(
shaFormat,
sha1.Sum([]byte(postCommentRequest.FileName)),
postCommentRequest.LineRange.EndRange.OldLine,
postCommentRequest.LineRange.EndRange.NewLine,
)
opt.Position.LineRange = &gitlab.LineRangeOptions{
Start: &gitlab.LinePositionOptions{
Type: &postCommentRequest.LineRange.StartRange.Type,
LineCode: &startFilenameSha,
},
End: &gitlab.LinePositionOptions{
Type: &postCommentRequest.LineRange.EndRange.Type,
LineCode: &endFilenameSha,
},
}
}
commentWithPositionData := CommentWithPosition{postCommentRequest.PositionData}
opt.Position = buildCommentPosition(commentWithPositionData)
}

discussion, res, err := a.client.CreateMergeRequestDiscussion(a.projectInfo.ProjectId, a.projectInfo.MergeId, &opt)
Expand All @@ -190,7 +142,7 @@ func (a *api) postComment(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
response := CommentResponse{
SuccessResponse: SuccessResponse{
Message: fmt.Sprintf("%s created successfully", friendlyName),
Message: "Comment created successfully",
Status: http.StatusOK,
},
Comment: discussion.Notes[0],
Expand Down
82 changes: 82 additions & 0 deletions cmd/comment_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package main

import (
"crypto/sha1"
"fmt"

"github.com/xanzy/go-gitlab"
)

/* LinePosition represents a position in a line range. Unlike the Gitlab struct, this does not contain LineCode with a sha1 of the filename */
type LinePosition struct {
Type string `json:"type"`
OldLine int `json:"old_line"`
NewLine int `json:"new_line"`
}

/* LineRange represents the range of a note. */
type LineRange struct {
StartRange *LinePosition `json:"start"`
EndRange *LinePosition `json:"end"`
}

/* PositionData represents the position of a comment or note (relative to a file diff) */
type PositionData struct {
FileName string `json:"file_name"`
NewLine *int `json:"new_line,omitempty"`
OldLine *int `json:"old_line,omitempty"`
HeadCommitSHA string `json:"head_commit_sha"`
BaseCommitSHA string `json:"base_commit_sha"`
StartCommitSHA string `json:"start_commit_sha"`
Type string `json:"type"`
LineRange *LineRange `json:"line_range,omitempty"`
}

/* RequestWithPosition is an interface that abstracts the handling of position data for a comment or a draft comment */
type RequestWithPosition interface {
GetPositionData() PositionData
}

/* buildCommentPosition takes a comment or draft comment request and builds the position data necessary for a location-based comment */
func buildCommentPosition(commentWithPositionData RequestWithPosition) *gitlab.PositionOptions {
positionData := commentWithPositionData.GetPositionData()

opt := &gitlab.PositionOptions{
PositionType: &positionData.Type,
StartSHA: &positionData.StartCommitSHA,
HeadSHA: &positionData.HeadCommitSHA,
BaseSHA: &positionData.BaseCommitSHA,
NewPath: &positionData.FileName,
OldPath: &positionData.FileName,
NewLine: positionData.NewLine,
OldLine: positionData.OldLine,
}

if positionData.LineRange != nil {
shaFormat := "%x_%d_%d"
startFilenameSha := fmt.Sprintf(
shaFormat,
sha1.Sum([]byte(positionData.FileName)),
positionData.LineRange.StartRange.OldLine,
positionData.LineRange.StartRange.NewLine,
)
endFilenameSha := fmt.Sprintf(
shaFormat,
sha1.Sum([]byte(positionData.FileName)),
positionData.LineRange.EndRange.OldLine,
positionData.LineRange.EndRange.NewLine,
)
opt.LineRange = &gitlab.LineRangeOptions{
Start: &gitlab.LinePositionOptions{
Type: &positionData.LineRange.StartRange.Type,
LineCode: &startFilenameSha,
},
End: &gitlab.LinePositionOptions{
Type: &positionData.LineRange.EndRange.Type,
LineCode: &endFilenameSha,
},
}
}

return opt
}
Loading