From 60b4e6be8b6308be3d7c41019b159cbf7af9a92c Mon Sep 17 00:00:00 2001 From: Max Savchenko Date: Sat, 2 Nov 2024 09:31:18 +0100 Subject: [PATCH] raise error when merging from picker failed add `default_delete_branch` setting which can be overridden with `delete`/`nodelete` argument to `Octo pr merge` also apply all merge defaults when merging from picker --- README.md | 133 +++++++++++++++++++++--------------------- lua/octo/commands.lua | 42 ++++++------- lua/octo/config.lua | 2 + lua/octo/utils.lua | 40 +++++++++++-- 4 files changed, 121 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index f359c546..95e93d79 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,8 @@ require"octo".setup({ use_local_fs = false, -- use local files on right side of reviews enable_builtin = false, -- shows a list of builtin actions when no action is provided default_remote = {"upstream", "origin"}; -- order to try remotes - default_merge_method = "commit", -- default merge method which should be used when calling `Octo pr merge`, could be `commit`, `rebase` or `squash` + default_merge_method = "commit", -- default merge method which should be used for both `Octo pr merge` and merging from picker, could be `commit`, `rebase` or `squash` + default_delete_branch = false, -- whether to delete branch when merging pull request with either `Octo pr merge` or from picker (can be overridden with `delete`/`nodelete` argument to `Octo pr merge`) ssh_aliases = {}, -- SSH aliases. e.g. `ssh_aliases = {["github.com-work"] = "github.com"}`. The key part will be interpreted as an anchored Lua pattern. picker = "telescope", -- or "fzf-lua" picker_config = { @@ -302,71 +303,71 @@ Just edit the issue title, body or comments as a regular buffer and use `:w(rite There is only an `Octo [arguments]` command: If no command is passed, the argument to `Octo` is treated as a URL from where an issue or pr repo and number are extracted. -| Object | Action | Arguments | -| -------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| issue | close | Close the current issue | -| | reopen | Reopen the current issue | -| | create [repo] | Creates a new issue in the current or specified repo | -| | develop | Create and checkout a new branch for an issue in the current repo | -| | edit [repo] | Edit issue `` in current or specified repo | -| | list [repo] [key=value] (1) | List all issues satisfying given filter | -| | search | Live issue search | -| | reload | Reload issue. Same as doing `e!` | -| | browser | Open current issue in the browser | -| | url | Copies the URL of the current issue to the system clipboard | -| pr | list [repo] [key=value] (2) | List all PRs satisfying given filter | -| | search | Live issue search | -| | edit [repo] | Edit PR `` in current or specified repo | -| | reopen | Reopen the current PR | -| | create | Creates a new PR for the current branch | -| | close | Close the current PR | -| | checkout | Checkout PR | -| | commits | List all PR commits | -| | changes | Show all PR changes (diff hunks) | -| | diff | Show PR diff | -| | merge [commit\|rebase\|squash] [delete] | Merge current PR using the specified method | -| | ready | Mark a draft PR as ready for review | -| | draft | Send a ready PR back to draft | -| | checks | Show the status of all checks run on the PR | -| | reload | Reload PR. Same as doing `e!` | -| | browser | Open current PR in the browser | -| | url | Copies the URL of the current PR to the system clipboard | -| repo | list (3) | List repos user owns, contributes or belong to | -| | fork | Fork repo | -| | browser | Open current repo in the browser | -| | url | Copies the URL of the current repo to the system clipboard | -| | view | Open a repo by path ({organization}/{name}) | -| gist | list [repo] [key=value] (4) | List user gists | -| comment | add | Add a new comment | -| | delete | Delete a comment | -| thread | resolve | Mark a review thread as resolved | -| | unresolve | Mark a review thread as unresolved | -| label | add [label] | Add a label from available label menu | -| | remove [label] | Remove a label | -| | create [label] | Create a new label | -| assignee | add [login] | Assign a user | -| | remove [login] | Unassign a user | -| reviewer | add [login] | Assign a PR reviewer | -| reaction | `thumbs_up` \| `+1` | Add 👍 reaction | -| | `thumbs_down` \| `-1` | Add 👎 reaction | -| | `eyes` | Add 👀 reaction | -| | `laugh` | Add 😄 reaction | -| | `confused` | Add 😕 reaction | -| | `rocket` | Add 🚀 reaction | -| | `heart` | Add ❤️ reaction | -| | `hooray` \| `party` \| `tada` | Add 🎉 reaction | -| card | add | Assign issue/PR to a project new card | -| | remove | Delete project card | -| | move | Move project card to different project/column | -| review | start | Start a new review | -| | submit | Submit the review | -| | resume | Edit a pending review for current PR | -| | discard | Deletes a pending review for current PR if any | -| | comments | View pending review comments | -| | commit | Pick a specific commit to review | -| | close | Close the review window and return to the PR | -| actions | | Lists all available Octo actions | -| search | | Search GitHub for issues and PRs matching the [query](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests) | +| Object | Action | Arguments | +| -------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| issue | close | Close the current issue | +| | reopen | Reopen the current issue | +| | create [repo] | Creates a new issue in the current or specified repo | +| | develop | Create and checkout a new branch for an issue in the current repo | +| | edit [repo] | Edit issue `` in current or specified repo | +| | list [repo] [key=value] (1) | List all issues satisfying given filter | +| | search | Live issue search | +| | reload | Reload issue. Same as doing `e!` | +| | browser | Open current issue in the browser | +| | url | Copies the URL of the current issue to the system clipboard | +| pr | list [repo] [key=value] (2) | List all PRs satisfying given filter | +| | search | Live issue search | +| | edit [repo] | Edit PR `` in current or specified repo | +| | reopen | Reopen the current PR | +| | create | Creates a new PR for the current branch | +| | close | Close the current PR | +| | checkout | Checkout PR | +| | commits | List all PR commits | +| | changes | Show all PR changes (diff hunks) | +| | diff | Show PR diff | +| | merge [commit\|rebase\|squash] [delete\|nodelete] | Merge current PR using the specified method | +| | ready | Mark a draft PR as ready for review | +| | draft | Send a ready PR back to draft | +| | checks | Show the status of all checks run on the PR | +| | reload | Reload PR. Same as doing `e!` | +| | browser | Open current PR in the browser | +| | url | Copies the URL of the current PR to the system clipboard | +| repo | list (3) | List repos user owns, contributes or belong to | +| | fork | Fork repo | +| | browser | Open current repo in the browser | +| | url | Copies the URL of the current repo to the system clipboard | +| | view | Open a repo by path ({organization}/{name}) | +| gist | list [repo] [key=value] (4) | List user gists | +| comment | add | Add a new comment | +| | delete | Delete a comment | +| thread | resolve | Mark a review thread as resolved | +| | unresolve | Mark a review thread as unresolved | +| label | add [label] | Add a label from available label menu | +| | remove [label] | Remove a label | +| | create [label] | Create a new label | +| assignee | add [login] | Assign a user | +| | remove [login] | Unassign a user | +| reviewer | add [login] | Assign a PR reviewer | +| reaction | `thumbs_up` \| `+1` | Add 👍 reaction | +| | `thumbs_down` \| `-1` | Add 👎 reaction | +| | `eyes` | Add 👀 reaction | +| | `laugh` | Add 😄 reaction | +| | `confused` | Add 😕 reaction | +| | `rocket` | Add 🚀 reaction | +| | `heart` | Add ❤️ reaction | +| | `hooray` \| `party` \| `tada` | Add 🎉 reaction | +| card | add | Assign issue/PR to a project new card | +| | remove | Delete project card | +| | move | Move project card to different project/column | +| review | start | Start a new review | +| | submit | Submit the review | +| | resume | Edit a pending review for current PR | +| | discard | Deletes a pending review for current PR if any | +| | comments | View pending review comments | +| | commit | Pick a specific commit to review | +| | close | Close the review window and return to the PR | +| actions | | Lists all available Octo actions | +| search | | Search GitHub for issues and PRs matching the [query](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests) | 0. `[repo]`: If repo is not provided, it will be derived from `/.git/config`. diff --git a/lua/octo/commands.lua b/lua/octo/commands.lua index 529fca51..670191f6 100644 --- a/lua/octo/commands.lua +++ b/lua/octo/commands.lua @@ -1117,43 +1117,35 @@ function M.pr_checks() end function M.merge_pr(...) - local conf = config.values - local defaultMergeMethod = conf.default_merge_method - local bufnr = vim.api.nvim_get_current_buf() local buffer = octo_buffers[bufnr] if not buffer or not buffer:isPullRequest() then return end + local args = { "pr", "merge", tostring(buffer.number) } local params = table.pack(...) - for i = 1, params.n do - if params[i] == "delete" then - table.insert(args, "--delete-branch") + local conf = config.values + + local merge_method = conf.default_merge_method + for _, param in ipairs(params) do + if utils.merge_method_to_flag[param] then + merge_method = param end end - local has_flag = false - for i = 1, params.n do - if params[i] == "commit" then - table.insert(args, "--merge") - has_flag = true - elseif params[i] == "squash" then - table.insert(args, "--squash") - has_flag = true - elseif params[i] == "rebase" then - table.insert(args, "--rebase") - has_flag = true + utils.insert_merge_flag(args, merge_method) + + local delete_branch = conf.default_delete_branch + for _, param in ipairs(params) do + if param == "delete" then + delete_branch = true end - end - if not has_flag then - if defaultMergeMethod == "squash" then - table.insert(args, "--squash") - elseif defaultMergeMethod == "rebase" then - table.insert(args, "--rebase") - else - table.insert(args, "--merge") + if param == "nodelete" then + delete_branch = false end end + utils.insert_delete_flag(args, delete_branch) + gh.run { args = args, cb = function(output, stderr) diff --git a/lua/octo/config.lua b/lua/octo/config.lua index 603c3130..ae2d0d15 100644 --- a/lua/octo/config.lua +++ b/lua/octo/config.lua @@ -54,6 +54,7 @@ local M = {} ---@field picker_config OctoPickerConfig ---@field default_remote table ---@field default_merge_method string +---@field default_delete_branch boolean ---@field ssh_aliases {[string]:string} ---@field reaction_viewer_hint_icon string ---@field users string @@ -99,6 +100,7 @@ function M.get_default_values() }, default_remote = { "upstream", "origin" }, default_merge_method = "commit", + default_delete_branch = false, ssh_aliases = {}, reaction_viewer_hint_icon = " ", users = "search", diff --git a/lua/octo/utils.lua b/lua/octo/utils.lua index 616ac099..e2825002 100644 --- a/lua/octo/utils.lua +++ b/lua/octo/utils.lua @@ -421,17 +421,47 @@ function M.checkout_pr_sync(pr_number) }):sync() end ----Mergest a PR b number +M.merge_method_to_flag = { + squash = "--squash", + rebase = "--rebase", + commit = "--merge", +} + +function M.insert_merge_flag(args, method) + table.insert(args, M.merge_method_to_flag[method]) +end + +function M.insert_delete_flag(args, delete) + if delete then + table.insert(args, "--delete-branch") + end +end + +---Merges a PR by number function M.merge_pr(pr_number) if not Job then + M.error "Aborting PR merge" return end + + local conf = config.values + local args = { "pr", "merge", pr_number } + + M.insert_merge_flag(args, conf.default_merge_method) + M.insert_delete_flag(args, conf.default_delete_branch) + Job:new({ - enable_recording = true, command = "gh", - args = { "pr", "merge", pr_number, "--merge", "--delete-branch" }, - on_exit = vim.schedule_wrap(function() - M.info("Merged PR " .. pr_number .. "!") + args = args, + on_exit = vim.schedule_wrap(function(job, code) + if code == 0 then + M.info("Merged PR " .. pr_number .. "!") + else + local stderr = table.concat(job:stderr_result(), "\n") + if not M.is_blank(stderr) then + M.error(stderr) + end + end end), }):start() end