r484 - in trunk: . examples/duke3d/scripts examples/ut3-dedicated/scripts scripts
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Wed Feb 13 03:52:25 EST 2008
Author: icculus
Date: 2008-02-13 03:52:23 -0500 (Wed, 13 Feb 2008)
New Revision: 484
Modified:
trunk/docs.txt
trunk/examples/duke3d/scripts/config.lua
trunk/examples/ut3-dedicated/scripts/config.lua
trunk/lua_glue.c
trunk/platform.h
trunk/platform_unix.c
trunk/scripts/config.lua
trunk/scripts/localization.lua
trunk/scripts/mojosetup_init.lua
trunk/scripts/mojosetup_mainline.lua
Log:
First shot at desktop menu items.
Modified: trunk/docs.txt
===================================================================
--- trunk/docs.txt 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/docs.txt 2008-02-13 08:52:23 UTC (rev 484)
@@ -182,6 +182,20 @@
Setup.Package attributes:
+ vendor (no default, mustExist, mustBeString, cantBeEmpty)
+
+ This is a unique identifier for your organization. This should be in the
+ format "companyname.dom" ... the hope is that your primary website is
+ a unique identifier for your company. If your website is www.icculus.org,
+ you'd enter your vendor setting as "icculus.org" ... just the hostname and
+ top-level domain. This is used largely by the OS to maintain packages
+ (Mac OS X application bundles, vendor IDs for Unix desktop menus, etc).
+ This is, in theory, never shown to the user, so you don't need this to
+ actually exist as a website with meaningful content, so long as you can
+ reasonably assure that the string is unique and follows the "host.dom"
+ format.
+
+
id (no default, mustExist, mustBeString, cantBeEmpty)
This is a unique identifier for your package. Currently it is used as
Modified: trunk/examples/duke3d/scripts/config.lua
===================================================================
--- trunk/examples/duke3d/scripts/config.lua 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/examples/duke3d/scripts/config.lua 2008-02-13 08:52:23 UTC (rev 484)
@@ -22,6 +22,7 @@
Setup.Package
{
+ vendor = "icculus.org",
id = "duke3d",
description = "Duke Nukem 3D",
version = "1.5",
Modified: trunk/examples/ut3-dedicated/scripts/config.lua
===================================================================
--- trunk/examples/ut3-dedicated/scripts/config.lua 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/examples/ut3-dedicated/scripts/config.lua 2008-02-13 08:52:23 UTC (rev 484)
@@ -3,6 +3,7 @@
Setup.Package
{
+ vendor = "epicgames.com",
id = "ut3-dedicated",
description = "Unreal Tournament 3 Dedicated Server",
version = "3487",
Modified: trunk/lua_glue.c
===================================================================
--- trunk/lua_glue.c 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/lua_glue.c 2008-02-13 08:52:23 UTC (rev 484)
@@ -1057,6 +1057,20 @@
} // luahook_platform_mkdir
+static int luahook_platform_installdesktopmenuitem(lua_State *L)
+{
+ const char *data = luaL_checkstring(L, 1);
+ return retvalBoolean(L, MojoPlatform_installDesktopMenuItem(data));
+} // luahook_platform_installdesktopmenuitem
+
+
+static int luahook_platform_uninstalldesktopmenuitem(lua_State *L)
+{
+ const char *data = luaL_checkstring(L, 1);
+ return retvalBoolean(L, MojoPlatform_uninstallDesktopMenuItem(data));
+} // luahook_platform_uninstalldesktopmenuitem
+
+
static int luahook_movefile(lua_State *L)
{
boolean retval = false;
@@ -1669,6 +1683,8 @@
set_cfunc(luaState, luahook_platform_isfile, "isfile");
set_cfunc(luaState, luahook_platform_symlink, "symlink");
set_cfunc(luaState, luahook_platform_mkdir, "mkdir");
+ set_cfunc(luaState, luahook_platform_installdesktopmenuitem, "installdesktopmenuitem");
+ set_cfunc(luaState, luahook_platform_uninstalldesktopmenuitem, "uninstalldesktopmenuitem");
lua_setfield(luaState, -2, "platform");
// Set the GUI functions...
Modified: trunk/platform.h
===================================================================
--- trunk/platform.h 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/platform.h 2008-02-13 08:52:23 UTC (rev 484)
@@ -231,6 +231,20 @@
// the browser will inform the user if there's a problem loading the URL.
boolean MojoPlatform_launchBrowser(const char *url);
+// Add a menu item to the Application menu or Start bar or whatever.
+// (data) is 100% platform dependent right now, and this interface will
+// likely change as we come to understand various systems' needs better.
+// On Unix, it expects this to be a path to a FreeDesktop .desktop file.
+// Returns (true) on success and (false) on failure.
+boolean MojoPlatform_installDesktopMenuItem(const char *data);
+
+// Remove a menu item from the Application menu or Start bar or whatever.
+// (data) is 100% platform dependent right now, and this interface will
+// likely change as we come to understand various systems' needs better.
+// On Unix, it expects this to be a path to a FreeDesktop .desktop file.
+// Returns (true) on success and (false) on failure.
+boolean MojoPlatform_uninstallDesktopMenuItem(const char *data);
+
#if !SUPPORT_MULTIARCH
#define MojoPlatform_switchBin(img, len)
#else
Modified: trunk/platform_unix.c
===================================================================
--- trunk/platform_unix.c 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/platform_unix.c 2008-02-13 08:52:23 UTC (rev 484)
@@ -26,7 +26,7 @@
#include <syslog.h>
#include <dirent.h>
#include <fcntl.h>
-#include <wait.h>
+#include <sys/wait.h>
#if MOJOSETUP_HAVE_SYS_UCRED_H
# ifdef MOJOSETUP_HAVE_MNTENT_H
@@ -1063,28 +1063,47 @@
} // shellEscape
-static boolean unix_launchBrowser(const char *url)
+static boolean unix_launchXdgUtil(const char *util, const char **argv)
{
boolean retval = false;
- char *path = findBinaryInPath("xdg-open");
+ char *path = findBinaryInPath(util);
if (path != NULL) // it's installed on the system; use that.
{
- char *escapedurl = shellEscape(url);
- char *cmd = format("xdg-open %0 >/dev/null 2>&1", escapedurl);
+ char *cmd = path;
+ char *tmp = NULL;
+ int i;
+ for (i = 0; argv[i]; i++)
+ {
+ char *escaped = shellEscape(argv[i]);
+ tmp = format("%0 %1", cmd, escaped);
+ free(escaped);
+ free(cmd);
+ cmd = tmp;
+ } // for
+
+ tmp = format("%0 >/dev/null 2>&1", cmd);
+ free(cmd);
+ cmd = tmp;
retval = (system(cmd) == 0);
free(cmd);
- free(escapedurl);
- free(path);
} // if
else // try our fallback copy of xdg-utils in GBaseArchive?
{
- const char *argv[] = { url, NULL };
- retval = (runScript("meta/xdg-utils/xdg-open", true, argv) == 0);
+ char *script = format("meta/xdg-utils/%0", util);
+ retval = (runScript(script, true, argv) == 0);
+ free(script);
} // if
return retval;
+} // unix_launchXdgUtil
+
+
+static boolean unix_launchBrowser(const char *url)
+{
+ const char *argv[] = { url, NULL };
+ return unix_launchXdgUtil("xdg-open", argv);
} // unix_launchBrowser
#endif
@@ -1106,6 +1125,32 @@
} // MojoPlatform_launchBrowser
+boolean MojoPlatform_installDesktopMenuItem(const char *data)
+{
+#if PLATFORM_MACOSX || PLATFORM_BEOS
+ // !!! FIXME: write me.
+ STUBBED("desktop menu support");
+ return false;
+#else
+ const char *argv[] = { "install", data, NULL };
+ return unix_launchXdgUtil("xdg-desktop-menu", argv);
+#endif
+} // MojoPlatform_installDesktopMenuItem
+
+
+boolean MojoPlatform_uninstallDesktopMenuItem(const char *data)
+{
+#if PLATFORM_MACOSX || PLATFORM_BEOS
+ // !!! FIXME: write me.
+ STUBBED("desktop menu support");
+ return false;
+#else
+ const char *argv[] = { "uninstall", data, NULL };
+ return unix_launchXdgUtil("xdg-desktop-menu", argv);
+#endif
+} // MojoPlatform_uninstallDesktopMenuItem
+
+
#if SUPPORT_MULTIARCH
void MojoPlatform_switchBin(const uint8 *img, size_t len)
{
Modified: trunk/scripts/config.lua
===================================================================
--- trunk/scripts/config.lua 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/scripts/config.lua 2008-02-13 08:52:23 UTC (rev 484)
@@ -35,6 +35,7 @@
Setup.Package
{
+ vendor = "com.mycompany",
id = "mygame",
description = "My Game",
version = "1.0",
@@ -131,6 +132,19 @@
end
},
+ Setup.DesktopMenuItem
+ {
+ disabled = false,
+ name = "My Game",
+ genericname = "Shoot-em up",
+ comment = "A game for shooting aliens.",
+ builtin_icon = false,
+ icon = "icon.png", -- relative to the dest; you must install it!
+ commandline = "command-line",
+ categories = "Game",
+ mimetype = { 'application/x-mygame-map', 'application/x-mygame-url' },
+ },
+
-- Here's an option that has it's own EULA.
Setup.Option
{
Modified: trunk/scripts/localization.lua
===================================================================
--- trunk/scripts/localization.lua 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/scripts/localization.lua 2008-02-13 08:52:23 UTC (rev 484)
@@ -303,6 +303,13 @@
nb = "FEIL: write_manifest krever støtte for Lua-parser",
};
+ -- This is shown if the config file wants us to add desktop menu items
+ -- but uninstaller support isn't enabled. This is considered bad taste
+ -- to add system menu items without a way to remove them. This is
+ -- a bug the developer must fix before shipping her installer.
+ ["BUG: Setup.DesktopMenuItem requires support_uninstall"] = {
+ };
+
-- This is a file's permissions. Programmers give these as strings, and
-- if one isn't valid, the program will report this. So, on Unix, they
-- might specify "0600" as a valid string, but "sdfksjdfk" wouldn't be
@@ -1014,6 +1021,18 @@
["[Make the window taller!]"] = {
nb = "[Gjør vinduet høyere!]",
};
+
+ -- This is written out if we failed to add an item to the desktop
+ -- application menu (or "Start" bar on Windows, or maybe the Dock on
+ -- Mac OS X, etc).
+ ["Failed to install desktop menu item"] = {
+ };
+
+ -- This is written out if we failed to remove an item from the desktop
+ -- application menu (or "Start" bar on Windows, or maybe the Dock on
+ -- Mac OS X, etc).
+ ["Failed to uninstall desktop menu item"] = {
+ };
};
-- end of localization.lua ...
Modified: trunk/scripts/mojosetup_init.lua
===================================================================
--- trunk/scripts/mojosetup_init.lua 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/scripts/mojosetup_init.lua 2008-02-13 08:52:23 UTC (rev 484)
@@ -245,6 +245,7 @@
tab = sanitize("Package", tab,
{
+ { "vendor", nil, mustExist, mustBeString, cantBeEmpty },
{ "id", nil, mustExist, mustBeString, cantBeEmpty },
{ "disabled", nil, mustBeBool },
{ "description", nil, mustExist, mustBeString, cantBeEmpty },
@@ -406,6 +407,20 @@
})
end
+function Setup.DesktopMenuItem(tab)
+ return sanitize("DesktopMenuItem", tab,
+ {
+ { "disabled", nil, mustBeBool },
+ { "name", nil, mustExist, mustBeString, cantBeEmpty },
+ { "genericname", nil, mustExist, mustBeString, cantBeEmpty },
+ { "comment", nil, mustExist, mustBeString, cantBeEmpty },
+ { "builtin_icon", nil, mustBeBool },
+ { "icon", nil, mustExist, mustBeString, cantBeEmpty },
+ { "commandline", nil, mustExist, mustBeString, cantBeEmpty },
+ { "category", nil, mustExist, mustBeStringOrTableOfStrings },
+ { "mimetype", nil, mustBeStringOrTableOfStrings },
+ })
+end
local function prepare_localization()
-- Map some legacy language identifiers into updated equivalents.
Modified: trunk/scripts/mojosetup_mainline.lua
===================================================================
--- trunk/scripts/mojosetup_mainline.lua 2008-02-12 19:59:30 UTC (rev 483)
+++ trunk/scripts/mojosetup_mainline.lua 2008-02-13 08:52:23 UTC (rev 484)
@@ -125,6 +125,24 @@
end
+local function flatten_list(list)
+ local retval = list
+ if type(list) == "table" then
+ retval = ''
+ local first = true
+ for i,v in ipairs(list) do
+ if first then
+ retval = v
+ first = false
+ else
+ retval = retval .. ';' .. v
+ end
+ end
+ end
+ return retval
+end
+
+
local function do_delete(fname)
local retval = false
if fname == nil then
@@ -228,21 +246,7 @@
-- (The real revertinstall is set later. This is a stub for startup.)
end
-local function real_revertinstall()
- if MojoSetup.gui_started then
- MojoSetup.gui.final(_("Incomplete installation. We will revert any changes we made."))
- end
- MojoSetup.loginfo("Cleaning up half-finished installation...")
-
- -- !!! FIXME: callbacks here.
- delete_files(MojoSetup.downloads)
- delete_files(flatten_manifest(MojoSetup.manifest, prepend_dest_dir))
- do_rollbacks()
- delete_scratchdirs()
-end
-
-
local function calc_percent(current, total)
if total == 0 then
return 0
@@ -605,7 +609,7 @@
if #wildcards > 1 then
single_match = false
else
- for k,v in ipairs(wildcards) do
+ for i,v in ipairs(wildcards) do
if string.find(v, "[*?]") ~= nil then
single_match = false
break -- no reason to keep iterating...
@@ -632,7 +636,7 @@
if wildcards == nil then
should_install = true
else
- for k,v in ipairs(wildcards) do
+ for i,v in ipairs(wildcards) do
if MojoSetup.wildcardmatch(ent.filename, v) then
should_install = true
break -- no reason to keep iterating...
@@ -927,10 +931,10 @@
-- Man, I hate escaping shell strings...
local bin = "\"`dirname $0`\"'/" .. MojoSetup.metadatadirname .. "/" ..
MojoSetup.controlappname .. "'"
- string.gsub(bin, "'", "'\\''") -- Escape single quotes for shell.
+ string.gsub(bin, "'", "'\\''") -- !!! FIXME: no-op!-- Escape single quotes for shell.
local id = MojoSetup.install.id
- string.gsub(id, "'", "'\\''")
+ string.gsub(id, "'", "'\\''") -- !!! FIXME: no-op!
local script =
"#!/bin/sh\n" ..
@@ -965,12 +969,14 @@
local package =
{
id = MojoSetup.install.id,
+ vendor = MojoSetup.install.vendor,
description = MojoSetup.install.description,
root = MojoSetup.destination,
update_url = MojoSetup.install.updateurl,
version = MojoSetup.install.version,
manifest = MojoSetup.manifest,
- splash = MojoSetup.install.splash
+ splash = MojoSetup.install.splash,
+ desktopmenuitems = MojoSetup.install.desktopmenuitems
}
-- now build these things...
@@ -981,6 +987,90 @@
end
+local function freedesktop_menuitem_filename(pkg, idx) -- only for Unix.
+ local vendor = string.gsub(pkg.vendor, "%..*$", "", 1) -- chop off TLD.
+ local fname = vendor .. "-" .. pkg.id .. idx .. ".desktop"
+ return MojoSetup.metadatadir .. "/" .. fname
+end
+
+
+local function uninstall_desktop_menu_items(pkg)
+ -- !!! FIXME: GUI progress?
+ if pkg.desktopmenuitems ~= nil then
+ for i,v in ipairs(pkg.desktopmenuitems) do
+ if MojoSetup.info.platform == "windows" then
+ MojoSetup.fatal(_("Unimplemented")) -- !!! FIXME: write me.
+ elseif MojoSetup.info.platform == "macosx" then
+ MojoSetup.fatal(_("Unimplemented")) -- !!! FIXME: write me.
+ elseif MojoSetup.info.platform == "beos" then
+ MojoSetup.fatal(_("Unimplemented")) -- !!! FIXME: write me.
+ else -- freedesktop, we hope.
+ local fname = freedesktop_menuitem_filename(pkg, idx)
+ if not MojoSetup.platform.uninstalldesktopmenuitem(fname) then
+ MojoSetup.fatal(_("Failed to uninstall desktop menu item"))
+ end
+ end
+ end
+ end
+end
+
+
+local function install_freedesktop_menuitem(pkg, idx, item) -- only for Unix.
+ local icon
+ if item.builtin_icon then
+ icon = item.icon
+ else
+ icon = MojoSetup.destination .. "/" .. item.icon
+ end
+
+ local str = "[Desktop Entry]\n" ..
+ "Encoding=UTF-8\n" ..
+ "Value=1.0\n" ..
+ "Type=Application\n" ..
+ "Name=" .. item.name .. "\n" ..
+ "GenericName=" .. item.genericname .. "\n" ..
+ "Comment=" .. item.comment .. "\n" ..
+ "Icon=" .. icon .. "\n" ..
+ "Exec=" .. item.commandline .. "\n" ..
+ "Categories=" .. flatten_list(item.categories) .. "\n"
+
+ if item.mimetype ~= nil then
+ str = str .. "MimeType=" .. flatten_list(item.mimetype) .. "\n"
+ end
+
+ str = str .. "\n"
+
+ local dest = freedesktop_menuitem_filename(pkg, idx)
+ local perms = "0644" -- !!! FIXME
+ local key = MojoSetup.metadatakey
+ local desc = MojoSetup.metadatadesc
+ install_file_from_string(dest, str, perms, desc, key)
+ if not MojoSetup.platform.installdesktopmenuitem(dest) then
+ MojoSetup.fatal(_("Failed to install desktop menu item"))
+ end
+end
+
+
+local function install_desktop_menu_items(pkg)
+ -- !!! FIXME: GUI progress?
+ if pkg.desktopmenuitems ~= nil then
+ for i,item in ipairs(pkg.desktopmenuitems) do
+ if not item.disabled then
+ if MojoSetup.info.platform == "windows" then
+ MojoSetup.fatal(_("Unimplemented")) -- !!! FIXME: write me.
+ elseif MojoSetup.info.platform == "macosx" then
+ MojoSetup.fatal(_("Unimplemented")) -- !!! FIXME: write me.
+ elseif MojoSetup.info.platform == "beos" then
+ MojoSetup.fatal(_("Unimplemented")) -- !!! FIXME: write me.
+ else -- freedesktop, we hope.
+ install_freedesktop_menuitem(pkg, i, item)
+ end
+ end
+ end
+ end
+end
+
+
local function start_gui(desc, splashfname)
if splashfname ~= nil then
splashfname = 'meta/' .. splashfname
@@ -1022,6 +1112,12 @@
MojoSetup.fatal(_("BUG: support_uninstall requires write_manifest"))
end
+ -- Desktop icons should probably require uninstall so we don't clutter
+ -- the system with no option for reversal later.
+ if (install.desktopmenuitems ~= nil) and (not install.support_uninstall) then
+ MojoSetup.fatal(_("BUG: Setup.DesktopMenuItem requires support_uninstall"))
+ end
+
-- Manifest support requires the Lua parser.
if (install.write_manifest) and (not MojoSetup.info.luaparser) then
MojoSetup.fatal(_("BUG: write_manifest requires Lua parser support"))
@@ -1408,7 +1504,7 @@
end
end
- run_config_defined_hook(install.postinstall, install)
+ install_desktop_menu_items(install)
if install.support_uninstall then
if MojoSetup.info.platform == "windows" then
@@ -1418,6 +1514,8 @@
end
end
+ run_config_defined_hook(install.postinstall, install)
+
if install.write_manifest then
install_control_app(MojoSetup.metadatadesc, MojoSetup.metadatakey)
install_manifests(MojoSetup.metadatadesc, MojoSetup.metadatakey)
@@ -1500,6 +1598,22 @@
end
+local function real_revertinstall()
+ if MojoSetup.gui_started then
+ MojoSetup.gui.final(_("Incomplete installation. We will revert any changes we made."))
+ end
+
+ MojoSetup.loginfo("Cleaning up half-finished installation...")
+
+ -- !!! FIXME: callbacks here.
+ uninstall_desktop_menu_items(MojoSetup.install)
+ delete_files(MojoSetup.downloads)
+ delete_files(flatten_manifest(MojoSetup.manifest, prepend_dest_dir))
+ do_rollbacks()
+ delete_scratchdirs()
+end
+
+
local function installer()
MojoSetup.loginfo("Installer starting")
@@ -1650,7 +1764,9 @@
if uninstall_permitted then
start_gui(package.description, package.splash)
- -- Upvalued so we don't look this up each time...
+ uninstall_desktop_menu_items(package)
+
+ -- Upvalued in callback so we don't look this up each time...
local ptype = _("Uninstalling")
local callback = function(fname, current, total)
fname = make_relative(fname, MojoSetup.destination)
More information about the mojosetup-commits
mailing list