squish.lua

changeset 0
b119b560ca3d
child 4
9806107f59ea
equal deleted inserted replaced
-1:000000000000 0:b119b560ca3d
1 #!/usr/bin/env lua
2
3 local short_opts = { v = "verbose", vv = "very_verbose", o = "output", q = "quiet", qq = "very_quiet" }
4 opts = {};
5
6 for _, opt in ipairs(arg) do
7 if opt:match("^%-") then
8 local name = opt:match("^%-%-?([^%s=]+)()")
9 name = (short_opts[name] or name):gsub("%-+", "_");
10 if name:match("^no_") then
11 name = name:sub(4, -1);
12 opts[name] = false;
13 else
14 opts[name] = opt:match("=(.*)$") or true;
15 end
16 else
17 base_path = opt;
18 end
19 end
20
21 if opts.very_verbose then opts.verbose = true; end
22 if opts.very_quiet then opts.quiet = true; end
23
24 local noprint = function () end
25 local print_err, print_info, print_verbose, print_debug = noprint, noprint, noprint, noprint;
26
27 if not opts.very_quiet then print_err = print; end
28 if not opts.quiet then print_info = print; end
29 if opts.verbose or opts.very_verbose then print_verbose = print; end
30 if opts.very_verbose then print_debug = print; end
31
32 local enable_debug = true;
33
34 local modules, main_files = {}, {};
35
36 -- Functions to be called from squishy file --
37
38 function Module(name)
39 local i = #modules+1;
40 modules[i] = { name = name, url = ___fetch_url };
41 return function (path)
42 modules[i].path = path;
43 end
44 end
45
46 function AutoFetchURL(url)
47 ___fetch_url = url;
48 end
49
50 function Main(fn)
51 table.insert(main_files, fn);
52 end
53
54 function Output(fn)
55 out_fn = fn;
56 end
57
58 function Option(name)
59 if opts[name] == nil then
60 opts[name] = true;
61 return function (value)
62 opts[name] = value;
63 end
64 else
65 return function () end;
66 end
67 end
68
69 -- -- -- -- -- -- -- --- -- -- -- -- -- -- -- --
70
71 base_path = (base_path or "."):gsub("/$", "").."/"
72 squishy_file = base_path .. "squishy";
73 out_fn = opts.output or "squished.out.lua";
74
75 local ok, err = pcall(dofile, squishy_file);
76
77 if not ok then
78 print_err("Couldn't read squishy file: "..err);
79 os.exit(1);
80 end
81
82 local fetch = {};
83 function fetch.filesystem(path)
84 local f, err = io.open(path);
85 if not f then return false, err; end
86
87 local data = f:read("*a");
88 f:close();
89
90 return data;
91 end
92
93 function fetch.http(url)
94 local http = require "socket.http";
95
96 local body, status = http.request(url);
97 if status == 200 then
98 return body;
99 end
100 return false, "HTTP status code: "..tostring(status);
101 end
102
103 print_info("Writing "..out_fn.."...");
104 local f = io.open(out_fn, "w+");
105
106 if opts.executable then
107 f:write("#!/usr/bin/env lua\n");
108 end
109
110 if enable_debug then
111 f:write [[
112 local function ___rename_chunk(chunk, name)
113 if type(chunk) == "function" then
114 chunk = string.dump(chunk);
115 end
116 local intsize = chunk:sub(8,8):byte();
117 local b = { chunk:sub(13, 13+intsize-1):byte(1, intsize) };
118 local oldlen = 0;
119 for i = 1, #b do
120 oldlen = oldlen + b[i] * 2^((i-1)*8);
121 end
122
123 local newname = name.."\0";
124 local newlen = #newname;
125
126 local b = { };
127 for i=1,intsize do
128 b[i] = string.char(math.floor(newlen / 2^((i-1)*8)) % (2^(i*8)));
129 end
130
131 return loadstring(chunk:sub(1, 12)..table.concat(b)..newname
132 ..chunk:sub(13+intsize+oldlen, -1));
133 end
134 ]];
135 end
136
137 for _, module in ipairs(modules) do
138 local modulename, path = module.name, base_path..module.path;
139 print_verbose("Packing "..modulename.." ("..path..")...");
140 local data, err = fetch.filesystem(path);
141 if (not data) and module.url then
142 print_debug("Fetching: ".. module.url:gsub("%?", module.path))
143 data, err = fetch.http(module.url:gsub("%?", module.path));
144 end
145 if data then
146 f:write("package.preload['", modulename, "'] = (function ()\n");
147 f:write(data);
148 f:write("end)\n");
149 if enable_debug then
150 f:write(string.format("package.preload[%q] = ___rename_chunk(package.preload[%q], %q);\n\n",
151 modulename, modulename, "@"..path));
152 end
153 else
154 print_err("Couldn't pack module '"..modulename.."': "..err);
155 os.exit(1);
156 end
157 end
158
159 print_debug("Finalising...")
160 for _, fn in pairs(main_files) do
161 local fin, err = io.open(base_path..fn);
162 if not fin then
163 print_err("Failed to open "..fn..": "..err);
164 os.exit(1);
165 else
166 f:write((fin:read("*a"):gsub("^#.-\n", "")));
167 fin:close();
168 end
169 end
170
171 f:close();
172
173 print_info("OK!");

mercurial