pwntester / octo.nvim

Edit and review GitHub issues and pull requests from the comfort of your favorite editor
MIT License
2.24k stars 124 forks source link

Bug: PR checkout fails if origin fetch and push url differ #542

Open srafi1 opened 2 months ago

srafi1 commented 2 months ago

Issue Description

Type: bug report

Describe what happened (or what feature you want)

I have a project set up in my local dev env where the origin fetch remote is set to the main project url and the push remote is set to my own fork. When I try to run :Octo pr checkout from an octo buffer in this project, I get the error "Not in PR repo." However, checking out to the PR branch should still be possible because the origin fetch remote is set to the same url as the PR.

Describe what you expected to happen

Octo should check out my project to the PR branch without error.

How to reproduce it (as minimally and precisely as possible)

  1. Fork a github project.
  2. Clone the project from the main project (not the fork).
  3. Set the push remote to the fork: git remote set-url --push origin git@github.com:<your repo>
  4. Open the project in neovim and navigate to any PR from the fork to the main project: :Octo <PR url>
  5. Try to checkout to the PR branch: :Octo pr checkout

Tell us your environment

macOS nvim v0.9.5 octo.nvim commit 5646539320cd62af6ff28f48ec92aeb724c68e18

Anything else we need to know?

I was able to get this to work locally by editing parse_git_remote() in lua/octo/utils.lua to the following:

function M.parse_git_remote()
  local conf = config.values
  local aliases = conf.ssh_aliases
  local job = Job:new { command = "git", args = { "remote", "-v" }, cwd = vim.fn.getcwd() }
  job:sync()
  local stderr = table.concat(job:stderr_result(), "\n")
  if not M.is_blank(stderr) then
    return {}
  end
  local remotes = {}
  for _, line in ipairs(job:result()) do
    local name, url, mode = line:match "^(%S+)%s+(%S+)%s+(%S+)"
    if name and mode == '(fetch)' then -- (push) always comes after (fetch), so it overwrites the (fetch) value
      local remote = M.parse_remote_url(url, aliases)
      if remote then
        remotes[name] = remote
      end
    end
  end
  return remotes
end