84 lines
2.9 KiB
Lua
84 lines
2.9 KiB
Lua
local path = require('path')
|
|
|
|
local exports = {}
|
|
|
|
---
|
|
-- Resolves closest .git directory location.
|
|
-- Navigates subsequently up one level and tries to find .git directory
|
|
-- @param {string} path Path to directory will be checked. If not provided
|
|
-- current directory will be used
|
|
-- @return {string} Path to .git directory or nil if such dir not found
|
|
exports.get_git_dir = function (start_dir)
|
|
|
|
-- Checks if provided directory contains '.git' directory
|
|
-- and returns path to that directory
|
|
local function has_git_dir(dir)
|
|
return #clink.find_dirs(dir..'/.git') > 0 and dir..'/.git'
|
|
end
|
|
|
|
-- checks if directory contains '.git' _file_ and if it does
|
|
-- parses it and returns a path to git directory from that file
|
|
local function has_git_file(dir)
|
|
local gitfile = io.open(dir..'/.git')
|
|
if not gitfile then return false end
|
|
|
|
local git_dir = gitfile:read():match('gitdir: (.*)')
|
|
gitfile:close()
|
|
|
|
if not git_dir then return false end
|
|
-- If found path is absolute don't prepend initial
|
|
-- directory - return absolute path value
|
|
return path.is_absolute(git_dir) and git_dir
|
|
or dir..'/'..git_dir
|
|
end
|
|
|
|
-- Set default path to current directory
|
|
if not start_dir or start_dir == '.' then start_dir = clink.get_cwd() end
|
|
|
|
-- Calculate parent path now otherwise we won't be
|
|
-- able to do that inside of logical operator
|
|
local parent_path = path.pathname(start_dir)
|
|
|
|
return has_git_dir(start_dir)
|
|
or has_git_file(start_dir)
|
|
-- Otherwise go up one level and make a recursive call
|
|
or (parent_path ~= start_dir and exports.get_git_dir(parent_path) or nil)
|
|
end
|
|
|
|
exports.get_git_common_dir = function (start_dir)
|
|
local git_dir = exports.get_git_dir(start_dir)
|
|
if not git_dir then return git_dir end
|
|
local commondirfile = io.open(git_dir..'/commondir')
|
|
if commondirfile then
|
|
-- If there's a commondir file, we're in a git worktree
|
|
local commondir = commondirfile:read()
|
|
commondirfile.close()
|
|
return path.is_absolute(commondir) and commondir
|
|
or git_dir..'/'..commondir
|
|
end
|
|
return git_dir
|
|
end
|
|
|
|
---
|
|
-- Find out current branch
|
|
-- @return {nil|git branch name}
|
|
---
|
|
exports.get_git_branch = function (dir)
|
|
local git_dir = dir or exports.get_git_dir()
|
|
|
|
-- If git directory not found then we're probably outside of repo
|
|
-- or something went wrong. The same is when head_file is nil
|
|
local head_file = git_dir and io.open(git_dir..'/HEAD')
|
|
if not head_file then return end
|
|
|
|
local HEAD = head_file:read()
|
|
head_file:close()
|
|
|
|
-- if HEAD matches branch expression, then we're on named branch
|
|
-- otherwise it is a detached commit
|
|
local branch_name = HEAD:match('ref: refs/heads/(.+)')
|
|
return branch_name or 'HEAD detached at '..HEAD:sub(1, 7)
|
|
end
|
|
|
|
return exports
|