summaryrefslogtreecommitdiff
path: root/pm.lua
blob: a9314e43678a3a0ef9a10eda81c71a898b72bded (plain)
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
149
150
151
152
153
154
-- 'package manager'

local rbase = "https://g.gh0.pw/ccprogs/plain/"

local function is_required()
	local n = 0
	local res = false
	while true do
		local x = debug.getinfo(n)
		if x == nil then break end
		n = n + 1
		if x.func == require then
			res = true
			break
		end
	end
	return res
end

local function perr(err,what)
	if err then error(what..": "..err) end
end

local _manifests = {}
local function clear_cache()
	for k in pairs(_manifests) do _manifests[k] = nil end
end

local function manifest(pkgname)
	if _manifests[pkgname] then return _manifests[pkgname] end
	print("fetching manifest of '"..pkgname.."'...")

	local files={}
	local files_present=false
	local deps={}

	local res,err,err_res = http.get(rbase..pkgname..".dat")
	if err then
		if err_res and (err_res.getResponseCode() == 404) then
			print("no manifest for '"..pkgname.."' found, using defaults")
		else
			error("http.get: "..err)
		end
	else
		for line in res.readAll():gmatch"[^\n]+" do
			local op,argstart = line:match "^(%w+)%s*()"
			if op then
				local argstr = line:sub(argstart)
				local args = {}
				for arg in argstr:gmatch"[^ ]+" do
					table.insert(args,arg)
				end
				
				if op == "dep" then
					for _,arg in ipairs(args) do deps[arg]=true end
				elseif op == "file" then
					files_present = true
					for _,arg in ipairs(args) do files[arg]=true end
				end
			end
		end
	end
	
	if not files_present then
		local default_filename = pkgname .. ".lua"
		if pkgname:match("%.") then
			default_filename = pkgname
		end
		files[default_filename]=true
	end
	local man = {files=files,deps=deps}
	_manifests[pkgname] = man
	return man
end

local function recursive_depsof(pkgname, out)
	local lookedat = {}
	local deps = out or {}
	local function F(pkgname)
		if not lookedat[pkgname] then
			lookedat[pkgname] = true
			for k,_ in pairs(manifest(pkgname).deps) do
				deps[k] = true
				F(k)
			end
		end
	end
	deps[pkgname] = true
	F(pkgname)
	return deps
end

local function filesof(dep_set)
	local files = {}
	for dep in pairs(dep_set) do
		for file in pairs(manifest(dep).files) do files[file] = true end 
	end
	return files
end

local function fmt_set(set)
	local keys = {}
	for k in pairs(set) do table.insert(keys,k) end
	table.sort(keys)
	return "("..#keys..") " .. table.concat(keys,", ")
end

	
local function dlfile(filename)
	local src=rbase..filename
	local dest="/"..filename
	print("downloading "..src.." to "..dest)
	local dir = fs.getDir(dest)
	if not fs.isDir(dir) then
		print("creating directory "..dir)
		fs.makeDir(dir)
	end
	local file,err=fs.open(dest,"wb")
	if err then error("fs.open "..err) end
	local res,err = http.get{url=src,binary=true}
	if err then error("http.get "..err) end
	file.write(res.readAll())
	file.flush()
	file.close()
end

local function dl_many(pkgnames)
	local dep_set = {}
	for _,pkgname in ipairs(pkgnames) do
		recursive_depsof(pkgname, dep_set)
	end
	local files = filesof(dep_set)
	print("all dependencies: "..fmt_set(dep_set))
	print("all files: "..fmt_set(files))
	for file in pairs(files) do
		dlfile(file)
	end
	print"done"
end

local function dl(pkgname)
	dl_many({pkgname})
end
	
if is_required() then
	return {manifest=manifest,
		rd=recursive_depsof,
		filesof=filesof,
		dl=dl,
		dl_many=dl_many,
		cc=clear_cache}
else
	dl_many(arg)
end