source: server/trunk/web/lib/Sophie/Controller/Rpms.pm @ 220

Last change on this file since 220 was 220, checked in by nanardon, 13 years ago
  • add rpms/analyse function
File size: 13.0 KB
Line 
1package Sophie::Controller::Rpms;
2use Moose;
3use namespace::autoclean;
4use Encode::Guess;
5use Encode;
6use POSIX;
7
8BEGIN {extends 'Catalyst::Controller'; }
9
10=head1 NAME
11
12Sophie::Controller::Rpms - Catalyst Controller
13
14=head1 DESCRIPTION
15
16Catalyst Controller.
17
18=head1 METHODS
19
20=cut
21
22
23=head2 index
24
25=cut
26
27sub index :Path :Args(0) {
28    my ( $self, $c ) = @_;
29
30    $c->response->redirect('/');
31}
32
33=head2 rpms.queryformat( PKGID, FORMAT )
34
35Perform an C<rpm -q --qf> on the package having C<PKGID>.
36
37=cut
38
39sub queryformat : XMLRPCLocal {
40    my ( $self, $c, $pkgid, $qf ) = @_;
41    $c->stash->{xmlrpc} = $c->model('base')->resultset('Rpms')->search(
42        { pkgid => $pkgid },
43        { 
44            select => [ qq{rpmqueryformat("header", ?)} ],
45            as => [ 'qf' ],
46            bind => [ $qf ],
47        }
48    )->next->get_column('qf');
49}
50
51=head2 rpms.tag( PKGID, TAG )
52
53Return the list of C<TAG> values for package C<PKGID>
54
55=cut
56
57sub tag : XMLRPCLocal {
58    my ( $self, $c, $pkgid, $tag ) = @_;
59    $c->stash->{xmlrpc} = [ map { $_->get_column('tag') } $c->model('Base')->resultset('Rpms')->search(
60        { pkgid => $pkgid },
61        { 
62            select => [ qq{rpmquery("header", rpmtag(?))} ],
63            as => [ 'tag' ],
64            bind => [ $tag ], 
65        }
66    )->all ]
67}
68
69sub basicinfo : XMLRPCLocal {
70    my ($self, $c, $pkgid) = @_;
71
72    my $rpm = $c->model('base::Rpms')->find(
73        { pkgid => $pkgid },
74    );
75    $rpm or return;
76    my %info = $rpm->get_columns;
77    $info{src} = $info{issrc} ? 1 : 0;
78    foreach (qw(version release arch)) {
79        if (my $r = $c->model('base')->resultset('Rpms')->search(
80            { pkgid => $pkgid },
81            { 
82                select => [ qq{rpmquery("header", ?)} ],
83                as => [ 'qf' ],
84                bind => [ $_ ],
85            }
86            )->next) { 
87            $info{$_} = $r->get_column('qf');
88        }
89    }
90
91    return $c->stash->{xmlrpc} = \%info;
92}
93
94
95sub info : XMLRPCLocal {
96    my ($self, $c, $pkgid) = @_;
97
98
99    my $info = $c->forward('basicinfo', [ $pkgid ]);
100    foreach (qw(name epoch url group size packager
101                url sourcerpm license buildhost
102                distribution)) {
103        if (my $r = $c->model('base')->resultset('Rpms')->search(
104            { pkgid => $pkgid },
105            { 
106                select => [ qq{rpmquery("header", ?)} ],
107                as => [ 'qf' ],
108                bind => [ $_ ],
109            }
110            )->next) { 
111            $info->{$_} = $r->get_column('qf');
112        }
113    }
114
115    return $c->stash->{xmlrpc} = $info;
116}
117
118sub deps : XMLRPCLocal {
119    my ($self, $c, $pkgid, $deptype) = @_;
120
121    $c->stash->{xmlrpc} = [ 
122        map { 
123            { 
124                name => $_->get_column('depname'),
125                flags => $_->get_column('flags'),
126                evr => $_->get_column('evr'),
127                sense => $_->get_column('sense'),
128            }
129        } 
130        $c->model('Base')->resultset('Deps')->search(
131            { 
132                pkgid => $pkgid,
133                deptype => $deptype,
134            },
135            { 
136                order_by => [ 'count' ],
137                select => [ 'rpmsenseflag("flags")', qw(depname flags evr) ],
138                as => [ qw'sense depname flags evr' ],
139
140            },
141        )->all ];
142}
143
144sub sources : XMLRPCLocal {
145    my ( $self, $c, $pkgid ) = @_;
146
147    my $sourcerpm = $c->forward('queryformat', [ $pkgid, '%{SOURCERPM}' ]);
148    my $nosourcerpm = $sourcerpm;
149    $nosourcerpm =~ s/\.src.rpm$/\.nosrc.rpm/;
150
151    $c->stash->{xmlrpc} = [ $c->model('Base::Rpms')->search(
152        {
153            pkgid => { 
154                IN => $c->model('Base::RpmFile')->search(
155                    { filename => [ $sourcerpm, $nosourcerpm ] }
156                )->get_column('pkgid')->as_query
157            },
158        }
159    )->get_column('pkgid')->all ];
160}
161
162sub binaries : XMLRPCLocal {
163    my ( $self, $c, $pkgid ) = @_;
164
165    my $sourcerpm = $c->forward('queryformat', [ $pkgid,
166            '%{NAME}-%{VERSION}-%{RELEASE}.src.rpm' ]);
167    my $nosourcerpm = $sourcerpm;
168    $nosourcerpm =~ s/\.src.rpm$/\.nosrc.rpm/;
169
170    my $tagrs = $c->model('Base')->resultset('Tags')
171        ->search({ tagname => 'sourcerpm', value => [ $sourcerpm, $nosourcerpm ] })
172        ->get_column('pkgid');
173    $c->stash->{xmlrpc} = [ $c->model('Base::Rpms')->search(
174        {
175            -and => [
176                { issrc => 0 },
177                { pkgid =>
178                    { IN => $tagrs->as_query, },
179                },
180            ]
181        },
182        {
183            order_by => [ qw(arch name), 'evr using >>' ],
184        },
185    )->get_column('pkgid')->all ];
186
187}
188
189
190=head2 rpms.maintainers( PKGID )
191
192Return the maintainers for this package.
193
194The list of maintainers is limited to distribution where the package is located.
195
196If the package is a binary the C<SOURCERPM> tag is used to find the source rpm
197name.
198
199=cut
200
201sub maintainers : XMLRPCLocal {
202    my ($self, $c, $pkgid) = @_;
203
204    my $binfo = $c->forward('/rpms/basicinfo', [ $pkgid ]);
205    my $rpmname;
206    if ($binfo->{issrc}) {
207        $rpmname = $binfo->{name};
208    } else {
209        my $sourcerpm = $c->forward('queryformat', [ $pkgid, '%{SOURCERPM}' ]);
210        $sourcerpm =~ /^(.*)-([^-]+)-([^-]+)\.[^\.]+.rpm$/;
211        $rpmname = $1;
212    }
213    my %dist;
214    foreach (@{ $c->forward('/rpms/location', [ $pkgid ]) }) {
215        $dist{$_->{distribution}} = 1;
216    }
217
218    $c->forward('/maintainers/byrpm', [ $rpmname, [ keys %dist ] ]);
219}
220
221sub rpms_ :PathPrefix :Chained :CaptureArgs(1) {
222    my ( $self, $c, $pkgid ) = @_;
223    $c->stash->{pkgid} = $pkgid if($pkgid);
224    {
225        my $match = $c->stash->{pkgid};
226    }
227    if (!$c->model('Base::Rpms')->find({ pkgid => $c->stash->{pkgid} })) {
228        $c->go('/404/index');
229    }
230    my $info = $c->stash->{rpms}{info} =
231        $c->forward('info', [ $c->stash->{pkgid} ]);
232
233    $c->stash->{metatitle} = sprintf("%s-%s %s",
234        $info->{name},
235        $info->{evr},
236        $info->{issrc} ? 'src' : $info->{arch},
237    );
238    push(@{ $c->stash->{keywords} }, $info->{name}, $info->{evr},
239        $info->{issrc} ? 'src' : $info->{arch},);
240    $c->stash->{metarevisit} = 30;
241
242    # for later usage, keep history of visited rpms
243    $c->session->{visited_rpms}{$c->stash->{pkgid}} = time;
244    if (keys %{ $c->session->{visited_rpms} } > 20) {
245        my @visited = sort
246        { $c->session->{visited_rpms}{$b} <=> $c->session->{visited_rpms}{$a} }
247        keys %{ $c->session->{visited_rpms} };
248        splice(@visited, 0, 20);
249        delete $c->session->{visited_rpms}{$_} foreach (@visited);
250    }
251
252    $c->stash->{rpms}{location} =
253        $c->forward('location', [ $c->stash->{pkgid} ]);
254}
255
256sub rpms : Private {
257    my ( $self, $c, $pkgid, $subpart, @args) = @_;
258    # Because $c->forward don't take into account Chained sub
259    $c->forward('rpms_', [ $pkgid ]);
260    for ($subpart || '') {
261        /^deps$/      and $c->go('alldeps',   [ $pkgid, @args ]);
262        /^files$/     and $c->go('files',     [ $pkgid, @args ]);
263        /^changelog$/ and $c->go('changelog', [ $pkgid, @args ]);
264        /^location$/  and $c->go('location',  [ $pkgid, @args ]);
265        /^analyse$/   and $c->go('analyse',  [ $pkgid, @args ]);
266    }
267    $c->stash->{rpmurl} = $c->req->path;
268
269    return $c->stash->{xmlrpc} = $c->stash->{rpms};
270}
271
272sub rpms__ : Chained('/rpms/rpms_') :PathPart('') :Args(0) :XMLRPCLocal {
273    my ( $self, $c ) = @_;
274
275    $c->go('rpms', [ $c->stash->{pkgid} ]);
276}
277
278
279sub alldeps :Chained('rpms_') :PathPart('deps') :Args(0) :XMLRPCLocal {
280    my ( $self, $c, $pkgid ) = @_;
281    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
282    $pkgid ||= $c->stash->{pkgid};
283
284    my %deps;
285    foreach (
286        $c->model('Base')->resultset('Deps')->search(
287            { 
288                pkgid => $pkgid,
289            },
290            { 
291                order_by => [ 'count' ],
292                select => [ 'rpmsenseflag("flags")',
293                    qw(depname flags evr deptype) ],
294                as => [ qw'sense depname flags evr deptype' ],
295
296            },
297        )->all) {
298        push( @{ $deps{$_->get_column('deptype')} },
299            {
300                name => $_->get_column('depname'),
301                flags => $_->get_column('flags'),
302                evr => $_->get_column('evr'),
303                sense => $_->get_column('sense'),
304            }
305        );
306    }
307    $c->stash->{xmlrpc} = \%deps;
308}
309
310sub files :Chained('rpms_') :PathPart('files') :Args(0) :XMLRPCLocal {
311    my ( $self, $c, $pkgid, $number ) = @_;
312    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
313    $pkgid ||= $c->stash->{pkgid};
314
315    if ($number) { # This come from a forward
316        $c->go('files_contents', [ $number ]);
317    }
318
319    my @col = qw(dirname basename md5 size count);
320    $c->stash->{xmlrpc} = [ map {
321        {
322            filename => $_->get_column('dirname') . $_->get_column('basename'),
323            dirname => $_->get_column('dirname'),
324            basename => $_->get_column('basename'),
325            md5 => $_->get_column('md5'),
326            perm => $_->get_column('perm'),
327            size => $_->get_column('size'),
328            user => $_->get_column('user'),
329            group => $_->get_column('group'),
330            has_content => $_->get_column('has_content'),
331            count => $_->get_column('count'),
332        }
333    } $c->model('Base')->resultset('Files')->search(
334            { 
335                pkgid => $pkgid,
336            },
337            { 
338                'select' => [ 'contents is NOT NULL as has_content', 'rpmfilesmode(mode) as perm', @col, '"group"',
339                    '"user"' ],
340                as => [ qw(has_content perm), @col, 'group', 'user' ],
341                order_by => [ 'dirname', 'basename' ],
342
343            },
344        )->all ];
345}
346
347sub files_contents :Chained('rpms_') :PathPart('files') :Args(1) {
348    my ( $self, $c, $number ) = @_;
349    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+/[^/]+:)[0];
350    my $pkgid = $c->stash->{pkgid};
351
352    $c->stash->{xmlrpc} = $c->model('Base::Files')->search(
353        {
354            pkgid => $pkgid,
355            count => $number,
356        },
357        {
358            select => ['contents'],
359        }
360    )->get_column('contents')->first;
361}
362
363sub changelog :Chained('rpms_') :PathPart('changelog') :Args(0) :XMLRPCLocal {
364    my ( $self, $c, $pkgid ) = @_;
365    $pkgid ||= $c->stash->{pkgid};
366    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
367
368    my @ch;
369    foreach ($c->model('Base')->resultset('RpmsChangelog')->search({},
370            { 
371                bind => [ $pkgid ],
372                order_by => [ 'time::int desc' ],
373            },
374        )->all) {
375        my $chentry;
376        my $enc = guess_encoding($_->get_column('text'), qw/latin1/);
377        $chentry->{text} = $enc && ref $enc
378            ? encode('utf8', $_->get_column('text'))
379            : $_->get_column('text');
380        $enc = guess_encoding($_->get_column('name'), qw/latin1/);
381        $chentry->{name} = $enc && ref $enc
382            ? encode('utf8', $_->get_column('name'))
383            : $_->get_column('name');
384        $chentry->{time} = $_->get_column('time');
385        $chentry->{date} = POSIX::strftime('%a %b %e %Y', gmtime($_->get_column('time')));
386        push(@ch, $chentry);
387    }
388
389    $c->stash->{xmlrpc} = \@ch;
390}
391
392=head2 rpms.location( PKGID )
393
394Return all distribution where the package having C<PKGID> can be found.
395
396=cut
397
398sub location :Chained('rpms_') :PathPart('location') :Args(0) {
399    my ( $self, $c, $pkgid ) = @_;
400    $pkgid ||= $c->stash->{pkgid};
401    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
402
403    $c->stash->{xmlrpc} = [
404        map {
405        {
406            distribution => $_->get_column('name'),
407            dist => $_->get_column('shortname'),
408            release => $_->get_column('version'),
409            arch => $_->get_column('arch'), 
410            media => $_->get_column('label'),
411            media_group => $_->get_column('group_label'),
412        }
413        }
414        $c->forward('/distrib/distrib_rs', [ {} ])
415         ->search_related('MediasPaths')
416                 ->search_related('Paths')
417        ->search_related('Rpmfiles',
418            { pkgid => $pkgid },
419            {
420                select => [ qw(shortname name version arch label group_label) ],
421                order_by => [ qw(name version arch label) ],
422            }
423        )->all ]
424}
425
426sub analyse :Chained('rpms_') :PathPart('analyse') :Args(0) :XMLRPC {
427    my ( $self, $c, $pkgid, $dist ) = @_;
428    $pkgid ||= $c->stash->{pkgid};
429    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
430    $dist->{distribution} ||= $c->req->param('distribution');
431    $dist->{release} ||= $c->req->param('release');
432    $dist->{arch} ||= $c->req->param('arch');
433
434    if ($c->req->param('analyse')) {
435
436        my @deplist = map {
437            [ $_->{name}, $_->{sense}, $_->{evr} ]
438        } @{ $c->forward('deps', [ $pkgid, 'R' ]) };
439
440        $c->stash->{xmlrpc} = $c->forward(
441            '/analysis/solver/find_requirements',
442            [ $dist,
443                'P', \@deplist, [] ]
444        );
445    } else {
446        $c->stash->{xmlrpc} = '';
447    }
448}
449
450=head1 AUTHOR
451
452Olivier Thauvin
453
454=head1 LICENSE
455
456This library is free software. You can redistribute it and/or modify
457it under the same terms as Perl itself.
458
459=cut
460
461__PACKAGE__->meta->make_immutable;
462
4631;
Note: See TracBrowser for help on using the repository browser.