Skip to content

Commit

Permalink
fix: support finding pr branch via git config branch keys (#806)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldelossa authored Jan 22, 2025
1 parent f75ec17 commit 9f90ec9
Showing 1 changed file with 74 additions and 2 deletions.
76 changes: 74 additions & 2 deletions lua/octo/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,14 @@ end
--- Determines if we are locally are in a branch matching the pr head ref
--- @param pr PullRequest
--- @return boolean
function M.in_pr_branch(pr)
function M.in_pr_branch_locally_tracked(pr)
local cmd = "git rev-parse --abbrev-ref --symbolic-full-name @{u}"
local local_branch_with_local_remote = vim.split(string.gsub(vim.fn.system(cmd), "%s+", ""), "/")
local cmd_out = vim.fn.system(cmd)
if vim.v.shell_error ~= 0 then
return false
end

local local_branch_with_local_remote = vim.split(string.gsub(cmd_out, "%s+", ""), "/")
local local_remote = local_branch_with_local_remote[1]
local local_branch = table.concat(local_branch_with_local_remote, "/", 2)

Expand All @@ -465,6 +470,73 @@ function M.in_pr_branch(pr)
return false
end

-- the gh cli stores the remote info for a PR branch in a branch specific
-- config value.
--
-- this function searches for the upstream info, if it exists, for the current
-- checked out branch, within git config branch specific values.
--
-- if a config value is found the upstream branch name is returned, verbatim.
-- if no config value is found an empty string is returned.
--
-- this is useful when you want to determine if the currently checked out branch
-- maps to a PR HEAD, when 'gh pr checkout' is used.
function M.get_upstream_branch_from_config()
local branch_cmd = "git rev-parse --abbrev-ref HEAD"
local branch = vim.fn.system(branch_cmd)
if vim.v.shell_error ~= 0 then
return ""
end

if #branch == 0 then
return ""
end

-- trim white space off branch
branch = string.gsub(branch, "%s+", "")

local merge_config_cmd = string.format('git config --get-regexp "^branch\\.%s\\.merge"', branch)

local merge_config = vim.fn.system(merge_config_cmd)
if vim.v.shell_error ~= 0 then
return ""
end

if #merge_config == 0 then
return ""
end

-- split merge_config to key, value with space delimeter
local merge_config_kv = vim.split(merge_config, "%s+")
-- use > 2 since there maybe some garbage white space at the end of the map.
if #merge_config_kv < 2 then
return ""
end

local upstream_branch_ref = merge_config_kv[2]

-- remove the prefix /refs/heads/ from upstream_branch_ref resulting in
-- branch's name.
local upstream_branch_name = string.gsub(upstream_branch_ref, "^refs/heads/", "")

return upstream_branch_name
end

-- Determines if we are locally in a branch matting the pr head ref when
-- the remote and branch information is stored in the branch's git config values
-- The gh CLI tool stores remote info directly in {branch.{branch}.x} configuration
-- fields and does not create a remote
function M.in_pr_branch_config_tracked(pr)
return M.get_upstream_branch_from_config():lower() == pr.head_ref_name
end

--- Determines if we are locally are in a branch matching the pr head ref
--- @param pr PullRequest
--- @return boolean
function M.in_pr_branch(pr)
return M.in_pr_branch_locally_tracked(pr) or M.in_pr_branch_config_tracked(pr)
end

function M.checkout_pr(pr_number)
gh.run {
args = { "pr", "checkout", pr_number },
Expand Down

0 comments on commit 9f90ec9

Please sign in to comment.