Daizu
view release on metacpan or search on metacpan
lib/Daizu/Publish.pm view on Meta::CPAN
sub publish_urls
{
my ($cms, $file, $generator, $method, $urls) = @_;
eval { _publish_urls_work($cms, $file, $generator, $method, $urls) };
if ($@) {
# Clean up any temp files left behind.
for my $url_info (@$urls) {
my $filename = $url_info->{_tmp_filename};
next unless defined $filename;
warn "Cleaning up unfinished temp file '$filename'.\n";
unlink $filename
or warn "Error deleting temp file '$filename': $!\n";
delete $url_info->{_tmp_filename};
}
die $@;
}
}
# This is called in an eval{} so that any half-published temp files can
# be cleaned up if it breaks.
sub _publish_urls_work
{
my ($cms, $file, $generator, $method, $urls) = @_;
for my $url_info (@$urls) {
my $out_url = $url_info->{url} = URI->new($url_info->{url});
my $full_filename = _url_output_filename($cms, $out_url, 1);
my $tmp_filename = "$full_filename.daizutmp";
open my $fh, '>', $tmp_filename
or die "Error opening output file '$tmp_filename': $!\n";
binmode $fh
or die "Error setting binmode on output file '$tmp_filename': $!\n";
assert(!defined $url_info->{fh}) if DEBUG;
$url_info->{fh} = $fh;
$url_info->{_full_filename} = $full_filename;
$url_info->{_tmp_filename} = $tmp_filename;
}
$generator->$method($file, $urls);
# Close the output files explicitly, so that any errors encountered while
# flushing buffers are correctly reported. Also make them executable
# if the original file in Subversion is (for CGI scripts).
for my $url_info (@$urls) {
my $filename = $url_info->{_full_filename};
my $tmpfile = $url_info->{_tmp_filename};
if (defined $url_info->{fh}) {
close $url_info->{fh}
or die "Error closing output file '$tmpfile': $!\n";
}
delete $url_info->{fh};
if ($file->property('svn:executable')) {
my $umask = umask;
if (defined $umask) {
chmod +(0777 & ~$umask), $tmpfile
or die "Error making '$tmpfile' executable: $!\n";
}
}
if (!-f $filename || _file_hash($tmpfile) ne _file_hash($filename) ||
-x $tmpfile ne -x $filename)
{
# Move the temp file into place, possibly overrwritting an older
# published version.
rename $tmpfile, $filename
or die "Error moving file '$tmpfile' into place: $!\n";
}
else {
# The new version of the file is identical to an older one which
# is still present in the document root, so we might as well just
# delete the temp file. This wil mean that the timestamp of the
# live version won't get fiddled with when no real changes have
# been made, and it will save rsync from having to do a comparison.
unlink $tmpfile
or die "Error deleting temp file '$tmpfile': $!\n";
}
}
}
sub _url_output_filename
{
my ($cms, $url, $create_dir) = @_;
my ($config, $docroot, $path, $filename) = $cms->output_config($url);
die "No output path defined for URL '$url'\n"
unless defined $docroot;
mkpath(file($docroot, $path)->stringify)
if $create_dir;
return file($docroot, $path, $filename);
}
# Return a SHA1 digest of a file's content (a file on the filesystem, not one
# in a database working copy).
sub _file_hash
{
my ($filename) = @_;
open my $fh, '<', $filename
or die "Error opening file '$filename' for digesting: $!\n";
binmode $fh
or die "Error binmoding file '$filename' for digesting: $!\n";
my $digest = Digest::SHA1->new;
$digest->addfile($fh);
return $digest->digest;
}
=item publish_redirect_map($cms, $wc_id, $config)
TODO
TODO - redirect and gone maps should be published in the same way as
URL content, with the file first written to a different filename, then
( run in 1.837 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )