LBNVQXUBEZ45SOTGVXK5UEZXIAIZTJLWZNUYFI4JZ6J65N3KPDVQC SMM4HQTPAY45254O7GQOJVLHP5LZ6BXDKGNE7IKUJHB5XKH244ZAC PKPWUHUXLGPQFQUTNHLVGWNT6AB3H2VMDCBKT6IPZDC53CEL4W7QC SHBLLAVHMMHOPCJ5NPGDZQPVRAMPMGXSFEMX7H7BETW6GTRGUUBAC J5UVLXOK6EDIL5I7VKWH4V2QDS4DPD7FHRK6XBWSXFRQS4JKXFZQC HK32XC42XOS7JKJMFT3XJKPXVSI44SFGKUUSJIL5VGPIHYNNWXLAC PBFZEQLZXMOBQIWL5WQWH7D62XG6M7ROEEAH6PWAKKKOM3W5I3RQC UAPS46BQNEZACYO2LYXEXIK5YESDG2N2B3BYIZGVETGP6LOM4OGAC GCHNNFZPCYM3BPOCU5GASALJ6ONWMEVEEGVD7KKLTWC7YQKJ5KZAC FHF6IZJQPUQHY5QWQYRPZVDBRLHREWRHGNKVQDT7F3GQKKLZXJKQC W6DC6K4INJQOJYR553ISCKZV7YIOGHEM3FZQPOLAPSZQ3KSJDMRQC JLDUSNUOOQNL63BOPXIWZOWFRQ5X35RWG33PJB3J3KMR6QR7TN7QC JD27RBKM7ROBUKBEQDFSCPO3MDE2AFZ6DSSKFUPJ7IC2MCGDVFGAC ELCI5T2ALF37VXYM5POHPO3CAMMPRB65BXGDRVUAZG53NKKLGIEAC WHAFVCEIHCWHKY2UVRGRQORERUAK6SZJI7ZENA367ZX4EXDIQMDQC LQNBKF3DKVYK3NPDGK7OLOTIWIF4HR3EKLRYNLZJB4G3NMIVBCEAC WZ3AEJ67LOG5L335AAC2BDLIJPIU4VSCGBMATBHDZC26ECRS5A6AC BD3GRK4BQUGRQGTAILUITIH3RRSVUH6AKINVMMKYLBAAHAAUSB4AC IW6XNRL7KVUUXV7JH2AEVKNPSJ4KOXCGRK7J7BS744L74TGLFORQC CLJQCY2XHIDNNMFBJ5PK3GQEN6RFALEFKXBJRWZPEIKR4PR5ZQ5AC AS5PAYLIRJWB4JGU6N7WKILONGDIGCKNKS4ZSLRYCNGMUAP3AQSAC BA46C5LNEQ57N52IJTCEXW4J74F33KKNYHYXE6ZJLQ5ARMCJPUHAC L5VIEXSC5R72SEDSWF7HWNXMSTAAADBUMCSREU5ITMRXLEJ6KZWQC MOCEUXZAS4CNZL2QDKGVTZCRZ6AMOO2WSFHJ4VPZPPPAXHANG4NAC KOTB7BKVML6T6S5ZNTQ6456FMGCRZCP3E3KVWCOW7T6SPRHC53LAC IK53RV4VGOHLCZGQCCIKPB45M3C7M7YMNBOJFBGZJ4LWIZNU4QNQC L7LFU6IQA7XLRG67U34INTUSYIWP66LFFJE43J6S3GMMQHXXFKRAC JFZNAYJXKCMXYHGCLTRH7Q6TOFGJ4BT6332GONCWVYRLNMDDG3KAC Y35C6GHH45ZUEZHHYZU4BQK3GOPJENOY2DZM3TMVUA6AMSPT2I7AC package Hydra::Controller::Build;use strict;use warnings;use parent 'Catalyst::Controller';use Hydra::Helper::Nix;use Hydra::Helper::CatalystUtils;# Security checking of filenames.my $pathCompRE = "(?:[A-Za-z0-9-\+][A-Za-z0-9-\+\._]*)";my $relPathRE = "(?:$pathCompRE(?:\/$pathCompRE)*)";sub build : Chained('/') PathPart CaptureArgs(1) {my ($self, $c, $id) = @_;$c->stash->{id} = $id;$c->stash->{build} = getBuild($c, $id);if (!defined $c->stash->{build}) {error($c, "Build with ID $id doesn't exist.");$c->response->status(404);return;}$c->stash->{curProject} = $c->stash->{build}->project;}sub view_build : Chained('build') PathPart('') Args(0) {my ($self, $c) = @_;my $build = $c->stash->{build};$c->stash->{template} = 'build.tt';$c->stash->{curTime} = time;$c->stash->{available} = isValidPath $build->outpath;if (!$build->finished && $build->schedulingInfo->busy) {my $logfile = $build->schedulingInfo->logfile;$c->stash->{logtext} = `cat $logfile`;}}sub view_nixlog : Chained('build') PathPart('nixlog') Args(1) {my ($self, $c, $stepnr) = @_;my $step = $c->stash->{build}->buildsteps->find({stepnr => $stepnr});return error($c, "Build doesn't have a build step $stepnr.") if !defined $step;$c->stash->{template} = 'log.tt';$c->stash->{step} = $step;# !!! should be done in the view (as a TT plugin).$c->stash->{logtext} = loadLog($c, $step->logfile);}sub view_log : Chained('build') PathPart('log') Args(0) {my ($self, $c) = @_;return error($c, "Build didn't produce a log.") if !defined $c->stash->{build}->resultInfo->logfile;$c->stash->{template} = 'log.tt';# !!! should be done in the view (as a TT plugin).$c->stash->{logtext} = loadLog($c, $c->stash->{build}->resultInfo->logfile);}sub loadLog {my ($c, $path) = @_;die unless defined $path;# !!! quick hackmy $pipeline = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path"). " | nix-log2xml | xsltproc " . $c->path_to("xsl/mark-errors.xsl") . " -". " | xsltproc " . $c->path_to("xsl/log2html.xsl") . " - | tail -n +2";return `$pipeline`;}sub download : Chained('build') PathPart('download') {my ($self, $c, $productnr, $filename, @path) = @_;my $product = $c->stash->{build}->buildproducts->find({productnr => $productnr});return error($c, "Build doesn't have a product $productnr.") if !defined $product;return error($c, "Product " . $product->path . " has disappeared.") unless -e $product->path;# Security paranoia.foreach my $elem (@path) {return error($c, "Invalid filename $elem.") if $elem !~ /^$pathCompRE$/;}my $path = $product->path;$path .= "/" . join("/", @path) if scalar @path > 0;# If this is a directory but no "/" is attached, then redirect.if (-d $path && substr($c->request->uri, -1) ne "/") {return $c->res->redirect($c->request->uri . "/");}$path = "$path/index.html" if -d $path && -e "$path/index.html";if (!-e $path) {return error($c, "File $path does not exist.");}$c->serve_static_file($path);}1;
}sub getBuild {my ($c, $id) = @_;my $build = $c->model('DB::Builds')->find($id);return $build;
}sub build : Chained('/') PathPart CaptureArgs(1) {my ($self, $c, $id) = @_;$c->stash->{id} = $id;$c->stash->{build} = getBuild($c, $id);if (!defined $c->stash->{build}) {error($c, "Build with ID $id doesn't exist.");$c->response->status(404);return;}$c->stash->{curProject} = $c->stash->{build}->project;}sub view_build : Chained('build') PathPart('') Args(0) {my ($self, $c) = @_;my $build = $c->stash->{build};$c->stash->{template} = 'build.tt';$c->stash->{curTime} = time;$c->stash->{available} = isValidPath $build->outpath;if (!$build->finished && $build->schedulingInfo->busy) {my $logfile = $build->schedulingInfo->logfile;$c->stash->{logtext} = `cat $logfile`;}}sub view_nixlog : Chained('build') PathPart('nixlog') Args(1) {my ($self, $c, $stepnr) = @_;my $step = $c->stash->{build}->buildsteps->find({stepnr => $stepnr});return error($c, "Build doesn't have a build step $stepnr.") if !defined $step;$c->stash->{template} = 'log.tt';$c->stash->{step} = $step;# !!! should be done in the view (as a TT plugin).$c->stash->{logtext} = loadLog($c, $step->logfile);}sub view_log : Chained('build') PathPart('log') Args(0) {my ($self, $c) = @_;return error($c, "Build didn't produce a log.") if !defined $c->stash->{build}->resultInfo->logfile;$c->stash->{template} = 'log.tt';# !!! should be done in the view (as a TT plugin).$c->stash->{logtext} = loadLog($c, $c->stash->{build}->resultInfo->logfile);}sub loadLog {my ($c, $path) = @_;die unless defined $path;# !!! quick hackmy $pipeline = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path"). " | nix-log2xml | xsltproc " . $c->path_to("xsl/mark-errors.xsl") . " -". " | xsltproc " . $c->path_to("xsl/log2html.xsl") . " - | tail -n +2";return `$pipeline`;
sub download : Chained('build') PathPart('download') {my ($self, $c, $productnr, $filename, @path) = @_;my $product = $c->stash->{build}->buildproducts->find({productnr => $productnr});return error($c, "Build doesn't have a product $productnr.") if !defined $product;return error($c, "Product " . $product->path . " has disappeared.") unless -e $product->path;# Security paranoia.foreach my $elem (@path) {return error($c, "Invalid filename $elem.") if $elem !~ /^$pathCompRE$/;}my $path = $product->path;$path .= "/" . join("/", @path) if scalar @path > 0;# If this is a directory but no "/" is attached, then redirect.if (-d $path && substr($c->request->uri, -1) ne "/") {return $c->res->redirect($c->request->uri . "/");}$path = "$path/index.html" if -d $path && -e "$path/index.html";if (!-e $path) {return error($c, "File $path does not exist.");}$c->serve_static_file($path);}
package Hydra::Helper::CatalystUtils;use strict;use Exporter;our @ISA = qw(Exporter);our @EXPORT = qw(getBuild error);sub getBuild {my ($c, $id) = @_;my $build = $c->model('DB::Builds')->find($id);return $build;}sub error {my ($c, $msg) = @_;$c->error($msg);$c->detach;}1;