[mojosetup] [2/13] Delete obsolete files and directories on upgrade.
Francois Gouget
fgouget at codeweavers.com
Mon May 21 13:53:29 EDT 2012
We try to be careful when loading the old Lua manifest so that a corrupted file does not crash the installer and does not clobber our state information.
---
Leaving obsolete libraries behind could cause major trouble for
instance. This requires reading the old manifest to know which files the
previous version had installed.
scripts/mojosetup_mainline.lua | 82 +++++++++++++++++++++++++++++++++++-----
1 file changed, 73 insertions(+), 9 deletions(-)
diff --git a/scripts/mojosetup_mainline.lua b/scripts/mojosetup_mainline.lua
index 1cd8ed9..79489ec 100644
--- a/scripts/mojosetup_mainline.lua
+++ b/scripts/mojosetup_mainline.lua
@@ -105,6 +105,10 @@ local function manifest_add(man, fname, _key, ftype, mode, sums, lndest)
checksums = sums,
linkdest = lndest
}
+
+ if MojoSetup.oldfiles[fname] ~= nil then
+ MojoSetup.oldfiles[fname].seen = true
+ end
end
end
@@ -505,6 +509,18 @@ local function install_parent_dirs(path, manifestkey)
end
+local function backup_file(path)
+ local id = #MojoSetup.rollbacks + 1
+ local f = MojoSetup.rollbackdir .. "/" .. id
+ install_parent_dirs(f, MojoSetup.metadatakey)
+ MojoSetup.rollbacks[id] = path
+ if not MojoSetup.movefile(path, f) then
+ MojoSetup.fatal(MojoSetup.format(_("Couldn't backup '%0' to '%1' for rollback"), path, f))
+ end
+ MojoSetup.loginfo("Moved rollback #" .. id .. ": '" .. path .. "' -> '" .. f .. "'")
+end
+
+
local function permit_write(dest, entinfo, file)
local allowoverwrite = true
if MojoSetup.platform.exists(dest) then
@@ -538,15 +554,7 @@ local function permit_write(dest, entinfo, file)
-- !!! FIXME: Setup.File.mustoverwrite to override "never"?
if allowoverwrite then
- local id = #MojoSetup.rollbacks + 1
- local f = MojoSetup.rollbackdir .. "/" .. id
- install_parent_dirs(f, MojoSetup.metadatakey)
- MojoSetup.rollbacks[id] = dest
- if not MojoSetup.movefile(dest, f) then
- MojoSetup.fatal(_("Couldn't backup file for rollback"))
- end
- MojoSetup.loginfo("Moved rollback #" .. id .. ": '" .. dest .. "' -> '" .. f .. "'")
-
+ backup_file(dest)
-- Make sure this isn't already in the manifest...
if MojoSetup.manifest[dest] ~= nil then
manifest_delete(MojoSetup.manifest, dest)
@@ -1262,6 +1270,33 @@ local function stop_gui()
end
+local function load_oldpackage()
+ local filename = MojoSetup.metadatadir .. "/manifest/" .. MojoSetup.install.id .. ".lua"
+ local fh, err = io.open(filename, "r")
+ if not fh then
+ MojoSetup.logerror("could not open '" .. filename .. "' for reading: " .. err)
+ return {}
+ end
+ local data = fh:read("*all")
+ fh:close()
+
+ local env = {MojoSetup = {}}
+ local lua_func, err = loadstring("function loadstring() end\n" .. data)
+ if not lua_func then
+ MojoSetup.logerror("could not parse '" .. filename .. "': " .. err)
+ return {}
+ end
+ setfenv(lua_func, env)
+
+ local ran, err = pcall(lua_func)
+ if not ran then
+ MojoSetup.logerror("could not run '" .. filename .. "' " .. err)
+ return {}
+ end
+ return env.MojoSetup.package
+end
+
+
local function do_install(install)
MojoSetup.forceoverwrite = nil
MojoSetup.written = 0
@@ -1555,6 +1590,16 @@ local function do_install(install)
-- This is not a GUI stage, it just needs to run between them.
-- This gets a little hairy.
stages[#stages+1] = function(thisstage, maxstage)
+ -- Load the list of files of the previous installation
+ -- (empty if this is a first time install)
+ MojoSetup.oldpackage = load_oldpackage()
+ MojoSetup.oldfiles = {}
+ if MojoSetup.oldpackage ~= nil and MojoSetup.oldpackage.manifest ~= nil then
+ for path,file in pairs(MojoSetup.oldpackage.manifest) do
+ MojoSetup.oldfiles[path] = file
+ end
+ end
+
-- Make sure we install the destination dir, so it's in the manifest.
if not MojoSetup.platform.exists(MojoSetup.destination) then
install_parent_dirs(MojoSetup.destination, MojoSetup.metadatakey)
@@ -1794,6 +1839,14 @@ local function do_install(install)
install_manifests(MojoSetup.metadatadesc, MojoSetup.metadatakey)
end
+ -- Move away obsolete files so they get deleted
+ for path,file in pairs(MojoSetup.oldfiles) do
+ if file.seen == nil and file.type == 'file' then
+ MojoSetup.loginfo("Obsoleting file '" .. path .. "'")
+ backup_file(MojoSetup.destination .. "/" .. path)
+ end
+ end
+
return 1 -- go to next stage.
end
@@ -1845,6 +1898,17 @@ local function do_install(install)
delete_files(MojoSetup.downloads)
delete_scratchdirs()
+ -- Delete obsolete directories
+ table.sort(MojoSetup.oldfiles, function(a,b) return MojoSetup.strcmp(a,b) < 0 end)
+ for path,file in pairs(MojoSetup.oldfiles) do
+ if file.seen == nil and file.type == 'directory' then
+ MojoSetup.loginfo("Obsoleting directory '" .. path .. "'")
+ -- It's ok if this fails. Most likely it just means the directory
+ -- is not empty.
+ MojoSetup.platform.unlink(MojoSetup.destination .. "/" .. path)
+ end
+ end
+
-- Don't let future errors delete files from successful installs...
MojoSetup.downloads = nil
MojoSetup.rollbacks = nil
--
1.7.10
More information about the mojosetup
mailing list