File Coverage

blib/lib/PkgForge/SourceUtils.pm
Criterion Covered Total %
statement 31 109 28.4
branch 1 42 2.3
condition 0 9 0.0
subroutine 9 15 60.0
pod 6 8 75.0
total 47 183 25.6


line stmt bran cond sub pod time code
1             package PkgForge::SourceUtils; # -*-perl-*-
2 2     2   29124 use strict;
  2         4  
  2         89  
3 2     2   10 use warnings;
  2         2  
  2         105  
4              
5             # $Id: SourceUtils.pm.in 16519 2011-03-25 15:50:07Z squinney@INF.ED.AC.UK $
6             # $Source:$
7             # $Revision: 16519 $
8             # $HeadURL: https://svn.lcfg.org/svn/source/tags/PkgForge/PkgForge_1_4_8/lib/PkgForge/SourceUtils.pm.in $
9             # $Date: 2011-03-25 15:50:07 +0000 (Fri, 25 Mar 2011) $
10              
11             our $VERSION = '1.4.8';
12              
13 2     2   888 use English qw(-no_match_vars);
  2         4844  
  2         19  
14 2     2   8741 use Module::Find ();
  2         3759  
  2         49  
15 2     2   1997 use Readonly;
  2         7755  
  2         141  
16 2     2   2227 use UNIVERSAL::require;
  2         3866  
  2         22  
17              
18 2     2   58 use Exporter;
  2         5  
  2         2871  
19             our @ISA = qw(Exporter);
20             our @EXPORT_OK = qw($SOURCE_PACKAGE_BASE $BUILDER_BASE);
21              
22             Readonly our $SOURCE_PACKAGE_BASE => 'PkgForge::Source';
23             Readonly our $BUILDER_BASE => 'PkgForge::Builder';
24              
25             sub list_builder_types {
26              
27 0     0 1 0 my @modules = Module::Find::findsubmod($BUILDER_BASE);
28 0         0 my @types = qw(None);
29 0         0 for my $mod (@modules) {
30 0 0       0 if ( $mod =~ m/^\Q$BUILDER_BASE\E::(.+)$/ ) {
31 0         0 push @types, $1;
32             }
33             }
34              
35 0         0 return @types;
36             }
37              
38             sub find_builder {
39 0     0 1 0 my ($type) = @_;
40              
41 0         0 my $module = join q{::}, $BUILDER_BASE, $type;
42              
43 0         0 my $loaded = $module->require;
44 0 0       0 if ( !$loaded ) {
45 0         0 die "Could not load '$module' : $UNIVERSAL::require::ERROR\n";
46             }
47              
48 0         0 return $module;
49             }
50              
51             sub load_source_handler {
52 0     0 1 0 my ($type) = @_;
53              
54             # This is used to verify and untaint the type
55 0 0       0 if ( $type =~ m/^(\w+)$/ ) {
56 0         0 $type = $1;
57             } else {
58 0         0 die "Source package type '$type' is not well formed.\n";
59             }
60              
61 0         0 my @valid_types = list_source_types();
62              
63 0         0 my $pkg_class;
64 0 0       0 if ( grep { $_ eq $type } @valid_types ) {
  0         0  
65 0         0 $pkg_class = join q{::}, $SOURCE_PACKAGE_BASE, $type;
66 0 0       0 $pkg_class->require or die $UNIVERSAL::require::ERROR;
67             } else {
68 0         0 die "Source package type '$type' is not supported.\n";
69             }
70              
71 0         0 return $pkg_class;
72             }
73              
74             sub list_source_types {
75              
76 0     0 1 0 my @modules = list_handlers();
77 0         0 my @types = qw(None);
78 0         0 for my $mod (@modules) {
79 0 0       0 if ( $mod =~ m/^\Q$SOURCE_PACKAGE_BASE\E::(.+)$/ ) {
80 0         0 push @types, $1;
81             }
82             }
83              
84 0         0 return @types;
85             }
86              
87             sub list_handlers {
88              
89             # Doing this in a single step results in weirdness...
90 2     2 1 21 my @modules = Module::Find::findsubmod($SOURCE_PACKAGE_BASE);
91 2         2685 my @sorted = sort @modules;
92 2         7 return @sorted;
93             }
94              
95             sub find_handler {
96 1     1 1 3021 my ($file) = @_;
97              
98 1         5 for my $module ( list_handlers() ) {
99 1         11 my $loaded = $module->require;
100 1 50       13 if ( !$loaded ) {
101 1         121 warn "Could not load '$module' : $UNIVERSAL::require::ERROR\n";
102 1         6 next;
103             }
104              
105 0 0       0 return $module if $module->can_handle($file);
106             }
107              
108 1         4 return;
109             }
110              
111             sub unpack_packages {
112 0     0 0   my ($data) = @_;
113              
114 0           my @packages;
115 0 0 0       if ( defined $data && ref $data eq 'ARRAY' ) {
116 0           for my $item ( @{$data} ) {
  0            
117 0 0 0       if ( !defined $item || ref $item ne 'HASH' ) {
118 0           next;
119             }
120              
121 0           my $type = $item->{type};
122 0 0         if ( !defined $type ) {
123 0           die "Source package type not defined, cannot load packages data'\n";
124             }
125              
126 0           my $pkg_class = eval { load_source_handler($type) };
  0            
127 0 0 0       if ( !defined $pkg_class || $EVAL_ERROR ) {
128 0           die "Cannot load a source package of type '$type'\n";
129             }
130              
131 0           my %pkg;
132 0           for my $attr ( $pkg_class->meta->get_all_attributes ) {
133 0           my $name = $attr->name;
134 0           my $value = $item->{$name};
135              
136 0 0         if ( $attr->does('PkgForge::Meta::Attribute::Trait::Serialise') ) {
137 0 0         if ( $attr->has_unpack_method ) {
138 0           my $method = $attr->unpack;
139 0 0         if ( ref $method eq 'CODE') {
    0          
140 0           $value = $method->($value);
141             } elsif ( $pkg_class->can($method) ) {
142 0           $value = $pkg_class->$method($value);
143             } else {
144 0           die "Could not find '$method' source package unserialisation method\n";
145             }
146             }
147              
148 0 0         $pkg{$name} = $value if defined $value;
149             }
150              
151             }
152              
153 0           my $pkg_obj = $pkg_class->new(%pkg);
154              
155 0           push @packages, $pkg_obj;
156             }
157             }
158              
159 0           return \@packages;
160             }
161              
162             sub pack_packages {
163 0     0 0   my ($packages) = @_;
164              
165 0           my @dump;
166 0           for my $package (@{$packages}) {
  0            
167 0           my %data;
168 0           for my $attr ( $package->meta->get_all_attributes ) {
169 0           my $name = $attr->name;
170 0           my $value = $attr->get_value($package);
171              
172 0 0         if ( $attr->does('PkgForge::Meta::Attribute::Trait::Serialise') ) {
173              
174 0 0         if ( $attr->has_pack_method ) {
175 0           my $method = $attr->pack;
176 0 0         if ( ref $method eq 'CODE') {
    0          
177 0           $value = $method->($value);
178             } elsif ( $package->can($method) ) {
179 0           $value = $package->$method($value);
180             } else {
181 0           die "Could not find '$method' source package serialisation method\n";
182             }
183             }
184              
185 0           $data{$name} = $value;
186             }
187              
188             }
189              
190 0           push @dump, {%data};
191             }
192              
193 0           return \@dump;
194             }
195              
196             1;
197             __END__
198              
199             =head1 NAME
200              
201             PkgForge::SourceUtils - Utilities to help with source module handling
202              
203             =head1 VERSION
204              
205             This documentation refers to PkgForge::SourceUtils version 1.4.8
206              
207             =head1 SYNOPSIS
208              
209             use PkgForge::SourceUtils;
210              
211             my @modules = PkgForge::SourceUtils::list_handlers();
212              
213             my $module = PkgForge::SourceUtils::find_handler($file);
214              
215             if ( defined $module ) {
216             my $pkg = $module->new( ... );
217             $pkg->validate();
218             }
219              
220             =head1 DESCRIPTION
221              
222             This module provides a set of utilities which are commonly useful to
223             handling source packages with L<PkgForge::Source> modules.
224              
225             =head1 SUBROUTINES/METHODS
226              
227             =over
228              
229             =item list_source_types
230              
231             This lists the types of source packages which are supported. It does
232             this by using a similar approach to C<list_handlers> except it returns
233             the short name rather than the full module name. For example,
234             L<PkgForge::Source::SRPM> has a type of C<SRPM>.
235              
236             =item list_handlers
237              
238             This lists all available source package handler modules. You will get
239             a sorted list of the names of all modules under the
240             L<PkgForge::Source> base.
241              
242             =item load_source_handler($type)
243              
244             This takes the type of a source package and attempts to find the
245             associated module in the L<PkgForge::Source> namespace. This will die
246             if the type is not a valid module name or the module cannot be loaded.
247              
248             =item find_handler($file)
249              
250             This will attempt to find a suitable source package handler for a
251             given file. For example, an SRPM might be handled by
252             L<PkgForge::Source::SRPM>. If none is found then undef will be
253             returned. Note that if the source package type is supported by
254             multiple modules then the first to be found wins.
255              
256             =item list_builder_types()
257              
258             This lists all the available types of source package builder
259             modules. Effectively, you will get a sorted list of the short names of
260             all modules under the L<PkgForge::Builder> base. For example, the
261             module L<PkgForge::Builder::RPM> will have a type of C<RPM>.
262              
263             =item find_builder($type)
264              
265             Finds and loads the specified type of source package builder
266             module. Returns a string containing the name of the module which can
267             be used to call the C<new()> method.
268              
269             =head1 DEPENDENCIES
270              
271             This module requires L<Module::Find>, L<Readonly> and L<UNIVERSAL::require>.
272              
273             =head1 SEE ALSO
274              
275             L<PkgForge>, L<PkgForge::Source>, L<PkgForge::Source::SRPM>,
276             L<PkgForge::Builder>
277              
278             =head1 PLATFORMS
279              
280             This is the list of platforms on which we have tested this
281             software. We expect this software to work on any Unix-like platform
282             which is supported by Perl.
283              
284             ScientificLinux5, Fedora13
285              
286             =head1 BUGS AND LIMITATIONS
287              
288             Please report any bugs or problems (or praise!) to bugs@lcfg.org,
289             feedback and patches are also always very welcome.
290              
291             =head1 AUTHOR
292              
293             Stephen Quinney <squinney@inf.ed.ac.uk>
294              
295             =head1 LICENSE AND COPYRIGHT
296              
297             Copyright (C) 2010-2011 University of Edinburgh. All rights reserved.
298              
299             This library is free software; you can redistribute it and/or modify
300             it under the terms of the GPL, version 2 or later.
301              
302             =cut
303