forked from a/repotool
151 lines
4.3 KiB
Lua
151 lines
4.3 KiB
Lua
local cmd = require("cmd")
|
|
|
|
local git = {}
|
|
|
|
-- Parse a git URL into domain and path components
|
|
function git.parse_url(url)
|
|
local domain, path
|
|
|
|
-- Check if it's an HTTP(S) URL
|
|
-- First try without authentication
|
|
domain, path = url:match("^https?://([^@/]+)/(.+)%.git$")
|
|
if not domain then
|
|
domain, path = url:match("^https?://([^@/]+)/(.+)$")
|
|
end
|
|
|
|
-- If that didn't match, try with authentication
|
|
if not domain then
|
|
domain, path = url:match("^https?://[^@]+@([^/]+)/(.+)%.git$")
|
|
end
|
|
if not domain then
|
|
domain, path = url:match("^https?://[^@]+@([^/]+)/(.+)$")
|
|
end
|
|
|
|
-- Check if it's an SSH URL (git@host:path or ssh://...)
|
|
if not domain then
|
|
domain, path = url:match("^[^@]+@([^:]+):(.+)%.git$")
|
|
end
|
|
if not domain then
|
|
domain, path = url:match("^[^@]+@([^:]+):(.+)$")
|
|
end
|
|
if not domain then
|
|
domain, path = url:match("^ssh://[^@]*@?([^/]+)/(.+)%.git$")
|
|
end
|
|
if not domain then
|
|
domain, path = url:match("^ssh://[^@]*@?([^/]+)/(.+)$")
|
|
end
|
|
|
|
-- Check if it's a bare domain path (e.g., gfx.cafe/oku/trade)
|
|
if not domain then
|
|
domain, path = url:match("^([^/]+%.%w+)/(.+)$")
|
|
end
|
|
|
|
return domain, path
|
|
end
|
|
|
|
-- Get domain and path from current git repository's origin
|
|
function git.parse_origin()
|
|
local origin_url = cmd.read_stdout("git config --get remote.origin.url")
|
|
origin_url = origin_url:gsub("\n", "")
|
|
|
|
if origin_url == "" then
|
|
return nil, nil
|
|
end
|
|
|
|
return git.parse_url(origin_url)
|
|
end
|
|
|
|
-- Validate if a URL is a valid git repository URL
|
|
function git.valid_url(url)
|
|
if url:match("^https?://") then
|
|
return 1 -- HTTP(S)
|
|
elseif url:match("^[^:]+@[^:]+:") or url:match("^ssh://") then
|
|
return 2 -- SSH
|
|
elseif url:match("^[^/]+%.%w+/[^/]+") then
|
|
return 3 -- Bare domain path
|
|
else
|
|
return -1 -- Invalid
|
|
end
|
|
end
|
|
|
|
-- Execute command and return output
|
|
function git.execute(command)
|
|
return cmd.read(command)
|
|
end
|
|
|
|
-- Check if we're in a git repository
|
|
function git.in_repo()
|
|
local _, success = git.execute("git rev-parse --git-dir")
|
|
return success
|
|
end
|
|
|
|
-- Get repository root
|
|
function git.get_repo_root()
|
|
local output, success = git.execute("git rev-parse --show-toplevel")
|
|
if success then
|
|
return output:gsub("\n", "")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- Get git common directory (for worktree detection)
|
|
function git.get_common_dir()
|
|
local output, success = git.execute("git rev-parse --git-common-dir")
|
|
if success then
|
|
return output:gsub("\n", "")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- Get list of all worktrees with their properties
|
|
function git.worktree_list()
|
|
local worktrees = {}
|
|
local output = cmd.read_stdout("git worktree list --porcelain")
|
|
local current_worktree = nil
|
|
|
|
for line in output:gmatch("[^\n]+") do
|
|
local worktree_path = line:match("^worktree (.+)$")
|
|
if worktree_path then
|
|
-- Save previous worktree if any
|
|
if current_worktree then
|
|
table.insert(worktrees, current_worktree)
|
|
end
|
|
-- Start new worktree
|
|
current_worktree = {
|
|
path = worktree_path,
|
|
head = nil,
|
|
branch = nil,
|
|
bare = false,
|
|
detached = false,
|
|
locked = false,
|
|
prunable = false
|
|
}
|
|
elseif current_worktree then
|
|
-- Parse other worktree properties
|
|
local head = line:match("^HEAD (.+)$")
|
|
if head then
|
|
current_worktree.head = head
|
|
elseif line:match("^branch (.+)$") then
|
|
current_worktree.branch = line:match("^branch (.+)$")
|
|
elseif line == "bare" then
|
|
current_worktree.bare = true
|
|
elseif line == "detached" then
|
|
current_worktree.detached = true
|
|
elseif line:match("^locked") then
|
|
current_worktree.locked = true
|
|
elseif line == "prunable gitdir file points to non-existent location" then
|
|
current_worktree.prunable = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Don't forget the last worktree
|
|
if current_worktree then
|
|
table.insert(worktrees, current_worktree)
|
|
end
|
|
|
|
return worktrees
|
|
end
|
|
|
|
return git
|