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