Was supposed to be a linux distribution, now just a collection of build scripts for packages on top of (ideally) any distribution.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
7.0 KiB

#!/usr/bin/env lua
function show_help()
print(string.format([[This program will help you keep your satellites fresh and up to date.
Usage: %s <sat|dir> <check> <save>
sat = Check only one satellite
dir = Check a dir full of satellites
check = What file (sat) or directory (dir) to check
save = What file (sat) or directory (dir) to save known versions into]], arg[0]))
end
-- Shamelessly stolen from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua
function spairs(t)
-- collect the keys
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
table.sort(keys)
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
function call(command)
--[[--
-- Runs a command, returns all output except trailing newline on success.
--]]--
local pipe = io.popen(command)
if pipe then
local output = pipe:read("*all")
if pipe:close() then
if #output > 0 then
return output:match("(.-)%s*$")
end
end
end
end
function astrohelp(satellite, func)
-- satellite_dir is an example of me being lazy and wanting to keep output clean in other functions.
if satellite_dir then
return call("astrohelp '" .. satellite_dir .. "/" .. satellite .. "' " .. func)
else
return call("astrohelp '" .. satellite .. "' " .. func)
end
end
function download(url)
return call("curl -Ls '" .. url .. "'")
end
function escape_regex(string)
-- http://www.lua.org/manual/5.3/manual.html#6.4.1
local magic = "^$().[]*+-?"
for i = 1, #magic do
local char = magic:sub(i, i)
string = string:gsub("%" .. char, "%%" .. char)
end
return string
end
function make_regex(filename, version)
--[[--
-- Converts a string into regex, by escaping all special (magic) characters.
-- Returns two regexes, meant to be used in a loop. (See code using this function to know what I mean)
--]]--
local regex = escape_regex(filename:gsub(escape_regex(version), "{{version}}"):gsub("%%", "%%%%"))
return regex:gsub("{{version}}", "(.-") .. ")", regex:gsub(".*{{version}}", "(.-)")
end
function get_available_versions(satellite)
--[[--
-- Returns a set table containing all available versions on update_url
--]]--
local version = astrohelp(satellite, "variable version")
local update_url = astrohelp(satellite, "variable update_url")
if not version or not update_url then
return
end
io.write("\x1B[1K\r" .. satellite .. ": Downloading update file...")
local update_file = download(update_url)
if not update_file then
print("\x1B[1K\rWARNING: " .. satellite .. ": Failed to download " .. update_url)
return
end
io.write("\x1B[1K\r" .. satellite .. ": Getting available versions...")
-- Try getting variable update_names, get downloads otherwise.
local update_names = astrohelp(satellite, "variable update_names")
if not update_names then
local tmp_update_names = astrohelp(satellite, "downloads")
assert(tmp_update_names, "Could not get update names for " .. satellite)
update_names = ""
-- Take the basename of every download url
for name in tmp_update_names:gmatch("[^\n]+") do
update_names = update_names .. name:match("[^/]+$") .. ","
end
end
local versions = {}
local count = 0
for update_name in update_names:gmatch("[^,]+") do
local loop_regex, end_regex = make_regex(update_name, version)
for x in update_file:gmatch(loop_regex) do
-- Sometimes, the match starts way too soon, and we get a very long "version" number.
-- Here we make sure we really get the shortest possible match.
local version
repeat
version = x
x = x:match(loop_regex)
until not x
version = version:match(end_regex)
versions[version] = true
count = count + 1
end
end
if count < 1 then
print("\x1B[1K\rWARNING: " .. satellite .. ": Couldn't retrieve any versions")
return
elseif not versions[version] then
print("\x1B[1K\rWARNING: " .. satellite .. ": Current version isn't available")
end
return versions, update_url
end
function check_new_versions(satellite, version_file_path)
--[[--
-- Check if new versions are available for a satellite.
-- Logs new versions to log_file, which should be a file descriptor.
-- Uses version_file_path to know where to store all known versions.
--]]--
local versions, update_url = get_available_versions(satellite)
if not versions then
return
end
local version_file = io.open(version_file_path, "r+")
local old_versions = nil
if version_file then
old_versions = {}
for version in version_file:lines() do
old_versions[version] = true
end
else
print("\x1B[1K\r" .. satellite .. ": First check")
version_file = io.open(version_file_path, "w")
assert(version_file, "Failed to create " .. version_file_path)
end
local new_versions = {}
if old_versions then
for version, _ in spairs(versions) do
if not old_versions[version] then
table.insert(new_versions, version)
end
end
else
for version, _ in spairs(versions) do
table.insert(new_versions, version)
end
end
if #new_versions > 0 then
print("\x1B[1K\r" .. satellite .. ": From '" .. update_url .. "'")
for _, version in ipairs(new_versions) do
version_file:write(version .. "\n")
print("\x1B[1K\r" .. satellite .. ": " .. version)
end
end
version_file:close()
end
if #arg < 3 then
show_help()
os.exit(1)
end
if arg[1] == "sat" then
check_new_versions(arg[2], arg[3])
elseif arg[1] == "dir" then
satellite_dir = arg[2]
local version_dir = arg[3]
assert(os.execute("mkdir -p " .. version_dir), "Failed to create " .. version_dir)
local find = call("find " .. satellite_dir .. " -type f -name '*.sat' -printf '%P\n'")
assert(find, "Failed to run find")
local total = select(2, find:gsub("\n", "\n"))
local cols = call("tput cols")
local count = 1
for satellite in find:gmatch("(.-)\n") do
if cols then
cols = tonumber(cols)
local countstr = tostring(count) .. "/" .. tostring(total)
io.write("\r")
for i = 1, cols - countstr:len() - 1 do
io.write(" ")
end
io.write(countstr .. "\r")
end
local version_file = version_dir .. "/" .. satellite
assert(os.execute("mkdir -p " .. version_file:match("^.+/")), "Failed to create dir for " .. satellite)
check_new_versions(satellite, version_file)
count = count + 1
end
else
show_help()
os.exit(1)
end