#/usr/bin/perl

package DistDir;

use strict;
use warnings;

use base 'Exporter';

use ExtUtils::Manifest qw{ maniread manicopy };
use File::Find qw{};
use File::Path;
use File::pushd;
use File::Spec::Functions;

our @EXPORT_OK = qw{ clear };

# --------------------------------------------------------------------------------------------------
#
#   manidirs
#
#       my $manidirs = manidirs( $manifest );
#
#   Returns directories implicitly used in manifest.
#
sub manidirs($) {
    my ( $manifest ) = @_;
    my $manidirs = { '.' => '' };
    foreach my $file ( keys( %$manifest ) ) {
        while ( $file =~ m{^(.*)/} ) {
            $manidirs->{ $1 } = '';
            $file = $1;
        };
    };
    return $manidirs;
}; # sub manidirs


# --------------------------------------------------------------------------------------------------
#
#   check
#
#       check( $dir );
#
#
sub check($) {
    my ( $dir ) = @_;
    my $pwd = pushd( $dir );
    my $manifest = maniread( $ExtUtils::Manifest::MANIFEST );
    my $manidirs = manidirs( $manifest );
    my $check = {};
    File::Find::find(
        {
            no_chdir => 1,
            wanted => sub {
                my $entry = $_;
                my $name  = ExtUtils::Manifest::clean_up_filename( $entry );
                if ( -f $entry ) {
                    if ( not exists( $manifest->{ $name } ) ) {
                        push( @{ $check->{ extra }->{ files } }, $entry );
                    };
                } elsif ( -d $entry ) {
                    if ( not exists( $manidirs->{ $name } ) ) {
                        push( @{ $check->{ extra }->{ dirs } }, $entry );
                        $File::Find::prune = 1;
                    };
                } else {
                    die "Oops";
                };
            },
        },
        File::Spec->curdir()
    );
    return $check;
}; # sub check


# --------------------------------------------------------------------------------------------------
#
#   clear
#
#       clear( $dir );
#
#   Remove from the directory *everything* (including subdirs) not listed in the manifest.
#
sub clear($) {
    my ( $dir ) = @_;
    my $check = check( $dir );
    foreach my $file ( @{ $check->{ extra }->{ files } } ) {
        my $path = catfile( $dir, $file );
        STDOUT->print( "rm $path\n" );
        unlink( $path ) or die "Cannot delete file `$file': $!\n";
    };
    foreach my $subdir ( @{ $check->{ extra }->{ dirs } } ) {
        my $path = catdir( $dir, $subdir );
        STDOUT->print( "rm -r $path\n" );
        File::Path::remove_tree( catdir( $dir, $subdir ) );
    };
}; # sub clear


1;

# end of file #
