1 | -- resty-gitweb@git/find_rev.lua |
2 | -- Finds and formats a revision by name |
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 git2_error = require("git/git2_error") |
10 |
|
11 | local _M = function(repo_obj, rev) |
12 | local err = 0 |
13 | rev = rev or "HEAD" |
14 |
|
15 | -- Get object/reference |
16 | local object = ffi.new("git_object*[1]") |
17 | local reference = ffi.new("git_reference*[1]") |
18 | err = git2.git_revparse_ext(ffi.cast("git_object**", object), ffi.cast("git_reference**", reference), repo_obj, ref_name) |
19 | git2_error(err, "Failed to find reference") |
20 | object = object[0] |
21 | reference = reference[0] |
22 |
|
23 | -- Get full name if intermediate reference exists |
24 | local name = rev |
25 | if reference ~= nil then |
26 | local ref_type = git2.git_reference_type(reference) |
27 | if ref_type == git2.GIT_REFERENCE_SYMBOLIC then |
28 | name = ffi.string(git2.git_reference_symbolic_target(reference)) |
29 | elseif ref_type == git2.GIT_REFERENCE_DIRECT then |
30 | name = ffi.string(git2.git_reference_name(reference)) |
31 | end |
32 | end |
33 |
|
34 | -- Get OID |
35 | local oid = git2.git_object_id(object) |
36 |
|
37 | -- Format oid as SHA1 hash |
38 | local hash = ffi.new("char[41]") -- SHA1 length (40 chars) + \0 |
39 | err = git2.git_oid_fmt(hash, oid) |
40 | git2_error(err, "Failed formatting OID") |
41 | hash = ffi.string(hash) |
42 |
|
43 | local shorthash_buf = ffi.new("git_buf") |
44 | err = git2.git_object_short_id(shorthash_buf, object) |
45 | git2_error(err, "Failed to calculate short id for object") |
46 | shorthash = ffi.string(shorthash_buf.ptr) |
47 |
|
48 | -- Free all |
49 | git2.git_buf_free(shorthash_buf) |
50 | git2.git_object_free(object) |
51 | if reference ~= nil then |
52 | git2.git_reference_free(reference) |
53 | end |
54 |
|
55 | -- Format |
56 | local ref = {} |
57 | ref.full = name |
58 | if name:match("^refs/heads/") then |
59 | ref.name = string.sub(name, 12, string.len(name)) |
60 | elseif name:match("^refs/tags/") then |
61 | ref.name = string.sub(name, 11, string.len(name)) |
62 | else |
63 | if rev == hash then -- input was 40-digit hex |
64 | ref.name = shorthash |
65 | else -- fallback |
66 | ref.name = rev -- just pass input as default output |
67 | end |
68 | end |
69 | ref.hash = hash |
70 | ref.shorthash = shorthash |
71 |
|
72 | return ref |
73 | end |
74 |
|
75 | return _M |
76 |
|