# package HTML::WebMake::DataSources::DirOfFiles; require Exporter; use File::Find; use Carp; use strict; use HTML::WebMake::DataSourceBase; use HTML::WebMake::MetaTable; use vars qw{ @ISA @EXPORT $TmpGlobalSelf }; @ISA = qw(HTML::WebMake::DataSourceBase); @EXPORT = qw(); ########################################################################### sub new { my $class = shift; $class = ref($class) || $class; my $self = $class->SUPER::new (@_); bless ($self, $class); $self; } # ------------------------------------------------------------------------- sub add { my ($self) = @_; local ($_); my $main = $self->{main}; my $src = $self->{src}; if ($src eq '') { $src = '.'; } my $use_find = 0; if ($self->{name} =~ s/^(RE:|)\.\.\.\//$1/) { $use_find = 1; } my $patt = $main->{util}->glob_to_re ($self->{name}); my $pattskip = $main->{util}->glob_to_re ($self->{skip}); my $pattmetas = $main->{util}->glob_to_re ($self->{metatable}); my @matched; my @matchedmetas; $self->{metas} = 0; if (defined $pattmetas) { $self->{metas} = 1; dbg ("searching for files that match \"$patt\" or \"$pattmetas\""); } else { dbg ("searching for files that match \"$patt\""); } $src =~ s,/+$,,; my $realsrc; if ($main->{base_dir} ne '' && ($src !~ /^(?:\/|[A-Za-z]\:)/)) { $realsrc = File::Spec->catdir ($main->{base_dir}, $src); } else { $realsrc = $src; } # this regexp is used to convert "/home/jm/jmason.org/raw/index.txt" # to just "index.txt", when "raw" is the searched dir and "/home/jm/jmason.org" # is the $main->{base_dir}. $self->{real_to_underdir_re} = qr/\Q$realsrc\E/; if ($use_find) { $self->{found} = [ ]; $self->{foundmetas} = [ ]; if ($patt =~ m,/,) { $self->{find_using_full_path} = 1; $patt =~ s/^\^/\//; # replace start-of-string marker with / if (defined $pattskip) { $pattskip =~ s/^\^/\//; } if (defined $pattmetas) { $pattmetas =~ s/^\^/\//; } } else { $self->{find_using_full_path} = 0; } $self->{find_file_pattern} = $patt; $self->{find_file_pattern_skip} = $pattskip; $self->{find_file_pattern_metas} = $pattmetas; $TmpGlobalSelf = $self; find (\&find_wanted, $realsrc); undef $TmpGlobalSelf; @matched = @{$self->{found}}; delete $self->{found}; if ($self->{metas}) { @matchedmetas = @{$self->{foundmetas}}; delete $self->{foundmetas}; } } else { if (!opendir (DIR, $realsrc)) { warn "can't open ".$self->as_string()." src dir \"$realsrc\": $!\n"; return; } # grep for files that (a) match the pattern and (b) are files, not dirs my @files = readdir(DIR); @matched = grep { /^${patt}$/ && ($_ ne 'NEW_FILE_TEMPLATE') && (!defined $pattskip || !/^${pattskip}$/) && -f (File::Spec->catfile ($realsrc, $_)); } @files; if (defined $pattmetas) { @matchedmetas = grep { /^${pattmetas}$/ && ($_ ne 'NEW_FILE_TEMPLATE') && (!defined $pattskip || !/^${pattskip}$/) && -f (File::Spec->catfile ($realsrc, $_)); } @files; } closedir DIR; } # add all the data content items foreach my $name (@matched) { my $fname = File::Spec->catfile ($realsrc, $name); my $mtime = $main->cached_get_modtime ($fname); if (!defined $mtime || $mtime == 0) { warn "cannot stat file $fname\n"; next; } $main->add_source_files ($fname); my $fixed = $self->{parent}->fixname ($name); $self->{parent}->add_file_to_list ($fixed); $self->{parent}->add_location ($fixed, "file:".$fname, $mtime); } # and parse all the metadata files foreach my $name (@matchedmetas) { my $fname = File::Spec->catfile ($realsrc, $name); my $mtime = $main->cached_get_modtime ($fname); if (!defined $mtime || $mtime == 0) { warn "cannot stat file $fname\n"; next; } $main->add_source_files ($fname); open (IN, "<$fname"); my $text = join ('', ); close IN; # if the metatable was loaded from a subdir, all the content # items in that dir will be called e.g. "foo/bar/baz", but the # metatable will contain references to "baz". Fix this... $self->{metatable_name_prefix} = ''; if ($name =~ /^(.+[\/\\])[^\/\\]+/) { $self->{metatable_name_prefix} = $1; } my $tbl = new HTML::WebMake::MetaTable ($self->{main}); $tbl->set_name_sed_callback ($self, \&fix_names_for_metatable); $self->{attrs}->{format} = $self->{attrs}->{metatableformat}; $tbl->parse_metatable ($self->{attrs}, $text); } } sub fix_names_for_metatable { my ($self, $name) = @_; $name = $self->{metatable_name_prefix} . $name; $name = $self->{parent}->fixname ($name); return $name; } sub find_wanted { -f $_ or return; # ensure not a dir etc. return if ($_ eq 'NEW_FILE_TEMPLATE'); my $self = $TmpGlobalSelf; my $matchstr; if ($self->{find_using_full_path}) { $matchstr = $File::Find::name; } else { $matchstr = $_; } my $skip = $self->{find_file_pattern_skip}; return if (defined $skip && $matchstr =~ /${skip}/); ($matchstr =~ /$self->{find_file_pattern}/) and $self->found_datafile(); if ($self->{metas}) { ($matchstr =~ /$self->{find_file_pattern_metas}/) and $self->found_metafile(); } } sub found_datafile { my $self = shift; my $name = $File::Find::name; $name =~ s/^$self->{real_to_underdir_re}\/+//g; push (@{$self->{found}}, $name); } sub found_metafile { my $self = shift; my $name = $File::Find::name; $name =~ s/^$self->{real_to_underdir_re}\/+//g; push (@{$self->{foundmetas}}, $name); } # ------------------------------------------------------------------------- sub get_location_url { my ($self, $fname) = @_; $fname =~ s/^file://; return $fname; } # ------------------------------------------------------------------------- sub get_location_contents { my ($self, $fname) = @_; $fname =~ s/^file://; if (!open (IN, "<$fname")) { carp "cannot open file \"$fname\"\n"; return ""; } my $text = join ('', ); close IN; return $text; } # ------------------------------------------------------------------------- sub get_location_mod_time { my ($self, $fname) = @_; $fname =~ /^file:(.*)$/; $self->{main}->cached_get_modtime ($1); } # ------------------------------------------------------------------------- sub get_location_edit_href { my ($self, $fname) = @_; return $self->{main}->{cgiglue}->contents_file_href ($self, $fname); } # ------------------------------------------------------------------------- sub dbg { HTML::WebMake::Main::dbg (@_); } # ------------------------------------------------------------------------- 1;