PERFORCE change 84408 for review
soc-andrew
soc-andrew at FreeBSD.org
Tue Sep 27 18:45:30 PDT 2005
http://perforce.freebsd.org/chv.cgi?CH=84408
Change 84408 by soc-andrew at soc-andrew_serv on 2005/09/28 01:44:54
Update the Lua backend to a new version from today
Rename uses of POSIX to posix as POSIX is boolean
Install more needed parts (still more to come)
Affected files ...
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/package.lua#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/uinav.lua#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/app/Makefile#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/app/app.lua#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/dfui/Makefile#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/dfui/common.c#3 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/dfui/dfui.c#3 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/dfui/dfui.lua#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/dfui/progress.c#3 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/filename/Makefile#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/filename/filename.lua#3 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/pty/Makefile#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/pty/pty.c#3 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/pty/pty.lua#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/etc/mtree/BSD.usr.dist#4 edit
.. //depot/projects/soc2005/bsdinstaller/src/lib/bsdinstaller/lua/Makefile.inc1#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/lib/bsdinstaller/lua/dfui/Makefile#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/libexec/bsdinstaller/Makefile#2 edit
.. //depot/projects/soc2005/bsdinstaller/src/libexec/bsdinstaller/lib/Makefile#1 add
Differences ...
==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/package.lua#2 (text+ko) ====
@@ -160,7 +160,7 @@
pkg_tmp = tab.tmp_dir
else
local tmp_dir = App.dir.root .. ts:get_base() .. "tmp"
- local link = POSIX.readlink(tmp_dir)
+ local link = posix.readlink(tmp_dir)
if link ~= nil then
pkg_tmp = FileName.remove_leading_slash(real_tmp_dir)
elseif FileName.is_dir(tmp_dir) then
@@ -358,7 +358,7 @@
method.enumerate_installed_on = function(ps, ts)
local i, filename, list, dir
- dir = POSIX.dir(
+ dir = posix.dir(
App.expand("${root}${base}var/db/pkg", {
base = ts:get_base()
})
==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/uinav.lua#2 (text+ko) ====
@@ -233,7 +233,7 @@
from_dir = FileName.dirname(App.current_script)
end
- filenames = POSIX.dir(from_dir)
+ filenames = posix.dir(from_dir)
table.sort(filenames)
for i, filename in ipairs(filenames) do
==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/app/Makefile#2 (text+ko) ====
@@ -1,10 +1,14 @@
-# $Id: Makefile,v 1.4 2005/04/05 20:53:46 cpressey Exp $
-# Dummy makefile.
+# $Id: Makefile,v 1.6 2005/08/27 02:11:33 cpressey Exp $
+
+BASE?=../../..
+include ${BASE}/Config
all:
- @echo "No building required."
-
-in_cvs: all
+ @echo "Nothing to build."
clean:
@echo "No cleaning required."
+
+distribution:
+ mkdir -p ${DESTDIR}/share/lua/5.0/
+ cp app.lua ${DESTDIR}/share/lua/5.0/
==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/lib/lua/app/app.lua#2 (text+ko) ====
@@ -1,6 +1,36 @@
--- app.lua
--- $Id: app.lua,v 1.54 2005/04/22 05:03:07 cpressey Exp $
--- Lua-based Application Environment static object.
+-- $Id: app.lua,v 1.70 2005/09/13 19:25:29 cpressey Exp $
+-- Lua-based Application Environment.
+
+--
+-- Copyright (c)2005 Chris Pressey. All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- 1. Redistributions of source code must retain the above copyright
+-- notices, this list of conditions and the following disclaimer.
+-- 2. Redistributions in binary form must reproduce the above copyright
+-- notices, this list of conditions, and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+-- 3. Neither the names of the copyright holders nor the names of their
+-- contributors may be used to endorse or promote products derived
+-- from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+-- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES INCLUDING, BUT NOT
+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+-- COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+-- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+-- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
-- BEGIN app.lua --
@@ -14,247 +44,166 @@
--[[ App ]]--
--[[-----]]--
--- Application Environment - roughly equivalent to
--- InstallerContext (or i_fn_args in the C version,) but:
+--
+-- Application Environment.
--
--- * this version is written purely in Lua, and
--- * this version is not specific to the Installer - it could just as well
--- be used for any application that needs:
+-- This package provides a global environment or framework for an
+-- application written in Lua. It was written for the BSD Installer,
+-- but should be general enough to be suitable for many applications
+-- which require some or all of the following:
--
--- o user interface facilities (highly abstracted)
--- o configuration, possibly loaded from config files
--- - locations of directories (root dir, temp dir, etc)
+-- o highly abstracted user interface facilities
+-- o configuration, either loaded from configuration files,
+-- or read from the command-line arguments, including:
+-- - locations of directories (cmd root dir, temp dir, etc)
-- - names of system commands
-- - etc
--- o application-wide options
-- o application-wide state
-- o logging
-- o temporary files
--
--- For simplicity, we consider this to be a singleton or
--- "static object" (with a single global "instance" called App.)
+-- Although App superficially resembles a class, it cannot be instantiated.
+-- Hence it can be considered a "package", or a "singleton class" or
+-- "static object", with a single global "instance".
+--
+
+--
+-- Container.
+--
App = {}
--
--- Initialize global stuff.
+-- Private data.
--
-App.init = function()
- App.defaults = {
- name = "Unnamed Application",
- logfile = "unnamed.log",
- dir = {
- root = "/",
- tmp = "/tmp/"
- },
- transport = "tcp",
- rendezvous = "9999"
- }
-
- App.last_log_time = -1
- App.conf_path = ""
- App.current_script = arg[0]
-
- App.config = {}
- App.option = {}
- App.state = {}
+local last_log_time = -1
+local current_script = nil
- App.add_pkg_path("./lib")
- App.add_pkg_path(FileName.dirname(App.current_script) .. "lib")
- App.add_conf_path("./conf")
- App.add_conf_path(FileName.dirname(App.current_script) .. "conf")
+--
+-- Private functions.
+--
- arg = App.process_cmdline(arg)
+--
+-- Add a directory to package.path (used by compat-5.1.)
+--
+local add_pkg_path = function(dir)
+ if package and package.path then
+ if package.path ~= "" then
+ package.path = package.path .. ";"
+ end
+ package.path = package.path .. tostring(dir) .. "/?.lua"
+ end
end
--
--- Startup and shutdown.
+-- Public static methods.
--
-App.start = function(opt)
- local k, v
+-----------------------------------------------------------------------
+-------------------------- Startup and Shutdown -----------------------
+-----------------------------------------------------------------------
+--
+-- Application startup.
+--
+App.start = function(arg)
--
- -- Private function to create a dummy user interface adapter
- -- if the App was started without one.
+ -- Begin setting up the App.
+ -- Initialize the global application containers.
+ -- Make the configuration table "see through" so that
+ -- the configuration files have access to all Lua functions.
--
- local new_dummy_ui = function()
- local method = {}
-
- method.start = function(method)
- App.log("Dummy user interface started")
- return true
- end
-
- method.stop = function(method)
- App.log("Dummy user interface stopped")
- return true
- end
-
- method.present = function(method, tab)
- App.dump_table(tab)
- return {
- action_id = tab.actions[1].id,
- datasets = tab.datasets
- }
- end
-
- method.inform = function(method, msg)
- App.log("INFORM: %s", msg)
- return { action_id = "ok", datasets = {} }
- end
-
- method.confirm = function(method, msg)
- App.log("CONFIRM: %s", msg)
- return true
- end
-
- method.select = function(method, msg, map)
- local k, v
- App.log("SELECT: %s", msg)
- for k, v in map do
- return v
- end
- end
-
- method.select_file = function(method, tab)
- App.log("SELECT FILE: %s", tab.title or "Select File")
- return "cancel"
- end
-
- --
- -- Constructor within a constructor, here...
- --
- method.new_progress_bar = function(method, tab)
- local method = {}
-
- method.start = function(method)
- App.log("START PROGRESS BAR")
- return true
- end
-
- method.set_amount = function(method, new_amount)
- App.log("SET PROGRESS AMOUNT: %d", new_amount)
- return true
- end
-
- method.set_short_desc = function(method, new_short_desc)
- App.log("SET PROGRESS DESC: %d", new_short_desc)
- return true
- end
-
- method.update = function(method)
- App.log("PROGRESS UPDATE: %d", new_amount)
- return true
- end
-
- method.stop = function(method)
- App.log("STOP PROGRESS BAR")
- return true
- end
-
- return method
- end
-
- return method
- end
+ App.conf = setmetatable({}, { __index = _G })
+ App.state = {}
--
- -- Begin setting up the App.
+ -- Set the current script to the script that was invoked, as it was
+ -- recorded as the first command-line argument.
--
+ current_script = assert(arg[0], "Missing script name")
- -- Set up defaults.
- if not opt then
- opt = {}
- end
+ --
+ -- Set up the default search path, based on the current script.
+ --
+ add_pkg_path(FileName.dirname(current_script) .. "lib")
- App.merge_tables(opt, App.defaults, function(key, dest_val, src_val)
- if not dest_val then
- return src_val
+ --
+ -- Process each command-line argument in turn.
+ --
+ local argn = 1
+ while arg[argn] do
+ if arg[argn] == "-L" then
+ argn = argn + 1
+ add_pkg_path(arg[argn])
+ elseif arg[argn] == "-t" then -- obsolete dfui transport
+ argn = argn + 1
+ App.set_property("ui.transport=" .. arg[argn])
+ elseif arg[argn] == "-r" then -- obsolete dfui rendezvous
+ argn = argn + 1
+ App.set_property("ui.rendezvous=" .. arg[argn])
+ elseif string.find(arg[argn], "=") then
+ App.set_property(arg[argn])
else
- return dest_val
+ App.load_conf(arg[argn])
end
- end)
- -- Set name of application.
- App.name = opt.name
- App.log_filename = opt.logfile
-
- -- Set up directories, and make sure each ends with a slash.
- App.dir = opt.dir
- for k, v in App.dir do
- if string.sub(v, -1) ~= "/" then
- App.dir[k] = v .. "/"
- end
+ argn = argn + 1
end
- -- Determine the operating system.
- App.os = {}
- App.os.name = App.determine_os_name()
- -- App.os.version = App.determine_os_version()
+ --
+ -- Fix up configuration:
+ --
- -- Open our logfile.
- App.open_log(App.dir.tmp .. App.log_filename)
- App.log(App.name .. " started")
+ --
+ -- Set the product name to the OS name, if not given.
+ --
+ App.conf.product.name =
+ App.conf.product.name or App.conf.os.name
+ App.conf.product.version =
+ App.conf.product.version or App.conf.os.version
- -- Load command names, if available.
- App.cmd_names = App.load_conf("cmdnames")
+ --
+ -- Make sure each directory in App.conf.dir ends with a slash.
+ --
+ local name, dir
+ for name, dir in App.conf.dir do
+ App.conf.dir[name] = FileName.add_trailing_slash(dir)
+ end
- -- Set up the ${}-expansion function.
- App.expand = function(str, ...)
- local ltables = arg or {}
- local gtables = {App.cmd_names, App.dir}
+ --
+ -- Open our logfile.
+ --
+ App.open_log(App.conf.dir.tmp .. App.conf.log_filename)
+ App.log("%s started", App.conf.app_name)
- local result = string.gsub(str, "%$%{([%w_]+)%}", function(key)
- local i, tab, value
-
- if table.getn(ltables) > 0 then
- for i, tab in ipairs(ltables) do
- value = tab[key]
- if value then
- return value
- end
- end
- end
-
- if table.getn(gtables) > 0 then
- for i, tab in ipairs(gtables) do
- value = tab[key]
- if value then
- return value
- end
- end
- end
-
- App.log_warn("Could not expand `${%s}'", key)
- return "${" .. key .. "}"
- end)
-
- return result
- end
-
+ --
-- Set up temporary files.
+ --
App.tmpfile = {}
-
- -- Set up application-specific containers:
- -- config: application configuration
- -- option: application-wide options
- -- state: application-wide state
- App.config = opt.config or App.config
- App.option = opt.option or App.option
- App.state = opt.state or App.state
+ --
-- Seed the random-number generator.
+ --
math.randomseed(os.time())
+end
- -- Set up the App's UI adapter.
- App.ui = opt.ui or new_dummy_ui()
+--
+-- Start the user interface. XXX this interface is a bit ugly now.
+--
+App.start_ui = function(ui)
+ --
+ -- Set up the App's UI bridge.
+ --
+ App.ui = ui or App.UIBridge.new(App.DummyUI)
if not App.ui:start() then
App.log_fatal("Could not start user interface")
end
end
+--
+-- Application shutdown.
+--
App.stop = function()
App.clean_tmpfiles()
App.ui:stop()
@@ -262,90 +211,18 @@
App.close_log()
end
-App.process_cmdline = function(arg)
- local argn = 1
- local remaining_arg = {}
-
- while arg[argn] do
- if arg[argn] == "-C" then
- argn = argn + 1
- App.add_conf_path(arg[argn])
- elseif arg[argn] == "-L" then
- argn = argn + 1
- App.add_pkg_path(arg[argn])
- elseif arg[argn] == "-R" then
- argn = argn + 1
- local script_name = App.find_script(arg[argn]) or arg[argn]
- local ok, result = App.run(script_name)
- if not ok then
- io.stderr:write("warning: could not run `" ..
- tostring(script_name) .. "':\n")
- io.stderr:write(result .. "\n")
- end
- elseif string.find(arg[argn], "=") then
- App.set_property(arg[argn])
- else
- table.insert(remaining_arg, arg[argn])
- end
-
- argn = argn + 1
- end
+-----------------------------------------------------------------------
+----------------- Locating and Running Scriptlets ---------------------
+-----------------------------------------------------------------------
- return remaining_arg
-end
-
--
--- Given a string in the form "foo.bar=baz", set the member "bar" of the
--- subtable "foo" of the App object to "baz".
+-- Determine the name of the currently running script.
--
-App.set_property = function(expr)
- local found, len, k, v, c, r, i, t
-
- t = App.defaults
- r = {}
- found, len, k, v = string.find(expr, "^(.*)=(.*)$")
- for c in string.gfind(k, "[^%.]+") do
- table.insert(r, c)
- end
- for i, c in r do
- if i == table.getn(r) then
- t[c] = v
- else
- if not t[c] then
- t[c] = {}
- end
- if type(t[c]) == "table" then
- t = t[c]
- else
- App.log_warn("%s: not a table", tostring(c))
- end
- end
- end
+App.get_current_script = function()
+ return current_script
end
--
--- Add a directory to package.path (used by compat-5.1.)
---
-App.add_pkg_path = function(dir)
- if package and package.path then
- if package.path ~= "" then
- package.path = package.path .. ";"
- end
- package.path = package.path .. tostring(dir) .. "/?.lua"
- end
-end
-
---
--- Add a directory to App.conf_path (used by App.load_conf().)
---
-App.add_conf_path = function(dir)
- if App.conf_path ~= "" then
- App.conf_path = App.conf_path .. ";"
- end
- App.conf_path = App.conf_path .. tostring(dir) .. "/?.lua"
-end
-
---
-- Run a Lua script.
-- Note that the script name must be either relative to the
-- current working directory, or fully-qualified.
@@ -356,11 +233,11 @@
-- if false, the second is an error message string.
--
App.run = function(script_name, ...)
- local save_script = App.current_script
+ local save_script = current_script
local save_args = ARG
local ok, result, fun, errmsg
- if App.option.fatal_errors then
+ if App.conf.fatal_errors then
assert(script_name and type(script_name) == "string",
"bad filename " .. tostring(script_name))
end
@@ -368,21 +245,18 @@
return false, "bad filename " .. tostring(script_name)
end
- App.add_pkg_path(FileName.dirname(script_name) .. "lib")
- App.add_conf_path(FileName.dirname(script_name) .. "conf")
-
fun, errmsg = loadfile(script_name)
- if App.option.fatal_errors then
+ if App.conf.fatal_errors then
assert(fun, errmsg)
end
if not fun then
return false, errmsg
end
- App.current_script = script_name
+ current_script = script_name
ARG = arg
- if App.option.fatal_errors then
+ if App.conf.fatal_errors then
ok = true
result = fun()
else
@@ -391,7 +265,7 @@
end)
end
ARG = save_args
- App.current_script = save_script
+ current_script = save_script
return ok, result
end
@@ -400,7 +274,7 @@
-- Find a Lua script.
--
App.find_script = function(script_name)
- script_name = FileName.dirname(App.current_script) .. script_name
+ script_name = FileName.dirname(current_script) .. script_name
if FileName.is_dir(script_name) then
if string.sub(script_name, -1, -1) ~= "/" then
@@ -422,64 +296,6 @@
end
--
--- Dump the contents of the given table to stdout,
--- primarily intended for debugging.
---
-App.dump_table = function(tab, indent)
- local k, v
-
- if not indent then
- indent = ""
- end
-
- for k, v in tab do
- if type(v) == "table" then
- print(indent .. tostring(k) .. "=")
- App.dump_table(v, indent .. "\t")
- else
- print(indent .. tostring(k) .. "=" .. tostring(v))
- end
- end
-end
-
---
--- Merge two tables by looking at each item from the second (src)
--- table and putting a value into the first (dest) table based on
--- the result of a provided callback function which receives the
--- key and bother values, and returns the resulting value.
---
--- An 'overriding' merge can be accomplished with:
--- function(key, dest_val, src_val)
--- return src_val
--- end
---
--- A 'non-overriding' merge can be accomplished with:
--- function(key, dest_val, src_val)
--- if dest_val == nil then
--- return src_val
--- else
--- return dest_val
--- end
--- end
---
-App.merge_tables = function(dest, src, fun)
- local k, v
-
- for k, v in src do
- if type(v) == "table" then
- if not dest[k] then
- dest[k] = {}
- end
- if type(dest[k]) == "table" then
- App.merge_tables(dest[k], v, fun)
- end
- else
- dest[k] = fun(k, dest[k], v)
- end
- end
-end
-
---
-- Run a script. Expects the full filename (will not search.)
-- Displays a nice dialog box if the script contained errors.
--
@@ -518,83 +334,64 @@
return App.run_script(App.find_script(script_name), unpack(arg))
end
+-----------------------------------------------------------------------
+-------------- Locating and Loading Configuration Files ---------------
+-----------------------------------------------------------------------
+
--
--- Wait for a condition to come true.
--- Display a (cancellable) progress bar while we wait.
--- Returns two values: whether the condition eventually
--- did come true, and roughly how long it took (if it
--- timed out, this value will be greater than the timeout.)
+-- A metatable that overloads the '+' operator on tables, so that
+-- 'a + b' results in an overriding merge of b's pairs into a.
--
-App.wait_for = function(tab)
- local predicate = tab.predicate
- local timeout = tab.timeout or 30
- local frequency = tab.frequency or 2
- local title = tab.title or "Please wait..."
- local short_desc = tab.short_desc or title
- local pr
- local time_elapsed = 0
- local cancelled = false
-
- assert(type(predicate) == "function")
-
- if predicate() then
- return true
+local overload_mt = {
+ __add = function(a, b)
+ App.merge_tables(a, b, function(key, dest_val, src_val)
+ return src_val
+ end)
+ return a
end
+}
- pr = App.ui:new_progress_bar{
- title = title,
- short_desc = short_desc
- }
- pr:start()
-
- while time_elapsed < timeout and not cancelled and not result do
- POSIX.nanosleep(frequency)
- time_elapsed = time_elapsed + frequency
- if predicate() then
- return true, time_elapsed
- end
- pr:set_amount((time_elapsed * 100) / timeout)
- cancelled = not pr:update()
- end
-
- pr:stop()
-
- return false, time_elapsed
-end
-
--
--- Configuration file loading.
+-- Load a configuration file, given its name.
--
+App.load_conf = function(filename)
+ App.log("Loading configuration file '%s'...", filename)
-App.locate_conf = function(name)
- local comp
+ --
+ -- Load and configuration file and compile it into a
+ -- function. Give the function the App.conf table
+ -- as its global context. Run the function, and all
+ -- of the values it has set will go into App.conf.
+ --
+ local conf_func, err = loadfile(filename)
+ if not conf_func then
+ App.log_fatal("Could not load configuration file '%s': %s",
+ name, err)
+ end
+ setfenv(conf_func, App.conf)
+ conf_func()
- for comp in string.gfind(App.conf_path, "[^;]+") do
- comp = string.gsub(comp, "?", name)
- if FileName.is_file(comp) then
- return comp
+ --
+ -- Make all the tables in the configuration extendable with
+ -- the '+' operator, for future conf files that may be loaded.
+ --
+ local name, value
+ for name, value in App.conf do
+ if type(value) == "table" then
+ setmetatable(value, overload_mt)
end
end
-
- return nil
end
-App.load_conf = function(name)
- local filename = App.locate_conf(name)
- if filename ~= nil then
- App.log("Loading configuration file '%s'...", filename)
- return App.run_script(filename)
- else
- App.log_warn("Could not locate configuration file '%s'!", name)
- return nil
- end
-end
+-----------------------------------------------------------------------
+----------------------------- Logging ---------------------------------
+-----------------------------------------------------------------------
--
--- Logging.
+-- Open the log.
+-- XXX This doesn't really need to be public, does it?
--
-
App.open_log = function(filename, mode)
if App.log_file then
return
@@ -611,6 +408,17 @@
end
end
+--
+-- Reopen the log with the same filename as it was opened with,
+-- after (temporarily) closing it.
+--
+App.reopen_log = function()
+ return App.open_log(App.conf.dir.tmp .. App.conf.log_filename, "a")
+end
+
+--
+-- Close the log.
+--
App.close_log = function()
if App.log_file then
App.log_file:close()
@@ -618,48 +426,72 @@
end
end
+--
+-- Write a line to the log.
+--
App.log = function(str, ...)
local stamp = math.floor(os.time())
- local line = ""
- local i, a
local write_log = function(s)
s = s .. "\n"
- io.stderr:write(s)
+ io.stdout:write(s)
+ io.stdout:flush()
if App.log_file then
App.log_file:write(s)
App.log_file:flush()
end
end
- if stamp > App.last_log_time then
- App.last_log_time = stamp
+ if stamp > last_log_time then
+ last_log_time = stamp
write_log("[" .. os.date() .. "]")
end
+ write_log(App.format(str, unpack(arg)))
+end
+App.format = function(str, ...)
str = string.gsub(str, "%%%a", "%%s")
- for i, a in ipairs(arg) do
- arg[i] = tostring(a)
+
+ local i
+ for i = 1, table.getn(arg) do
+ arg[i] = tostring(arg[i])
end
- write_log(string.format(str, unpack(arg)))
+
+ return string.format(str, unpack(arg))
+end
+
+--
+-- Write a plain string to the log (no formatting.)
+--
+App.log_string = function(str)
+ App.log("%s", str)
end
+--
+-- Write a warning to the log.
+--
App.log_warn = function(str, ...)
App.log("WARNING: " .. str, unpack(arg))
end
+--
+-- Write an error to the log.
+--
App.log_fatal = function(str, ...)
App.log(str, unpack(arg))
- error(str)
+ error(App.format(str, unpack(arg)))
end
+--
+-- Display the log in the abstract user interface.
+--
App.view_log = function()
local contents = ""
local fh
App.close_log()
- fh = io.open(App.dir.tmp .. App.log_filename, "r")
+ fh = io.open(App.conf.dir.tmp .. App.conf.log_filename, "r")
for line in fh:lines() do
contents = contents .. line .. "\n"
end
@@ -667,7 +499,7 @@
App.ui:present({
id = "app_log",
- name = App.name .. ": Log",
+ name = App.conf.app_name .. ": Log",
short_desc = contents,
role = "informative",
minimum_width = "72",
@@ -677,40 +509,64 @@
}
})
- App.open_log(App.dir.tmp .. App.log_filename, "a")
+ App.open_log(App.conf.dir.tmp .. App.conf.log_filename, "a")
end
--
--- Temporary file handling.
+-- Install logging wrappers around every method in a class/object.
+-- This is more useful for debugging purposes than for everyday use.
--
+App.log_methods = function(obj_method_table)
+ local k, v
+ for k, v in pairs(obj_method_table) do
+ local method_name, orig_fun = k, method[k]
+ method[k] = function(...)
+ App.log("ENTERING: %s", method_name)
+ orig_fun(unpack(arg))
+ App.log("EXITED: %s", method_name)
+ end
+ end
+end
+-----------------------------------------------------------------------
+------------------------- Temporary Files -----------------------------
+-----------------------------------------------------------------------
+
+--
+-- Delete all known temporary files.
+--
App.clean_tmpfiles = function()
local filename, unused
for filename, unused in App.tmpfile do
App.log("Deleting tmpfile: " .. filename)
- os.remove(App.dir.tmp .. filename)
+ os.remove(App.conf.dir.tmp .. filename)
end
end
--- Registers that the given file (which resides in App.dir.tmp)
+--
+-- Register that the given file (which resides in App.conf.dir.tmp)
-- is a temporary file, and may be deleted when upon exit.
+--
App.register_tmpfile = function(filename)
App.tmpfile[filename] = 1
end
--- Creates and opens a new temporary file (in App.dir.tmp).
+--
+-- Create and open a new temporary file (in App.conf.dir.tmp).
-- If the filename is omitted, one is chosen using the mkstemp
-- system call. If the mode is omitted, updating ("w+") is
-- assumed. The file object and the file name are returned.
+--
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list