/usr/local/CPAN/VCI/VCI/VCS/Git/Directory.pm


package VCI::VCS::Git::Directory;
use Moose;

extends 'VCI::Abstract::Directory';
with 'VCI::VCS::Git::Committable';

# XXX This should probably be optimized to not build a File object for
#     every file in the whole tree--it's a bit slow on the kernel sources
#     (over 20,000 files).
sub _build_contents {
    my $self = shift;
    my @path_part;
    @path_part = ('--', $self->path->stringify) unless $self->path->is_empty;
    my $files = $self->project->x_do('ls-tree',
        ['-r',  $self->revision, @path_part]);
    
    @$files = map { s/^\d+ \w+ \S+\s+//; $_ } @$files;
    
    # Get the directory names from the output
    my %dirs;
    foreach my $line (@$files) {
        # XXX This assumes the path separator is always /.
        if ($line =~ m|^(.+)/[^/]+$|) {
            $dirs{$1} = 1;
        }
    }
    
    # Make sure that every dir has a parent in the list.
    my @new_dirs;
    my @check_dirs = keys %dirs;
    my $found_parent = 1;
    while ($found_parent) {
        $found_parent = 0;
        foreach my $dir (@check_dirs) {
            # If this directory has a parent... (XXX path separator assumption)
            if ($dir =~ m|^(.+)/[^/]+$|) {
                my $parent_dir = $1;
                # And that parent isn't already in the list...
                if (!$dirs{$parent_dir}) {
                    push(@new_dirs, $parent_dir);
                    $found_parent = 1;
                }
            }
        }
    
        $dirs{$_} = 1 foreach @new_dirs;
        @check_dirs = @new_dirs;
    }
    
    $self->_set_contents_from_list([keys %dirs], $files, $self->path->stringify);
    return $self->{contents};
}

__PACKAGE__->meta->make_immutable;

1;