|
|
|
#!/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
|
|
|
|
|
|
|
|
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 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 = filename:gsub(version, "{{version}}"):gsub("%%", "%%%%")
|
|
|
|
|
|
|
|
-- 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)
|
|
|
|
regex = regex:gsub("%" .. char, "%%" .. char)
|
|
|
|
end
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
local update_file = download(update_url)
|
|
|
|
if not update_file then
|
|
|
|
print("WARNING: " .. satellite .. ": Failed to download " .. update_url)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- 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("WARNING: " .. satellite .. ": Couldn't retrieve any versions")
|
|
|
|
return
|
|
|
|
elseif not versions[version] then
|
|
|
|
print("WARNING: " .. satellite .. ": Current version isn't available")
|
|
|
|
end
|
|
|
|
|
|
|
|
return versions
|
|
|
|
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 = 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(satellite .. ": First check")
|
|
|
|
version_file = io.open(version_file_path, "w")
|
|
|
|
assert(version_file, "Failed to create " .. version_file_path)
|
|
|
|
end
|
|
|
|
|
|
|
|
for version, _ in pairs(versions) do
|
|
|
|
if old_versions then
|
|
|
|
if not old_versions[version] then
|
|
|
|
print(satellite .. ": " .. version)
|
|
|
|
version_file:write(version .. "\n")
|
|
|
|
end
|
|
|
|
else
|
|
|
|
print(satellite .. ": " .. version)
|
|
|
|
version_file:write(version .. "\n")
|
|
|
|
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 = io.popen("find " .. satellite_dir .. " -type f -name '*.sat' -printf '%P\n'")
|
|
|
|
assert(find, "Failed to run find")
|
|
|
|
|
|
|
|
for satellite in find:lines() do
|
|
|
|
local version_file = version_dir .. "/" .. satellite
|
|
|
|
if os.execute("mkdir -p " .. version_file:match("^.+/")) then
|
|
|
|
check_new_versions(satellite, version_file)
|
|
|
|
else
|
|
|
|
print("Failed to create dir for " .. satellite)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
show_help()
|
|
|
|
os.exit(1)
|
|
|
|
end
|