Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release: Miscellaneous bug fix #459

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4ff27c2
fix: Fixes issues w/ shared pointers to structs (#378)
harrisoncramer Sep 16, 2024
87e224a
feat: adds even better debugging and linting support (#376)
harrisoncramer Sep 16, 2024
e17d713
fix: error messages and run all tests (#381)
gkze Sep 21, 2024
523bdd4
feat: Automatically open fold under cursor (#380)
jakubbortlik Sep 23, 2024
6ac8895
Merge branch 'main' into develop
harrisoncramer Sep 24, 2024
879ee20
fix: discussion ID is not required (#383)
harrisoncramer Sep 26, 2024
125cfbb
Chore: Add more emojis (#384)
jakubbortlik Oct 4, 2024
7171f4c
Fix: Publish all drafts (#391)
jakubbortlik Oct 10, 2024
0e19857
fix: make discussion tree buffers nomodifiable (#394)
jakubbortlik Oct 11, 2024
96efdc2
fix: Incorrect warning about commits (#395)
harrisoncramer Oct 12, 2024
b359b47
Fix: Show draft replies in the correct tree (#396)
jakubbortlik Oct 13, 2024
a63823c
fix: Cannot choose merge requests (#398)
harrisoncramer Oct 13, 2024
0f3841f
fix: parse dates without timezone offset (#404)
harrisoncramer Oct 14, 2024
04976db
Fix: Use correct name for emoji
jakubbortlik Oct 15, 2024
cd8a404
Merge pull request #405 from jakubbortlik/fix-party-emoji
jakubbortlik Oct 18, 2024
c8c0395
fix: enable replying if tree is in a different tab (#407)
jakubbortlik Oct 25, 2024
e4c9dbe
fix: wrong get url (#413)
OscarCreator Nov 5, 2024
5f657fd
Fix: Restore cursor when updating from outside of tree (#406)
jakubbortlik Nov 5, 2024
a03b2f6
Merge branch 'main' into develop
harrisoncramer Nov 5, 2024
839257a
Fix: Show non-resolvable notes in winbar (#417)
jakubbortlik Nov 5, 2024
a0d10a4
Fix: add more emojis and make emoji picker configurable (#414)
jakubbortlik Nov 6, 2024
c44daf5
fix: comment creation should not be possible for renamed and moved fi…
harrisoncramer Nov 10, 2024
b606ceb
fix: color highlight groups are invalid (#421)
harrisoncramer Nov 10, 2024
ddf0f41
fix: plugin failing to build on Windows (#419)
harrisoncramer Nov 12, 2024
d8d289d
Merge branch 'main' into develop
harrisoncramer Nov 12, 2024
15a3839
Feat: Enable sorting discussions by original comment (#422)
jakubbortlik Dec 6, 2024
08d289c
Feat: Improve popup UX (#426)
jakubbortlik Dec 6, 2024
a3aa79a
Feat: Automatically update MR summary details (#427)
jakubbortlik Dec 8, 2024
b2d64fa
Feat: Show update progress in winbar (#432)
jakubbortlik Dec 8, 2024
768dfaf
Feat: Abbreviate winbar (#439)
harrisoncramer Dec 8, 2024
621bfa6
Merge branch 'main' into develop
harrisoncramer Dec 8, 2024
606d931
Fix: Note Creation Bug (#441)
harrisoncramer Dec 8, 2024
508a394
Fix: Checking whether comment can be created (#434)
jakubbortlik Dec 8, 2024
3d76b8d
Fix: Syntax in discussion tree (#433)
jakubbortlik Dec 10, 2024
aebdaf4
fix: improve indication of resolved threads and drafts (#442)
jakubbortlik Dec 10, 2024
72f2155
Docs: Various minor improvements (#445)
jakubbortlik Dec 11, 2024
3b83880
Fix: Removes Retry, fixes mess of errors for #425 (#449)
harrisoncramer Dec 26, 2024
46d1c14
Fix: Don't jump to file if it doesn't exist (#452)
jakubbortlik Jan 18, 2025
ad0f445
fix: force linewise motion in suggestion keybinding (#454)
jakubbortlik Jan 18, 2025
9591605
Fix: Check nil with stderr in plenary Job (#456)
jakubbortlik Jan 18, 2025
8490d40
fix: rebased develop
harrisoncramer Jan 18, 2025
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
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Thank you for taking time to contribute to this plugin! Please follow these step

It's possible that the feature you want is already implemented, or does not belong in `gitlab.nvim` at all. By creating an issue first you can have a conversation with the maintainers about the functionality first. While this is not strictly necessary, it greatly increases the likelihood that your merge request will be accepted.

2. Fork the repository, and create a new feature branch for your desired functionality. Make your changes.
2. Fork the repository, and create a new feature branch off the `develop` branch for your desired functionality. Make your changes.

If you are using Lazy as a plugin manager, the easiest way to work on changes is by setting a specific path for the plugin that points to your repository locally. This is what I do:

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
branches:
- main
- develop
paths:
- 'cmd/**' # Ignore changes to the Lua code
- 'go.sum'
- 'go.mod'
jobs:
go_lint:
name: Lint Go 💅
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/lua.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
branches:
- main
- develop
paths:
- 'lua/**' # Ignore changes to the Go code
jobs:
lua_lint:
name: Lint Lua 💅
Expand Down
54 changes: 25 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ This Neovim plugin is designed to make it easy to review Gitlab MRs from within
- View and manage pipeline Jobs
- Upload files, jump to the browser, and a lot more!

![Screenshot 2024-01-13 at 10 43 32 AM](https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/8dd8b961-a6b5-4e09-b87f-dc4a17b14149)
![Screenshot 2024-01-13 at 10 43 17 AM](https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/079842de-e8a4-45c5-98c2-dcafc799c904)
![Screenshot 2024-12-08 at 5 43 53 PM](https://github.com/user-attachments/assets/cb9e94e3-3817-4846-ba44-16ec06ea7654)

https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/dc5c07de-4ae6-4335-afe1-d554e3804372

Expand All @@ -36,47 +35,48 @@ For more detailed information about the Lua APIs please run `:h gitlab.nvim.api`
With <a href="https://github.com/folke/lazy.nvim">Lazy</a>:

```lua
return {
{
"harrisoncramer/gitlab.nvim",
dependencies = {
"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.
"nvim-tree/nvim-web-devicons", -- Recommended but not required. Icons in discussion tree.
},
enabled = true,
build = function () require("gitlab.server").build(true) end, -- Builds the Go binary
config = function()
require("gitlab").setup()
end,
}
```

And with Packer:
And with <a href="https://github.com/lewis6991/pckr.nvim">pckr.nvim</a>:

```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.
},
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,
}
{
"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() end, -- Builds the Go binary
config = function()
require("diffview") -- We require some global state from diffview
require("gitlab").setup()
end,
}
```

Add `branch = "develop",` to your configuration if you want to use the (possibly unstable) development version of `gitlab.nvim`.

## Contributing

Contributions to the plugin are welcome. Please read [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) before you start working on a pull request.

## Connecting to Gitlab

This plugin requires an <a href="https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token">auth token</a> to connect to Gitlab. The token can be set in the root directory of the project in a `.gitlab.nvim` environment file, or can be set via a shell environment variable called `GITLAB_TOKEN` instead. If both are present, the `.gitlab.nvim` file will take precedence.
Expand Down Expand Up @@ -122,7 +122,3 @@ For a list of all these settings please run `:h gitlab.nvim.configuring-the-plug
The plugin sets up a number of useful keybindings in the special buffers it creates, and some global keybindings as well. Refer to the relevant section of the manual `:h gitlab.nvim.keybindings` for more details.

For more information about each of these commands, and about the APIs in general, run `:h gitlab.nvim.api`

## Contributing

Contributions to the plugin are welcome. Please read [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) before you start working on a pull request.
45 changes: 21 additions & 24 deletions after/syntax/gitlab.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,26 @@ if filereadable($VIMRUNTIME . '/syntax/markdown.vim')
source $VIMRUNTIME/syntax/markdown.vim
endif

syntax match Date "\v\d+\s+\w+\s+ago"
highlight link Date GitlabDate

execute 'syntax match Unresolved /\s' . g:gitlab_discussion_tree_unresolved . '\s\?/'
highlight link Unresolved GitlabUnresolved

execute 'syntax match Resolved /\s' . g:gitlab_discussion_tree_resolved . '\s\?/'
highlight link Resolved GitlabResolved

execute 'syntax match GitlabDiscussionOpen /^\s*' . g:gitlab_discussion_tree_expander_open . '/'
highlight link GitlabDiscussionOpen GitlabExpander

execute 'syntax match GitlabDiscussionClosed /^\s*' . g:gitlab_discussion_tree_expander_closed . '/'
highlight link GitlabDiscussionClosed GitlabExpander

execute 'syntax match Draft /' . g:gitlab_discussion_tree_draft . '/'
highlight link Draft GitlabDraft

execute 'syntax match Username "@[a-zA-Z0-9.]\+"'
highlight link Username GitlabUsername

execute 'syntax match Mention "\%(' . g:gitlab_discussion_tree_expander_open . '\|'
\ . g:gitlab_discussion_tree_expander_closed . '\)\@<!@[a-zA-Z0-9.]*"'
highlight link Mention GitlabMention
let expanders = '^\s*\%(' . g:gitlab_discussion_tree_expander_open . '\|' . g:gitlab_discussion_tree_expander_closed . '\)'
let username = '@[a-zA-Z0-9.]\+'

" Covers times like '14 days ago', 'just now', as well as 'October 3, 2024'
let time_ago = '\d\+ \w\+ ago'
let formatted_date = '\w\+ \{1,2}\d\{1,2}, \d\{4}'
let date = '\%(' . time_ago . '\|' . formatted_date . '\|just now\)'

let published = date . ' \%(' . g:gitlab_discussion_tree_resolved . '\|' . g:gitlab_discussion_tree_unresolved . '\|' . g:gitlab_discussion_tree_unlinked . '\)\?'
let state = ' \%(' . published . '\|' . g:gitlab_discussion_tree_draft . '\)'

execute 'syntax match GitlabNoteHeader "' . expanders . username . state . '" contains=GitlabDate,GitlabUnresolved,GitlabUnlinked,GitlabResolved,GitlabExpander,GitlabDraft,GitlabUsername'

execute 'syntax match GitlabDate "' . date . '" contained'
execute 'syntax match GitlabUnresolved "' . g:gitlab_discussion_tree_unresolved . '" contained'
execute 'syntax match GitlabUnlinked "' . g:gitlab_discussion_tree_unlinked . '" contained'
execute 'syntax match GitlabResolved "' . g:gitlab_discussion_tree_resolved . '" contained'
execute 'syntax match GitlabExpander "' . expanders . '" contained'
execute 'syntax match GitlabDraft "' . g:gitlab_discussion_tree_draft . '" contained'
execute 'syntax match GitlabUsername "' . username . '" contained'
execute 'syntax match GitlabMention "' . username . '"'

let b:current_syntax = 'gitlab'
1 change: 1 addition & 0 deletions cmd/app/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func NewClient() (*Client, error) {

retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr
retryClient.RetryMax = 0
gitlabOptions = append(gitlabOptions, gitlab.WithHTTPClient(retryClient.HTTPClient))

client, err := gitlab.NewClient(pluginOptions.AuthToken, gitlabOptions...)
Expand Down
47 changes: 36 additions & 11 deletions cmd/app/list_discussions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"net/http"
"sort"
"sync"
"time"

"encoding/json"

Expand All @@ -19,8 +20,16 @@ func Contains[T comparable](elems []T, v T) bool {
return false
}

type SortBy string

const (
SortByLatestReply SortBy = "latest_reply"
SortByOriginalComment SortBy = "original_comment"
)

type DiscussionsRequest struct {
Blacklist []string `json:"blacklist" validate:"required"`
SortBy SortBy `json:"sort_by"`
}

type DiscussionsResponse struct {
Expand All @@ -30,20 +39,30 @@ type DiscussionsResponse struct {
Emojis map[int][]*gitlab.AwardEmoji `json:"emojis"`
}

type SortableDiscussions []*gitlab.Discussion
type SortableDiscussions struct {
Discussions []*gitlab.Discussion
SortBy SortBy
}

func (n SortableDiscussions) Len() int {
return len(n)
func (d SortableDiscussions) Len() int {
return len(d.Discussions)
}

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 (d SortableDiscussions) Less(i, j int) bool {
var iTime, jTime *time.Time
if d.SortBy == SortByOriginalComment {
iTime = d.Discussions[i].Notes[0].CreatedAt
jTime = d.Discussions[j].Notes[0].CreatedAt
return iTime.Before(*jTime)
} else { // SortByLatestReply
iTime = d.Discussions[i].Notes[len(d.Discussions[i].Notes)-1].CreatedAt
jTime = d.Discussions[j].Notes[len(d.Discussions[j].Notes)-1].CreatedAt
return iTime.After(*jTime)
}
}

func (n SortableDiscussions) Swap(i, j int) {
n[i], n[j] = n[j], n[i]
func (d SortableDiscussions) Swap(i, j int) {
d.Discussions[i], d.Discussions[j] = d.Discussions[j], d.Discussions[i]
}

type DiscussionsLister interface {
Expand Down Expand Up @@ -115,8 +134,14 @@ func (a discussionsListerService) ServeHTTP(w http.ResponseWriter, r *http.Reque
return
}

sortedLinkedDiscussions := SortableDiscussions(linkedDiscussions)
sortedUnlinkedDiscussions := SortableDiscussions(unlinkedDiscussions)
sortedLinkedDiscussions := SortableDiscussions{
Discussions: linkedDiscussions,
SortBy: request.SortBy,
}
sortedUnlinkedDiscussions := SortableDiscussions{
Discussions: unlinkedDiscussions,
SortBy: request.SortBy,
}

sort.Sort(sortedLinkedDiscussions)
sort.Sort(sortedUnlinkedDiscussions)
Expand Down
55 changes: 44 additions & 11 deletions cmd/app/list_discussions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ func (f fakeDiscussionsLister) ListMergeRequestDiscussions(pid interface{}, merg
if err != nil {
return nil, nil, err
}
now := time.Now()
newer := now.Add(time.Second * 100)

timePointers := make([]*time.Time, 6)
timePointers[0] = new(time.Time)
*timePointers[0] = time.Now()
for i := 1; i < len(timePointers); i++ {
timePointers[i] = new(time.Time)
*timePointers[i] = timePointers[i-1].Add(time.Second * 100)
}

type Author struct {
ID int `json:"id"`
Expand All @@ -35,8 +41,18 @@ func (f fakeDiscussionsLister) ListMergeRequestDiscussions(pid interface{}, merg
}

testListDiscussionsResponse := []*gitlab.Discussion{
{Notes: []*gitlab.Note{{CreatedAt: &now, Type: "DiffNote", Author: Author{Username: "hcramer"}}}},
{Notes: []*gitlab.Note{{CreatedAt: &newer, Type: "DiffNote", Author: Author{Username: "hcramer2"}}}},
{Notes: []*gitlab.Note{
{CreatedAt: timePointers[0], Type: "DiffNote", Author: Author{Username: "hcramer0"}},
{CreatedAt: timePointers[4], Type: "DiffNote", Author: Author{Username: "hcramer1"}},
}},
{Notes: []*gitlab.Note{
{CreatedAt: timePointers[2], Type: "DiffNote", Author: Author{Username: "hcramer2"}},
{CreatedAt: timePointers[3], Type: "DiffNote", Author: Author{Username: "hcramer3"}},
}},
{Notes: []*gitlab.Note{
{CreatedAt: timePointers[1], Type: "DiffNote", Author: Author{Username: "hcramer4"}},
{CreatedAt: timePointers[5], Type: "DiffNote", Author: Author{Username: "hcramer5"}},
}},
}
return testListDiscussionsResponse, resp, err
}
Expand Down Expand Up @@ -66,8 +82,23 @@ func getDiscussionsList(t *testing.T, svc http.Handler, request *http.Request) D
}

func TestListDiscussions(t *testing.T) {
t.Run("Returns sorted discussions", func(t *testing.T) {
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{}})
t.Run("Returns discussions sorted by latest reply", func(t *testing.T) {
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{}, SortBy: "latest_reply"})
svc := middleware(
discussionsListerService{testProjectData, fakeDiscussionsLister{}},
withMr(testProjectData, fakeMergeRequestLister{}),
withPayloadValidation(methodToPayload{http.MethodPost: newPayload[DiscussionsRequest]}),
withMethodCheck(http.MethodPost),
)
data := getDiscussionsList(t, svc, request)
assert(t, data.Message, "Discussions retrieved")
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer4") /* Sorting applied */
assert(t, data.Discussions[1].Notes[0].Author.Username, "hcramer0")
assert(t, data.Discussions[2].Notes[0].Author.Username, "hcramer2")
})

t.Run("Returns discussions sorted by original comment", func(t *testing.T) {
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{}, SortBy: "original_comment"})
svc := middleware(
discussionsListerService{testProjectData, fakeDiscussionsLister{}},
withMr(testProjectData, fakeMergeRequestLister{}),
Expand All @@ -76,12 +107,13 @@ func TestListDiscussions(t *testing.T) {
)
data := getDiscussionsList(t, svc, request)
assert(t, data.Message, "Discussions retrieved")
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer2") /* Sorting applied */
assert(t, data.Discussions[1].Notes[0].Author.Username, "hcramer")
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer0") /* Sorting applied */
assert(t, data.Discussions[1].Notes[0].Author.Username, "hcramer4")
assert(t, data.Discussions[2].Notes[0].Author.Username, "hcramer2")
})

t.Run("Uses blacklist to filter unwanted authors", func(t *testing.T) {
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{"hcramer"}})
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{"hcramer0"}, SortBy: "latest_reply"})
svc := middleware(
discussionsListerService{testProjectData, fakeDiscussionsLister{}},
withMr(testProjectData, fakeMergeRequestLister{}),
Expand All @@ -90,8 +122,9 @@ func TestListDiscussions(t *testing.T) {
)
data := getDiscussionsList(t, svc, request)
assert(t, data.SuccessResponse.Message, "Discussions retrieved")
assert(t, len(data.Discussions), 1)
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer2")
assert(t, len(data.Discussions), 2)
assert(t, data.Discussions[0].Notes[0].Author.Username, "hcramer4")
assert(t, data.Discussions[1].Notes[0].Author.Username, "hcramer2")
})
t.Run("Handles errors from Gitlab client", func(t *testing.T) {
request := makeRequest(t, http.MethodPost, "/mr/discussions/list", DiscussionsRequest{Blacklist: []string{}})
Expand Down
Loading
Loading