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__ |