Files
eat-it/eatit.lua
Squibid 6f091a7648 Major changes!
- add name expansion gh:po5/thumbfast -> https://github.com/po5/thumbfast
- allow multiple files to be downloaded to one dir
- add pin option to stop updates on specific plugins
2023-10-17 22:03:41 -04:00

222 lines
5.7 KiB
Lua

--[[
Eat It - a Mpv plugin manager
Copyright © 2023 squibid
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
]]
local mp = require('mp')
-- load the config file
dofile(mp.command_native({'expand-path', '~~/eatit-cfg.lua'}))
-- helper functions --
local function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
local function fileexists(name)
local ok, err, code = os.rename(name, name)
if not ok then
if code == 13 then
-- Permission denied, but it exists
return true
end
end
return ok, err
end
local function testforslash(str)
if string.match(str, '/') then
return string.match(str, '/([^/]+)$')
else
return str
end
end
local function run(cmd)
local x = io.popen(cmd)
if not x then return 1 end
local y = x:read("*a")
x:close()
return y
end
local function cp(a, b)
local i = io.open(a, 'r')
if not i then return 1 end
local o = io.open(b, 'w')
if not o then return 2 end
o:write(i:read('*a'))
o:close()
i:close()
end
local function getsrc(id)
local src
if string.find(id, ":") then src = id:match("^[a-z]+[^:]") end
local name = id:match([[[^:]*$]])
if name then
local pre = opts.nameexp.pre or "https://"
local map = opts.nameexp.map or {
gl = 'gitlab.com',
cb = 'codeberg.org',
sr = 'sr.ht',
gh = 'github.com'
}
return {
link = (pre..map[src]) or false,
repo = name
}
end
end
local function openlog()
if opts.logging.log then -- log if asked to
-- get our logfile's full path
fn = mp.command_native({'expand-path', opts.logging.logfile})
f = io.open(fn, 'a') -- open file buffer
if not f then return 1 end
io.output(f) -- set it as default
end
end
local function logwrite(string)
if opts.logging.log then
io.write(os.date(opts.logging.logdate)..' '..string..'\n')
end
end
local function closelog()
if opts.logging.log then
io.close(f)
end
end
-- get the requested git repos
local function clonegit(plugdir, url, branch)
logwrite('downloading '..url)
-- clone the repo
-- BUG: logwriting the git command doesn't actually log the output
run('git -C '..opts.dl.dir..' clone '..url..' '..plugdir)
run('git -C '..plugdir..' checkout -q '..branch)
end
-- check for updates
local function checkupdates(plugdir)
local localhash = run('git -C '..plugdir..' log -1 --format=format:"%H"')
local remotehash = run('git -C '..plugdir..' rev-parse $(git -C '..
plugdir..' branch -r) | tail -1')
if localhash ~= remotehash then return true else return false end
end
-- start install
local function startinstall(i)
local src = getsrc(plugins[i][1])
local plugin = { -- plugin table spec
id = plugins[i][1] or false,
url = plugins[i]['url'] or (src['link'].."/"..src['repo']),
file = plugins[i]['file'] or false,
dir = plugins[i]['dir'] or 'scripts',
pin = plugins[i]['pin'] or false,
branch = plugins[i]['branch'] or false,
}
-- check if the user has defined a file for the current plugin
if not plugin['file'] then
logwrite('WARNING! File not configured for '..plugin[1])
goto continue
end
-- skip install of pinned files
if plugin['pin'] == true then goto continue end
-- get the plugins tmp download dir
local plugdir = opts.dl.dir..'/'..testforslash(src['repo']):gsub('.git', '')
-- if no specified branch we use the default
plugin['branch'] = plugin['branch'] or testforslash(
run('git -C '..plugdir..' symbolic-ref refs/remotes/origin/HEAD')
)
-- check for multiple files
if type(plugin['file']) == 'string' then
plugin['file'] = {}
table.insert(plugin['file'], plugins[i]['file'])
end
-- get the requested file(s)
for j = 1, #plugin['file'] or 1 do
-- get the file's dir
local pluginfile = plugdir..'/'..plugin['file'][j]
-- get the dest dir
local destfile = mp.command_native({'expand-path', '~~/'})..
'/'..plugin['dir']..'/'..testforslash(plugin['file'][j])
if fileexists(plugdir..'/') then
-- if we need to update, update
if checkupdates(plugdir) then
logwrite(plugin['file'][j]..' is updating.')
-- make sure we are on the main branch
run('git -C '..plugdir..' checkout -q '..plugin['branch'])
run('git -C '..plugdir..' pull') -- get the latest commits
else
logwrite(plugin['file'][j]..' is up to date!')
end
else
clonegit(plugdir, plugin['url'], plugin['branch'])
end
-- copy the file contents over to the desired location
cp(pluginfile, destfile)
end
::continue::
end
local function initupdate()
openlog()
logwrite('# of plugins defined in table: '..tablelength(plugins))
os.execute('mkdir -p '..opts.dl.dir) -- make download dir
-- start the install process
logwrite('Starting Download...')
mp.osd_message('Downloading plugins!')
-- start iterating through plugins
for i = 1, tablelength(plugins) do
local f = coroutine.create(function() startinstall(i) end)
coroutine.resume(f)
end
-- closing/removing everything
if opts.dl.powerwash == true then
logwrite('powerwashing the tmp dir "'..opts.dl.dir..'"')
os.execute('rm -rf '..opts.dl.dir)
end
closelog()
end
-- remove logfile on startup
if opts.logging.log then
openlog()
os.remove(fn)
closelog()
end
mp.add_key_binding(opts.bind, 'UpdatePlugins', initupdate)