diff --git a/src/Hydra/lib/Hydra/Controller/Root.pm b/src/Hydra/lib/Hydra/Controller/Root.pm index 817882c1..a5b2fcaa 100644 --- a/src/Hydra/lib/Hydra/Controller/Root.pm +++ b/src/Hydra/lib/Hydra/Controller/Root.pm @@ -707,6 +707,17 @@ sub closure :Local { } +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; + + $c->stash->{current_view} = 'Hydra::View::NixManifest'; + $c->stash->{storePath} = $build->outpath; +} + + sub end : ActionClass('RenderView') {} diff --git a/src/Hydra/lib/Hydra/View/NixManifest.pm b/src/Hydra/lib/Hydra/View/NixManifest.pm new file mode 100644 index 00000000..7f41953b --- /dev/null +++ b/src/Hydra/lib/Hydra/View/NixManifest.pm @@ -0,0 +1,56 @@ +package Hydra::View::NixManifest; + +use strict; +use base qw/Catalyst::View/; +use IO::Pipe; +use IPC::Run; +use POSIX qw(dup2); + +sub captureStdoutStderr { + my $stdin = ""; my $stdout; my $stderr; + my $res = IPC::Run::run(\@_, \$stdin, \$stdout, \$stderr); + return ($res, $stdout, $stderr); +} + + +sub process { + my ($self, $c) = @_; + + my $storePath = $c->stash->{storePath}; + + $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 $manifest = + "version {\n" . + " ManifestVersion: 3\n" . + "}\n"; + + foreach my $path (@paths) { + my ($res, $out, $err) = captureStdoutStderr(qw(nix-store --query --references), $path); + die "cannot query references of `$path':\n$err" unless $res; + my @refs = split '\n', $out; + + my $hash = `nix-store --query --hash $path` + or die "cannot query hash of `$path': $?"; + chomp $hash; + + my $url = $c->uri_for('/nar' . $path); + + $manifest .= + "{\n" . + " StorePath: $path\n" . + " NarURL: $url\n" . + " References: @refs\n" . + " Hash: $hash\n" . + "}\n"; + } + + $c->response->body($manifest); + + return 1; +} + +1;