Skip to content

Commit

Permalink
Put tasks into their own namespace
Browse files Browse the repository at this point in the history
Experiment to see if we can encapsulate a task in its own namespace.
Should work, need more testing ASAP.
  • Loading branch information
pudge committed Jun 3, 2008
1 parent 07e6bb4 commit 1d3983f
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 3 deletions.
53 changes: 51 additions & 2 deletions bin/runtask
Expand Up @@ -11,6 +11,7 @@ use Getopt::Std;
use File::Basename;
use File::Path;
use File::Spec::Functions;
use File::Temp 'tempfile';
use FindBin '$Bin';
use LWP::UserAgent;
use HTTP::Request;
Expand Down Expand Up @@ -177,8 +178,56 @@ EOT
my $file = basename($fullname);
next unless $file eq $task_name or $file eq "$task_name.pl";
$task_name = $file;

# we want to encapsulate each task automatically. to do that,
# we automatically create a package name for each task, and
# then we manually import the symbols we want into that package.
# then it is written out as a temp file, and THAT file is
# require'd, not the actual task.
# we may be importing more than we need for coderefs, but
# i didn't feel like looking at each task individually.

(my $tmppackage = $file) =~ s/\.pl$//;
$tmppackage =~ s/\W/_/g;
$tmppackage =~ s/^([^a-zA-Z])/a_$1/g;
$tmppackage = "Slash::Task::$tmppackage";

# replace tmppackage in string where appropriate
(my $addtxt = <<'EOT') =~ s/\${?tmppackage}?/$tmppackage/g;
package $tmppackage;
{ no strict 'refs';
my @scalar = qw(me task_exit_flag);
my @hash = qw(task);
my @code = (qw(
slashdLog slashdErrnote slashdLogDie
tagboxLog verbosity db_time init_cron
),
grep { *{"main::$_"}{CODE} }
@Slash::EXPORT, @Slash::Display::EXPORT,
@Slash::Utility::EXPORT,
@File::Spec::Functions::EXPORT,
@LWP::UserAgent::EXPORT, @URI::Escape::EXPORT,
@File::Basename::EXPORT, @File::Path::EXPORT,
@Time::Local::EXPORT, @Time::HiRes::EXPORT
);
*{"${tmppackage}::$_"} = *{"main::$_"}{HASH} for @hash;
*{"${tmppackage}::$_"} = *{"main::$_"}{SCALAR} for @scalar;
*{"${tmppackage}::$_"} = *{"main::$_"}{CODE} for @code;
}
EOT

my($tmpfh, $tmpfile) = tempfile();
my $tmptxt = do { open my $fh, '<', $fullname; local $/; <$fh> };
print $tmpfh $addtxt, $tmptxt;
$tmpfh->flush; # can't close fh until we require the file,
# else the file might disappear

my $ok = 0;
eval { local $me = $file; $ok = require $fullname; };
eval { local $me = $file; $ok = require $tmpfile };

if ($@) {
slashdLog("requiring '$fullname' raised exception: $@");
$ok = 0;
Expand All @@ -187,7 +236,7 @@ EOT
slashdLog("requiring '$fullname' caused error: $!");
$ok = 0;
}
if (!$task{$file}{code} or ref $task{$file}{code} ne 'CODE') {
if (!$task{$file}{code} || ref $task{$file}{code} ne 'CODE') {
slashdLog("'$fullname' did not set code properly");
$ok = 0;
}
Expand Down
51 changes: 50 additions & 1 deletion sbin/slashd
Expand Up @@ -23,6 +23,7 @@ use Carp;
use Errno;
use File::Basename;
use File::Path;
use File::Temp 'tempfile';
use File::Spec::Functions qw(:DEFAULT devnull);
use LWP::UserAgent;
use HTTP::Request;
Expand Down Expand Up @@ -335,8 +336,56 @@ you really don't want me to use a task file that's world-writable: $fullname
EOT
}
my $file = basename($fullname);

# we want to encapsulate each task automatically. to do that,
# we automatically create a package name for each task, and
# then we manually import the symbols we want into that package.
# then it is written out as a temp file, and THAT file is
# require'd, not the actual task.
# we may be importing more than we need for coderefs, but
# i didn't feel like looking at each task individually.

(my $tmppackage = $file) =~ s/\.pl$//;
$tmppackage =~ s/\W/_/g;
$tmppackage =~ s/^([^a-zA-Z])/a_$1/g;
$tmppackage = "Slash::Task::$tmppackage";

# replace tmppackage in string where appropriate
(my $addtxt = <<'EOT') =~ s/\${?tmppackage}?/$tmppackage/g;
package $tmppackage;
{ no strict 'refs';
my @scalar = qw(me task_exit_flag);
my @hash = qw(task);
my @code = (qw(
slashdLog slashdErrnote slashdLogDie
tagboxLog verbosity db_time init_cron
),
grep { *{"main::$_"}{CODE} }
@Slash::EXPORT, @Slash::Display::EXPORT,
@Slash::Utility::EXPORT,
@File::Spec::Functions::EXPORT,
@LWP::UserAgent::EXPORT, @URI::Escape::EXPORT,
@File::Basename::EXPORT, @File::Path::EXPORT,
@Time::Local::EXPORT, @Time::HiRes::EXPORT
);
*{"${tmppackage}::$_"} = *{"main::$_"}{HASH} for @hash;
*{"${tmppackage}::$_"} = *{"main::$_"}{SCALAR} for @scalar;
*{"${tmppackage}::$_"} = *{"main::$_"}{CODE} for @code;
}
EOT

my($tmpfh, $tmpfile) = tempfile();
my $tmptxt = do { open my $fh, '<', $fullname; local $/; <$fh> };
print $tmpfh $addtxt, $tmptxt;
$tmpfh->flush; # can't close fh until we require the file,
# else the file might disappear

my $ok = 0;
eval { local $me = $file; $ok = require $fullname; };
eval { local $me = $file; $ok = require $tmpfile };

if ($@) {
slashdLog("requiring '$fullname' raised exception: $@");
$ok = 0;
Expand Down

0 comments on commit 1d3983f

Please sign in to comment.