|
|
396caf |
-- Lua code used by macros.forge and derivatives
|
|
|
396caf |
|
|
|
396caf |
-- Computes the suffix of a version string, removing vprefix if it matches
|
|
|
396caf |
-- For example with vprefix 1.2.3: 1.2.3.rc2 → .rc2 but 1.2.30 → 1.2.30 not 0
|
|
|
396caf |
local function getversionsuffix(vstring,vprefix)
|
|
|
396caf |
if (string.sub(vstring, 1, #vprefix) == vprefix) and
|
|
|
396caf |
(not string.match(string.sub(vstring, #vprefix + 1), "^%.?%d")) then
|
|
|
396caf |
return string.sub(vstring, #vprefix + 1)
|
|
|
396caf |
else
|
|
|
396caf |
return vstring
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
|
|
|
396caf |
-- Check if an identified url is sane
|
|
|
396caf |
local function checkforgeurl(url, id, silent)
|
|
|
396caf |
local checkedurl = nil
|
|
|
396caf |
local checkedid = nil
|
|
|
396caf |
local urlpatterns = {
|
|
|
396caf |
gitlab = {
|
|
|
396caf |
pattern = 'https://[^/]+/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://(…[-.])gitlab[-.]…/owner/repo'},
|
|
|
396caf |
pagure = {
|
|
|
396caf |
pattern = 'https://[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://pagure.io/repo'},
|
|
|
396caf |
pagure_ns = {
|
|
|
396caf |
pattern = 'https://[^/]+/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://pagure.io/namespace/repo'},
|
|
|
396caf |
pagure_fork = {
|
|
|
396caf |
pattern = 'https://[^/]+/fork/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://pagure.io/fork/owner/repo'},
|
|
|
396caf |
pagure_ns_fork = {
|
|
|
396caf |
pattern = 'https://[^/]+/fork/[^/]+/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://pagure.io/fork/owner/namespace/repo'},
|
|
|
396caf |
["gitea.com"] = {
|
|
|
396caf |
pattern = 'https://[^/]+/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://gitea.com/owner/repo'},
|
|
|
396caf |
github = {
|
|
|
396caf |
pattern = 'https://[^/]+/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://(…[-.])github[-.]…/owner/repo'},
|
|
|
396caf |
["code.googlesource.com"] = {
|
|
|
396caf |
pattern = 'https://code.googlesource.com/[^#?]*[^/#?]+',
|
|
|
396caf |
description = 'https://code.googlesource.com/…/repo'},
|
|
|
396caf |
["bitbucket.org"] = {
|
|
|
396caf |
pattern = 'https://[^/]+/[^/]+/[^/#?]+',
|
|
|
396caf |
description = 'https://bitbucket.org/owner/repo'}}
|
|
|
396caf |
if (urlpatterns[id] ~= nil) then
|
|
|
396caf |
checkedurl = string.match(url,urlpatterns[id]["pattern"])
|
|
|
396caf |
if (checkedurl == nil) then
|
|
|
396caf |
if not silent then
|
|
|
396caf |
rpm.expand("%{error:" .. id .. " URLs must match " .. urlpatterns[id]["description"] .. " !}")
|
|
|
396caf |
end
|
|
|
396caf |
else
|
|
|
396caf |
checkedid = id
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
return checkedurl, checkedid
|
|
|
396caf |
end
|
|
|
396caf |
|
|
|
396caf |
-- Check if an url matches a known forge
|
|
|
396caf |
local function idforge(url, silent)
|
|
|
396caf |
local forgeurl = nil
|
|
|
396caf |
local forge = nil
|
|
|
396caf |
if (url ~= "") then
|
|
|
396caf |
forge = string.match(url, "^[^:]+://([^/]+)/")
|
|
|
396caf |
if (forge == nil) then
|
|
|
396caf |
if not silent then
|
|
|
396caf |
rpm.expand("%{error:URLs must include a protocol such as https:// and a path starting with / !}")
|
|
|
396caf |
end
|
|
|
396caf |
else
|
|
|
396caf |
if (forge == "pagure.io") then
|
|
|
396caf |
if string.match(url, "[^:]+://pagure.io/fork/[^/]+/[^/]+/[^/]+") then
|
|
|
396caf |
forge = "pagure_ns_fork"
|
|
|
396caf |
elseif string.match(url, "[^:]+://pagure.io/fork/[^/]+/[^/]+") then
|
|
|
396caf |
forge = "pagure_fork"
|
|
|
396caf |
elseif string.match(url, "[^:]+://pagure.io/[^/]+/[^/]+") then
|
|
|
396caf |
forge = "pagure_ns"
|
|
|
396caf |
elseif string.match(url, "[^:]+://pagure.io/[^/]+") then
|
|
|
396caf |
forge = "pagure"
|
|
|
396caf |
end
|
|
|
396caf |
elseif (string.match(forge, "^gitlab[%.-]") or string.match(forge, "[%.-]gitlab[%.]")) then
|
|
|
396caf |
forge = "gitlab"
|
|
|
396caf |
elseif (string.match(forge, "^github[%.-]") or string.match(forge, "[%.-]github[%.]")) then
|
|
|
396caf |
forge = "github"
|
|
|
396caf |
end
|
|
|
396caf |
forgeurl, forge = checkforgeurl(url, forge, silent)
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
return forgeurl, forge
|
|
|
396caf |
end
|
|
|
396caf |
|
|
|
396caf |
-- The forgemeta macro main processing function
|
|
|
396caf |
-- See the documentation in the macros.forge file for argument description
|
|
|
396caf |
-- Also called directly by gometa
|
|
|
396caf |
local function meta(suffix, verbose, informative, silent)
|
|
|
396caf |
local fedora = require "fedora.common"
|
|
|
396caf |
local ismain = (suffix == "") or (suffix == "0")
|
|
|
396caf |
if ismain then
|
|
|
396caf |
fedora.zalias({"forgeurl", "forgesource", "forgesetupargs",
|
|
|
396caf |
"archivename", "archiveext", "archiveurl",
|
|
|
396caf |
"topdir", "extractdir", "repo", "owner", "namespace",
|
|
|
396caf |
"scm", "tag", "commit", "shortcommit", "branch", "version",
|
|
|
396caf |
"date", "distprefix"}, verbose)
|
|
|
396caf |
end
|
|
|
396caf |
local variables = {
|
|
|
396caf |
default = {
|
|
|
396caf |
scm = "git",
|
|
|
396caf |
archiveext = "tar.bz2",
|
|
|
396caf |
repo = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/[^/]+/([^/?#]+)"))}',
|
|
|
396caf |
archivename = "%{repo" .. suffix .. "}-%{ref" .. suffix .. "}",
|
|
|
396caf |
topdir = "%{archivename" .. suffix .. "}" },
|
|
|
396caf |
gitlab = {
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/-/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },
|
|
|
396caf |
pagure = {
|
|
|
396caf |
archiveext = "tar.gz",
|
|
|
396caf |
repo = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/([^/?#]+)"))}',
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },
|
|
|
396caf |
pagure_ns = {
|
|
|
396caf |
archiveext = "tar.gz",
|
|
|
396caf |
namespace = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/([^/]+)/[^/?#]+"))}',
|
|
|
396caf |
repo = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/[^/]+/([^/?#]+)"))}',
|
|
|
396caf |
archivename = "%{namespace" .. suffix .. "}-%{repo" .. suffix .. "}-%{ref" .. suffix .. "}",
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },
|
|
|
396caf |
pagure_fork = {
|
|
|
396caf |
archiveext = "tar.gz",
|
|
|
396caf |
owner = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/([^/]+)/[^/?#]+"))}',
|
|
|
396caf |
repo = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/[^/]+/([^/?#]+)"))}',
|
|
|
396caf |
archivename = "%{owner" .. suffix .. "}-%{repo" .. suffix .. "}-%{ref" .. suffix .. "}",
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },
|
|
|
396caf |
pagure_ns_fork = {
|
|
|
396caf |
owner = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/([^/]+)/[^/]+/[^/?#]+"))}',
|
|
|
396caf |
namespace = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/[^/]+/([^/]+)/[^/?#]+")}',
|
|
|
396caf |
repo = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/[^/]+/[^/]+/([^/?#]+)")}',
|
|
|
396caf |
archivename = "%{owner" .. suffix .. "}-%{namespace" .. suffix .. "}-%{repo" .. suffix .. "}-%{ref" .. suffix .. "}",
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },
|
|
|
396caf |
["gitea.com"] = {
|
|
|
396caf |
archiveext = "tar.gz",
|
|
|
396caf |
archivename = "%{fileref" .. suffix .. "}",
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/archive/%{ref" .. suffix .. "}.%{archiveext" .. suffix .. "}",
|
|
|
396caf |
topdir = "%{repo}" },
|
|
|
396caf |
github = {
|
|
|
396caf |
archiveext = "tar.gz",
|
|
|
396caf |
archivename = "%{repo" .. suffix .. "}-%{fileref" .. suffix .. "}",
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },
|
|
|
396caf |
["code.googlesource.com"] = {
|
|
|
396caf |
archiveext = "tar.gz",
|
|
|
396caf |
repo = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://.+/([^/?#]+)"))}',
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/+archive/%{ref" .. suffix .. "}.%{archiveext" .. suffix .. "}",
|
|
|
396caf |
topdir = "" },
|
|
|
396caf |
["bitbucket.org"] = {
|
|
|
396caf |
shortcommit = '%{lua:print(string.sub(rpm.expand("%{commit' .. suffix .. '}"), 1, 12))}',
|
|
|
396caf |
owner = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/([^/?#]+)"))}',
|
|
|
396caf |
archivename = "%{owner" .. suffix .. "}-%{repo" .. suffix .. "}-%{shortcommit" .. suffix .. "}",
|
|
|
396caf |
archiveurl = "%{forgeurl" .. suffix .. "}/get/%{ref" .. suffix .. "}.%{archiveext" .. suffix .. "}" } }
|
|
|
396caf |
-- Packaging a moving branch is quite a bad idea, but since at least Gitlab
|
|
|
396caf |
-- will treat branches and tags the same way better support branches explicitly
|
|
|
396caf |
-- than have packagers hijack %{tag} to download branch states
|
|
|
396caf |
local spec = {}
|
|
|
396caf |
for _, v in ipairs({'forgeurl','tag','commit','branch','version'}) do
|
|
|
396caf |
spec[v] = rpm.expand("%{?" .. v .. suffix .. "}")
|
|
|
396caf |
end
|
|
|
396caf |
-- Compute the reference of the object to fetch
|
|
|
396caf |
local isrelease = false
|
|
|
396caf |
if (spec["tag"] ~= "") then ref = "%{?tag" .. suffix .. "}"
|
|
|
396caf |
elseif (spec["commit"] ~= "") then ref = "%{?commit" .. suffix .. "}"
|
|
|
396caf |
elseif (spec["branch"] ~= "") then ref = "%{?branch" .. suffix .. "}"
|
|
|
396caf |
else ref = "%{?version" .. suffix .. "}"
|
|
|
396caf |
isrelease = true
|
|
|
396caf |
end
|
|
|
396caf |
if (rpm.expand(ref) == "") then
|
|
|
396caf |
if (suffix == "") then
|
|
|
396caf |
rpm.expand("%{error:You need to define Version:, %{commit} or %{tag} before the macro invocation !}")
|
|
|
396caf |
else
|
|
|
396caf |
rpm.expand("%{error:You need to define %{version" .. suffix .. "}, %{commit" .. suffix .. "} or %{tag" .. suffix .. "} before the macro invocation !}")
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
local forgeurl = spec["forgeurl"]
|
|
|
396caf |
-- For backwards compatibility only
|
|
|
396caf |
local expliciturl = rpm.expand("%{?-u*}")
|
|
|
396caf |
if (expliciturl ~= "") then
|
|
|
396caf |
rpm.expand("%{warn:-u use in %%forgemeta is deprecated, use -z instead to select a separate set of rpm variables!}")
|
|
|
396caf |
forgeurl = expliciturl
|
|
|
396caf |
end
|
|
|
396caf |
local forge
|
|
|
396caf |
forgeurl, forge = idforge(forgeurl, silent)
|
|
|
396caf |
if (forge ~= nil) then
|
|
|
396caf |
fedora.explicitset("forgeurl" .. suffix, forgeurl, verbose)
|
|
|
396caf |
-- Custom processing of quirky forges that can not be handled with simple variables
|
|
|
396caf |
if (forge == "github") then
|
|
|
396caf |
-- Workaround the way GitHub injects "v"s before some version strings (but not all!)
|
|
|
396caf |
-- To package one of the minority of sane GitHub projects that do not munge their version
|
|
|
396caf |
-- strings set tag to %{version} in your spec
|
|
|
396caf |
local fileref = ref
|
|
|
396caf |
if (ref == "%{?version" .. suffix .. "}") then
|
|
|
396caf |
ref = "v" .. ref
|
|
|
396caf |
elseif (fileref ~= "%{?commit" .. suffix .. "}") and
|
|
|
396caf |
string.match(rpm.expand(fileref), "^v[%d]") then
|
|
|
396caf |
fileref = string.gsub(rpm.expand(fileref), "^v", "")
|
|
|
396caf |
elseif (string.match(rpm.expand(fileref), "/")) then
|
|
|
396caf |
fileref = string.gsub(rpm.expand(fileref), "/", "-")
|
|
|
396caf |
end
|
|
|
396caf |
fedora.safeset("fileref" .. suffix, fileref, verbose)
|
|
|
396caf |
elseif (forge == "gitea.com") then
|
|
|
396caf |
-- Workaround the way gitea mangles /s in ref names
|
|
|
396caf |
local fileref = ref
|
|
|
396caf |
fileref = string.gsub(rpm.expand(fileref), "/", "-")
|
|
|
396caf |
fedora.safeset("fileref" .. suffix, fileref, verbose)
|
|
|
396caf |
elseif (forge == "code.googlesource.com") then
|
|
|
396caf |
if (ref == "%{?version" .. suffix .. "}") then
|
|
|
396caf |
ref = "v" .. ref
|
|
|
396caf |
end
|
|
|
396caf |
elseif (forge == "bitbucket.org") then
|
|
|
396caf |
if (spec["commit"] == "") then
|
|
|
396caf |
rpm.expand("%{error:All BitBucket URLs require commit value knowledge: you need to define %{commit}!}")
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
fedora.safeset("ref" .. suffix, ref, verbose)
|
|
|
396caf |
-- Mass setting of the remaining variables
|
|
|
396caf |
for k,v in pairs(variables[forge]) do
|
|
|
396caf |
fedora.safeset(k .. suffix, variables[forge][k], verbose)
|
|
|
396caf |
end
|
|
|
396caf |
for k,v in pairs(variables["default"]) do
|
|
|
396caf |
if (variables[forge][k] == nil) then
|
|
|
396caf |
fedora.safeset(k .. suffix, variables["default"][k], verbose)
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
-- Generic rules
|
|
|
396caf |
for _, v in ipairs({'archiveurl','archivename','archiveext','topdir'}) do
|
|
|
396caf |
spec[v] = rpm.expand("%{?" .. v .. suffix .. "}")
|
|
|
396caf |
end
|
|
|
396caf |
-- Source URL processing (computing the forgesource spec variable)
|
|
|
396caf |
local forgesource = "%{archiveurl" .. suffix .. "}"
|
|
|
396caf |
if (string.match(spec["archiveurl"], "/([^/]+)$") ~= spec["archivename"] .. "." .. spec["archiveext"]) then
|
|
|
396caf |
forgesource = "%{?archiveurl" .. suffix .. "}#/%{?archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}"
|
|
|
396caf |
end
|
|
|
396caf |
fedora.safeset("forgesource" .. suffix, forgesource, verbose)
|
|
|
396caf |
-- Setup processing (computing the forgesetup and extractdir variables)
|
|
|
396caf |
local forgesetupargs = "-n %{extractdir" .. suffix .. "}"
|
|
|
396caf |
local extractdir = "%{topdir" .. suffix .. "}"
|
|
|
396caf |
if (spec["topdir"] == "") then
|
|
|
396caf |
forgesetupargs = "-c " .. forgesetupargs
|
|
|
396caf |
extractdir = "%{archivename" .. suffix .. "}"
|
|
|
396caf |
end
|
|
|
396caf |
if not ismain then
|
|
|
396caf |
if (spec["topdir"] ~= "") then
|
|
|
396caf |
forgesetupargs = "-T -D -b " .. suffix .. " " .. forgesetupargs
|
|
|
396caf |
else
|
|
|
396caf |
forgesetupargs = "-T -D -a " .. suffix .. " " .. forgesetupargs
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
fedora.safeset("forgesetupargs" .. suffix, forgesetupargs, verbose)
|
|
|
396caf |
fedora.safeset("extractdir" .. suffix, extractdir, verbose)
|
|
|
396caf |
-- dist processing (computing the correct prefix for snapshots)
|
|
|
396caf |
local distprefix = ""
|
|
|
396caf |
if not isrelease then
|
|
|
396caf |
distprefix = string.lower(rpm.expand(ref))
|
|
|
396caf |
if (ref == "%{?commit" .. suffix .. "}") then
|
|
|
396caf |
distprefix = string.sub(distprefix, 1, 7)
|
|
|
396caf |
elseif (ref ~= "%{?branch" .. suffix .. "}") then
|
|
|
396caf |
distprefix = string.gsub(distprefix, "[%p%s]+", ".")
|
|
|
396caf |
distprefix = string.gsub(distprefix, "^" .. string.lower(rpm.expand("%{?repo}")) .. "%.?", "")
|
|
|
396caf |
local v = string.gsub(rpm.expand("%{version}"), "[%p%s]+", ".")
|
|
|
396caf |
for _, p in ipairs({'','v','v.','version','version.','tags.v', 'tags.v.'}) do
|
|
|
396caf |
distprefix = getversionsuffix(distprefix, p .. v)
|
|
|
396caf |
end
|
|
|
396caf |
distprefix = string.gsub(distprefix, "^%.", "")
|
|
|
396caf |
end
|
|
|
396caf |
if (distprefix ~= "") then
|
|
|
396caf |
distprefix = "%{scm" .. suffix .. "}" .. distprefix
|
|
|
396caf |
date = rpm.expand("%{?date" .. suffix .. "}")
|
|
|
396caf |
if (date ~= "") then
|
|
|
396caf |
distprefix = date .. distprefix
|
|
|
396caf |
else
|
|
|
396caf |
distprefix = "%([ -r %{_sourcedir}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "} ] && date +%Y%m%d -u -r %{_sourcedir}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "})" .. distprefix
|
|
|
396caf |
end
|
|
|
396caf |
distprefix = "." .. distprefix
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
if (spec["version"] ~= "") and
|
|
|
396caf |
(spec["version"] ~= "0") and
|
|
|
396caf |
(spec["version"] ~= rpm.expand("%{?version}")) then
|
|
|
396caf |
distprefix = ".%{version" .. suffix .. "}" .. distprefix
|
|
|
396caf |
end
|
|
|
396caf |
if (rpm.expand(distprefix) ~= "") then
|
|
|
396caf |
if not ismain then
|
|
|
396caf |
distprefix = string.gsub(distprefix, "^%.", ".s")
|
|
|
396caf |
end
|
|
|
396caf |
fedora.safeset ("distprefix" .. suffix, distprefix, verbose)
|
|
|
396caf |
end
|
|
|
396caf |
if ismain then
|
|
|
396caf |
fedora.zalias({"forgeurl", "forgesource", "forgesetupargs",
|
|
|
396caf |
"archivename", "archiveext", "archiveurl",
|
|
|
396caf |
"topdir", "extractdir", "repo", "owner", "namespace",
|
|
|
396caf |
"scm", "shortcommit", "distprefix"}, verbose)
|
|
|
396caf |
end
|
|
|
396caf |
-- Final spec variable summary if the macro was called with -i
|
|
|
396caf |
if informative then
|
|
|
396caf |
rpm.expand("%{echo:Packaging variables read or set by %%forgemeta}")
|
|
|
396caf |
fedora.echovars({"forgeurl", "forgesource", "forgesetupargs",
|
|
|
396caf |
"archivename", "archiveext", "archiveurl",
|
|
|
396caf |
"topdir", "extractdir", "repo", "owner", "namespace",
|
|
|
396caf |
"scm", "tag", "commit", "shortcommit", "branch", "version",
|
|
|
396caf |
"date", "distprefix"}, suffix)
|
|
|
396caf |
fedora.echovars({"dist"},"")
|
|
|
396caf |
rpm.expand("%{echo: (snapshot date is either manually supplied or computed once %%{_sourcedir}/%%{archivename" .. suffix .. "}.%%{archiveext" .. suffix .. "} is available)}")
|
|
|
396caf |
end
|
|
|
396caf |
end
|
|
|
396caf |
|
|
|
396caf |
return {
|
|
|
396caf |
meta = meta,
|
|
|
396caf |
}
|
|
|
396caf |
|