* Refactoring.

This commit is contained in:
Eelco Dolstra 2009-02-25 14:34:29 +00:00
parent 537f7c8c88
commit 76c3ae1cef
7 changed files with 109 additions and 109 deletions

View file

@ -0,0 +1,27 @@
package Hydra::Base::Controller::Nix;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
sub closure : Chained('nix') PathPart {
my ($self, $c) = @_;
$c->stash->{current_view} = 'Hydra::View::NixClosure';
# !!! quick hack; this is to make HEAD requests return the right
# MIME type. This is set in the view as well, but the view isn't
# called for HEAD requests. There should be a cleaner solution...
$c->response->content_type('application/x-nix-export');
}
sub manifest : Chained('nix') PathPart Args(0) {
my ($self, $c) = @_;
$c->stash->{current_view} = 'Hydra::View::NixManifest';
}
1;

View file

@ -2,7 +2,7 @@ package Hydra::Controller::Build;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use base 'Hydra::Base::Controller::Nix';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
@ -18,12 +18,9 @@ sub build : Chained('/') PathPart CaptureArgs(1) {
$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;
}
notFound($c, "Build with ID $id doesn't exist.")
if !defined $c->stash->{build};
$c->stash->{curProject} = $c->stash->{build}->project;
}
@ -49,7 +46,7 @@ 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;
notFound($c, "Build doesn't have a build step $stepnr.") if !defined $step;
$c->stash->{template} = 'log.tt';
$c->stash->{step} = $step;
@ -62,7 +59,7 @@ sub view_nixlog : Chained('build') PathPart('nixlog') Args(1) {
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;
error($c, "Build didn't produce a log.") if !defined $c->stash->{build}->resultInfo->logfile;
$c->stash->{template} = 'log.tt';
@ -89,13 +86,13 @@ 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;
notFound($c, "Build doesn't have a product $productnr.") if !defined $product;
return error($c, "Product " . $product->path . " has disappeared.") unless -e $product->path;
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$/;
error($c, "Invalid filename $elem.") if $elem !~ /^$pathCompRE$/;
}
my $path = $product->path;
@ -108,12 +105,26 @@ sub download : Chained('build') PathPart('download') {
$path = "$path/index.html" if -d $path && -e "$path/index.html";
if (!-e $path) {
return error($c, "File $path does not exist.");
}
notFound($c, "File $path does not exist.") if !-e $path;
$c->serve_static_file($path);
}
sub nix : Chained('build') PathPart('nix') CaptureArgs(0) {
my ($self, $c) = @_;
my $build = $c->stash->{build};
error($c, "Build cannot be downloaded as a closure or Nix package.")
if !$build->buildproducts->find({type => "nix-build"});
error($c, "Path " . $build->outpath . " is no longer available.")
unless isValidPath($build->outpath);
$c->stash->{name} = $build->nixname;
$c->stash->{storePaths} = [$build->outpath];
}
1;

View file

@ -2,7 +2,7 @@ package Hydra::Controller::Root;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use base 'Catalyst::Controller';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
@ -152,7 +152,7 @@ sub releasesets :Local {
$c->stash->{template} = 'releasesets.tt';
my $project = $c->model('DB::Projects')->find($projectName);
return error($c, "Project $projectName doesn't exist.") if !defined $project;
notFound($c, "Project $projectName doesn't exist.") if !defined $project;
$c->stash->{curProject} = $project;
$c->stash->{releaseSets} = [$project->releasesets->all];
@ -225,7 +225,7 @@ sub releases :Local {
return requireLogin($c) if !$c->user_exists;
return error($c, "Only the project owner or the administrator can perform this operation.")
error($c, "Only the project owner or the administrator can perform this operation.")
unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username;
if ($subcommand eq "edit") {
@ -247,7 +247,7 @@ sub releases :Local {
return $c->res->redirect($c->uri_for("/releasesets", $projectName));
}
else { return error($c, "Unknown subcommand."); }
else { error($c, "Unknown subcommand."); }
}
$c->stash->{template} = 'releases.tt';
@ -267,24 +267,19 @@ sub create_releaseset :Local {
return requireLogin($c) if !$c->user_exists;
return error($c, "Only the project owner or the administrator can perform this operation.")
error($c, "Only the project owner or the administrator can perform this operation.")
unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username;
if (defined $subcommand && $subcommand eq "submit") {
eval {
my $releaseSetName = $c->request->params->{name};
$c->model('DB')->schema->txn_do(sub {
# Note: $releaseSetName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid.
my $releaseSet = $project->releasesets->create({name => $releaseSetName});
updateReleaseSet($c, $releaseSet);
return $c->res->redirect($c->uri_for("/releases", $projectName, $releaseSet->name));
});
};
if ($@) {
return error($c, $@);
}
my $releaseSetName = $c->request->params->{name};
$c->model('DB')->schema->txn_do(sub {
# Note: $releaseSetName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid.
my $releaseSet = $project->releasesets->create({name => $releaseSetName});
updateReleaseSet($c, $releaseSet);
return $c->res->redirect($c->uri_for("/releases", $projectName, $releaseSet->name));
});
}
$c->stash->{template} = 'edit-releaseset.tt';
@ -301,7 +296,7 @@ sub release :Local {
if ($releaseId eq "latest") {
# Redirect to the latest successful release.
my $latest = getLatestSuccessfulRelease($project, $primaryJob, $jobs);
return error($c, "This release set has no successful releases yet.") if !defined $latest;
error($c, "This release set has no successful releases yet.") if !defined $latest;
return $c->res->redirect($c->uri_for("/release", $projectName, $releaseSetName, $latest->id));
}
@ -309,7 +304,7 @@ sub release :Local {
# build, but who cares?
my $primaryBuild = $project->builds->find($releaseId,
{ join => 'resultInfo', '+select' => ["resultInfo.releasename"], '+as' => ["releasename"] });
return error($c, "Release $releaseId doesn't exist.") if !defined $primaryBuild;
error($c, "Release $releaseId doesn't exist.") if !defined $primaryBuild;
$c->stash->{release} = getRelease($primaryBuild, $jobs);
}
@ -447,7 +442,7 @@ sub project :Local {
$c->stash->{template} = 'project.tt';
my $project = $c->model('DB::Projects')->find($projectName);
return error($c, "Project $projectName doesn't exist.") if !defined $project;
notFound($c, "Project $projectName doesn't exist.") if !defined $project;
my $isPosted = $c->request->method eq "POST";
@ -468,7 +463,7 @@ sub project :Local {
return requireLogin($c) if !$c->user_exists;
return error($c, "Only the project owner or the administrator can perform this operation.")
error($c, "Only the project owner or the administrator can perform this operation.")
unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username;
if ($subcommand eq "edit") {
@ -490,7 +485,7 @@ sub project :Local {
}
else {
return error($c, "Unknown subcommand $subcommand.");
error($c, "Unknown subcommand $subcommand.");
}
}
@ -506,25 +501,20 @@ sub createproject :Local {
return requireLogin($c) if !$c->user_exists;
return error($c, "Only administrators can create projects.")
error($c, "Only administrators can create projects.")
unless $c->check_user_roles('admin');
if (defined $subcommand && $subcommand eq "submit") {
eval {
my $projectName = trim $c->request->params->{name};
$c->model('DB')->schema->txn_do(sub {
# Note: $projectName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid. Idem for the owner.
my $project = $c->model('DB::Projects')->create(
{name => $projectName, displayname => "", owner => trim $c->request->params->{owner}});
updateProject($c, $project);
});
return $c->res->redirect($c->uri_for("/project", $projectName));
};
if ($@) {
return error($c, $@);
}
my $projectName = trim $c->request->params->{name};
$c->model('DB')->schema->txn_do(sub {
# Note: $projectName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid. Idem for the owner.
my $project = $c->model('DB::Projects')->create(
{name => $projectName, displayname => "", owner => trim $c->request->params->{owner}});
updateProject($c, $project);
});
return $c->res->redirect($c->uri_for("/project", $projectName));
}
$c->stash->{template} = 'project.tt';
@ -538,7 +528,7 @@ sub job :Local {
$c->stash->{template} = 'job.tt';
my $project = $c->model('DB::Projects')->find($projectName);
return error($c, "Project $projectName doesn't exist.") if !defined $project;
notFound($c, "Project $projectName doesn't exist.") if !defined $project;
$c->stash->{curProject} = $project;
$c->stash->{jobName} = $jobName;
@ -550,44 +540,7 @@ sub job :Local {
sub default :Path {
my ($self, $c) = @_;
error($c, "Page not found.");
$c->response->status(404);
}
sub closure :Local {
my ($self, $c, $buildId) = @_;
my $build = getBuild($c, $buildId);
return error($c, "Build $buildId doesn't exist.") if !defined $build;
return error($c, "Build $buildId cannot be downloaded as a closure.")
if !$build->buildproducts->find({type => "nix-build"});
return error($c, "Path " . $build->outpath . " is no longer available.") unless isValidPath($build->outpath);
$c->stash->{current_view} = 'Hydra::View::NixClosure';
$c->stash->{storePath} = $build->outpath;
$c->stash->{name} = $build->nixname;
# !!! quick hack; this is to make HEAD requests return the right
# MIME type. This is set in the view as well, but the view isn't
# called for HEAD requests. There should be a cleaner solution...
$c->response->content_type('application/x-nix-export');
$c->response->header('Content-Disposition' => 'attachment; filename=' . $c->stash->{name} . '.closure.gz');
}
sub manifest :Local {
my ($self, $c, $buildId) = @_;
my $build = getBuild($c, $buildId);
return error($c, "Build with ID $buildId doesn't exist.") if !defined $build;
return error($c, "Path " . $build->outpath . " is no longer available.") unless isValidPath($build->outpath);
$c->stash->{current_view} = 'Hydra::View::NixManifest';
$c->stash->{storePath} = $build->outpath;
notFound($c, "Page not found.");
}
@ -595,12 +548,12 @@ sub nixpkg :Local {
my ($self, $c, $buildId) = @_;
my $build = getBuild($c, $buildId);
return error($c, "Build $buildId doesn't exist.") if !defined $build;
notFound($c, "Build $buildId doesn't exist.") if !defined $build;
return error($c, "Build $buildId cannot be downloaded as a Nix package.")
error($c, "Build $buildId cannot be downloaded as a Nix package.")
if !$build->buildproducts->find({type => "nix-build"});
return error($c, "Path " . $build->outpath . " is no longer available.") unless isValidPath($build->outpath);
error($c, "Path " . $build->outpath . " is no longer available.") unless isValidPath($build->outpath);
$c->stash->{current_view} = 'Hydra::View::NixPkg';
$c->stash->{build} = $build;
@ -614,7 +567,7 @@ sub nar :Local {
my $path .= "/" . join("/", @rest);
return error($c, "Path " . $path . " is no longer available.") unless isValidPath($path);
error($c, "Path " . $path . " is no longer available.") unless isValidPath($path);
$c->stash->{current_view} = 'Hydra::View::NixNAR';
$c->stash->{storePath} = $path;

View file

@ -4,7 +4,7 @@ use strict;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(getBuild error);
our @EXPORT = qw(getBuild error notFound);
sub getBuild {
@ -21,4 +21,11 @@ sub error {
}
sub notFound {
my ($c, $msg) = @_;
$c->response->status(404);
error($c, $msg);
}
1;

View file

@ -5,14 +5,13 @@ use base qw/Catalyst::View/;
use IO::Pipe;
sub process {
my ( $self, $c ) = @_;
my ($self, $c) = @_;
$c->response->content_type('application/x-nix-export');
$c->response->header('Content-Disposition' => 'attachment; filename=' . $c->stash->{name} . '.closure.gz');
my $storePath = $c->stash->{storePath};
my @storePaths = @{$c->stash->{storePaths}};
open(OUTPUT, "nix-store --export `nix-store -qR $storePath` | gzip |");
open(OUTPUT, "nix-store --export `nix-store -qR @storePaths` | gzip |");
my $fh = new IO::Handle;
$fh->fdopen(fileno(OUTPUT), "r") or die;

View file

@ -16,12 +16,12 @@ sub captureStdoutStderr {
sub process {
my ($self, $c) = @_;
my $storePath = $c->stash->{storePath};
my @storePaths = @{$c->stash->{storePaths}};
$c->response->content_type('text/x-nix-manifest');
my @paths = split '\n', `nix-store --query --requisites $storePath`
or die "cannot query dependencies of `$storePath': $?";
my @paths = split '\n', `nix-store --query --requisites @storePaths`
or die "cannot query dependencies of path(s) @storePaths: $?";
my $manifest =
"version {\n" .

View file

@ -43,7 +43,10 @@
<li class="product">
<a href="[% c.uri_for('/closure' build.id) %]">
[% filename = "${build.nixname}.closure.gz" %]
[% uri = c.uri_for('/build' build.id 'nix' 'closure' filename ) %]
<a href="[% uri %]">
<img src="/static/images/nix-build.png" alt="Source" />
Nix closure of path <tt>[% product.path %]</tt>
</a>
@ -54,11 +57,11 @@
all its dependencies can be unpacked into your local Nix
store by doing:</p>
<pre>$ gunzip &lt; [% HTML.escape(build.nixname) %].closure.gz | nix-store --import</pre>
<pre>$ gunzip &lt; [% filename %] | nix-store --import</pre>
or to download and unpack in one command:
<pre>$ curl [% c.uri_for('/closure' build.id) %] | gunzip | nix-store --import</pre>
<pre>$ curl [% uri %] | gunzip | nix-store --import</pre>
<p>The package can then be found in the path <tt>[%
product.path %]</tt>. Youll probably also want to do