diff options
author | Hisham Muhammad <hisham@gobolinux.org> | 2018-12-10 15:53:26 -0200 |
---|---|---|
committer | Hisham Muhammad <hisham@gobolinux.org> | 2018-12-10 15:53:26 -0200 |
commit | 9bb5c285f007d4d2f83ff5593db5afa7fa2a0310 (patch) | |
tree | 63caa335d2bb74e7c039284b861fdc1d6c151405 | |
parent | 914a2b7503b15c40894ac9efb8f33352f1a75cd1 (diff) | |
download | luarocks-9bb5c285f007d4d2f83ff5593db5afa7fa2a0310.tar.gz luarocks-9bb5c285f007d4d2f83ff5593db5afa7fa2a0310.tar.bz2 luarocks-9bb5c285f007d4d2f83ff5593db5afa7fa2a0310.zip |
persist: handle keys that are keywords correctly.
Closes #947.
-rw-r--r-- | spec/persist_spec.lua | 8 | ||||
-rw-r--r-- | src/luarocks/persist.lua | 75 |
2 files changed, 70 insertions, 13 deletions
diff --git a/spec/persist_spec.lua b/spec/persist_spec.lua index dccb0ec4..734b2a4e 100644 --- a/spec/persist_spec.lua +++ b/spec/persist_spec.lua | |||
@@ -36,6 +36,14 @@ foo = { | |||
36 | ]], persist.save_from_table_to_string({foo = {1, 2, 3, 4}, bar = {baz = "string"}})) | 36 | ]], persist.save_from_table_to_string({foo = {1, 2, 3, 4}, bar = {baz = "string"}})) |
37 | end) | 37 | end) |
38 | 38 | ||
39 | it("table with a keyword key (#947)", function() | ||
40 | assert.are.same([[ | ||
41 | bar = { | ||
42 | ["function"] = "foo" | ||
43 | } | ||
44 | ]], persist.save_from_table_to_string({bar = {["function"] = "foo"}})) | ||
45 | end) | ||
46 | |||
39 | it("strings with quotes", function() | 47 | it("strings with quotes", function() |
40 | assert.are.same([[ | 48 | assert.are.same([[ |
41 | bar = "a \\backslash?" | 49 | bar = "a \\backslash?" |
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua index 6dc8b9ab..73f92bea 100644 --- a/src/luarocks/persist.lua +++ b/src/luarocks/persist.lua | |||
@@ -42,6 +42,51 @@ local function write_value(out, v, level, sub_order) | |||
42 | end | 42 | end |
43 | end | 43 | end |
44 | 44 | ||
45 | local is_valid_plain_key | ||
46 | do | ||
47 | local keywords = { | ||
48 | ["and"] = true, | ||
49 | ["break"] = true, | ||
50 | ["do"] = true, | ||
51 | ["else"] = true, | ||
52 | ["elseif"] = true, | ||
53 | ["end"] = true, | ||
54 | ["false"] = true, | ||
55 | ["for"] = true, | ||
56 | ["function"] = true, | ||
57 | ["goto"] = true, | ||
58 | ["if"] = true, | ||
59 | ["in"] = true, | ||
60 | ["local"] = true, | ||
61 | ["nil"] = true, | ||
62 | ["not"] = true, | ||
63 | ["or"] = true, | ||
64 | ["repeat"] = true, | ||
65 | ["return"] = true, | ||
66 | ["then"] = true, | ||
67 | ["true"] = true, | ||
68 | ["until"] = true, | ||
69 | ["while"] = true, | ||
70 | } | ||
71 | function is_valid_plain_key(k) | ||
72 | return type(k) == "string" | ||
73 | and k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") | ||
74 | and not keywords[k] | ||
75 | end | ||
76 | end | ||
77 | |||
78 | local function write_table_key_assignment(out, k, level) | ||
79 | if is_valid_plain_key(k) then | ||
80 | out:write(k) | ||
81 | else | ||
82 | out:write("[") | ||
83 | write_value(out, k, level) | ||
84 | out:write("]") | ||
85 | end | ||
86 | |||
87 | out:write(" = ") | ||
88 | end | ||
89 | |||
45 | --- Write a table as Lua code in curly brackets notation to a writer object. | 90 | --- Write a table as Lua code in curly brackets notation to a writer object. |
46 | -- Only numbers, strings and tables (containing numbers, strings | 91 | -- Only numbers, strings and tables (containing numbers, strings |
47 | -- or other recursively processed tables) are supported. | 92 | -- or other recursively processed tables) are supported. |
@@ -64,15 +109,7 @@ write_table = function(out, tbl, level, field_order) | |||
64 | if k == i then | 109 | if k == i then |
65 | i = i + 1 | 110 | i = i + 1 |
66 | else | 111 | else |
67 | if type(k) == "string" and k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then | 112 | write_table_key_assignment(out, k, level) |
68 | out:write(k) | ||
69 | else | ||
70 | out:write("[") | ||
71 | write_value(out, k, level) | ||
72 | out:write("]") | ||
73 | end | ||
74 | |||
75 | out:write(" = ") | ||
76 | end | 113 | end |
77 | 114 | ||
78 | write_value(out, v, level, sub_order) | 115 | write_value(out, v, level, sub_order) |
@@ -95,12 +132,17 @@ end | |||
95 | -- @param out table or userdata: a writer object supporting :write() method. | 132 | -- @param out table or userdata: a writer object supporting :write() method. |
96 | -- @param tbl table: the table to be written. | 133 | -- @param tbl table: the table to be written. |
97 | -- @param field_order table: optional prioritization table | 134 | -- @param field_order table: optional prioritization table |
135 | -- @return true if successful; nil and error message if failed. | ||
98 | local function write_table_as_assignments(out, tbl, field_order) | 136 | local function write_table_as_assignments(out, tbl, field_order) |
99 | for k, v, sub_order in util.sortedpairs(tbl, field_order) do | 137 | for k, v, sub_order in util.sortedpairs(tbl, field_order) do |
138 | if not is_valid_plain_key(k) then | ||
139 | return nil, "cannot store '"..tostring(k).."' as a plain key." | ||
140 | end | ||
100 | out:write(k.." = ") | 141 | out:write(k.." = ") |
101 | write_value(out, v, 0, sub_order) | 142 | write_value(out, v, 0, sub_order) |
102 | out:write("\n") | 143 | out:write("\n") |
103 | end | 144 | end |
145 | return true | ||
104 | end | 146 | end |
105 | 147 | ||
106 | --- Write a table as series of assignments to a writer object. | 148 | --- Write a table as series of assignments to a writer object. |
@@ -109,7 +151,8 @@ end | |||
109 | local function write_table_as_table(out, tbl) | 151 | local function write_table_as_table(out, tbl) |
110 | out:write("return {\n") | 152 | out:write("return {\n") |
111 | for k, v, sub_order in util.sortedpairs(tbl) do | 153 | for k, v, sub_order in util.sortedpairs(tbl) do |
112 | out:write(" " .. k .. " = ") | 154 | out:write(" ") |
155 | write_table_key_assignment(out, k, 1) | ||
113 | write_value(out, v, 1, sub_order) | 156 | write_value(out, v, 1, sub_order) |
114 | out:write(",\n") | 157 | out:write(",\n") |
115 | end | 158 | end |
@@ -122,11 +165,14 @@ end | |||
122 | -- or other recursively processed tables) are supported. | 165 | -- or other recursively processed tables) are supported. |
123 | -- @param tbl table: the table containing the data to be written | 166 | -- @param tbl table: the table containing the data to be written |
124 | -- @param field_order table: an optional array indicating the order of top-level fields. | 167 | -- @param field_order table: an optional array indicating the order of top-level fields. |
125 | -- @return string | 168 | -- @return persisted data as string; or nil and an error message |
126 | function persist.save_from_table_to_string(tbl, field_order) | 169 | function persist.save_from_table_to_string(tbl, field_order) |
127 | local out = {buffer = {}} | 170 | local out = {buffer = {}} |
128 | function out:write(data) table.insert(self.buffer, data) end | 171 | function out:write(data) table.insert(self.buffer, data) end |
129 | write_table_as_assignments(out, tbl, field_order) | 172 | local ok, err = write_table_as_assignments(out, tbl, field_order) |
173 | if not ok then | ||
174 | return nil, err | ||
175 | end | ||
130 | return table.concat(out.buffer) | 176 | return table.concat(out.buffer) |
131 | end | 177 | end |
132 | 178 | ||
@@ -144,8 +190,11 @@ function persist.save_from_table(filename, tbl, field_order) | |||
144 | if not out then | 190 | if not out then |
145 | return nil, "Cannot create file at "..filename | 191 | return nil, "Cannot create file at "..filename |
146 | end | 192 | end |
147 | write_table_as_assignments(out, tbl, field_order) | 193 | local ok, err = write_table_as_assignments(out, tbl, field_order) |
148 | out:close() | 194 | out:close() |
195 | if not ok then | ||
196 | return nil, err | ||
197 | end | ||
149 | return true | 198 | return true |
150 | end | 199 | end |
151 | 200 | ||