-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit_utils.lua
More file actions
113 lines (99 loc) · 3.21 KB
/
Copy pathgit_utils.lua
File metadata and controls
113 lines (99 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
-- Author: S.Ghamri
-- mod-version:3
local core = require "core"
local common = require "core.common"
local system = require "system"
local process = require "process"
local M = {}
-- m: queue
local git_queue = {} -- single thread queue
local git_busy = false
local function process_next_git_task()
if #git_queue == 0 then
git_busy = false
return
end
git_busy = true
local task = table.remove(git_queue, 1)
core.add_thread(function()
task()
process_next_git_task() -- call next task in queue
end)
end
local function enqueue_git_task(task)
table.insert(git_queue, task)
if not git_busy then
process_next_git_task()
end
end
-- m: git process
local function execute_git(repo_root, args_table)
local command = { "git", "-C", repo_root }
for _, arg in ipairs(args_table) do table.insert(command, arg) end
local git_process = process.start(command)
if not git_process then
core.error("git: failed to start process for %s, cmd: %s", repo_root, table.concat(command, " "))
return "", -1, ""
end
local stdout_output, stderr_output = "", ""
while git_process:running() do
coroutine.yield()
stdout_output = stdout_output .. (git_process:read_stdout() or "")
stderr_output = stderr_output .. (git_process:read_stderr() or "")
end
local exit_code = git_process:returncode() or -1
if exit_code ~= 0 then
core.warn("git: command failed (%d) for %s, cmd: %s", exit_code, repo_root, table.concat(command, " "))
if #stderr_output > 0 then
core.warn("git: stderr: %s", stderr_output:match("^[^\n]+"))
end
end
return stdout_output, exit_code, stderr_output
end
local function get_repo_root(filepath)
if not filepath then return nil end
local current_dir = common.dirname(filepath)
-- check all parent folders
while current_dir and current_dir ~= "" and current_dir ~= "/" do
local info = system.get_file_info(current_dir .. "/.git")
if info and info.type == "dir" then
return current_dir
end
current_dir = common.dirname(current_dir)
end
return nil
end
-- getters ------------------------------------------------------------------------------
-- m: current branch
function M.get_branch(filepath, callback)
enqueue_git_task(function()
local branch_name = ""
local repo_root = filepath and get_repo_root(filepath)
if repo_root then
branch_name = execute_git(repo_root, { "rev-parse", "--abbrev-ref", "HEAD" }):match("[^\n]+") or ""
end
if type(callback) == "function" then
callback(branch_name)
end
end)
end
-- m: stats
function M.get_diff_stats(filepath, callback)
enqueue_git_task(function()
local repo_root = filepath and get_repo_root(filepath)
local added, deleted = 0, 0
if repo_root and filepath then
local relpath = filepath:sub(#repo_root + 2) -- remove root + "/"
local output = execute_git(repo_root, { "diff", "--numstat", relpath })
for plus, minus in output:gmatch("(%d+)%s+(%d+)") do
added = added + tonumber(plus)
deleted = deleted + tonumber(minus)
end
end
if type(callback) == "function" then
callback(added, deleted)
end
end)
end
----------------------------------------------------------------------------------------
return M