Module:Toolforge images

From Wikitech
Module documentation

Helper module for parsing the image data that's updated by a bot. This is used by Template:Toolforge latest image and others.

local function getData()
	return mw.loadJsonData( 'Module:Toolforge images/data.json' )	
end

local function listImagesFilter( name, data, prefix, hideDeprecated, variant )
	if hideDeprecated ~= "no" and data["state"] == "deprecated" then
		return false
	end
	
	if variant and data["variants"][variant] == nil then
		return false
	end
	
	if name:sub( 1, prefix:len() ) ~= prefix then
		return false
	end

	return true
end

local function listImages( prefix, hideDeprecated, variant )
	prefix = prefix or ""
	hideDeprecated = hideDeprecated or true
	variant = variant or nil
	
	local ret = {}

	for name, data in pairs( getData() ) do
		if listImagesFilter( name, data, prefix, hideDeprecated, variant ) then
			ret[name] = data
		end
	end

	return ret
end

local function versionCompare(a, b)
	-- Compare alphabetic prefix strings
	local aPrefix = mw.ustring.match( a, "^(%a+)" )
	local bPrefix = mw.ustring.match( b, "^(%a+)" )
	if aPrefix ~= bPrefix then
		return aPrefix < bPrefix
	end
	
	-- Compare '.' separated numeric version strings.
	-- Version strings have different semantics than floating point numbers.
    local aNums = mw.text.split( a:sub( aPrefix:len() + 1 ), '.', true )
    local bNums = mw.text.split( b:sub( bPrefix:len() + 1 ), '.', true )
    local limit = math.min(#aNums, #bNums)
    for i=1,math.min(#aNums, #bNums) do
        local aVal = tonumber( aNums[ i ] ) or 0;
        local bVal = tonumber( bNums[ i ] ) or 0;
        if aVal ~= bVal then
        	return aVal < bVal
        end
    end
    return #aNums < #bNums
end

local p = {}

function p.getLatestImage( frame )
	if frame.args[1] == "debian" then
		-- TODO: hack
		return "bookworm"
	end
	
	local images = listImages( frame.args[1], "yes", frame.args[2] )
	local versions = {}
	for n in pairs( images ) do
		table.insert( versions, n )
	end
	table.sort( versions, versionCompare )
	return versions[ #versions ] or "(not found)"
end

function p.generateJobsFrameworkImageTable( frame )
	local tag = "latest"
	local variant = "jobs-framework"

	local images = {}
	local imageKeys = {}
	local longestName = ("Short name"):len()
	local longestImageUrl = ("Container image URL"):len()
	
	local imageUrl = ""

	for name, data in pairs( listImages( "", true, variant ) ) do
		imageUrl = data["variants"][variant]["image"] .. ":" .. tag
		images[name] = imageUrl
		table.insert(imageKeys, name)
		
		if name:len() > longestName then
			longestName = name:len()
		end
		if imageUrl:len() > longestImageUrl then
			longestImageUrl = imageUrl:len()
		end
	end
	
	local data = "Short name"
	if data:len() < longestName then
		data = data .. string.rep( " ", longestName - data:len() )
	end
	
	data = data .. "    Container image URL\n"
	data = data .. string.rep( "-", longestName + 2 )
	data = data .. "  "
	data = data .. string.rep( "-", longestImageUrl )
	data = data .. "\n"
	
	table.sort( imageKeys, versionCompare )
	for _, name in pairs( imageKeys ) do
		data = data .. name
		data = data .. string.rep( " ", longestName - name:len() )
		data = data .. "    "
		data = data .. images[name]
		data = data .. "\n"
	end
	
	return data
end

return p