summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2016-10-16 14:26:21 +0100
committerdakkar <dakkar@thenautilus.net>2016-10-16 14:26:21 +0100
commite5d50fa5293ca55a5fea23be344c524c76e007ae (patch)
tree62cce48e457fbc33cfa5a9fb71d3a18fbdbdde91
parentrough skeleton of the script (diff)
downloadanidb-renamer-e5d50fa5293ca55a5fea23be344c524c76e007ae.tar.gz
anidb-renamer-e5d50fa5293ca55a5fea23be344c524c76e007ae.tar.bz2
anidb-renamer-e5d50fa5293ca55a5fea23be344c524c76e007ae.zip
more rough pieces
-rw-r--r--anidb-renamer9
-rw-r--r--lib/AniDB/Datastore.pm97
-rw-r--r--lib/AniDB/Manager.pm64
3 files changed, 166 insertions, 4 deletions
diff --git a/anidb-renamer b/anidb-renamer
index e9a3451..64d6fc9 100644
--- a/anidb-renamer
+++ b/anidb-renamer
@@ -7,6 +7,7 @@ use Log::Any::Adapter::Util;
use Log::Any '$log';
use Path::Tiny;
use Getopt::Long::Descriptive;
+use AniDB::Manager;
my ($opt, $usage) = describe_options(
'%c %o <directories>',
@@ -29,7 +30,7 @@ Log::Any::Adapter->set(
+ $opt->verbose,
);
-my $data = AniDB::Data->new($opt->database);
+my $anidb = AniDB::Manager->new({database=>$opt->database});
my %new_name_for;
for my $dir (@ARGV) {
@@ -37,8 +38,8 @@ for my $dir (@ARGV) {
while (my $path = $path_iter->()) {
next unless $path->is_file;
$log->info("looking at $path")
- $data->update($path);
- if (my $new_name = $data->maybe_new_name_for($path)) {
+ $anidb->update($path);
+ if (my $new_name = $anidb->maybe_new_name_for($path)) {
$new_name_for{$path->stringify} = $new_name;
}
}
@@ -46,6 +47,6 @@ for my $dir (@ARGV) {
for my $current_name (sort keys %new_name_for) {
$log->infof('renaming %s to %s',$current_name,$new_name_for{$current_name});
- $data->rename($current_name,$new_name_for{$current_name});
+ $anidb->rename($current_name,$new_name_for{$current_name});
}
diff --git a/lib/AniDB/Datastore.pm b/lib/AniDB/Datastore.pm
new file mode 100644
index 0000000..8db4e16
--- /dev/null
+++ b/lib/AniDB/Datastore.pm
@@ -0,0 +1,97 @@
+package AniDB::Datastore;
+use 5.024;
+use experimental 'signatures';
+use Moo;
+use Path::Tiny;
+use AniDB::Hashing;
+use namespace::clean;
+
+has database => ( is => 'ro', required => 1 );
+has dbh => ( is => 'ro', lazy => 1 );
+
+sub _build_dbh($self) {
+ require DBI;
+ return DBI->connect(
+ 'dbi:SQLite:dbname='.$self->database,
+ '', '',
+ {
+ AutoCommit => 1,
+ RaiseError => 1,
+ PrintError => 0,
+ },
+ );
+}
+
+sub update($self,$path) {
+ my $stat = $path->stat;
+
+ return 0 unless $self->_has_changed($path,$stat);
+ my $hash = AniDB::Hashing::hash_fd($path->openr_raw);
+ $self->_update_path_info(
+ $path => {
+ size => $stat->size,
+ mtime => $stat->mtime,
+ hash => $hash,
+ },
+ );
+ return 1;
+}
+
+sub _has_changed($self,$path,$stat) {
+ my $path_info = $self->path_info_for($path);
+ return (
+ $path_info->{size} == $stat->size
+ && $path_info->{mtime} == $stat->mtime
+ );
+}
+
+sub rename($self,$path,$new_path) {
+ $self->dbh->do(
+ q{UPDATE path_info SET name=? WHERE name=?},
+ $path->stringify,$new_path->stringify,
+ );
+}
+
+sub full_info_for($self,$path) {
+ my $path_info = $self->path_info_for($path);
+ my $episode_info = $self->episode_info_for(
+ $path_info,
+ );
+ my $anime_info = $self->anime_info_for(
+ $episode_info,
+ );
+ return {
+ path => $path_info,
+ episode => $episode_info,
+ anime => $anime_info,
+ };
+}
+
+sub path_info_for($self,$path) {
+ my $ret = $self->dbh->selectall_arrayref(
+ qr{SELECT * FROM path_info WHERE name=?},
+ { Slice => {} },
+ $path->stringify,
+ );
+ return $ret->[0];
+}
+
+sub episode_info_for($self,$args) {
+ my $ret = $self->dbh->selectall_arrayref(
+ qr{SELECT * FROM episode_info WHERE hash=? AND size=?},
+ { Slice => {} },
+ @{$args}{qw(hash size)},
+ );
+ return $ret->[0];
+}
+
+sub anime_info_for($self,$args) {
+ my $ret = $self->dbh->selectall_arrayref(
+ qr{SELECT * FROM anime_info WHERE aid=?},
+ { Slice => {} },
+ @{$args}{qw(aid)},
+ );
+ return $ret->[0];
+}
+
+1;
diff --git a/lib/AniDB/Manager.pm b/lib/AniDB/Manager.pm
new file mode 100644
index 0000000..eeb724f
--- /dev/null
+++ b/lib/AniDB/Manager.pm
@@ -0,0 +1,64 @@
+package AniDB::Manager;
+use 5.024;
+use experimental 'signatures';
+use Moo;
+use Log::Any '$log';
+use Path::Tiny;
+use namespace::clean;
+
+has datastore => (
+ is => 'ro',
+ required => 1,
+ handles => [qw(update)],
+);
+
+around BUILDARGS => sub($orig,$class,@args) {
+ my $args = $class->$orig(@args);
+ if (my $db_name = $args->{database}) {
+ require AniDB::Datastore;
+ $args->{datastore} = AniDB::Datastore->new({
+ database => $db_name,
+ });
+ }
+ return $args;
+};
+
+has renamer => (
+ is => 'ro',
+ lazy => 1,
+);
+
+sub _build_renamer {
+ require AniDB::Renamer;
+ return AniDB::Renamer->new();
+}
+
+sub new_name_for($self,$path) {
+ $path = path($path)->realpath;
+ my $full_info = $self->datastore->full_info_for($path);
+ return $self->renamer->new_name_for($path,$full_info);
+}
+
+sub maybe_new_name_for($self,$path) {
+ my $new_name = $self->new_name_for($path);
+ return if $new_name eq $path;
+ return $new_name;
+}
+
+sub rename($self,$path,$new_path) {
+ $path = path($path)->realpath;
+ $new_path ||= $self->new_name_for($path);
+ if ($path->move($new_path)) {
+ $self->datastore->rename($path,$new_path);
+ return 1;
+ }
+ else {
+ $log->errorf(
+ 'failed to rename %s to %s',
+ $path, $new_path,
+ );
+ return;
+ }
+}
+
+1;