Fix a FilePump bug in handling file URIs that are directories.
This commit is contained in:
parent
67df78608d
commit
4dc2d58a02
4 changed files with 184 additions and 17 deletions
|
|
@ -18,6 +18,7 @@
|
|||
- fixed: Story subtitle is supposed to be a text field, not a text area.
|
||||
- fixed: Display of short pagination bar when there's less than 1 page of data in StoryArchive
|
||||
- added: Storage now has a getHexId method for returning a cached hexadecimal version of the storageId.
|
||||
- fixed: FilePump should copy filesystem directories and their files when given a file URI that is a directory.
|
||||
|
||||
7.7.6
|
||||
- Added mobile style template. If enabled in settings, will serve alternate style templates
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package WebGUI::FilePump::Bundle;
|
||||
|
||||
use base qw/WebGUI::Crud/;
|
||||
use strict;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Utility;
|
||||
use URI;
|
||||
|
|
@ -120,7 +121,7 @@ sub build {
|
|||
##Create the new build directory
|
||||
my $newDir = $self->getPathClassDir($newBuild);
|
||||
my $mkpathErrors;
|
||||
my $dirsCreated = $newDir->mkpath({ errors => $mkpathErrors });
|
||||
my $dirsCreated = $newDir->mkpath({ errors => \$mkpathErrors });
|
||||
if (! $dirsCreated) {
|
||||
$newDir->rmtree;
|
||||
my $errorMessages = join "\n", @{ $mkpathErrors };
|
||||
|
|
@ -129,7 +130,6 @@ sub build {
|
|||
|
||||
##Copy files over
|
||||
my $otherFiles = $self->get('otherFiles');
|
||||
my $i18n = WebGUI::International->new($self->session, 'FilePump');
|
||||
OTHERFILE: foreach my $file (@{ $otherFiles }) {
|
||||
my $uri = $file->{uri};
|
||||
my $results = $self->fetch($uri);
|
||||
|
|
@ -138,18 +138,14 @@ sub build {
|
|||
last OTHERFILE;
|
||||
}
|
||||
$file->{lastModified} = $results->{lastModified};
|
||||
my $uriPath = URI->new($uri)->opaque;
|
||||
$uriPath =~ tr{/}{/}s;
|
||||
my $filename = basename($uriPath);
|
||||
my $newFile = $newDir->file($filename);
|
||||
if (-e $newFile->stringify) {
|
||||
$error = join ' ', $uri, $i18n->get('duplicate file');
|
||||
last OTHERFILE;
|
||||
if ($results->{type} eq 'file') {
|
||||
$error = $self->_buildFile($newDir, $uri, $results);
|
||||
}
|
||||
my $fh = $newFile->open('>');
|
||||
$fh->binmode;
|
||||
print $fh $results->{content};
|
||||
close $fh;
|
||||
elsif ($results->{type} eq 'directory') {
|
||||
$error = $self->_buildDir($newDir, $uri, $results);
|
||||
}
|
||||
last OTHERFILE if ($error);
|
||||
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
|
|
@ -188,6 +184,102 @@ sub build {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 _buildDir ( $newDir, $uri, $results )
|
||||
|
||||
Copy over a directory and all its files from the filesystem into the build directory. It does
|
||||
not copy deeply.
|
||||
|
||||
=head3 $newDir
|
||||
|
||||
A Path::Class::Dir object pointing to the new build directory.
|
||||
|
||||
=head3 $uri
|
||||
|
||||
A URI to the original directory.
|
||||
|
||||
=head3 $results
|
||||
|
||||
The returned results from fetchDir, with the file contents to
|
||||
install into the build directory.
|
||||
|
||||
=cut
|
||||
|
||||
sub _buildDir {
|
||||
my ($self, $newDir, $uri, $results) = @_;
|
||||
my $uriPath = URI->new($uri)->opaque;
|
||||
$uriPath =~ tr{/}{/}s;
|
||||
my $uriDir = Path::Class::Dir->new($uriPath);
|
||||
my $dirname = $uriDir->dir_list(-1, 1);
|
||||
my $newSubDir = $newDir->subdir($dirname);
|
||||
if (-e $newSubDir->stringify) {
|
||||
my $i18n = WebGUI::International->new($self->session, 'FilePump');
|
||||
return join ' ', $uri, $i18n->get('duplicate directory');
|
||||
}
|
||||
my $mkpathErrors;
|
||||
my $dirsCreated = $newSubDir->mkpath({ errors => \$mkpathErrors });
|
||||
if (! $dirsCreated) {
|
||||
$newSubDir->rmtree;
|
||||
my $errorMessages = join "\n", @{ $mkpathErrors };
|
||||
return $errorMessages;
|
||||
}
|
||||
##Note, we built the directory, so there should be no problems with
|
||||
##file permissions. Likewise, since you can't have files with the same
|
||||
##name in the source directory, there's no need to check for filename collisions.
|
||||
foreach my $subFile (@{ $results->{content} }) {
|
||||
my $inFH = $subFile->open('<');
|
||||
my $newFile = $newSubDir->file($subFile->basename);
|
||||
my $outFH = $newFile->open('>');
|
||||
$inFH->binmode;
|
||||
$outFH->binmode;
|
||||
local $/;
|
||||
my $inFile = <$inFH>;
|
||||
print $outFH $inFile;
|
||||
$inFH->close;
|
||||
$outFH->close;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 _buildFile ( $newDir, $uri, $results )
|
||||
|
||||
Copy over a file from the filesystem into the build directory.
|
||||
|
||||
=head3 $newDir
|
||||
|
||||
A Path::Class::Dir object pointing to the new build directory.
|
||||
|
||||
=head3 $uri
|
||||
|
||||
A URI to the original file.
|
||||
|
||||
=head3 $results
|
||||
|
||||
The returned results from fetchFile, with the file contents to
|
||||
install into the build directory.
|
||||
|
||||
=cut
|
||||
|
||||
sub _buildFile {
|
||||
my ($self, $newDir, $uri, $results) = @_;
|
||||
my $uriPath = URI->new($uri)->opaque;
|
||||
$uriPath =~ tr{/}{/}s;
|
||||
my $filename = basename($uriPath);
|
||||
my $newFile = $newDir->file($filename);
|
||||
if (-e $newFile->stringify) {
|
||||
my $i18n = WebGUI::International->new($self->session, 'FilePump');
|
||||
return join ' ', $uri, $i18n->get('duplicate file');
|
||||
}
|
||||
my $fh = $newFile->open('>');
|
||||
$fh->binmode;
|
||||
print $fh $results->{content};
|
||||
close $fh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 crud_definition
|
||||
|
||||
WebGUI::Crud definition for this class.
|
||||
|
|
@ -460,11 +552,46 @@ sub fetchAsset {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 fetchDirectory ( $uri )
|
||||
|
||||
Fetches all files from a filesystem directory. Returns a hashref
|
||||
with the date that the directory was last updated, a contents entry
|
||||
which is an arrayref of Path::Class objects from the directory. '.', and '../'
|
||||
are always ommitted, and a type entry which is the string 'directory'.
|
||||
|
||||
If there is any problem with getting files, it returns an empty hashref.
|
||||
|
||||
=head3 $uri
|
||||
|
||||
A URI object.
|
||||
|
||||
=cut
|
||||
|
||||
sub fetchDir {
|
||||
my ($self, $uri ) = @_;
|
||||
my $filepath = $uri->path;
|
||||
return {} unless (-e $filepath && -r _ && -d _);
|
||||
my @stats = stat(_);
|
||||
my $dir = Path::Class::Dir->new($filepath);
|
||||
my $guts = {
|
||||
lastModified => $stats[9],
|
||||
content => [ $dir->children ],
|
||||
type => 'directory',
|
||||
};
|
||||
return $guts;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 fetchFile ( $uri )
|
||||
|
||||
Fetches a bundle file from the local filesystem. Returns a hashref
|
||||
with the content and date that it was last updated. If there is any problem
|
||||
with getting the file, it returns an empty hashref.
|
||||
Fetches a bundle file from the local filesystem. Returns a hashref with the
|
||||
content, date that it was last updated, and a type entry which is the string
|
||||
'file'. If there is any problem with getting the file, it returns an
|
||||
empty hashref.
|
||||
|
||||
If fetchFile is passed a URI which is a directory, it will call fetchDir on
|
||||
that URI and return the results.
|
||||
|
||||
=head3 $uri
|
||||
|
||||
|
|
@ -476,12 +603,14 @@ sub fetchFile {
|
|||
my ($self, $uri ) = @_;
|
||||
my $filepath = $uri->path;
|
||||
return {} unless (-e $filepath && -r _);
|
||||
return $self->fetchDir($uri) if -d _;
|
||||
my @stats = stat(_); # recycle stat data from file tests.
|
||||
open my $file, '<', $filepath or return {};
|
||||
local $/;
|
||||
my $guts = {
|
||||
lastModified => $stats[9],
|
||||
content => <$file>,
|
||||
type => 'file',
|
||||
};
|
||||
close $file;
|
||||
return $guts;
|
||||
|
|
|
|||
|
|
@ -106,6 +106,12 @@ our $I18N = {
|
|||
context => q|Error message when building a new bundle.|
|
||||
},
|
||||
|
||||
'duplicate directory' => {
|
||||
message => q|A directory with the same name already exists in the build directory.|,
|
||||
lastUpdated => 1242515308,
|
||||
context => q|Error message when building a new bundle.|
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ my $session = WebGUI::Test->session;
|
|||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
|
||||
my $tests = 50; # Increment this number for each test you create
|
||||
my $tests = 54; # Increment this number for each test you create
|
||||
plan tests => 1 + $tests; # 1 for the use_ok
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -240,6 +240,11 @@ my $fileAsset = $root->addChild({
|
|||
|
||||
$fileAsset->getStorageLocation->addFileFromScalar('pumpfile', 'Pump up the jam');
|
||||
|
||||
my $storage = WebGUI::Storage->create($session);
|
||||
WebGUI::Test->storagesToDelete($storage);
|
||||
$storage->addFileFromScalar('addendum', 'Red was too');
|
||||
$storage->addFileFromFilesystem(WebGUI::Test->getTestCollateralPath('ShawshankRedemptionMoviePoster.jpg'));
|
||||
|
||||
my $snippetTag = WebGUI::VersionTag->getWorking($session);
|
||||
WebGUI::Test->tagsToRollback($snippetTag);
|
||||
$snippetTag->commit;
|
||||
|
|
@ -274,10 +279,26 @@ cmp_deeply(
|
|||
{
|
||||
content => 'Pump up the jam',
|
||||
lastModified => re('^\d+$'),
|
||||
type => 'file',
|
||||
},
|
||||
'fetchFile: retrieved a file from the filesystem'
|
||||
);
|
||||
|
||||
my $uriDir = URI->new('file:'.$storage->getPath);
|
||||
$guts = $bundle->fetchDir($uriDir);
|
||||
cmp_deeply(
|
||||
$guts,
|
||||
{
|
||||
lastModified => re('^\d+$'),
|
||||
content => [
|
||||
isa('Path::Class::File'),
|
||||
isa('Path::Class::File'),
|
||||
],
|
||||
type => 'directory',
|
||||
},
|
||||
'fetchDir: retrieved information about a directory and its subfiles from the filesystem'
|
||||
);
|
||||
|
||||
###################################################################
|
||||
#
|
||||
# getPathClassDir
|
||||
|
|
@ -335,6 +356,7 @@ $fileAsset->update({filename => 'pumpfile.css'});
|
|||
$bundle->addFile('JS', 'asset://filePumpSnippet');
|
||||
$bundle->addFile('CSS', 'asset://filePumpFileAsset');
|
||||
$bundle->addFile('OTHER', 'file:'.WebGUI::Test->getTestCollateralPath('gooey.jpg'));
|
||||
$bundle->addFile('OTHER', 'file:'.$storage->getPath);
|
||||
my ($buildFlag, $error) = $bundle->build();
|
||||
ok($buildFlag, 'build returns true when there are no errors');
|
||||
diag $error unless $buildFlag;
|
||||
|
|
@ -347,13 +369,22 @@ ok(!-e $oldBuildDir->stringify && !-d _, '... old build directory deleted');
|
|||
my $jsFile = $buildDir->file($bundle->bundleUrl . '.js');
|
||||
my $cssFile = $buildDir->file($bundle->bundleUrl . '.css');
|
||||
my $otherFile = $buildDir->file('gooey.jpg');
|
||||
my $otherDir = $buildDir->subdir($storage->getHexId);
|
||||
ok(-e $jsFile->stringify && -f _ && -s _, '... minified JS file built, not empty');
|
||||
ok(-e $cssFile->stringify && -f _ && -s _, '... minified CSS file built, not empty');
|
||||
ok(-e $otherFile->stringify && -f _ && -s _, '... other file copied over, not empty');
|
||||
ok(-e $otherDir->stringify && -d _ , '... other directory copied over');
|
||||
|
||||
cmp_deeply(
|
||||
[ map { $_->basename } $otherDir->children ],
|
||||
[ qw/addendum ShawshankRedemptionMoviePoster.jpg/ ],
|
||||
'... File copied over to new directory'
|
||||
);
|
||||
|
||||
ok($bundle->get('jsFiles')->[0]->{lastModified}, '... updated JS file lastModified');
|
||||
ok($bundle->get('cssFiles')->[0]->{lastModified}, '... updated CSS file lastModified');
|
||||
ok($bundle->get('otherFiles')->[0]->{lastModified}, '... updated OTHER file lastModified');
|
||||
ok($bundle->get('otherFiles')->[1]->{lastModified}, '... updated OTHER directory lastModified');
|
||||
|
||||
###################################################################
|
||||
#
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue