diff options
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/hashl | 224 | 
1 files changed, 97 insertions, 127 deletions
| @@ -24,11 +24,14 @@ my $total = 0;  my $cur = 0;  my $timer;  my $incoming_dir; +my ($find_ref, $find_db_write);  my $VERSION = '0.1';  my $db; +STDOUT->autoflush(1); +  GetOptions(  	'd|database=s'  => \$db_file,  	's|read-size=i' => sub { $read_size = $_[1] * 1024 }, @@ -38,7 +41,7 @@ if (substr($db_file, 0, 1) ne '/') {  	$db_file = "${base}/${db_file}";  } -my $action = $ARGV[0]; +my $action = shift;  sub usage {  	die(<<"EOF"); @@ -77,6 +80,17 @@ sub drop_deleted {  	}  } +sub copy_file { +	my ($file, $to) = @_; + +	my $base = substr($file, length($base) + 1); +	if ($base =~ s{ / [^/]+ $}{}x) { +		mkdirs($incoming_dir, $base); +	} + +	copy($file, "${to}/${base}"); +} +  sub hash_file {  	my ($file) = @_;  	my ($fh, $data); @@ -116,29 +130,6 @@ sub file_in_db {  	return hash_in_db(hash_file($file));  } -sub db_find { -	if ($ARGV[1]) { -		given ($action) { -			when ('know-file') { exit (not defined file_in_db($ARGV[1])) } -			when ('know-hash') { exit (not defined hash_in_db($ARGV[1])) } -			when ('new-file') { exit (defined file_in_db($ARGV[1])) } -			when ('new-hash') { exit (defined hash_in_db($ARGV[1])) } -		} -	} -	else { -		while (my $line = <STDIN>) { -			chomp $line; -			if ( -					($action eq 'know-file' and     defined file_in_db($line)) or -					($action eq 'know-hash' and     defined hash_in_db($line)) or -					($action eq  'new-file' and not defined file_in_db($line)) or -					($action eq  'new-hash' and not defined hash_in_db($line))) { -				say $line; -			} -		} -	} -} -  sub db_info {  	printf(  		"Read size: %d bytes (%.f KiB)\n", @@ -159,22 +150,33 @@ sub file_info {  }  sub process_file { +	my ($code, $write) = ($find_ref, $find_db_write);  	my $file = $File::Find::name;  	my $path = $file; -	my ($size, $mtime) = (stat($file))[7,9];  	if (not -f $file or -l $file or $file eq $db_file) {  		return;  	} -	$cur++; -  	if ($rel_paths) {  		$file = substr($file, length($base) + 1);  	} +	$cur++; +  	print $timer->report("\r\e[2KUpdating: %p done, %L elapsed, %E remaining", $cur); +	&{$code}($file, $path); + +	if ($write and (($cur % 100) == 0)) { +		nstore($db, $db_file); +	} +} + +sub db_update { +	my ($file, $path) = @_; +	my ($size, $mtime) = (stat($path))[7,9]; +  	if (exists($db->{'files'}->{$file}) and  			$db->{'files'}->{$file}->{'mtime'} == $mtime and  			$db->{'files'}->{$file}->{'size'} == $size ) { @@ -186,33 +188,24 @@ sub process_file {  		mtime => $mtime,  		size => $size,  	}; - -	if (($cur % 100) == 0) { -		nstore($db, $db_file); -	}  } -sub ignore_file { -	my $file = $File::Find::name; - -	if (not -f $file or -l $file or $file eq $db_file) { -		return; -	} - -	my $hash = hash_file($file); - -	$cur++; - -	print $timer->report("\r\e[2KUpdating: %p done, %L elapsed, %E remaining", $cur); +sub db_ignore { +	my ($file, $path) = @_; +	my $hash = hash_file($path);  	if (hash_in_db($hash)) {  		return;  	}  	push(@{$db->{'ignored'}->{'hashes'}}, $hash); +} -	if (($cur % 100) == 0) { -		nstore($db, $db_file); +sub db_copy { +	my ($file, $path) = @_; + +	if (not defined file_in_db($path)) { +		copy_file($path, $incoming_dir);  	}  } @@ -227,119 +220,96 @@ sub mkdirs {  	}  } -sub copy_file { -	my ($file, $to) = @_; - -	my $base = substr($file, length($base) + 1); -	if ($base =~ s{ / [^/]+ $}{}x) { -		mkdirs($incoming_dir, $base); -	} +sub prepare_db_run { +	find(\&get_total, $base); -	copy($file, "${to}/${base}"); +	$timer = Time::Progress->new(); +	$timer->attr( +		min => 1, +		max => $total, +	); +	return;  } -sub maybe_copy_file { -	my $file = $File::Find::name; +sub cmd_copy { +	prepare_db_run(); +	$incoming_dir = (@_); -	if (not -f $file or -l $file or $file eq $db_file) { -		return; +	if (not $incoming_dir) { +		usage();  	} -	$cur++; - -	print $timer->report("\r\e[KCopying: %p done, %L elapsed, %E remaining", $cur); - -	if (not defined file_in_db($file)) { -		copy_file($file, $incoming_dir); +	if (substr($incoming_dir, 0, 1) ne '/') { +		$incoming_dir = $base . '/' . $incoming_dir;  	} + +	$find_ref = \&db_copy; +	$find_db_write = 0; +	find(\&process_file, $base); +	print "\n";  } -if ($action eq 'update') { +sub cmd_ignore { +	my ($ign_dir) = @_; -	STDOUT->autoflush(1); +	$ign_dir //= $base; -	drop_deleted(); -	find(\&get_total, $base); +	prepare_db_run(); -	$timer = Time::Progress->new(); -	$timer->attr( -		min => 1, -		max => $total -	); +	if (substr($ign_dir, 0, 1) ne '/') { +		$ign_dir = $base . '/' . $ign_dir; +	} +	$find_ref = \&db_ignore; +	$find_db_write = 1;  	find(\&process_file, $base); -	print "\n";  	nstore($db, $db_file); +	print "\n";  } -elsif ($action eq 'list') { + +sub cmd_info { +	my ($file) = @_; + +	if ($file) { +		file_info($file); +	} +	else { +		db_info(); +	} +} + +sub cmd_list {  	for my $name (sort keys %{$db->{'files'}}) {  		my $file = $db->{'files'}->{$name};  		printf("%s %s\n", $file->{'hash'}, $name);  	}  } -elsif ($action eq 'list-ignored') { + +sub cmd_list_ignored {  	if (exists $db->{'ignored'}->{'hashes'}) {  		for my $hash (@{$db->{'ignored'}->{'hashes'}}) {  			say $hash;  		}  	}  } -elsif ($action ~~ [qw[know-file know-hash new-file new-hash]]) { -	db_find(); -} -elsif ($action eq 'info') { -	if ($ARGV[1]) { -		file_info($ARGV[1]); -	} -	else { -		db_info(); -	} -} -elsif ($action eq 'copy') { - -	if (not $ARGV[1]) { -		usage(); -	} -	$incoming_dir = $ARGV[1]; -	if (substr($incoming_dir, 0, 1) ne '/') { -		$incoming_dir = $base . '/' . $incoming_dir; -	} - -	STDOUT->autoflush(1); -	find(\&get_total, $base); - -	$timer = Time::Progress->new(); -	$timer->attr( -		min => 1, -		max => $total, -	); - -	find(\&maybe_copy_file, $base); +sub cmd_update { +	prepare_db_run(); +	$find_ref = \&db_update; +	$find_db_write = 1; +	find(\&process_file, $base);  	print "\n"; -} -elsif ($action eq 'ignore') { -	my $ign_dir = $ARGV[1] // $base; - -	if (substr($ign_dir, 0, 1) ne '/') { -		$ign_dir = $base . '/' . $ign_dir; -	} - -	STDOUT->autoflush(1); -	find(\&get_total, $base); - -	$timer = Time::Progress->new(); -	$timer->attr( -		min => 1, -		max => $total, -	); - -	find(\&ignore_file, $base);  	nstore($db, $db_file); -	print "\n";  } -else { -	usage(); + +given ($action) { +	when ('copy')         { cmd_copy(@ARGV) } +	when ('ignore')       { cmd_ignore(@ARGV) } +	when ('info')         { cmd_info(@ARGV) } +	when ('list')         { cmd_list(@ARGV) } +	when ('list-ignored') { cmd_list_ignored(@ARGV) } +	when ('update')       { cmd_update(@ARGV) } +	default { usage() }  }  __END__ | 
