-- gall.object -- -- Git Abstraction Layer for Lua -- Generic object interface -- -- Copyright 2012 Daniel Silverstone -- -- --- -- Generic object interface -- -- @module gall.object local ll = require "gall.ll" local commit = require "gall.commit" local tree = require "gall.tree" local tag = require "gall.tag" local repos = setmetatable({}, {__mode="k"}) local blobs = setmetatable({}, {__mode="k"}) local known_types = { blob = true, commit = true, tree = true, tag = true, } local function _objectindex(obj, field) local ok, ret local blob = blobs[obj] if field == "type" then if blob then ok, ret = 0, ll.git2.get_object_type(blob) else ok, ret = repos[obj]:gather("cat-file", "-t", obj.sha) end elseif field == "size" then if blob then ok, ret = 0, ll.git2.get_object_size(blob) else ok, ret = repos[obj]:gather("cat-file", "-s", obj.sha) end elseif field == "raw" then if blob and obj.type ~= "tree" then ok, ret = 0, ll.git2.get_object_raw(blob) else ok, ret = repos[obj]:rawgather("cat-file", (obj.type == "tag" and "tag" or "-p"), obj.sha) end elseif field == "content" then assert(known_types[obj.type], "Unknown type: " .. obj.type) if obj.type == "blob" then ok, ret = 0, obj.raw elseif obj.type == "commit" then 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) end else error("Unknown field <" .. tostring(field) .. ">") end assert(ok == 0, "Unable to retrieve " .. field) if field == "size" then ret = tonumber(ret) end rawset(obj, field, ret) return ret end function _objecttostring(obj) return "" end local objectmeta = { __index = _objectindex, __tostring = _objecttostring } --- -- Low level git object -- -- @type object --- -- The type of the object -- -- @field type --- -- The size of the object -- -- @field size --- -- The object's raw content -- -- @field raw --- -- The object's processed content. -- -- * If the object is a commit, then this will be a @{commit} instance. -- * If the object is a tree, then this will be a @{tree} instance. -- * If the object is a tag, then this will be a @{tag} instance. -- -- @field content --- -- The object's OID (SHA1) -- -- @field sha --- @section end --- -- Create a new raw object. -- -- Create a new instance of @{object} referring to the given SHA1 OID. -- -- @function new -- @tparam repository repo The repository within which the object resides. -- @tparam string sha The SHA1 OID of the object in the repository. -- @treturn object The object instance encapsulating the given object. local function _new(repo, sha) local ret = setmetatable({sha=sha}, objectmeta) repos[ret] = repo if ll.git2 then blobs[ret] = ll.git2.get_object(repo.git2.repo, sha) end return ret end --- -- Create a new raw object. -- -- Create a new raw object and insert it into the given repository. This will -- not only create the @{object} instance but also insert it into the -- repository storage. -- -- @function create -- @tparam repository repo The repository within which the object resides. -- @tparam string type The type of the object (e.g. blob or commit) -- @tparam string content The content to insert as the object's content. -- @treturn[1] object The object instance encapsulating the given object. -- @treturn[2] nil Nil on error -- @treturn[2] string The error message local function _create(repo, type, content) local why, sha = repo:_run_with_input(content, ll.chomp, "hash-object", "-t", type, "-w", "--stdin") if why ~= 0 then return nil, "hash-object returned " .. tostring(why) end return _new(repo, sha) end return { new = _new, create = _create, }