summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2017-12-30 14:41:38 +0000
committerdakkar <dakkar@thenautilus.net>2017-12-30 14:41:38 +0000
commit375827657ffbb153d30778070a86c6873ee5b3c5 (patch)
tree02f8c66e997af4b5b9407656b4cafcd4922edfc3
parentmove coercions to signatures (diff)
downloadUltramarine-375827657ffbb153d30778070a86c6873ee5b3c5.tar.gz
Ultramarine-375827657ffbb153d30778070a86c6873ee5b3c5.tar.bz2
Ultramarine-375827657ffbb153d30778070a86c6873ee5b3c5.zip
handle file deletion
-rw-r--r--lib/Ultramarine/Model/Collection.pm615
-rw-r--r--lib/Ultramarine/Model/DB.pm674
2 files changed, 76 insertions, 13 deletions
diff --git a/lib/Ultramarine/Model/Collection.pm6 b/lib/Ultramarine/Model/Collection.pm6
index e894f1c..4a09b46 100644
--- a/lib/Ultramarine/Model/Collection.pm6
+++ b/lib/Ultramarine/Model/Collection.pm6
@@ -21,20 +21,27 @@ class Ultramarine::Model::Collection {
CATCH { default { .perl.say } }
react whenever $.dirscan.scan -> $path {
when $path ~~ Ultramarine::Model::DirScanner::EndOfScan {
- # we should use this to check that all the files in
+ # we use this to check that all the files in
# the db have been seen, and delete those that haven't
- #
- # calling db.remove-unseen-files, plus db.remove-empty
+ $.db.remove-unseen-files();
$!mark-ready.keep(True);
}
when $path ~~ IO::Path & :f {
my $mtime = $path.modified.floor;
- # call db.ensure-song and db.seen-file
+ # we only care to keep track of which files we've
+ # seen during the initial scan (so we can clean up
+ # rows for files that were removed while we were
+ # not running); after that, we'll get notification
+ # of deleted files, and we'll remove those
+ $.db.seen-file(:$path) unless $.is-ready.status ~~ Kept;
unless $.db.is-up-to-date(:$path,:$mtime) {
my %metadata = $.file-class.new(:$path).metadata;
$.db.ensure-song(:$path,:$mtime,:%metadata) if %metadata.keys;
}
}
+ when $path ~~ IO::Path & :!f {
+ $.db.ensure-file-absent(:$path);
+ }
}
}
}
diff --git a/lib/Ultramarine/Model/DB.pm6 b/lib/Ultramarine/Model/DB.pm6
index 24a6a4a..9673d8e 100644
--- a/lib/Ultramarine/Model/DB.pm6
+++ b/lib/Ultramarine/Model/DB.pm6
@@ -53,6 +53,12 @@ class Ultramarine::Model::DB {
FOREIGN KEY (album_id) REFERENCES albums(id)
)
END
+
+ $dbh.do(q:to/END/);
+ CREATE TABLE seen_files (
+ path TEXT NOT NULL
+ )
+ END
},
);
@@ -144,15 +150,65 @@ class Ultramarine::Model::DB {
$sth.execute($path.Str,$mtime,$last-dir-id,$album-id,to-json(%metadata));
}
- # seen-file
- # * add a row into a "seen" table, fk to songs
- # remove-unseen-files
- # * delete from songs where not in seen
- # remove-empty
- # * delete from directories where not in directories or songs
- # ** repeat until nothing gets deleted
- # * delete from albums where not in songs
- # * delete from artists where not in albums
+ method seen-file(Str() :$path!) {
+ $!dbh.do(q:to/END/,$path);
+ INSERT INTO seen_files(path) VALUES (?)
+ END
+ }
+ method remove-unseen-files() {
+ $!dbh.do(q:to/END/);
+ DELETE FROM songs
+ WHERE NOT EXISTS (
+ SELECT * FROM seen_files f WHERE f.path = songs.path
+ )
+ END
+ $!dbh.do('DELETE FROM seen_files');
+
+ self.remove-empty();
+ }
+
+ method ensure-file-absent(Str() :$path!) {
+ $!dbh.do(q:to/END/,$path);
+ DELETE FROM songs
+ WHERE path=?
+ END
+
+ self.remove-empty();
+ }
+
+ method remove-empty() {
+ my $affected-rows=1;
+ while $affected-rows > 0 {
+ $affected-rows = $!dbh.do(q:to/END/);
+ DELETE FROM directories
+ WHERE NOT EXISTS (
+ SELECT directory_id
+ FROM songs
+ WHERE songs.directory_id=directories.id
+ UNION ALL
+ SELECT parent_id
+ FROM directories d2
+ WHERE d2.parent_id=directories.id
+ )
+ END
+ }
+ $!dbh.do(q:to/END/);
+ DELETE FROM albums
+ WHERE NOT EXISTS (
+ SELECT album_id
+ FROM songs
+ WHERE songs.album_id=albums.id
+ )
+ END
+ $!dbh.do(q:to/END/);
+ DELETE FROM artists
+ WHERE NOT EXISTS (
+ SELECT artist_id
+ FROM albums
+ WHERE albums.artist_id=artists.id
+ )
+ END
+ }
sub unpack-row(%song is copy) {
%song<metadata> = from-json(%song<metadata>);