-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.lua
148 lines (129 loc) · 4.41 KB
/
main.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
local utils = require "mp.utils"
local msg = require "mp.msg"
local legacy = mp.command_native_async == nil
local config = {}
local dir_cache = {}
-- Run a command
function run(args)
if legacy then
return utils.subprocess({args = args})
end
return mp.command_native({name = "subprocess", capture_stdout = true, playback_only = false, args = args})
end
-- Get the parent directory of a path
function parent(path)
return string.match(path, "(.*)[/\\]")
end
-- Cache a directory
function cache(path)
local p_path = parent(path)
if p_path == nil or p_path == "" or dir_cache[p_path] then return end
cache(p_path)
dir_cache[path] = 1
end
-- Create a directory
function mkdir(path)
if dir_cache[path] then return end
cache(path)
run({"git", "init", path})
end
-- Match a string against a list of patterns
function match(str, patterns)
for pattern in string.gmatch(patterns, "[^|]+") do
-- Remove whitespaces and check the pattern
pattern = pattern:gsub("^%s*(.-)%s*$", "%1")
if string.match(str, pattern) then
return true
end
end
return false -- Return false when no match is found
end
-- Apply default values to a script info
function apply_defaults(info)
if info.git == nil then return false end
if info.whitelist == nil then info.whitelist = "" end
if info.blacklist == nil then info.blacklist = "" end
if info.dest == nil then info.dest = "~~/scripts" end
if info.branch == nil then info.branch = "master" end
return info
end
--[[
* Update a script
* @param info The script info
* @return true if the script was updated, false otherwise
]]
function update(info)
info = apply_defaults(info)
if not info then return false end
-- Get the destination directory or file
local e_dest = string.match(mp.command_native({"expand-path", info.dest}), "(.-)[/\\]?$")
local dest_dir = parent(e_dest) or e_dest
mkdir(dest_dir)
local files = {}
-- Remove remote if it exists and add it again
run({"git", "-C", dest_dir, "remote", "remove", "manager"})
run({"git", "-C", dest_dir, "remote", "add", "manager", info.git})
run({"git", "-C", dest_dir, "fetch", "manager", info.branch})
for file in string.gmatch(run({"git", "-C", dest_dir, "ls-tree", "-r", "--name-only", "remotes/manager/"..info.branch}).stdout, "[^\r\n]+") do
local l_file = string.lower(file)
if (info.whitelist == "" or match(l_file, info.whitelist)) and
(info.blacklist == "" or not match(l_file, info.blacklist)) then
table.insert(files, file)
end
end
if next(files) == nil then
print("no files matching patterns")
return false
end
for _, file in ipairs(files) do
-- If dest is a file, write directly to it
if parent(e_dest) then
local c = string.match(run({"git", "-C", dest_dir, "--no-pager", "show", "remotes/manager/"..info.branch..":"..file}).stdout, "(.-)[\r\n]?$")
local f = io.open(e_dest, "w")
f:write(c)
f:close()
break -- Only write the first matching file
else
-- Otherwise handle as directory
local p_based = parent(file)
if p_based and not info.flatten_folders then
mkdir(e_dest.."/"..p_based)
end
local c = string.match(run({"git", "-C", dest_dir, "--no-pager", "show", "remotes/manager/"..info.branch..":"..file}).stdout, "(.-)[\r\n]?$")
local f = io.open(e_dest.."/"..(info.flatten_folders and file:match("[^/]+$") or file), "w")
f:write(c)
f:close()
end
end
return true
end
--[[
Update all scripts
]]
function update_all()
-- Open the manager.json file
local f = io.open(
mp.command_native(
{"expand-path", "~~/manager.json"}
),
"r"
)
-- Check if the file was opened successfully
if f then
-- Read the file
local json = f:read("*all")
f:close()
-- Parse the JSON
local props = utils.parse_json(json or "")
if props then
config = props
end
end
-- Update each script
for i, info in ipairs(config) do
msg.info("Updating script "..i ..":", update(info))
end
end
msg.info("Updating all scripts")
-- Update all scripts when the file is loaded
mp.register_event("file-loaded", update_all)