1 | -- resty-gitweb@git/git_commands.lua |
2 | -- git commands and parser functions |
3 |
|
4 | -- Copyright (c) 2020 Joshua 'joshuas3' Stockin |
5 | -- <https://git.joshstock.in/resty-gitweb> |
6 | -- This software is licensed under the MIT License. |
7 |
|
8 | local ffi = require("ffi") |
9 | local utils = require("utils/utils") |
10 | local git2_error = require("git/git2_error") |
11 |
|
12 | local _M = {} |
13 |
|
14 | local git = function(repo_dir, command) |
15 | local formatted_command = string.format( |
16 | "git --git-dir=%s %s", |
17 | repo_dir, command |
18 | ) |
19 | return utils.process(formatted_command) |
20 | end |
21 |
|
22 | _M.count = function(repo_dir, hash) |
23 | hash = hash or "@" |
24 | local output = git(repo_dir, "rev-list --count "..hash.." --") |
25 | return tonumber(string.trim(output)) |
26 | end |
27 |
|
28 | _M.log = function(repo_dir, hash, file, number, skip, gpg) |
29 | hash = hash or "@" |
30 | file = file or "" |
31 | number = tostring(number or 25) |
32 | skip = tostring(skip or 0) |
33 | gpg = gpg or false |
34 | local output |
35 | if gpg then |
36 | output = git(repo_dir, "log --pretty=tformat:'%x00%x01%H%x00%cI%x00%cn%x00%ce%x00%s%x00%b%x00%G?%x00%GK%x00%GG%x00' --numstat -n "..number.." --skip "..skip.." "..hash.." -- "..file) |
37 | else |
38 | output = git(repo_dir, "log --pretty=tformat:'%x00%x01%H%x00%cI%x00%cn%x00%ce%x00%s%x00%b%x00' --numstat -n "..number.." --skip "..skip.." "..hash.." -- "..file) |
39 | end |
40 | local commits = {} |
41 | local a = string.split(output,"\0\1") |
42 | local f = false |
43 | for i,v in pairs(a) do |
44 | if f == true then |
45 | local commit = {} |
46 | local c = string.split(v, "\0") |
47 | commit.hash = c[1] |
48 | commit.shorthash = string.sub(c[1], 1,7) |
49 | commit.timestamp = c[2] |
50 | commit.author = c[3] |
51 | commit.email = c[4] |
52 | commit.subject = c[5] |
53 | commit.body = string.trim(c[6]) |
54 | local diffs |
55 | if gpg then |
56 | commit.gpggood = c[7] |
57 | commit.gpgkey = c[8] |
58 | commit.gpgfull = string.trim(c[9]) |
59 | diffs = string.trim(c[10]) |
60 | else |
61 | diffs = string.trim(c[7]) |
62 | end |
63 | commit.diff = {} |
64 | local b = string.split(diffs, "\n") |
65 | commit.diff.plus = 0 |
66 | commit.diff.minus = 0 |
67 | commit.diff.num = 0 |
68 | commit.diff.files = {} |
69 | for i,v in pairs(b) do |
70 | local d = string.split(v,"\t") |
71 | local x = {} |
72 | x.plus = tonumber(d[1]) or 0 |
73 | commit.diff.plus = commit.diff.plus + x.plus |
74 | x.minus = tonumber(d[2]) or 0 |
75 | commit.diff.minus = commit.diff.minus + x.minus |
76 | commit.diff.files[d[3]] = x |
77 | commit.diff.num = commit.diff.num + 1 |
78 | end |
79 | table.insert(commits, commit) |
80 | else |
81 | f = true |
82 | end |
83 | end |
84 | return commits |
85 | end |
86 |
|
87 | _M.commit = function(repo_dir, hash) |
88 | local commit = _M.log(repo_dir, hash, "", 1, 0, true)[1] |
89 | commit.count = _M.count(repo_dir, hash) |
90 | return commit |
91 | end |
92 |
|
93 | local list_dirs = function(repo_dir, hash, path) |
94 | hash = hash or "@" |
95 | path = path or "" |
96 | local output = git(repo_dir, "ls-tree -d --name-only "..hash.." -- "..path) |
97 | local dirs = string.split(output, "\n") |
98 | table.remove(dirs, #dirs) -- remove trailing \n |
99 | return dirs |
100 | end |
101 |
|
102 | local list_all = function(repo_dir, hash, path) |
103 | hash = hash or "@" |
104 | path = path or "" |
105 | local output = git(repo_dir, "ls-tree --name-only "..hash.." -- "..path) |
106 | local all = string.split(output, "\n") |
107 | table.remove(all, #all) -- remove trailing \n |
108 | return all |
109 | end |
110 |
|
111 | _M.list_tree = function(repo_dir, hash, path) |
112 | hash = hash or "@" |
113 | path = path or "" |
114 | local files = list_all(repo_dir, hash, path) |
115 | local dirs = list_dirs(repo_dir, hash, path) |
116 | local ret = {} |
117 | ret.dirs = {} |
118 | ret.files = {} |
119 | for i,v in pairs(files) do -- iterate over all objects, separate directories from files |
120 | local not_dir = true |
121 | for _,d in pairs(dirs) do -- check if object is directory |
122 | if v == d then |
123 | not_dir = false |
124 | break |
125 | end |
126 | end |
127 | if not_dir then |
128 | table.insert(ret.files, v) |
129 | else |
130 | table.insert(ret.dirs, v) |
131 | end |
132 | end |
133 | return ret |
134 | end |
135 |
|
136 | _M.repo = require("git/repo") |
137 | _M.read_blob = require("git/read_blob") |
138 | _M.find_rev = require("git/find_rev") |
139 | _M.list_refs = require("git/list_refs") |
140 | return _M |
141 |
|