#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (C) 2010, 2012  Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Do a size comparison of the files on two ISOs. This can be used to find out
# which packages were added, removed, and significantly changed in size between
# two releases or daily builds. Note that this only really works for
# alternates, since desktop CDs by and large just have one big squashfs image.

from __future__ import print_function

import subprocess
import sys


def deb_size_map(iso_path):
    map = {}  # package -> (version, size)
    isoinfo = subprocess.Popen(
        ['isoinfo', '-lR', '-i', iso_path],
        stdout=subprocess.PIPE, universal_newlines=True)
    out = isoinfo.communicate()[0]
    assert isoinfo.returncode == 0

    for l in out.splitlines():
        l = l.strip()
        if not l.endswith('.deb'):
            continue

        fields = l.split()
        size = int(fields[4])
        fname = fields[11]

        (pkg, version, _) = fname.split('_')
        map[pkg] = (version, size)

    return map

#
# main
#

if len(sys.argv) != 3:
    print('Usage: %s <old iso> <new iso>' % sys.argv[0], file=sys.stderr)
    sys.exit(1)

old_map = deb_size_map(sys.argv[1])
new_map = deb_size_map(sys.argv[2])

print('== Removed packages ==')
sum = 0
for p, (v, s) in old_map.iteritems():
    if p not in new_map:
        print('%s (%.1f MB)' % (p, s / 1000000.))
        sum += s
print('TOTAL: -%.1f MB' % (sum / 1000000.))

sum = 0
print('\n== Added packages ==')
for p, (v, s) in new_map.iteritems():
    if p not in old_map:
        print('%s (%.1f MB)' % (p, s / 1000000.))
        sum += s
print('TOTAL: +%.1f MB' % (sum / 1000000.))

print('\n== Changed packages ==')
sum = 0
for p, (v, s) in old_map.iteritems():
    if p not in new_map:
        continue

    new_s = new_map[p][1]
    sum += new_s - s

    # only show differences > 100 kB to filter out noise
    if new_s - s > 100000:
        print('%s (Δ %.1f MB - %s: %.1f MB   %s: %.1f MB)' % (
              p, (new_s - s) / 1000000., v, s / 1000000., new_map[p][0],
              new_s / 1000000.))

print('TOTAL difference: %.1f MB' % (sum / 1000000.))
