summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2012-05-29 22:18:26 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2012-05-29 22:18:26 +0100
commit3bfd0792bf1011b76db07aeba5f5c6903ed9bd60 (patch)
treecde4c2a9c890f638bc6367b2275d207ec53475f6
parentbf37f704704f524276ac1bfaab87dd3ac2d5d807 (diff)
downloadgitano-3bfd0792bf1011b76db07aeba5f5c6903ed9bd60.tar.gz
GIT: Add annotated tag support
-rw-r--r--lib/gitano/git.lua2
-rw-r--r--lib/gitano/git/object.lua3
-rw-r--r--lib/gitano/git/tag.lua97
3 files changed, 102 insertions, 0 deletions
diff --git a/lib/gitano/git.lua b/lib/gitano/git.lua
index ee1edf0..f77e0bd 100644
--- a/lib/gitano/git.lua
+++ b/lib/gitano/git.lua
@@ -11,6 +11,7 @@ local object = require "gitano.git.object"
local commit = require "gitano.git.commit"
local tree = require "gitano.git.tree"
local repo = require "gitano.git.repository"
+local tag = require "gitano.git.tag"
return {
@@ -21,6 +22,7 @@ return {
object = object,
commit = commit,
tree = tree,
+ tag = tag,
-- Finally LL
ll = ll
} \ No newline at end of file
diff --git a/lib/gitano/git/object.lua b/lib/gitano/git/object.lua
index 7858bcb..a6c32a8 100644
--- a/lib/gitano/git/object.lua
+++ b/lib/gitano/git/object.lua
@@ -9,6 +9,7 @@
local ll = require "gitano.git.ll"
local commit = require "gitano.git.commit"
local tree = require "gitano.git.tree"
+local tag = require "gitano.git.tag"
local repos = setmetatable({}, {__mode="k"})
@@ -27,6 +28,8 @@ local function _objectindex(obj, field)
ok, ret = 0, commit.new(repos[obj], obj)
elseif obj.type == "tree" then
ok, ret = 0, tree.new(repos[obj], obj)
+ elseif obj.type == "tag" then
+ ok, ret = 0, tag.new(repos[obj], obj)
else
error("Unknown type <" .. obj.type .. "> for content parse")
end
diff --git a/lib/gitano/git/tag.lua b/lib/gitano/git/tag.lua
new file mode 100644
index 0000000..4c07691
--- /dev/null
+++ b/lib/gitano/git/tag.lua
@@ -0,0 +1,97 @@
+-- gitano.git.tag
+--
+-- Core Git functionality for Gitano
+--
+-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
+--
+--
+
+local ll = require "gitano.git.ll"
+
+local objs = setmetatable({}, {__mode="k"})
+local repos = setmetatable({}, {__mode="k"})
+local parsed = setmetatable({}, {__mode="k"})
+
+local _new
+
+local function parse_person(pers)
+ local real, email, when, tz = pers:match("^(.-) <([^>]+)> ([0-9]+) ([+-][0-9]+)$")
+ return {
+ realname = real,
+ email = email,
+ unixtime = when,
+ timezone = tz
+ }
+end
+
+local function tagindex(tag, field)
+ if not parsed[tag] then
+ local raw = objs[tag].raw
+ local headers, body, signature = {}, ""
+ local state = "headers"
+
+ for l in raw:gmatch("([^\n]*)\n") do
+ if state == "headers" then
+ local first, second = l:match("^([^ ]+) (.+)$")
+ if first then
+ if headers[first] then
+ headers[first][#headers[first]+1] = second
+ else
+ headers[first] = { second }
+ end
+ else
+ state = "message"
+ end
+ elseif state == "message" then
+ if l == PGP_SIG_START then
+ signature = l .. "\n"
+ state = "signature"
+ else
+ body = body .. l .. "\n"
+ end
+ else
+ signature = signature .. l .. "\n"
+ end
+ end
+
+ -- there's always one object
+ rawset(tag, "object", repos[tag]:get(headers.object[1]))
+ -- Always one type
+ rawset(tag, "type", headers.type[1])
+ -- Always one tag name
+ rawset(tag, "tag", headers.tag[1])
+ -- Always one tagger
+ rawset(tag, "tagger", parse_person(headers.tag[1]))
+ -- A message
+ rawset(tag, "message", body)
+ -- And an optional signature
+ rawset(tag, "signature", signature)
+ -- Promote the SHA
+ rawset(tag, "sha", objs[tag].sha)
+
+ -- Signal we are parsed
+ parsed[tag] = true
+ end
+
+ return rawget(tag, field)
+end
+
+local function tagtostring(tag)
+ return "<GitTag(" .. tostring(objs[tag].sha) .. ") in " .. tostring(repos[tag]) .. ">"
+end
+
+local tagmeta = {
+ __index = tagindex,
+ __tostring = tagtostring
+}
+
+function _new(repo, obj)
+ local ret = setmetatable({}, tagmeta)
+ objs[ret] = obj
+ repos[ret] = repo
+ return ret
+end
+
+return {
+ new = _new
+}