App-Hashl

 view release on metacpan or  search on metacpan

lib/App/Hashl.pm  view on Meta::CPAN

	my ( $obj, %conf ) = @_;

	my $ref = {
		files   => {},
		ignored => {},
	};

	$ref->{config} = \%conf;
	$ref->{config}->{read_size} //= ( 2**20 ) * 4;    # 4 MiB
	$ref->{version} = $VERSION;

	return bless( $ref, $obj );
}

sub new_from_file {
	my ( $obj, $file ) = @_;

	my $ref = retrieve($file);

	if ( not defined $ref->{version} ) {
		$ref->{version} = '1.00';
	}

	return bless( $ref, $obj );
}

sub si_size {
	my ( $self, $bytes ) = @_;
	my @post = ( q{ }, qw(k M G T) );

	if ( $bytes == 0 ) {
		return 'infinite';
	}

	while ( $bytes >= 1024 ) {
		$bytes /= 1024;
		shift @post;
	}

	return sprintf( '%6.1f%s', $bytes, $post[0] );
}

sub hash_file {
	my ( $self, $file ) = @_;
	my $data;
	my $digest = Digest::SHA->new(1);

	# read() fails for empty files
	if ( ( stat($file) )[7] == 0 ) {
		return $digest->hexdigest;
	}
	if ( $self->{config}->{read_size} == 0 ) {
		$digest->addfile($file);
		return $digest->hexdigest;
	}

	#<<< perltidy has problems indenting 'or die' with tabs

	open( my $fh, '<', $file )
		or die("Can't open ${file} for reading: $!\n");
	binmode($fh)
		or die("Can't set binmode on ${file}: $!\n");
	read( $fh, $data, $self->{config}->{read_size} )
		or die("Can't read ${file}: $!\n");
	close($fh)
		or die("Can't close ${file}: $!\n");

	#>>>
	$digest->add($data);
	return $digest->hexdigest;
}

sub hash_in_db {
	my ( $self, $hash ) = @_;

	if ( $self->{ignored}->{$hash} ) {
		return '// ignored';
	}

	for my $name ( $self->files() ) {
		my $file = $self->file($name);

		if ( $file->{hash} eq $hash ) {
			return $name;
		}
	}
	return;
}

sub file_in_db {
	my ( $self, $file ) = @_;

	return $self->hash_in_db( $self->hash_file($file) );
}

sub read_size {
	my ($self) = @_;

	return $self->{config}->{read_size};
}

sub db_info {
	my ($self) = @_;

	return sprintf(
		"Database created by hashl v%s\n"
		  . "Read size: %d bytes (%s)\n"
		  . "contains: %d file%s and %d ignored hash%s\n",
		$self->db_version,
		$self->read_size,
		$self->si_size( $self->read_size ),
		scalar( $self->files ),
		( scalar( $self->files ) == 1 ? q{} : 's' ),
		scalar( $self->ignored ),
		( scalar( $self->ignored ) == 1 ? q{} : 'es' ),
	);
}

sub db_version {
	my ($self) = @_;

	return $self->{version};



( run in 0.890 second using v1.01-cache-2.11-cpan-39bf76dae61 )