| 1 | -- git_commands.lua |
| 2 | -- Index of git commands used for the git status site |
| 3 |
|
| 4 | -- Copyright (c) 2020 Joshua 'joshuas3' Stockin |
| 5 | -- <https://github.com/JoshuaS3/joshstock.in> |
| 6 | -- <https://joshstock.in> |
| 7 |
|
| 8 |
|
| 9 | local utils = require("utils") |
| 10 |
|
| 11 | local _M = {} |
| 12 |
|
| 13 | local git = function(repo_dir, command) |
| 14 | local formatted_command = string.format( |
| 15 | "git --git-dir=%s/.git --work-tree=%s %s", |
| 16 | repo_dir, repo_dir, command |
| 17 | ) |
| 18 | return utils.process(formatted_command) |
| 19 | end |
| 20 |
|
| 21 | _M.show_file = function(repo_dir, hash, filename) |
| 22 | hash = hash or "@" |
| 23 | filename = filename or "" |
| 24 | local output = git(repo_dir, "show "..hash..":"..filename) |
| 25 | return output |
| 26 | end |
| 27 |
|
| 28 | _M.get_head = function(repo_dir) |
| 29 | local head = {} |
| 30 | local name = string.trim(git(repo_dir, "rev-parse --abbrev-ref HEAD")) |
| 31 | local output = git(repo_dir, "show-ref --heads "..name) |
| 32 | local a = string.split(string.trim(output), " ") |
| 33 | head.hash = a[1] |
| 34 | head.shorthash = string.sub(a[1], 1, 7) |
| 35 | head.full = a[2] |
| 36 | head.name = name |
| 37 | return head |
| 38 | end |
| 39 |
|
| 40 | _M.count = function(repo_dir, hash) |
| 41 | hash = hash or "@" |
| 42 | local output = git(repo_dir, "rev-list --count "..hash.." --") |
| 43 | return tonumber(string.trim(output)) |
| 44 | end |
| 45 |
|
| 46 | _M.log = function(repo_dir, hash, file, number, skip, gpg) |
| 47 | hash = hash or "@" |
| 48 | file = file or "" |
| 49 | number = tostring(number or 25) |
| 50 | skip = tostring(skip or 0) |
| 51 | gpg = gpg or false |
| 52 | local output |
| 53 | if gpg then |
| 54 | 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) |
| 55 | else |
| 56 | 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) |
| 57 | end |
| 58 | local commits = {} |
| 59 | local a = string.split(output,"\0\1") |
| 60 | local f = false |
| 61 | for i,v in pairs(a) do |
| 62 | if f == true then |
| 63 | local commit = {} |
| 64 | local c = string.split(v, "\0") |
| 65 | commit.hash = c[1] |
| 66 | commit.shorthash = string.sub(c[1], 1,7) |
| 67 | commit.timestamp = c[2] |
| 68 | commit.author = c[3] |
| 69 | commit.email = c[4] |
| 70 | commit.subject = c[5] |
| 71 | commit.body = string.trim(c[6]) |
| 72 | local diffs |
| 73 | if gpg then |
| 74 | commit.gpggood = c[7] |
| 75 | commit.gpgkey = c[8] |
| 76 | commit.gpgfull = string.trim(c[9]) |
| 77 | diffs = string.trim(c[10]) |
| 78 | else |
| 79 | diffs = string.trim(c[7]) |
| 80 | end |
| 81 | commit.diff = {} |
| 82 | local b = string.split(diffs, "\n") |
| 83 | commit.diff.plus = 0 |
| 84 | commit.diff.minus = 0 |
| 85 | commit.diff.num = 0 |
| 86 | commit.diff.files = {} |
| 87 | for i,v in pairs(b) do |
| 88 | local d = string.split(v,"\t") |
| 89 | local x = {} |
| 90 | x.plus = tonumber(d[1]) or 0 |
| 91 | commit.diff.plus = commit.diff.plus + x.plus |
| 92 | x.minus = tonumber(d[2]) or 0 |
| 93 | commit.diff.minus = commit.diff.minus + x.minus |
| 94 | commit.diff.files[d[3]] = x |
| 95 | commit.diff.num = commit.diff.num + 1 |
| 96 | end |
| 97 | table.insert(commits, commit) |
| 98 | else |
| 99 | f = true |
| 100 | end |
| 101 | end |
| 102 | return commits |
| 103 | end |
| 104 |
|
| 105 | _M.number = function(repo_dir, hash) |
| 106 | hash = hash or "@" |
| 107 | local output = git(repo_dir, "rev-list --count "..hash.." --") |
| 108 | end |
| 109 |
|
| 110 | _M.commit = function(repo_dir, hash) |
| 111 | local commit = _M.log(repo_dir, hash, 1, 0)[1] |
| 112 | commit.number = _M.number(repo_dir, hash) |
| 113 | return commit |
| 114 | end |
| 115 |
|
| 116 | _M.heads = function(repo_dir) |
| 117 | local output = git(repo_dir, "show-ref --heads") |
| 118 | local a = string.split(output, "\n") |
| 119 | table.remove(a,#a) |
| 120 | local heads = {} |
| 121 | for i,v in pairs(a) do |
| 122 | local b = string.split(v, " ") |
| 123 | local head = {} |
| 124 | head.hash = b[1] |
| 125 | head.shorthash = string.sub(b[1], 1, 7) |
| 126 | head.full = b[2] |
| 127 | head.name = string.split(b[2], "/")[3] |
| 128 | table.insert(heads, head) |
| 129 | end |
| 130 | return heads |
| 131 | end |
| 132 |
|
| 133 | _M.tags = function(repo_dir) |
| 134 | local output = git(repo_dir, "show-ref --tags") |
| 135 | local a = string.split(output, "\n") |
| 136 | table.remove(a,#a) |
| 137 | local tags = {} |
| 138 | for i,v in pairs(a) do |
| 139 | local b = string.split(v, " ") |
| 140 | local tag = {} |
| 141 | tag.hash = b[1] |
| 142 | tag.shorthash = string.sub(b[1], 1, 7) |
| 143 | tag.full = b[2] |
| 144 | tag.name = string.split(b[2], "/")[3] |
| 145 | table.insert(tags, tag) |
| 146 | end |
| 147 | return tags |
| 148 | end |
| 149 |
|
| 150 | _M.list_refs = function(repo_dir) |
| 151 | local refs = {} |
| 152 | refs.heads = _M.heads(repo_dir) |
| 153 | refs.tags = _M.tags(repo_dir) |
| 154 | return refs |
| 155 | end |
| 156 |
|
| 157 | _M.list_dirs = function(repo_dir, hash, path) |
| 158 | hash = hash or "@" |
| 159 | path = path or "" |
| 160 | local output = git(repo_dir, "ls-tree -d --name-only "..hash.." -- "..path) |
| 161 | local dirs = string.split(output, "\n") |
| 162 | table.remove(dirs, #dirs) -- remove trailing \n |
| 163 | return dirs |
| 164 | end |
| 165 |
|
| 166 | _M.list_all = function(repo_dir, hash, path) |
| 167 | hash = hash or "@" |
| 168 | path = path or "" |
| 169 | local output = git(repo_dir, "ls-tree --name-only "..hash.." -- "..path) |
| 170 | local all = string.split(output, "\n") |
| 171 | table.remove(all, #all) -- remove trailing \n |
| 172 | return all |
| 173 | end |
| 174 |
|
| 175 | _M.list_tree = function(repo_dir, hash, path) |
| 176 | hash = hash or "@" |
| 177 | path = path or "" |
| 178 | local files = _M.list_all(repo_dir, hash, path) |
| 179 | local dirs = _M.list_dirs(repo_dir, hash, path) |
| 180 | local ret = {} |
| 181 | ret.dirs = {} |
| 182 | ret.files = {} |
| 183 | for i,v in pairs(files) do -- iterate over all objects, separate directories from files |
| 184 | local not_dir = true |
| 185 | for _,d in pairs(dirs) do -- check if object is directory |
| 186 | if v == d then |
| 187 | not_dir = false |
| 188 | break |
| 189 | end |
| 190 | end |
| 191 | if not_dir then |
| 192 | table.insert(ret.files, v) |
| 193 | else |
| 194 | local b = v.."/" |
| 195 | table.insert(ret.dirs, b) |
| 196 | end |
| 197 | end |
| 198 | return ret |
| 199 | end |
| 200 |
|
| 201 | return _M |
| 202 |
|