diff --git a/lapis/cmd/actions/annotate.lua b/lapis/cmd/actions/annotate.lua index 7893cb8..63ddedf 100644 --- a/lapis/cmd/actions/annotate.lua +++ b/lapis/cmd/actions/annotate.lua @@ -1,7 +1,103 @@ -local extract_schema_sql, extract_schema_table -do - local _obj_0 = require("lapis.annotate.pg_schema") - extract_schema_sql, extract_schema_table = _obj_0.extract_schema_sql, _obj_0.extract_schema_table +local default_environment +default_environment = require("lapis.cmd.util").default_environment +local shell_escape +shell_escape = function(str) + return "'" .. tostring(str:gsub("'", "''")) .. "'" +end +local exec +exec = function(cmd) + local f = io.popen(cmd) + do + local _with_0 = f:read("*all"):gsub("%s*$", "") + f:close() + return _with_0 + end +end +local DEFAULT_SCHEMA = "public" +local build_command +build_command = function(cmd, config) + local database = assert(config.postgres and config.postgres.database, "missing postgres database configuration") + local command = { + cmd + } + do + local password = config.postgres.password + if password then + table.insert(command, 1, "PGPASSWORD=" .. tostring(shell_escape(password))) + end + end + do + local host = config.postgres.host + if host then + table.insert(command, "-h " .. tostring(shell_escape(host))) + end + end + do + local user = config.postgres.user + if user then + table.insert(command, "-U " .. tostring(shell_escape(user))) + end + end + table.insert(command, shell_escape(database)) + return table.concat(command, " ") +end +local extract_schema_sql +extract_schema_sql = function(config, model) + local table_name = model:table_name() + local schema = exec(build_command("pg_dump --schema-only -t " .. tostring(shell_escape(table_name)), config)) + local in_block = false + return (function() + local _accum_0 = { } + local _len_0 = 1 + for line in schema:gmatch("[^\n]+") do + local _continue_0 = false + repeat + if in_block then + if not (line:match("^%s")) then + in_block = false + end + if in_block then + _continue_0 = true + break + end + end + if line:match("^%-%-") then + _continue_0 = true + break + end + if line:match("^SET") then + _continue_0 = true + break + end + if line:match("^ALTER SEQUENCE") then + _continue_0 = true + break + end + if line:match("^SELECT") then + _continue_0 = true + break + end + line = line:gsub(tostring(DEFAULT_SCHEMA) .. "%." .. tostring(table_name), table_name) + if line:match("^ALTER TABLE") and not line:match("^ALTER TABLE ONLY") or line:match("nextval") then + _continue_0 = true + break + end + if line:match("CREATE SEQUENCE") then + in_block = true + _continue_0 = true + break + end + local _value_0 = line:gsub(" ", " ") + _accum_0[_len_0] = _value_0 + _len_0 = _len_0 + 1 + _continue_0 = true + until true + if not _continue_0 then + break + end + end + return _accum_0 + end)() end local enum_to_comment enum_to_comment = function(enum) @@ -119,8 +215,16 @@ annotate_model = function(config, fname, options) end local header = table.concat(header_lines, "\n") .. "\n" local updated_source = replace_header(source, header) - if not (updated_source) then - updated_source = source:gsub("class ", tostring(header) .. "class ", 1) + if fname:match(".lua$") and not updated_source then + local lua_declaration = "local %w+ = Model:extend" + if not source:match(lua_declaration) then + print("\tLine matching '" .. tostring(lua_declaration) .. "' not found") + end + updated_source = source:gsub(lua_declaration, tostring(header) .. "%1 ", 1) + else + if not updated_source then + updated_source = source:gsub("class ", tostring(header) .. "class ", 1) + end end local source_out = assert(io.open(fname, "w")) source_out:write(updated_source) diff --git a/lapis/cmd/actions/annotate.moon b/lapis/cmd/actions/annotate.moon index 6e3a742..e3f6941 100644 --- a/lapis/cmd/actions/annotate.moon +++ b/lapis/cmd/actions/annotate.moon @@ -1,4 +1,61 @@ -import extract_schema_sql, extract_schema_table from require "lapis.annotate.pg_schema" +import default_environment from require "lapis.cmd.util" + +shell_escape = (str) -> + "'#{str\gsub "'", "''"}'" + +exec = (cmd) -> + f = io.popen cmd + with f\read("*all")\gsub "%s*$", "" + f\close! + +DEFAULT_SCHEMA = "public" + +-- add configuration arguments to cmd, return unjoined command +build_command = (cmd, config) -> + database = assert config.postgres and config.postgres.database, "missing postgres database configuration" + + command = { cmd } + + if password = config.postgres.password + table.insert command, 1, "PGPASSWORD=#{shell_escape password}" + + if host = config.postgres.host + table.insert command, "-h #{shell_escape host}" + + if user = config.postgres.user + table.insert command, "-U #{shell_escape user}" + + table.insert command, shell_escape database + table.concat command, " " + +extract_schema_sql = (config, model) -> + table_name = model\table_name! + + schema = exec build_command "pg_dump --schema-only -t #{shell_escape table_name}", config + + in_block = false + + return for line in schema\gmatch "[^\n]+" + if in_block + in_block = false unless line\match "^%s" + continue if in_block + + continue if line\match "^%-%-" + continue if line\match "^SET" + continue if line\match "^ALTER SEQUENCE" + continue if line\match "^SELECT" + + line = line\gsub "#{DEFAULT_SCHEMA}%.#{table_name}", table_name + + if line\match("^ALTER TABLE" ) and not line\match("^ALTER TABLE ONLY") or line\match "nextval" + continue + + if line\match "CREATE SEQUENCE" + in_block = true + continue + + line\gsub " ", " " + -- this can be used to annotate enum columns with a comment in the schema enum_to_comment = (enum) -> @@ -85,8 +142,12 @@ annotate_model = (config, fname, options={}) -> updated_source = replace_header source, header - -- TODO: this is kinda sloppy and only works with MoonScript - unless updated_source + -- TODO: this is kinda sloppy + if fname\match(".lua$") and not updated_source + lua_declaration = "local %w+ = Model:extend" + print "\tLine matching '#{lua_declaration}' not found" if not source\match lua_declaration + updated_source = source\gsub lua_declaration, "#{header}%1 ", 1 + else if not updated_source updated_source = source\gsub "class ", "#{header}class ", 1 source_out = assert io.open fname, "w"