#!perl -w
# (C) 2003-2007 Willem Jan Hengeveld <itsme@xs4all.nl>
# Web: http://www.xs4all.nl/~itsme/
#      http://wiki.xda-developers.com/
#
# $Id$
#
use strict;
use warnings;

my %fileinfo;
my $curpath;
$|=1;

sub shellescape {
    my $arg= shift;
    # ?? what do I escape for windows shell?
    return $arg;
}
my $cmdline= join(" ", map { '"'.shellescape($_).'"' } @ARGV);

open CVS, "cvs update $cmdline 2>&1 |" or die "running cvs update: $!\n";
while (<CVS>) {
    chomp;
    if (/^\? (.*)/) {
        my $fn=$1;

        if (-d $fn) {
            $fileinfo{$fn}= "noncvsdir";
        }
        elsif (-f $fn) {
            $fileinfo{$fn}= "noncvsfile";
        }
        else {
            printf("WARNING: NEW???: %s\n", $fn);
        }
    }
    elsif (/^cvs update: Updating (.*)/) {
        $curpath= "$1/";
        if ($curpath eq "./") {
            $curpath= "";
        }
    }
    elsif (/^cvs update: warning: (.*) was lost/) {
        if (exists $fileinfo{$1}) { warn "WARNING: lost $1 is already $fileinfo{$1}\n"; }
        $fileinfo{"$1"}= "lost";
    }
    elsif (/^cvs update: (.*) is no longer in the repository/) {
        if (exists $fileinfo{$1}) { warn "WARNING: deleted $1 is already $fileinfo{$1}\n"; }
        $fileinfo{"$curpath$1"}= "deleted";
    }
    elsif (/^cvs update: conflicts found in (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: conflict $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "conflict";
    }
    elsif (/^cvs update: checksum failure after patch to (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: checksum $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "checksum";
    }
    elsif (/^cvs update: move away (.*); it is in the way/) {
        if (exists $fileinfo{$1}) { warn "WARNING: intheway $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "intheway";
    }
    elsif (/^cvs client: refetching unpatchable files/) {
        # ignore
    }
    elsif (/^C (.*)/) {
        if (!exists $fileinfo{$1}) { warn "WARNING: expected conflict for $1\n"; }
    }
    elsif (/^R (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: unremoved $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "unremoved";
    }
    elsif (/^A (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: uncommitted $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "uncommitted";
    }
    elsif (/^M (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: merged $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "merged";
    }
    elsif (/^P (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: patched $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "patched";
    }
    elsif (/^U (.*)/) {
        if (exists $fileinfo{$1}) { warn "WARNING: updated $1 is already $fileinfo{$1}\n"; }
        $fileinfo{$1}= "updated";
    }
    elsif (/^Merging differences between/) {
        # ignore
    }
    elsif (/^RCS file: \/.*,v/) {
        # ignore
    }
    elsif (/^rcsmerge: warning: conflicts during merge/) {
        # ignore
    }
    elsif (/^retrieving revision .*/) {
        # ignore
    }
    elsif (/^(.*) already contains the differences between \S+ and \S+/) {
        $fileinfo{$1}= "already";
    }
    else {
        warn "WARNING: unexpected line: $_\n";
    }
}
close CVS;
my %ref;
$ref{$_}++ for (values %fileinfo);

for my $type (qw(conflict intheway deleted uncommitted lost unremoved checksum)) {
    my @files= grep { $fileinfo{$_} eq $type } keys %fileinfo;
    next if (!@files);

    print "$type:\n";
    print map { "    $_\n" } sort @files;
    print "\n";
}


print join ", ", map { sprintf("%d %s", $ref{$_}, $_); } keys %ref;
print "\n";
