#!/usr/bin/perl -w
-# Ian Beckwith <ianb@erislabs.net>
#
+# id3fs - a FUSE-based filesystem for browsing audio metadata
+# Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
use lib '/home/ianb/projects/id3fs/id3fs/lib'; # FIXME: remove
use strict;
Configure(qw(bundling no_ignore_case));
my $optret=GetOptions(
"verbose|v" => \$verbose,
- "quiet|q" => sub { $verbose=0; },
"help|h" => \$help,
"dir|d=s" => \$basedir,
"database|f=s" => \$dbpath,
"list|l" => \$list,
);
+if($list && !@ARGV)
+{
+ push(@ARGV, ".");
+}
usage() if(!@ARGV || !$optret || $help);
$init=1 unless($list);
-if(@ARGV > 1 && !defined($basedir))
+unless(defined($basedir) && defined($dbpath))
{
- die("$me: --basedir must be specified if multiple paths are supplied\n");
+ $basedir=ID3FS::DB::find_db($me, $init, @ARGV);
+ exit unless($basedir);
+ my $absbase=Cwd::abs_path($basedir);
+ for my $dir (@ARGV)
+ {
+ if(Cwd::abs_path($dir) !~ /^\Q$absbase\E/)
+ {
+ die("$me: $dir: must be under basedir $absbase - use --basedir to specify\n");
+ }
+ }
}
-
-my $db=ID3FS::DB->new($me, $verbose, $init, $dbpath, $basedir, $ARGV[0]);
+my $db=ID3FS::DB->new($me, $verbose, $init, $basedir, $dbpath);
exit unless($db);
if($list)
else
{
$db->last_update(time());
-
- my $directories_pruned=$db->prune_directories();
+ my $base=$db->base_dir();
+ my $abs_base=Cwd::abs_path($base);
while(my $path=shift)
{
+ if(Cwd::abs_path($path) !~ /^$abs_base/)
+ {
+ print "$me: $path is outside $base, skipping\n";
+ }
File::Find::find( {wanted => \&wanted, follow => 1, no_chdir => 1}, $path);
}
+ my $directories_pruned=$db->prune_directories();
if($files_pruned || $directories_pruned)
{
- print "Removing data from pruned files\n" if $verbose;
+ print "$me: pruning removed files from db\n" if $verbose;
$db->remove_unused();
}
+ print "$me: analyzing db\n" if $verbose;
+ $db->analyze();
}
sub wanted
}
}
-
sub prune
{
my $dir=shift;
+ $dir=Cwd::abs_path($dir);
return unless(opendir(DIR, $dir));
- print "Pruning $dir\n";
+ my $base=Cwd::abs_path($db->base_dir());
+ $dir=~s/^$base\/?//;
my @oldfiles=$db->files_in($dir);
my @newfiles=grep { !/^\.\.?$/; } readdir(DIR);
closedir(DIR);
@oldfiles=sort @oldfiles;
@newfiles=sort @newfiles;
my %hash;
+ # hash slice!
@hash{@newfiles}=();
for my $file (@oldfiles)
{
unless(exists($hash{$file}))
{
- # FIXME: add path, rebasify
$files_pruned=1;
- $db->unindex($file);
+ $db->unindex($dir, $file);
}
}
}
sub usage
{
- die("Usage: $me [-vqh] [-d basedir] [-f dbpath] [-e mp3,ogg,flac] [--] DIR...\n".
- " -v|--verbose\t\t\tVerbose\n".
- " -q|--quiet\t\t\tQuiet (default)\n".
- " -d|--dir=PATH\t\t\tBase directory of source files (default: ARGV[0])\n".
- " -f|--database=FILE\t\tPath to database file (default: basedir/.id3fs)\n".
- " -e|--extensions=EXT1,EXT2\tFile extensions to index (default: mp3, ogg, flac)\n".
- " -h|--help\t\t\tThis help\n".
- " --\t\t\t\tEnd of options\n");
+ die("Usage: $me [-lvh] [-d basedir] [-f dbpath] [-e mp3,ogg,flac] [--] DIR...\n".
+ " -d|--dir=PATH Base directory of source files (default: ARGV[0])\n".
+ " -f|--database=FILE Path to database file (default: basedir/.id3fs)\n".
+ " -e|--extensions=EXT1,EXT2 File extensions to index (default: mp3, ogg, flac)\n".
+ " -l|list List tags in use\n" .
+ " -v|--verbose Verbose\n".
+ " -h|--help This help\n".
+ " -- End of options\n");
}
__END__
=head1 SYNOPSIS
-B<id3fs-index> [B<-vqh>] S<[B<-d >I<basedir>]> S<[B<-f >I<dbpath>]> S<[B<-e >I<mp3,ogg,flac>]> [B<-->] [I<DIR>...]
+B<id3fs-index> [B<-lvh>] S<[B<-d >I<basedir>]> S<[B<-f >I<dbpath>]> S<[B<-e >I<mp3,ogg,flac>]> [B<-->] [I<DIR>...]
=head1 DESCRIPTION
=over 4
-=item B<-v>
-
-Enable verbose operation.
-
-=item B<-q>
+=item B<-l> | B<--list>
-Quiet (no output). This is the default.
+List tags in use in specified database.
=item S<B<-d >I<PATH>> | S<B<--dir=>I<PATH>>
File extensions to consider when indexing.
Defaults to B<.mp3>, B<.ogg> and B<.flac>.
+=item B<-v>
+
+Enable verbose operation.
+
=item B<-h>
Show a short help message.
=head1 SEE ALSO
-L<id3fsd(8)>
+L<id3fsd(8)>, L<MP3::Tag>, L<Audio::Flac::Header>, L<Ogg::Vorbis::Header>
=head1 AUTHOR
Ian Beckwith <ianb@erislabs.net>
+Many thanks to Aubrey Stark-Toller for help wrangling SQL.
+
=head1 AVAILABILITY
The latest version can be found at:
-B<http://erislabs.net/ianb/projects/id3fs/>
+L<http://erislabs.net/ianb/projects/id3fs/>
=head1 COPYRIGHT
-Copyright 2010 Ian Beckwith <ianb@erislabs.net>
+Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
+the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,