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

Last change on this file since 211 was 202, checked in by nanardon, 14 years ago
  • fix visited rpms history
File size: 12.2 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}{deps}{$deptype} } = 
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    }
266    $c->stash->{rpmurl} = $c->req->path;
267
268    return $c->stash->{xmlrpc} = $c->stash->{rpms};
269}
270
271sub rpms__ : Chained('/rpms/rpms_') :PathPart('') :Args(0) :XMLRPCLocal {
272    my ( $self, $c ) = @_;
273
274    $c->go('rpms', [ $c->stash->{pkgid} ]);
275}
276
277
278sub alldeps :Chained('rpms_') :PathPart('deps') :Args(0) :XMLRPCLocal {
279    my ( $self, $c, $pkgid ) = @_;
280    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
281    $pkgid ||= $c->stash->{pkgid};
282
283    my %deps;
284    foreach (
285        $c->model('Base')->resultset('Deps')->search(
286            { 
287                pkgid => $pkgid,
288            },
289            { 
290                order_by => [ 'count' ],
291                select => [ 'rpmsenseflag("flags")',
292                    qw(depname flags evr deptype) ],
293                as => [ qw'sense depname flags evr deptype' ],
294
295            },
296        )->all) {
297        push( @{ $deps{$_->get_column('deptype')} },
298            {
299                name => $_->get_column('depname'),
300                flags => $_->get_column('flags'),
301                evr => $_->get_column('evr'),
302                sense => $_->get_column('sense'),
303            }
304        );
305    }
306    $c->stash->{xmlrpc} = \%deps;
307}
308
309sub files :Chained('rpms_') :PathPart('files') :Args(0) :XMLRPCLocal {
310    my ( $self, $c, $pkgid, $number ) = @_;
311    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
312    $pkgid ||= $c->stash->{pkgid};
313
314    if ($number) { # This come from a forward
315        $c->go('files_contents', [ $number ]);
316    }
317
318    my @col = qw(dirname basename md5 size count);
319    $c->stash->{xmlrpc} = [ map {
320        {
321            filename => $_->get_column('dirname') . $_->get_column('basename'),
322            dirname => $_->get_column('dirname'),
323            basename => $_->get_column('basename'),
324            md5 => $_->get_column('md5'),
325            perm => $_->get_column('perm'),
326            size => $_->get_column('size'),
327            user => $_->get_column('user'),
328            group => $_->get_column('group'),
329            has_content => $_->get_column('has_content'),
330            count => $_->get_column('count'),
331        }
332    } $c->model('Base')->resultset('Files')->search(
333            { 
334                pkgid => $pkgid,
335            },
336            { 
337                'select' => [ 'contents is NOT NULL as has_content', 'rpmfilesmode(mode) as perm', @col, '"group"',
338                    '"user"' ],
339                as => [ qw(has_content perm), @col, 'group', 'user' ],
340                order_by => [ 'dirname', 'basename' ],
341
342            },
343        )->all ];
344}
345
346sub files_contents :Chained('rpms_') :PathPart('files') :Args(1) {
347    my ( $self, $c, $number ) = @_;
348    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+/[^/]+:)[0];
349    my $pkgid = $c->stash->{pkgid};
350
351    $c->stash->{xmlrpc} = $c->model('Base::Files')->search(
352        {
353            pkgid => $pkgid,
354            count => $number,
355        },
356        {
357            select => ['contents'],
358        }
359    )->get_column('contents')->first;
360}
361
362sub changelog :Chained('rpms_') :PathPart('changelog') :Args(0) :XMLRPCLocal {
363    my ( $self, $c, $pkgid ) = @_;
364    $pkgid ||= $c->stash->{pkgid};
365    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
366
367    my @ch;
368    foreach ($c->model('Base')->resultset('RpmsChangelog')->search({},
369            { 
370                bind => [ $pkgid ],
371                order_by => [ 'time::int desc' ],
372            },
373        )->all) {
374        my $chentry;
375        my $enc = guess_encoding($_->get_column('text'), qw/latin1/);
376        $chentry->{text} = $enc && ref $enc
377            ? encode('utf8', $_->get_column('text'))
378            : $_->get_column('text');
379        $enc = guess_encoding($_->get_column('name'), qw/latin1/);
380        $chentry->{name} = $enc && ref $enc
381            ? encode('utf8', $_->get_column('name'))
382            : $_->get_column('name');
383        $chentry->{time} = $_->get_column('time');
384        $chentry->{date} = POSIX::strftime('%a %b %e %Y', gmtime($_->get_column('time')));
385        push(@ch, $chentry);
386    }
387
388    $c->stash->{xmlrpc} = \@ch;
389}
390
391=head2 rpms.location( PKGID )
392
393Return all distribution where the package having C<PKGID> can be found.
394
395=cut
396
397sub location :Chained('rpms_') :PathPart('location') :Args(0) {
398    my ( $self, $c, $pkgid ) = @_;
399    $pkgid ||= $c->stash->{pkgid};
400    $c->stash->{rpmurl} = ($c->req->path =~ m:(.*)/[^/]+:)[0];
401
402    $c->stash->{xmlrpc} = [
403        map {
404        {
405            distribution => $_->get_column('name'),
406            dist => $_->get_column('shortname'),
407            release => $_->get_column('version'),
408            arch => $_->get_column('arch'), 
409            media => $_->get_column('label'),
410            media_group => $_->get_column('group_label'),
411        }
412        }
413        $c->forward('/distrib/distrib_rs', [ {} ])
414         ->search_related('MediasPaths')
415                 ->search_related('Paths')
416        ->search_related('Rpmfiles',
417            { pkgid => $pkgid },
418            {
419                select => [ qw(shortname name version arch label group_label) ],
420                order_by => [ qw(name version arch label) ],
421            }
422        )->all ]
423}
424
425=head1 AUTHOR
426
427Olivier Thauvin
428
429=head1 LICENSE
430
431This library is free software. You can redistribute it and/or modify
432it under the same terms as Perl itself.
433
434=cut
435
436__PACKAGE__->meta->make_immutable;
437
4381;
Note: See TracBrowser for help on using the repository browser.