Skip to content

Commit ee96727

Browse files
authored
Merge pull request #3056 from chrisant996/support_git_reftables
Update the Lua git prompt to support repos with git reftables.
2 parents 9e6e148 + 6ba699a commit ee96727

File tree

1 file changed

+107
-9
lines changed

1 file changed

+107
-9
lines changed

vendor/clink.lua

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ end
324324
-- Find out current branch
325325
-- @return {nil|git branch name}
326326
---
327-
local function get_git_branch(git_dir)
327+
local function get_git_branch(git_dir, fast)
328328
git_dir = git_dir or get_git_dir()
329329

330330
-- If git directory not found then we're probably outside of repo
@@ -341,8 +341,90 @@ local function get_git_branch(git_dir)
341341
-- if HEAD matches branch expression, then we're on named branch
342342
-- otherwise it is a detached commit
343343
local branch_name = HEAD:match('ref: refs/heads/(.+)')
344+
if os.getenv("CLINK_DEBUG_GIT_REFTABLE") then
345+
branch_name = '.invalid'
346+
end
347+
348+
-- If the branch name is ".invalid" and the fast method wasn't requested,
349+
-- then invoke git.exe to get accurate current branch info (slow method).
350+
if branch_name == ".invalid" and not fast then
351+
local file
352+
branch_name = nil
353+
354+
-- Handle the most common case first.
355+
if not branch_name then
356+
file = io_popenyield("git --no-optional-locks branch 2>nul")
357+
if file then
358+
for line in file:lines() do
359+
local b = line:match("^%*%s+(.*)")
360+
if b then
361+
b = b:match("^%((HEAD detached at .*)%)") or b
362+
branch_name = b
363+
break
364+
end
365+
end
366+
file:close()
367+
end
368+
end
369+
370+
-- Handle the cases where "git branch" output is empty, but "git
371+
-- branch --show-current" shows the branch name (e.g. a new repo).
372+
if not branch_name then
373+
file = io_popenyield("git --no-optional-locks branch --show-current 2>nul")
374+
if file then
375+
for line in file:lines() do -- luacheck: ignore 512
376+
branch_name = line
377+
break
378+
end
379+
file:close()
380+
end
381+
end
382+
else
383+
branch_name = branch_name or 'HEAD detached at '..HEAD:sub(1, 7)
384+
end
385+
386+
return branch_name
387+
end
388+
389+
local function get_git_remote(git_dir, branch)
390+
if not git_dir then return nil end
391+
if not branch then return nil end
392+
393+
local file = io.open(git_dir.."/config", 'r')
394+
if not file then return nil end
395+
396+
local git_config = {}
397+
398+
local function get_git_config_value(section, param)
399+
return git_config[section] and git_config[section][param] or nil
400+
end
344401

345-
return branch_name or 'HEAD detached at '..HEAD:sub(1, 7)
402+
local section
403+
for line in file:lines() do
404+
if (line:sub(1,1) == "[" and line:sub(-1) == "]") then
405+
if (line:sub(2,5) == "lfs ") then
406+
section = nil -- skip LFS entries as there can be many and we never use them
407+
else
408+
section = line:sub(2,-2)
409+
git_config[section] = git_config[section] or {}
410+
end
411+
elseif section then
412+
local param, value = line:match('^%s-([%w|_]+)%s-=%s+(.+)$')
413+
if (param and value ~= nil) then
414+
git_config[section][param] = value
415+
end
416+
end
417+
end
418+
file:close()
419+
420+
local remote_to_push = get_git_config_value('branch "'..branch..'"', 'remote') or ''
421+
local remote_ref = get_git_config_value('remote "'..remote_to_push..'"', 'push') or
422+
get_git_config_value('push', 'default')
423+
424+
local text = remote_to_push
425+
if remote_ref then text = text..'/'..remote_ref end
426+
427+
return text ~= '' and text or nil
346428
end
347429

348430
---
@@ -394,7 +476,7 @@ end
394476
-- Get the status and conflict status of working dir
395477
-- @return {bool <status>, bool <is_conflict>}
396478
---
397-
local function get_git_status()
479+
local function get_git_status(git_dir)
398480
local file = io_popenyield("git --no-optional-locks status --porcelain 2>nul")
399481
if not file then
400482
return {}
@@ -416,7 +498,10 @@ local function get_git_status()
416498
end
417499
file:close()
418500

419-
return { status = is_status, conflict = conflict_found }
501+
local branch = get_git_branch(git_dir, false--[[fast]])
502+
local remote = get_git_remote(git_dir, branch)
503+
504+
return { status = is_status, branch = branch, remote = remote, conflict = conflict_found }
420505
end
421506

422507
---
@@ -515,11 +600,11 @@ end
515600
-- Use a prompt coroutine to get git status in the background.
516601
-- Cache the info so we can reuse it next time to reduce flicker.
517602
---
518-
local function get_git_info_table()
603+
local function get_git_info_table(git_dir)
519604
local info = clink_promptcoroutine(function ()
520605
-- Use git status if allowed.
521606
local cmderGitStatusOptIn = get_git_status_setting()
522-
return cmderGitStatusOptIn and get_git_status() or {}
607+
return cmderGitStatusOptIn and get_git_status(git_dir) or {}
523608
end)
524609
if not info then
525610
info = cached_info.git_info or {}
@@ -539,21 +624,34 @@ local function git_prompt_filter()
539624
local git_dir = get_git_dir()
540625
local color
541626
if git_dir then
542-
local branch = get_git_branch(git_dir)
627+
local branch = get_git_branch(git_dir, true--[[fast]])
543628
if branch then
544629
-- If in a different repo or branch than last time, discard cached info.
545-
if cached_info.git_dir ~= git_dir or cached_info.git_branch ~= branch then
630+
if cached_info.git_dir ~= git_dir or
631+
(branch ~= ".invalid" and cached_info.git_branch ~= branch) then
546632
cached_info.git_info = nil
547633
cached_info.git_dir = git_dir
548634
cached_info.git_branch = branch
549635
end
550636

551637
-- If we're inside of git repo then try to detect current branch
552638
-- Has branch => therefore it is a git folder, now figure out status
553-
local gitInfo = get_git_info_table()
639+
local gitInfo = get_git_info_table(git_dir)
554640
local gitStatus = gitInfo.status
555641
local gitConflict = gitInfo.conflict
556642

643+
-- Compensate for git reftables.
644+
branch = gitInfo.branch or branch
645+
if branch == ".invalid" then
646+
branch = "Loading..."
647+
elseif gitInfo.remote then
648+
branch = branch.." -> "..gitInfo.remote
649+
end
650+
651+
-- Prevent an older clink-completions git_prompt.lua scripts from
652+
-- modifying the prompt.
653+
branch = "\x1b[10m"..branch
654+
557655
if gitStatus == nil then
558656
color = get_unknown_color()
559657
elseif gitStatus then

0 commit comments

Comments
 (0)