Add option to choose random server port (#65)

Updates the plugin to automatically choose a random port when started when no port is provided. This will allow multiple Neovim instances to open at the same time in different projects.
This commit is contained in:
johnybx
2023-10-21 17:39:37 +02:00
committed by GitHub
parent 2100bf2e43
commit c8a0267ba6
5 changed files with 119 additions and 66 deletions

View File

@@ -13,7 +13,6 @@ And a lot more!
https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/50f44eaf-5f99-4cb3-93e9-ed66ace0f675
## Requirements
- <a href="https://go.dev/">Go</a> >= v1.19
@@ -22,10 +21,10 @@ https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/50f44eaf-5f99-4cb3
1. Install Go
2. Install reviewer: <a href="https://github.com/dandavison/delta">delta</a> or <a href="https://github.com/sindrets/diffview.nvim">diffview</a>
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
3. Add configuration (see Installation section)
4. Checkout your feature branch: `git checkout feature-branch`
5. Open Neovim
6. Run `:lua require("gitlab").review()` to open the reviewer pane
## Installation
@@ -85,7 +84,7 @@ Here is the default setup function. All of these values are optional, and if you
```lua
require("gitlab").setup({
port = 21036, -- The port of the Go server, which runs in the background
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
reviewer = "delta", -- The reviewer type ("delta" or "diffview")
attachment_dir = nil, -- The local directory for files (see the "summary" section)
@@ -138,13 +137,13 @@ require("gitlab").setup({
## Usage
First, check out the branch that you want to review locally.
First, check out the branch that you want to review locally.
```
git checkout feature-branch
```
Then open Neovim. The `project_id` you specify in your configuration file must match the project_id of the Gitlab project your terminal is inside of.
Then open Neovim. The `project_id` you specify in your configuration file must match the project_id of the Gitlab project your terminal is inside of.
### Summary
@@ -169,9 +168,9 @@ The reviewer is Delta by default, but you can configure the plugin to use Diffvi
### Discussions and Notes
Gitlab groups threads of comments together into "discussions."
Gitlab groups threads of comments together into "discussions."
To display all discussions for the current MR, use the `toggle_discussions` action, which will show the discussions in a split window.
To display all discussions for the current MR, use the `toggle_discussions` action, which will show the discussions in a split window.
```lua
require("gitlab").toggle_discussions()
@@ -189,7 +188,7 @@ require("gitlab").create_note()
### Uploading Files
To attach a file to an MR description, reply, comment, and so forth use the `settings.popup.perform_linewise_action` keybinding when the the popup is open. This will open a picker that will look in the directory you specify in the `settings.attachment_dir` folder (this must be an absolute path) for files.
To attach a file to an MR description, reply, comment, and so forth use the `settings.popup.perform_linewise_action` keybinding when the the popup is open. This will open a picker that will look in the directory you specify in the `settings.attachment_dir` folder (this must be an absolute path) for files.
When you have picked the file, it will be added to the current buffer at the current line.
@@ -277,7 +276,7 @@ This is the API call that is happening from within Neovim when you run the `summ
If you are able to build and start the Go server and hit the endpoint successfully for the action you are trying to run (such as creating a comment or approving a merge request) then something is wrong with the Lua code. In that case, please file a bug report.
This Go server, in turn, writes logs to the log path that is configured in your setup function. These are written by default to `~/.cache/nvim/gitlab.nvim.log` and will be written each time the server reaeches out to Gitlab.
This Go server, in turn, writes logs to the log path that is configured in your setup function. These are written by default to `~/.cache/nvim/gitlab.nvim.log` and will be written each time the server reaeches out to Gitlab.
If the Golang server is not starting up correctly, please check your `.gitlab.nvim` file and your setup function. You can, however, try running the Golang server independently of Neovim. For instance, to start it up for a certain project, navigate to your plugin directory, and build the binary (these are instructions for Lazy) and move that binary to your project. You can then try running the binary directly, or even with a debugger like Delve:

View File

@@ -4,10 +4,12 @@ import (
"context"
"fmt"
"log"
"net"
"net/http"
"os"
"os/exec"
"strings"
"time"
)
func main() {
@@ -29,6 +31,7 @@ func main() {
}
m := http.NewServeMux()
m.Handle("/ping", http.HandlerFunc(PingHandler))
m.Handle("/mr/summary", withGitlabContext(http.HandlerFunc(SummaryHandler), c))
m.Handle("/mr/attachment", withGitlabContext(http.HandlerFunc(AttachmentHandler), c))
m.Handle("/mr/reviewer", withGitlabContext(http.HandlerFunc(ReviewersHandler), c))
@@ -44,19 +47,45 @@ func main() {
m.Handle("/pipeline", withGitlabContext(http.HandlerFunc(PipelineHandler), c))
m.Handle("/job", withGitlabContext(http.HandlerFunc(JobHandler), c))
port := fmt.Sprintf(":%s", os.Args[3])
server := &http.Server{
Addr: port,
Handler: m,
port := os.Args[3]
if port == "" {
// port was not specified
port = "0"
}
addr := fmt.Sprintf("localhost:%s", port)
listener, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
fmt.Fprintf(os.Stderr, "Error starting server: %s\n", err)
os.Exit(1)
}
listner_port := listener.Addr().(*net.TCPAddr).Port
errCh := make(chan error)
go func() {
err := http.Serve(listener, m)
errCh <- err
}()
go func() {
for i := 0; i < 10; i++ {
resp, err := http.Get("http://localhost:" + fmt.Sprintf("%d", listner_port) + "/ping")
if resp.StatusCode == 200 && err == nil {
/* This print is detected by the Lua code and used to fetch project information */
fmt.Println("Server started on port: ", listner_port)
return
}
// Wait for healthcheck to pass - at most 1 sec.
time.Sleep(100 * time.Microsecond)
}
errCh <- err
}()
if err := <-errCh; err != nil {
fmt.Fprintf(os.Stderr, "Error starting server: %s\n", err)
os.Exit(1)
}
done := make(chan bool)
go server.ListenAndServe()
/* This print is detected by the Lua code and used to fetch project information */
fmt.Println("Server started.")
<-done
}
func withGitlabContext(next http.HandlerFunc, c Client) http.Handler {
@@ -77,3 +106,7 @@ func getCurrentBranch() (res string, e error) {
return strings.TrimSpace(string(output)), nil
}
func PingHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "pong")
}

View File

@@ -2,45 +2,75 @@
-- the Golang server. The Go server is responsible for making API calls
-- to Gitlab and returning the data
local state = require("gitlab.state")
local u = require("gitlab.utils")
local M = {}
local u = require("gitlab.utils")
local M = {}
-- Starts the Go server and call the callback provided
M.start = function(callback)
M.start = function(callback)
local empty_port = "''"
local port = state.settings.port or empty_port
local parsed_port = nil
local callback_called = false
local command = state.settings.bin
.. " "
.. state.settings.project_id
.. " "
.. state.settings.gitlab_url
.. " "
.. state.settings.port
.. " "
.. state.settings.auth_token
.. " "
.. state.settings.log_path
.. " "
.. state.settings.project_id
.. " "
.. state.settings.gitlab_url
.. " "
.. port
.. " "
.. state.settings.auth_token
.. " "
.. state.settings.log_path
vim.fn.jobstart(command, {
on_stdout = function(job_id)
if job_id <= 0 then
vim.notify("Could not start gitlab.nvim binary", vim.log.levels.ERROR)
else
local job_id = vim.fn.jobstart(command, {
on_stdout = function(_, data)
-- if port was not provided then we need to parse it from output of server
if parsed_port == nil then
for _, line in ipairs(data) do
port = line:match("Server started on port:%s+(%d+)")
if port ~= nil then
parsed_port = port
state.settings.port = port
break
end
end
end
-- This assumes that first output of server will be parsable and port will be correctly set.
-- Make sure that this actually check if port was correctly parsed based on server output
-- because server outputs port only if it started successfully.
if parsed_port ~= nil and not callback_called then
callback()
callback_called = true
elseif not callback_called then
vim.notify("Failed to parse server port", vim.log.levels.ERROR)
end
end,
on_stderr = function(_, errors)
local err_msg = ''
local err_msg = ""
for _, err in ipairs(errors) do
if err ~= "" and err ~= nil then
err_msg = err_msg .. err .. "\n"
end
end
if err_msg ~= '' then vim.notify(err_msg, vim.log.levels.ERROR) end
end
if err_msg ~= "" then
vim.notify(err_msg, vim.log.levels.ERROR)
end
end,
on_exit = function(job_id, exit_code, ...)
vim.notify(
"Golang gitlab server exited: job_id: " .. job_id .. ", exit_code: " .. exit_code,
vim.log.levels.ERROR
)
end,
})
if job_id <= 0 then
vim.notify("Could not start gitlab.nvim binary", vim.log.levels.ERROR)
end
end
-- Builds the Go binary
M.build = function(override)
local file_path = u.current_file_path()
@@ -50,12 +80,13 @@ M.build = function(override)
if not override then
local binary_exists = vim.loop.fs_stat(state.settings.bin)
if binary_exists ~= nil then return end
if binary_exists ~= nil then
return
end
end
local cmd = u.is_windows() and
'cd %s\\cmd && go build -o bin.exe && move bin.exe ..\\' or
'cd %s/cmd && go build -o bin && mv bin ../bin'
local cmd = u.is_windows() and "cd %s\\cmd && go build -o bin.exe && move bin.exe ..\\"
or "cd %s/cmd && go build -o bin && mv bin ../bin"
local command = string.format(cmd, state.settings.bin_path)
local null = u.is_windows() and " >NUL" or " > /dev/null"

View File

@@ -7,11 +7,11 @@ local u = require("gitlab.utils")
local M = {}
-- These are the default settings for the plugin
M.settings = {
port = 21036,
M.settings = {
port = nil, -- choose random port
log_path = (vim.fn.stdpath("cache") .. "/gitlab.nvim.log"),
reviewer = "delta",
attachment_dir = '',
attachment_dir = "",
popup = {
exit = "<Esc>",
perform_action = "<leader>s",
@@ -29,15 +29,15 @@ M.settings = {
relative = "editor",
position = "left",
size = "20%",
resolved = '',
unresolved = '',
resolved = "",
unresolved = "",
},
review_pane = {
delta = {
added_file = "",
modified_file = "",
removed_file = "",
}
},
},
pipeline = {
created = "",

View File

@@ -126,20 +126,10 @@ M.create_popup_state = function(title, width, height)
end
M.merge = function(defaults, overrides)
local result = {}
if type(defaults) == "table" and M.table_size(defaults) == 0 and type(overrides) == "table" then
return overrides
end
for key, value in pairs(defaults) do
if type(value) == "table" then
result[key] = M.merge(value, overrides[key] or {})
else
result[key] = overrides[key] or value
end
end
return result
return vim.tbl_deep_extend("force", defaults, overrides)
end
M.join = function(tbl, separator)