#! /usr/bin/perl

# $OpenBSD: register-plist,v 1.7 2006/02/09 12:03:55 espie Exp $
# Copyright (c) 2005
# Marc Espie.  All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Neither the name of OpenBSD nor the names of its contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY ITS AUTHOR AND THE OpenBSD project ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

use strict;

use OpenBSD::PackageLocator;
use OpenBSD::PackageInfo;
use OpenBSD::PackingList;

package OpenBSD::PackingElement;

sub forget_details
{
}

sub flatten
{
	my ($self, $l) = @_;
	push(@$l, $self);
}

sub compare
{
	my ($self, $self2) = @_;
	my ($data, $data2);
	open(my $fh, '>',  \$data);
	open(my $fh2, '>',  \$data2);
	$self->write($fh);
	$self2->write($fh2);
	close($fh);
	close($fh2);
	if ($data ne $data2) {
		return 1;
	} else {
		return 0;
	}
}


package OpenBSD::PackingElement::FileBase;

sub forget_details
{
	my $self = shift;
	undef $self->{md5};
	undef $self->{size};
}

package OpenBSD::PackingElement::SpecialFile;
sub forget_details
{
	my $self = shift;
#	undef $self->{md5};
	undef $self->{size};
}

sub compare
{
	my ($self, $self2) = @_;
	if (ref($self) ne ref($self2)) {
		return 1;
	}
	if ($self->{name} ne $self2->{name}) {
		return 1;
	}
	if (defined $self->{md5} && defined $self2->{md5}) {
		if ($self->{md5} eq $self2->{md5}) {
			return 0;
		} else {
			return 1;
		}
	} elsif (!defined $self->{md5} && !defined $self2->{md5}) {
		return 0;
	}
	return 2;
}

package OpenBSD::PackingElement::Dependency;
sub forget_details
{
	my $self = shift;
	$self->{def} = 'def';
}

package OpenBSD::PackingElement::Wantlib;

sub forget_details
{
	my $self = shift;
	$self->{name} =~ s/\d+\.\d+$/0.0/;
}

package OpenBSD::PackingElement::CVSTag;

# XXX needed to avoid CVS expansion

our $openbsd = 'OpenBSD';

sub forget_details
{
	my $self = shift;
	$self->{name} =~ s/^(\$$openbsd: .*,v).*/$1\$/;
}

sub compare
{
	my ($self, $self2) = @_;
	if (ref($self) ne ref($self2)) {
		return 1;
	}
	if ($self->{name} eq $self2->{name}) {
		return 0;
	}
	if ($self->{name} eq "\$$openbsd\$" or 
	    $self2->{name} eq "\$$openbsd\$") {
		return 2;
	}
	return 1;
}

package OpenBSD::PackingElement::ExtraInfo;

sub compare
{
	my ($self, $self2) = @_;
	if (ref($self) ne ref($self2)) {
		return 1;
	}
	if ($self->{ftp} ne $self2->{ftp} or 
	    $self->{cdrom} ne $self2->{cdrom}) {
		return 1;
	}
	if ($self->{subdir} eq $self2->{subdir}) {
		return 0;
	}
	if ($self->{subdir} =~ m/^mystuff\// && $self2->{subdir} eq $') {
		return 2;
	}
	if ($self2->{subdir} =~ m/^mystuff\// && $self->{subdir} eq $') {
		return 2;
	}
	return 1;
}

package main;

sub my_compare
{
	my ($p, $p2) = @_;
	my $l = [];
	my $l2 = [];
	my $final = 0;
	$p->visit('flatten', $l);
	$p2->visit('flatten', $l2);
	if (@$l != @$l2) {
		return 1;
	}
	for my $e (@$l) {
		my $e2 = shift @$l2;
		my $r = $e->compare($e2);
		if ($r == 1) {
			return $r;
		}
		if ($r == 2) {
			$final = 2;
		}
	}
	return $final;
}

if (@ARGV < 2) {
	die "usage issue";
}

my @dirs = split(/:/, shift);
if (!-d $dirs[0]) {
	die "not a directory: ", $dirs[0];
}

my $error =0;

for my $pkgfile (@ARGV) {
	my $pkg = OpenBSD::PackageLocator->find($pkgfile);
	if (!$pkg) {
		die "Bad package $pkgfile";
	}

	my $plist = $pkg->plist();
	undef $plist->{ OpenBSD::PackageInfo::COMMENT };

	my $l = $plist->{items};
	if ($l->[@$l-1]->isa('OpenBSD::PackingElement::Cwd') &&
		$l->[@$l-1]->{name} eq '.') {
	    pop @$l;
	}

	$plist->visit('forget_details');
	$pkg->close();
	$pkg->wipe_info();
	for my $dir (@dirs) {
		next unless -d $dir;
		my $result = $dir.'/'.$plist->pkgname();
		if (-f $result) {
			my $plist2 = OpenBSD::PackingList->fromfile($result);
			my $r = my_compare($plist, $plist2);
			if ($r == 1) {
				my $t = "$result-new";
				$plist->tofile($t);
				print STDERR "Error: $t and $result are different\n";
				$error++;
			}
			if ($r == 2) {
				$plist->tofile($result);
				print STDERR "$result was updated\n";
			}
		}
	}
	if (!$error) {
		my $result = $dirs[0].'/'.$plist->pkgname();
		if (!-f $result) {
			$plist->tofile($result);
		}
	}
}
exit($error != 0);
