source: server/trunk/web/lib/Sophie/Controller/Distrib.pm @ 263

Last change on this file since 263 was 263, checked in by nanardon, 13 years ago
  • fix search over binary/source
File size: 16.1 KB
Line 
1package Sophie::Controller::Distrib;
2use Moose;
3use namespace::autoclean;
4
5BEGIN {extends 'Catalyst::Controller'; }
6
7=head1 NAME
8
9Sophie::Controller::Distrib - Catalyst Controller
10
11=head1 DESCRIPTION
12
13Catalyst Controller.
14
15=head1 METHODS
16
17=cut
18
19=head2 distrib.list( [ DISTRIBUTION [, RELEASE [, ARCH ]]]
20
21List content of distrib according arguments given. IE list available
22C<distribution> if no argument is given, list C<release> if C<DISTRIBUTION> is
23given, list C<arch> if both C<DISTRIBUTION> and C<RELEASE> are given. Etc... Up
24to give C<MEDIA> if C<ARCH> is specified.
25
26Results are given as C<ARRAY>.
27
28=cut
29
30sub list :XMLRPC {
31    my ( $self, $c, $distrib, $release, $arch ) = @_;
32
33    my $distribution;
34    if (ref $distrib) {
35        ($distribution, $release, $arch) = (
36            $distrib->{distribution},
37            $distrib->{release},
38            $distrib->{arch},
39        );
40    } else {
41        $distribution = $distrib;
42    }
43
44    my $rs = $c->model('Base')->resultset('Distribution');
45    if (!$distribution) {
46        return $c->stash->{xmlrpc} = [ map { $_->name }
47            $rs->search(undef, { order_by => ['name'] })->all ];
48    }
49    $rs = $rs->search({
50            -or => [
51                { name      => $distribution },
52                { shortname => $distribution },
53            ],
54        })->search_related('Release');
55    if (!$release) {
56        return $c->stash->{xmlrpc} = [ map { $_->version }
57            $rs->search(undef, { order_by => ['version'] })->all ];
58    }
59    $rs = $rs->search(version => $release)->search_related('Arch');
60    if (!$arch) {
61        return $c->stash->{xmlrpc} = [ map { $_->arch } 
62            $rs->search(undef, { order_by => ['arch'] })->all ];
63    }
64    $rs = $rs->search(arch => $arch)->search_related('Medias');
65    return $c->stash->{xmlrpc} = [ map { $_->label }
66        $rs->search(undef, { order_by => ['label'] })->all ];
67}
68
69sub struct :XMLRPC {
70    my ( $self, $c, $distribution, $release, $arch ) = @_;
71
72    if (!ref $distribution) {
73        $distribution = {
74            distribution => $distribution,
75            release => $release,
76            arch => $arch,
77        }
78    }
79
80    my $rs = $c->forward('distrib_rs', [ $distribution ])
81        ->search({}, { order_by => 'label' });
82    $c->stash->{xmlrpc} = [ map { 
83        { 
84            label => $_->label,
85            group_label => $_->group_label,
86        } 
87    } $rs->all ];
88}
89
90sub distrib_rs : Private {
91    my ( $self, $c, $distrib, $asfilter ) = @_;
92    if ($asfilter && !(
93            $distrib->{distribution} ||
94            $distrib->{release} ||
95            $distrib->{arch} ||
96            $distrib->{media} ||
97            $distrib->{media_group})) {
98        return;
99    }
100
101    return $c->model('Base')->resultset('Distribution')
102        ->search(
103            {
104                $distrib->{distribution}
105                    ? (-or => [
106                            { name =>      $distrib->{distribution} },
107                            { shortname => $distrib->{distribution} },
108                        ],
109                    )
110                    : ()
111            },
112            {
113                select => [ qw(name shortname) ],
114            }
115        )->search_related('Release',
116            {
117                $distrib->{release}
118                    ? (version => $distrib->{release})
119                    : ()
120            },
121            {
122                select => [ qw(version) ],
123            }
124        )->search_related('Arch',
125            {
126                $distrib->{arch}
127                    ? (arch => $distrib->{arch})
128                    : ()
129            },
130            {
131                select => [ qw(arch) ],
132            }
133        )->search_related('Medias',
134            {
135                ($distrib->{media} ? (label => $distrib->{media}) : ()),
136                ($distrib->{media_group}
137                    ? (group_label => $distrib->{media_group})
138                    : ()),
139            },
140            {
141                select => [ qw(label group_label) ],
142            }
143        );
144}
145
146=head2 distrib.exists( DISTRIB )
147
148Return true or false if disteibution C<DISTRIB> exists.
149
150C<DISTRIB> is a structure with following key/value:
151
152=over 4
153
154=item distribution
155
156The distribution name
157
158=item release
159
160The release name
161
162=item arch
163
164The arch name
165
166=back
167
168This function is usefull to check if a search have chance to suceed, eg if the
169user is not searching a rpm on a not existing ditribution.
170
171=cut
172
173sub exists : XMLRPC {
174    my ( $self, $c, $d ) = @_;
175
176    my $rs = $c->forward('distrib_rs', [ $d ]);
177
178    if ($rs->search({}, { rows => 1 })->next) {
179        $c->stash->{xmlrpc} = 1;
180    } else {
181        $c->stash->{xmlrpc} = 0;
182    }
183}
184
185=head2 index
186
187=cut
188
189=head2 Url: /distrib
190
191Return the list of currently stored distributions.
192
193=cut
194
195sub index :Path :Chained :Args(0)  {
196    my ( $self, $c ) = @_;
197
198    $c->stash->{metarevisite} = 60;
199    $c->stash->{metatitle} = 'Available Distribution';
200    push(@{$c->stash->{keywords}}, 'Rpm Distribution');
201    $c->forward('list');
202}
203
204=head2 release
205
206=cut
207
208=head2 Url: /distrib/<DISTRIBUTION>
209
210Return the list of available release for given C<DISTRIBUTION>.
211
212=cut
213
214sub list_release :Path :Args(1) {
215    my ( $self, $c, $distribution ) = @_;
216    $c->stash->{dist}{distribution} = $distribution;
217    if (!$c->forward('exists', [ $c->stash->{dist} ])) {
218        $c->go('/404/index');
219    }
220    $c->stash->{metarevisite} = 60;
221    $c->stash->{metatitle} = 'Available release for ' . $distribution;
222    push(@{$c->stash->{keywords}}, $distribution);
223    $c->forward('list', [ $c->stash->{dist} ] );
224}
225
226=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>
227
228Return the list of available architecture for given C<DISTRIBUTION>,
229C<RELEASE>.
230
231=cut
232
233sub list_arch :Path :Args(2) {
234    my ( $self, $c, $distribution, $release ) = @_;
235
236    # Compatability with Sophie1
237    if ($distribution =~ /^([^,]+,)?[^,]+,[^,]+$/) {
238        $c->go('/compat/distrib', [ $distribution, $release ]);
239    }
240
241    $c->stash->{dist}{distribution} = $distribution;
242    $c->stash->{dist}{release} = $release;
243    if (!$c->forward('exists', [ $c->stash->{dist} ])) {
244        $c->go('/404/index');
245    }
246    $c->stash->{metarevisite} = 60;
247    $c->stash->{metatitle} =
248        'Available architecture for ' . $distribution . ' / ' . $release;
249    push(@{$c->stash->{keywords}}, $distribution, $release);
250    $c->forward('list', [ $c->stash->{dist} ] );
251}
252
253
254sub distrib_view :PathPrefix :Chained :CaptureArgs(3) {
255    my ( $self, $c, $distribution, $release, $arch ) = @_;
256    $c->stash->{dist}{distribution} = $distribution;
257    $c->stash->{dist}{release} = $release;
258    $c->stash->{dist}{arch} = $arch;
259    if (!$c->forward('exists', [ $c->stash->{dist} ])) {
260        $c->go('/404/index');
261    }
262    $c->stash->{metarevisite} = 60;
263    $c->stash->{metatitle} =
264        'Available medias for ' . $distribution . ' / ' . $release . ' / ' . $arch;
265    push(@{$c->stash->{keywords}}, $distribution, $release, $arch);
266    $c->stash->{distrib} = $c->stash->{dist};
267}
268
269=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>/<ARCH>
270
271Return the list of available medias for given C<DISTRIBUTION>,
272C<RELEASE>, C<ARCH>.
273
274=cut
275
276sub distrib :Chained('distrib_view') PathPart('') :Args(0) {
277    my ( $self, $c ) = @_;
278    $c->forward('list', [ $c->stash->{dist} ]);
279    # TODO store properly results
280    # No call from json here
281}
282
283sub media :Chained('/distrib/distrib_view') PathPart('media') :Args(0) {
284    my ( $self, $c ) = @_;
285    $c->forward('struct', [ $c->stash->{dist} ]);
286}
287
288=head2 distrib.anyrpms( DISTRIB )
289
290Return a list of packages available for C<DISTRIB>.
291
292C<DISTRIB> is a struct with following keys/values:
293
294=over 4
295
296=item distribution
297
298The distribution name
299
300=item release
301
302The release name
303
304=item arch
305
306The arch name
307
308=back
309
310=cut
311
312sub anyrpms :XMLRPC {
313    my ( $self, $c, $distribution, $release, $arch ) = @_;
314
315    if (!ref $distribution) {
316        $distribution = {
317            distribution => $distribution,
318            release => $release,
319            arch => $arch,
320        }
321    }
322
323    @{$c->stash->{rpm}} = map {
324            { 
325              pkgid => $_->pkgid,
326              filename => $_->filename,
327            }
328        }
329        $c->forward('distrib_rs', [ $distribution ])
330        ->search_related('MediasPaths')
331        ->search_related('Paths')
332        ->search_related('Rpmfiles', {}, { order_by => qw(filename) })
333        ->all;
334
335    $c->stash->{xmlrpc} = $c->stash->{rpm};
336}
337
338=head2 distrib.rpms( DISTRIB )
339
340Return a list of binary packages available for C<DISTRIB>.
341
342C<DISTRIB> is a struct with following keys/values:
343
344=over 4
345
346=item distribution
347
348The distribution name
349
350=item release
351
352The release name
353
354=item arch
355
356The arch name
357
358=back
359
360=cut
361
362sub rpms :XMLRPC {
363    my ( $self, $c, $distribution, $release, $arch ) = @_;
364
365    if (!ref $distribution) {
366        $distribution = {
367            distribution => $distribution,
368            release => $release,
369            arch => $arch,
370        }
371    }
372
373    $c->stash->{rpm} = [ map {
374            { 
375              pkgid => $_->pkgid,
376              filename => $_->filename,
377            }
378        }
379        $c->forward('distrib_rs', [ $distribution ])
380        ->search_related('MediasPaths')
381        ->search_related('Paths')
382        ->search_related('Rpmfiles', {
383            pkgid => {
384                IN => $c->model('Base')->resultset('Rpms')
385                ->search({ issrc => 'false' })->get_column('pkgid') ->as_query }
386        },
387        { order_by => [ qw(filename) ] }
388        )->all ];
389
390    $c->stash->{xmlrpc} = $c->stash->{rpm};
391}
392
393=head2 distrib.srpms( DISTRIB )
394
395Return a list of sources packages available for C<DISTRIB>.
396
397C<DISTRIB> is a struct with following keys/values:
398
399=over 4
400
401=item distribution
402
403The distribution name
404
405=item release
406
407The release name
408
409=item arch
410
411The arch name
412
413=back
414
415=cut
416
417sub srpms :XMLRPC {
418    my ( $self, $c, $distribution, $release, $arch ) = @_;
419
420    if (!ref $distribution) {
421        $distribution = {
422            distribution => $distribution,
423            release => $release,
424            arch => $arch,
425        }
426    }
427
428    @{$c->stash->{rpm}} = map {
429            { 
430              pkgid => $_->pkgid,
431              filename => $_->filename,
432            }
433        }
434        $c->forward('distrib_rs', [ $distribution ])
435        ->search_related('MediasPaths')
436        ->search_related('Paths')
437        ->search_related('Rpmfiles', {
438            pkgid => {
439                IN => $c->model('Base')->resultset('Rpms')
440                ->search({ issrc => 'true' })->get_column('pkgid') ->as_query }
441        },
442        { order_by => [ qw(filename) ] }
443        )->all;
444
445    $c->stash->{xmlrpc} = $c->stash->{rpm};
446}
447
448sub rpms_name :XMLRPC {
449    my ( $self, $c, $distribution, $release, $arch ) = @_;
450
451    if (!ref $distribution) {
452        $distribution = {
453            distribution => $distribution,
454            release => $release,
455            arch => $arch,
456        }
457    }
458
459    $c->stash->{xmlrpc} = [
460        $c->model('Base')->resultset('Rpms')->search(
461            { pkgid => {
462                IN =>
463        $c->forward('distrib_rs', [ $distribution ])
464        ->search_related('MediasPaths')
465        ->search_related('Paths')
466        ->search_related('Rpmfiles')->get_column('pkgid')->as_query
467        } },
468        { group_by => [ qw(name) ], order_by => [ qw(name) ] }
469        )->get_column('name')->all ];
470}
471
472
473=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>/<ARCH>/rpms
474
475Return the list of available rpms for given C<DISTRIBUTION>,
476C<RELEASE>, C<ARCH>.
477
478=cut
479
480sub list_rpms :Chained('distrib_view') PathPart('rpms') Args(0) {
481    my ( $self, $c ) = @_;
482    $c->forward('rpms', [ $c->stash->{dist} ]);
483}
484
485=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>/<ARCH>/srpms
486
487Return the list of available sources rpms for given C<DISTRIBUTION>,
488C<RELEASE>, C<ARCH>.
489
490=cut
491
492sub list_srpms :Chained('distrib_view') PathPart('srpms') Args(0) {
493    my ( $self, $c ) = @_;
494    $c->forward('srpms', [ $c->stash->{dist} ]);
495}
496
497=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>/<ARCH>/srpms/<RPMNAME>
498
499Show the highter version of source rpm named C<RPMNAME> for given
500C<DISTRIBUTION>, C<RELEASE>, C<ARCH>.
501
502=cut
503
504sub srpm_by_name :Chained('distrib_view') PathPart('srpms') {
505    my ($self, $c, $name, @subpart) = @_;
506    $c->stash->{dist}{src} = 1;
507    ($c->stash->{pkgid}) = @{ $c->forward('/search/rpm/byname',
508        [ $c->stash->{dist}, $name ]) };
509    $c->go('/404/index') unless ($c->stash->{pkgid});
510    $c->go('/rpms/rpms', [ $c->stash->{pkgid}, @subpart ]);
511}
512
513=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>/<ARCH>/rpms/<RPMNAME>
514
515Show the highter version of binary rpm named C<RPMNAME> for given
516C<DISTRIBUTION>, C<RELEASE>, C<ARCH>.
517
518=cut
519
520sub rpm_by_name :Chained('distrib_view') PathPart('rpms') {
521    my ($self, $c, $name, @subpart) = @_;
522    $c->stash->{dist}{src} = 0;
523    ($c->stash->{pkgid}) = @{ $c->forward('/search/rpm/byname',
524        [ $c->stash->{dist}, $name ]) };
525    $c->go('/404/index') unless ($c->stash->{pkgid});
526    $c->go('/rpms/rpms', [ $c->stash->{pkgid}, @subpart ]);
527}
528
529
530=head2 Url: /distrib/<DISTRIBUTION>/<RELEASE>/<ARCH>/by-pkgid/<PKGID>
531
532Show information about rpm having pkgid C<PKGID> for given
533C<DISTRIBUTION>, C<RELEASE>, C<ARCH>.
534
535This is likelly the same thing than C</rpm/PKGID> but website will return 404
536error if the rpm is not in this distrib
537
538=cut
539
540sub rpm_bypkgid :Chained('distrib_view') PathPart('by-pkgid') {
541    my ( $self, $c, $pkgid, @subpart ) = @_;
542    if ($pkgid) {
543        if (@{ $c->forward('/search/rpm/bypkgid',
544            [ $c->stash->{dist}, $pkgid ]) } ) {
545            $c->go('/rpms/rpms', [ $pkgid, @subpart ]);
546        } else {
547            $c->go('/404/index');
548        }
549    } else {
550        $c->forward('anyrpms', [ $c->stash->{dist} ]);
551    }
552}
553
554sub _media_list_rpms :Chained('distrib_view') PathPart('media') CaptureArgs(1) {
555    my ( $self, $c, $media ) = @_;
556    $c->stash->{dist}{media} = $media;
557}
558
559=head2 Url: /distrib/<DISTRIB>/<RELEASE>/<ARCH>/media/<MEDIA>
560
561Return the list of rpms in media C<MEDIA> for distribution C<DISTRIB>,
562C<RELEASE>, C<ARCH>.
563
564The return list is an array of struct:
565
566    [
567        {
568            filename => 'zvbi-0.2.33-5.fc14.x86_64.rpm',
569            pkgid => 'bb9cc5113f0de3e4c7140a1ee8694900'
570        },
571        {
572            filename => 'zvbi-devel-0.2.33-5.fc14.i686.rpm',
573            pkgid => '2c3b41c5e1c475dfa31492998eb4de9f'
574        }
575    ]
576
577=cut
578
579sub media_list_rpms :Chained('_media_list_rpms') PathPart('') :Args(0) {
580    my ( $self, $c ) = @_;
581    $c->forward('anyrpms', [ $c->stash->{dist} ]);
582}
583
584=head2 Url: /distrib/<DISTRIB>/<RELEASE>/<ARCH>/media/<MEDIA>/rpms/<NAME>
585
586Show binary rpm named C<NAME> in this distribution/media.
587
588Return C<404> error if such rpm does not exists
589
590=cut
591
592sub media_rpm_byname :Chained('_media_list_rpms') PathPart('rpms') {
593    my ( $self, $c, $name, @subpart ) = @_;
594    $c->stash->{dist}{src} = 0;
595    ($c->stash->{pkgid}) = @{ $c->forward('/search/rpm/byname',
596        [ $c->stash->{dist}, $name ]) };
597    $c->go('/404/index') unless ($c->stash->{pkgid});
598    $c->go('/rpms/rpms', [ $c->stash->{pkgid}, @subpart ]);
599}
600
601=head2 Url: /distrib/<DISTRIB>/<RELEASE>/<ARCH>/media/<MEDIA>/srpms/<NAME>
602
603Show source rpm named C<NAME> in this distribution/media.
604
605Return C<404> error if such rpm does not exists
606
607=cut
608
609sub media_srpm_byname :Chained('_media_list_rpms') PathPart('srpms') {
610    my ( $self, $c, $name, @subpart ) = @_;
611    $c->stash->{dist}{src} = 1;
612    ($c->stash->{pkgid}) = @{ $c->forward('/search/rpm/byname',
613        [ $c->stash->{dist}, $name ]) };
614    $c->go('/404/index') unless ($c->stash->{pkgid});
615    $c->go('/rpms/rpms', [ $c->stash->{pkgid}, @subpart ]);
616}
617
618=head2 Url: /distrib/<DISTRIB>/<RELEASE>/<ARCH>/media/<MEDIA>/by-pkgid/<PKGID>
619
620Show rpm having C<PKGID> in this distribution/media.
621
622Return C<404> error if such rpm does not exists
623
624=cut
625
626sub media_rpm_bypkgid :Chained('_media_list_rpms') PathPart('by-pkgid') {
627    my ( $self, $c, $pkgid, @part ) = @_;
628    if ($pkgid) {
629        if (@{ $c->forward('/search/rpm/bypkgid', [ $c->stash->{dist}, $pkgid
630            ]) } ) {
631            $c->stash->{pkgid} = $pkgid;
632            $c->go('/rpms/rpms', [ $pkgid, @part ]);
633        } else {
634            $c->go('/404/index');
635        }
636    } else {
637        $c->forward('anyrpms', [ $c->stash->{dist} ]);
638    }
639}
640
641=head1 AUTHOR
642
643Olivier Thauvin
644
645=head1 LICENSE
646
647This library is free software. You can redistribute it and/or modify
648it under the same terms as Perl itself.
649
650=cut
651
652__PACKAGE__->meta->make_immutable;
653
6541;
Note: See TracBrowser for help on using the repository browser.