GBrowse

 view release on metacpan or  search on metacpan

lib/Bio/Graphics/Browser2/DataLoader/archive.pm  view on Meta::CPAN

package Bio::Graphics::Browser2::DataLoader::archive;

# $Id$
use strict;
use base 'Bio::Graphics::Browser2::DataLoader';
use Bio::DB::BigWigSet;
use File::Spec;

sub new {
    my $class = shift;
    my $self  = $class->SUPER::new(@_);
    $self->{default_track_name} = 'track000';
    $self;
}

sub default_track_name {
    my $self = shift;
    return $self->{default_track_name}++;
}

sub load {
    my $self = shift;
    my ($initial_lines,$fh) = @_;
    
    $self->flag_busy(1);
    eval {
	$self->open_conf;
	$self->set_status('starting load');
	
	mkdir $self->sources_path or die $!;
	$self->{archive} = File::Spec->catfile($self->sources_path,$self->track_name);
	my $source_file = IO::File->new($self->{archive},'>');

	warn "sourcefile=$self->{archive}";

	$self->start_load;

	$self->set_status('load data');
	my $bytes_loaded = 0;
	foreach (@$initial_lines) {
	    $source_file->print($_);
	    $bytes_loaded += length $_;
	}

	my $buffer;
	while ((my $bytes = read($fh,$buffer,8192) > 0)) {
	    $source_file->print($buffer);
	    $bytes_loaded += length $ buffer;
	    $self->set_status("loaded $bytes_loaded bytes") if $bytes++ % 10000;
	}
	$source_file->close();
    
	$self->finish_load;
	$self->check_metadata;
	$self->write_conf;
	$self->close_conf;
	$self->set_processing_complete;
    };

    $self->flag_busy(0);
    die $@ if $@;
    return $self->tracks;
}

sub finish_load {
	my $self = shift;
	$self->set_status("extracting files from archive");
	
	my $archive = $self->{archive};
	my $bin = $archive =~ /\.tar$/i ? $self->search_for_binary('tar') :
		$archive =~ /\.zip$/i ? $self->search_for_binary('unzip') :
		'';
	die "unrecognized file type!" unless $bin;
	
	my $command = $archive =~ /\.tar$/i ? "$bin -tf" : "$bin -l";
	my $fh;
	open $fh, "($command $archive && echo 'success') 2>&1 |";
	my @contents = <$fh>;
	close $fh;
	unless ($contents[-1] =~ /success/) {
		die "ARCHIVE LIST ERROR: @contents";
	}
	pop @contents;
	
	my @to_extract;
	while (@contents) {
		my $item = shift @contents;
		next if ($item =~ /^(Archive\:| Length|\-{5,})/); # unzip headers
		$item = (split / {2,}/, $item)[-1]; # split on two or more spaces
		chomp $item;
		my (undef, undef, $file) = File::Spec->splitpath($item);
		if ($file =~ /^meta/i) {
			push @to_extract, [$item, $file];
		}
		elsif ($file =~ /^\./) {
			next; # skip .files if present
		}
		elsif ($file =~ /\.bw$/i) {
			push @to_extract, [$item, $file];
		}
	}
	die "no recognizable files in archive to extract" unless @to_extract;
	
	# we are trying to be safe here and extract just the file contents
	# without directory paths to avoid ill- or mis-intentioned stray files
	my $path = $self->sources_path;
	my $count;
	$command = $archive =~ /\.tar$/i ? "$bin -x -O -f" : "$bin -p";
	foreach (@to_extract) {
		my $target = File::Spec->catfile($path, $_->[1]);
		# extract file from tar archive and redirect to file in our path
		open my $in, "$command $archive \"$_->[0]\" |" or 
			die "unable to open achive for extraction";
		open my $out, '>', $target or die "unable to open target file";
		while (<$in>) {print $out $_}
		close $in;
		close $out;
		$count++ if -e $target && -s _ ;
	}
	die "not all files could be extracted\n" unless $count == scalar(@to_extract);



( run in 0.566 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )