-- This is a helper script for update-watch.
-- Run apt-get and extract packaged that to be installed,
-- updated, removed and duplicated.

rex = require("rex_posix")

basefile = "/var/tmp/update-watch-info."
filename = basefile.."tmp"

-- Function to extract real package name from allow-duplicated packages.
function realname(name)
    local s, e, name = string.find(name, "(.+)#")
    return name
end

-- Open output file that store list of to-be changed packages,
file = io.open(filename, "w")
if not file then
    print("error: can't open output file at "..filename)
    return
end

-- Get list ofmanually held packages and store it to local table.
-- those packages should be ignored by update-watch.

local holdlist = confgetlist("RPM::Hold") 

for i, expr in ipairs(holdlist) do
    holdlist[i] = rex.new(expr)
end

-- Mark whole system for upgrading to enable executing
-- apt-get upgrade --simulate for non root users.

markupgrade()

-- *NOTE* bellow block is copied from allow-duplicated.lua
-- to handle allow-duplicated packages properly.
----------<start copied block>----------
-- 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 copied block>----------

-- Print upgrade/new install/remove/hold package name if exist.
-- *NOTE: newinstall package appeares as upgrade one too. naze...

local new = {}
local upgrade = {}
local remove = {}
local hold = {}
local dup = {}

for i, pkg in pairs(pkglist()) do
    -- Check new and update package
    if statnewinstall(pkg) then
        table.insert(new,string.format("new:%s\n",pkgname(pkg)))
    elseif statupgrade(pkg) then
        table.insert(upgrade,string.format("upgrade:%s\n",pkgname(pkg)))
    end

    --- Check remove package
    if statremove(pkg) then
        table.insert(remove,string.format("remove:%s\n",pkgname(pkg)))
    end

    --- Check hold package
    if pkgvercur(pkg) ~= nil and pkgvercand(pkg) ~= nil and statupgrade(pkg) == nil then
        local found = false
        for i, expr in ipairs(holdlist) do
            if expr:match(pkgname(pkg)) then
                found = true
            end
        end
        if not found then
            table.insert(hold,string.format("hold:%s\n",pkgname(pkg)))
        end
    end
    
    --- check duplicate package
    local name = realname(pkgname(pkg))
    if name then
        local found = false
	for i, expr in ipairs(updatelist) do
            if expr:match(name) then
                found = true
                break
            end
        end
        if not found then
            table.insert(dup,string.format("duplicate:%s\n",pkgname(pkg)))
        end
    end

    
end

local function write(index, str)
    file:write(str)
end
table.foreach(new, write)
table.foreach(upgrade, write)
table.foreach(remove, write)
table.foreach(hold, write)
table.foreach(dup, write)
file:close()

os.execute("mv "..filename.." "..basefile.."`id -u`")
