-- This script will handle Allow-Duplicated packages when more -- than one is available during an install operation, and will -- also upgrade these packages in a dist-upgrade operation (if -- they match a regex in RPM::Allow-Duplicated-Upgrade). -- -- This script must be plugged in the following slots: -- -- Scripts::AptGet::Install::SelectPackage -- Scripts::AptGet::DistUpgrade -- Scripts::Synaptic::DistUpgrade -- -- Author: Gustavo Niemeyer rex = require("rex_posix") function realname(name) local s, e, name = string.find(name, "(.+)#") return name end function get_pkglist(name) local j = 1 local packages = {} for i, p in ipairs(pkglist()) do if realname(pkgname(p)) == name then packages[j] = p j = j + 1 end end return packages end -- select best choice of virtual provided packages function select_goodpackage(packages) local goodpkg = packages[1] local goodpkgname = realname(pkgname(goodpkg)) if goodpkgname then -- Check if every package has the same real name, and -- leave only the one with the greatest version, if -- that's the case. for i = 2, table.getn(packages) do local nextpkg = packages[i] local nextpkgname = realname(pkgname(nextpkg)) if nextpkgname ~= goodpkgname then --markkeep(goodpkg) goodpkg = nil break end if not pkgvercand(goodpkg) or pkgvercand(nextpkg) and verstrcmp(verstr(pkgvercand(goodpkg)), verstr(pkgvercand(nextpkg))) == -1 then --markkeep(goodpkg) goodpkg = nextpkg end end if goodpkg and pkgvercand(goodpkg) then selected = goodpkg markinstall(goodpkg) end end if not selected then -- Strip #... from package names if we can't find a good solution. for i, name in ipairs(packagenames) do local name = realname(name) if name and name ~= virtualname then packagenames[i] = name end end end end if script_slot == "Scripts::AptGet::Install::PreResolve" then for i, pkg in ipairs(pkglist()) do s, e, name = string.find(pkgname(pkg), "(.+)#") if statinstall(pkg) and s then -- unmark selected packages markkeep(pkg) local packages = {} packages = get_pkglist(name) select_goodpackage(packages) end end end if script_slot == "Scripts::AptGet::Install::SelectPackage" then local found = 0 for i, pkg in ipairs(packages) do p = pkgfind(pkgname(pkg)) if pkgvercur(p) then found = 1 end end if found == 0 then select_goodpackage(packages) end end if script_slot == "Scripts::AptGet::DistUpgrade" or script_slot == "Scripts::AptGet::Upgrade" or script_slot == "Scripts::Synaptic::DistUpgrade" or script_slot == "Scripts::Synaptic::Upgrade" then -- Automatically install newer versions of all packages which -- are registered in the Allow-Duplicated scheme and are matched -- by the regular expressions in RPM::Allow-Duplicated-Upgrade. -- Compile expressions with package names which should -- be considered for upgrade. local updatelist = confgetlist("RPM::Allow-Duplicated-Upgrade") for i, expr in ipairs(updatelist) do updatelist[i] = rex.new(expr) end if table.getn(updatelist) ~= 0 then -- Gather information about Allow-Duplicated packges. local canddups = {} local curdups = {} for i, pkg in pairs(pkglist()) do local name = realname(pkgname(pkg)) if name then if pkgvercur(pkg) then if not curdups[name] then curdups[name] = {} end table.insert(curdups[name], verstr(pkgvercur(pkg))) elseif pkgvercand(pkg) then if not canddups[name] then canddups[name] = {} end table.insert(canddups[name], verstr(pkgvercand(pkg))) end end end -- Compile expressions with package names which should be hold. local holdlist = confgetlist("RPM::Hold") for i, expr in ipairs(holdlist) do holdlist[i] = rex.new(expr) end -- Remove packages without any matches in updatelist, or with -- any matches in holdlist. for name, _ in pairs(curdups) do local found = false for i, expr in ipairs(updatelist) do if expr:match(name) then found = true break end end if found then for i, expr in ipairs(holdlist) do if expr:match(name) then found = false break end end end if not found then curdups[name] = nil end end -- Mark the newest packages for installation. for name, _ in pairs(curdups) do if canddups[name] then -- Check the best candidate version. local bestver = nil for i, ver in ipairs(canddups[name]) do if not bestver or verstrcmp(bestver, ver) == -1 then bestver = ver end end -- Now check if it's newer than all installed -- versions. for i, ver in ipairs(curdups[name]) do if verstrcmp(ver, bestver) == 1 then bestver = nil break end end -- Finally, mark it for installation. if bestver then markinstall(name.."#"..bestver) end end end end end -- vim:ts=4:sw=4:et