diff options
-rw-r--r-- | src/luarocks/persist.lua | 92 |
1 files changed, 48 insertions, 44 deletions
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua index 9a40785c..04440670 100644 --- a/src/luarocks/persist.lua +++ b/src/luarocks/persist.lua | |||
@@ -9,8 +9,14 @@ package.loaded["luarocks.persist"] = persist | |||
9 | 9 | ||
10 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
11 | 11 | ||
12 | --- Load and run a Lua file in an environment. | ||
13 | -- @param filename string: the name of the file. | ||
14 | -- @param env table: the environment table. | ||
15 | -- @return (true, any) or (nil, string, string): true and the return value | ||
16 | -- of the file, or nil, an error message and an error code ("open", "load" | ||
17 | -- or "run") in case of errors. | ||
12 | local function run_file(filename, env) | 18 | local function run_file(filename, env) |
13 | local fd, err, errno = io.open(filename) | 19 | local fd, err = io.open(filename) |
14 | if not fd then | 20 | if not fd then |
15 | return nil, err, "open" | 21 | return nil, err, "open" |
16 | end | 22 | end |
@@ -28,7 +34,7 @@ local function run_file(filename, env) | |||
28 | ran, err = pcall(chunk) | 34 | ran, err = pcall(chunk) |
29 | end | 35 | end |
30 | else -- Lua 5.2 | 36 | else -- Lua 5.2 |
31 | chunk, err = loadfile(filename, "t", env) | 37 | chunk, err = load(str, filename, "t", env) |
32 | if chunk then | 38 | if chunk then |
33 | ran, err = pcall(chunk) | 39 | ran, err = pcall(chunk) |
34 | end | 40 | end |
@@ -47,9 +53,10 @@ end | |||
47 | -- @param filename string: the name of the file. | 53 | -- @param filename string: the name of the file. |
48 | -- @param tbl table or nil: if given, this table is used to store | 54 | -- @param tbl table or nil: if given, this table is used to store |
49 | -- loaded values. | 55 | -- loaded values. |
50 | -- @return table or (nil, string, string): a table with the file's assignments | 56 | -- @return (table, table) or (nil, string, string): a table with the file's |
51 | -- as fields, or nil, an error message and an error code ("load" or "run") | 57 | -- assignments as fields and set of undefined globals accessed in file, |
52 | -- in case of errors. | 58 | -- or nil, an error message and an error code ("open", "load" or "run") in |
59 | -- case of errors. | ||
53 | function persist.load_into_table(filename, tbl) | 60 | function persist.load_into_table(filename, tbl) |
54 | assert(type(filename) == "string") | 61 | assert(type(filename) == "string") |
55 | assert(type(tbl) == "table" or not tbl) | 62 | assert(type(tbl) == "table" or not tbl) |
@@ -57,9 +64,8 @@ function persist.load_into_table(filename, tbl) | |||
57 | local result = tbl or {} | 64 | local result = tbl or {} |
58 | local globals = {} | 65 | local globals = {} |
59 | local globals_mt = { | 66 | local globals_mt = { |
60 | __index = function(t, n) | 67 | __index = function(t, k) |
61 | globals[n] = true | 68 | globals[k] = true |
62 | return rawget(t, n) | ||
63 | end | 69 | end |
64 | } | 70 | } |
65 | local save_mt = getmetatable(result) | 71 | local save_mt = getmetatable(result) |
@@ -77,10 +83,10 @@ end | |||
77 | 83 | ||
78 | local write_table | 84 | local write_table |
79 | 85 | ||
80 | --- Write a value as Lua code, invoking write_table. | 86 | --- Write a value as Lua code. |
81 | -- This function handles only numbers, strings and tables | 87 | -- This function handles only numbers and strings, invoking write_table |
82 | -- are keys (tables are handled recursively). | 88 | -- to write tables. |
83 | -- @param out userdata: a file object, open for writing. | 89 | -- @param out table or userdata: a writer object supporting :write() method. |
84 | -- @param v: the value to be written. | 90 | -- @param v: the value to be written. |
85 | -- @param level number: the indentation level | 91 | -- @param level number: the indentation level |
86 | -- @param sub_order table: optional prioritization table | 92 | -- @param sub_order table: optional prioritization table |
@@ -89,28 +95,27 @@ local function write_value(out, v, level, sub_order) | |||
89 | if type(v) == "table" then | 95 | if type(v) == "table" then |
90 | write_table(out, v, level + 1, sub_order) | 96 | write_table(out, v, level + 1, sub_order) |
91 | elseif type(v) == "string" then | 97 | elseif type(v) == "string" then |
92 | if v:match("\n") then | 98 | if v:match("[\r\n]") then |
93 | local open, close = "[[", "]]" | 99 | local open, close = "[[", "]]" |
94 | local equals = 0 | 100 | local equals = 0 |
95 | while v:find(open,1,true) or v:find(close,1,true) do | 101 | while v:find(close, 1, true) do |
96 | equals = equals + 1 | 102 | equals = equals + 1 |
97 | local eqs = ("="):rep(equals) | 103 | local eqs = ("="):rep(equals) |
98 | open, close = "["..eqs.."[", "]"..eqs.."]" | 104 | open, close = "["..eqs.."[", "]"..eqs.."]" |
99 | end | 105 | end |
100 | out:write(open.."\n"..v..close) | 106 | out:write(open.."\n"..v..close) |
101 | else | 107 | else |
102 | out:write("\""..v:gsub("\"", "\\\"").."\"") | 108 | out:write("\""..v:gsub("\\", "\\\\"):gsub("\"", "\\\"").."\"") |
103 | end | 109 | end |
104 | else | 110 | else |
105 | out:write(tostring(v)) | 111 | out:write(tostring(v)) |
106 | end | 112 | end |
107 | end | 113 | end |
108 | 114 | ||
109 | --- Write a table as Lua code representing a table to disk | 115 | --- Write a table as Lua code in curly brackets notation to a writer object. |
110 | -- (that is, in curly brackets notation). | 116 | -- Only numbers, strings and tables (containing numbers, strings |
111 | -- This function handles only numbers, strings and tables | 117 | -- or other recursively processed tables) are supported. |
112 | -- are keys (tables are handled recursively). | 118 | -- @param out table or userdata: a writer object supporting :write() method. |
113 | -- @param out userdata: a file object, open for writing. | ||
114 | -- @param tbl table: the table to be written. | 119 | -- @param tbl table: the table to be written. |
115 | -- @param level number: the indentation level | 120 | -- @param level number: the indentation level |
116 | -- @param field_order table: optional prioritization table | 121 | -- @param field_order table: optional prioritization table |
@@ -125,28 +130,29 @@ write_table = function(out, tbl, level, field_order) | |||
125 | if indent then | 130 | if indent then |
126 | for n = 1,level do out:write(indentation) end | 131 | for n = 1,level do out:write(indentation) end |
127 | end | 132 | end |
128 | sep = ",\n" | 133 | |
129 | indent = true | 134 | if k == i then |
130 | if type(k) == "number" then | 135 | i = i + 1 |
131 | if k ~= i then | ||
132 | out:write("["..tostring(k).."]=") | ||
133 | else | ||
134 | i = i + 1 | ||
135 | end | ||
136 | indent = false | ||
137 | sep = ", " | ||
138 | elseif type(k) == "table" then | ||
139 | out:write("[") | ||
140 | write_table(out, k, level + 1) | ||
141 | out:write("] = ") | ||
142 | else | 136 | else |
143 | if k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then | 137 | if type(k) == "string" and k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then |
144 | out:write(k.." = ") | 138 | out:write(k) |
145 | else | 139 | else |
146 | out:write("['"..k:gsub("'", "\\'").."'] = ") | 140 | out:write("[") |
141 | write_value(out, k, level) | ||
142 | out:write("]") | ||
147 | end | 143 | end |
144 | |||
145 | out:write(" = ") | ||
148 | end | 146 | end |
147 | |||
149 | write_value(out, v, level, sub_order) | 148 | write_value(out, v, level, sub_order) |
149 | if type(k) == "number" then | ||
150 | sep = ", " | ||
151 | indent = false | ||
152 | else | ||
153 | sep = ",\n" | ||
154 | indent = true | ||
155 | end | ||
150 | end | 156 | end |
151 | if sep ~= "\n" then | 157 | if sep ~= "\n" then |
152 | out:write("\n") | 158 | out:write("\n") |
@@ -155,18 +161,16 @@ write_table = function(out, tbl, level, field_order) | |||
155 | out:write("}") | 161 | out:write("}") |
156 | end | 162 | end |
157 | 163 | ||
158 | --- Writes a table to an io-like object. | 164 | --- Write a table as series of assignments to a writer object. |
159 | -- @param out userdata: a file object, open for writing. | 165 | -- @param out table or userdata: a writer object supporting :write() method. |
160 | -- @param tbl table: the table to be written. | 166 | -- @param tbl table: the table to be written. |
161 | -- @param field_order table: optional prioritization table | 167 | -- @param field_order table: optional prioritization table |
162 | -- @return userdata The file object originally passed in as the `out` parameter. | 168 | local function write_table_as_assignments(out, tbl, field_order) |
163 | local function write_table(out, tbl, field_order) | ||
164 | for k, v, sub_order in util.sortedpairs(tbl, field_order) do | 169 | for k, v, sub_order in util.sortedpairs(tbl, field_order) do |
165 | out:write(k.." = ") | 170 | out:write(k.." = ") |
166 | write_value(out, v, 0, sub_order) | 171 | write_value(out, v, 0, sub_order) |
167 | out:write("\n") | 172 | out:write("\n") |
168 | end | 173 | end |
169 | return out | ||
170 | end | 174 | end |
171 | 175 | ||
172 | --- Save the contents of a table to a string. | 176 | --- Save the contents of a table to a string. |
@@ -179,7 +183,7 @@ end | |||
179 | function persist.save_from_table_to_string(tbl, field_order) | 183 | function persist.save_from_table_to_string(tbl, field_order) |
180 | local out = {buffer = {}} | 184 | local out = {buffer = {}} |
181 | function out:write(data) table.insert(self.buffer, data) end | 185 | function out:write(data) table.insert(self.buffer, data) end |
182 | write_table(out, tbl, field_order) | 186 | write_table_as_assignments(out, tbl, field_order) |
183 | return table.concat(out.buffer) | 187 | return table.concat(out.buffer) |
184 | end | 188 | end |
185 | 189 | ||
@@ -197,7 +201,7 @@ function persist.save_from_table(filename, tbl, field_order) | |||
197 | if not out then | 201 | if not out then |
198 | return nil, "Cannot create file at "..filename | 202 | return nil, "Cannot create file at "..filename |
199 | end | 203 | end |
200 | write_table(out, tbl, field_order) | 204 | write_table_as_assignments(out, tbl, field_order) |
201 | out:close() | 205 | out:close() |
202 | return true | 206 | return true |
203 | end | 207 | end |