File Coverage

blib/lib/Package/Builder.pm
Criterion Covered Total %
statement 42 117 35.9
branch 2 34 5.8
condition 0 3 0.0
subroutine 13 23 56.5
pod 9 10 90.0
total 66 187 35.2


line stmt bran cond sub pod time code
1             package Package::Builder;
2             require Exporter;
3              
4             our @ISA = qw(Exporter);
5             our @EXPORT = qw(extractArchive isReservedDir isDocFile isConfigFile substituteAliasDir getChangeLogs checkVersionFormat checkReleaseFormat getParameterFromConfig getSpecTemplate); # Symbols to be exported by default
6 1     1   23483 use warnings;
  1         3  
  1         34  
7 1     1   6 use strict;
  1         2  
  1         36  
8              
9 1     1   6 use Cwd;
  1         6  
  1         77  
10 1     1   1849 use Text::Template;
  1         3739  
  1         53  
11 1     1   1362 use Archive::Tar;
  1         233000  
  1         93  
12 1     1   1668 use File::stat;
  1         55558  
  1         15  
13 1     1   100 use File::Path;
  1         3  
  1         52  
14 1     1   2834 use Getopt::Long;
  1         13474  
  1         8  
15 1     1   189 use File::Find;
  1         3  
  1         58  
16 1     1   6 use File::Basename;
  1         2  
  1         66  
17 1     1   6 use File::Spec;
  1         3  
  1         19  
18              
19 1     1   638 use Package::Utils;
  1         3  
  1         1772  
20             =head1 NAME
21              
22             Package::Builder - The great new Package::Builder!
23              
24             =head1 VERSION
25              
26             Version 5.01
27              
28             =cut
29              
30             our $VERSION = '5.03';
31              
32              
33             =head1 SYNOPSIS
34              
35             Quick summary of what the module does.
36              
37             Perhaps a little code snippet.
38              
39             use Package::Builder;
40              
41             my $foo = Package::Builder->new();
42             ...
43              
44             =head1 EXPORT
45              
46             A list of functions that can be exported. You can delete this section
47             if you don't export anything, such as for a purely object-oriented module.
48              
49             =cut
50              
51             our %user_infos = getUserMap();
52             our %group_infos = getGroupMap();
53              
54             our @reserved_dirs = (
55             '^\/bin$', '^\/sbin$', '^\/dev$', '^\/home$',
56             '^\/lib$', '^\/media$', '^\/mnt$', '^\/proc$',
57             '^\/srv$', '^\/tmp$', '^\/var\/log$', '^\/var\/lib$',
58             '^\/var$', '^\/boot$', '^\/etc$', '^\/etc\/rc.d',
59             '^\/initrd$', '^\/lost+found$', '^\/root$', '^\/selinux$',
60             '^\/sys$', '^\/usr$', '\/usr\/sbin$', '\/usr\/bin$'
61             );
62              
63             our @config_pattern = (
64             "config", "conf",, "etc",
65             "initrd", "\.conf", "\.properties", "\.cnf",
66             "\.ini", "\.xml"
67             );
68             our @doc_pattern =
69             ( "doc", "\.txt", "README", "LICENCE", "LICENSE", "TODO", "\.html", "\.tex" );
70              
71             my %dirAlias = (
72             "/usr/sbin" => "%{_sbindir}",
73             "/usr/bin" => "%{_bindir}",
74             "/usr/lib" => "%{_libdir}",
75             "/usr/libexec" => "%{_libexecdir}",
76             "/usr/share" => "%{_datadir}",
77             "/var" => "%{_var}"
78             );
79              
80             our $macrosFile = $ENV{'HOME'} . "/.rpmmacros";
81              
82             our $topdir = getParameterFromConfig( "_topdir", "/usr/src/redhat" );
83             our $specDir = $topdir . "/SPECS";
84             our $srcDir = $topdir . "/SOURCES";
85             our $archiveRootPath = "/tmp/myrpm";
86              
87             =head1 FUNCTIONS
88              
89             =head2 extractArchive
90              
91             =cut
92             sub extractArchive {
93 0     0 1 0 my $archive = shift;
94 0         0 my $root_dir = shift;
95 0         0 my $uid = shift;
96 0         0 my $gid = shift;
97              
98             # Create temporary dir
99 0         0 my $snap_dir = "$archiveRootPath/$$";
100 0         0 my $tmp_dir = "$snap_dir/$root_dir";
101 0         0 eval { mkpath($tmp_dir) };
  0         0  
102 0 0       0 if ($@) {
103 0         0 print STDERR "\n * Couldn't create $tmp_dir: $@";
104 0         0 return undef;
105             }
106 0         0 my $cwdir = getcwd;
107 0         0 chdir $tmp_dir;
108              
109 0         0 my $compressed_archive = ( $archive =~ /.+?\.(?:tar\.gz|tgz)$/i );
110 0         0 my $arch_obj = Archive::Tar->new( $archive, $compressed_archive );
111 0         0 $arch_obj->extract();
112              
113 0 0 0     0 if ( defined $uid && defined $gid ) {
114             #change uid if necessary
115 0         0 $uid = getUserId($uid);
116 0         0 $gid = getGroupId($gid);
117             find(
118             sub {
119 0     0   0 chown $uid, $gid, $_;
120             },
121 0         0 $tmp_dir
122             );
123             }
124 0         0 chdir $cwdir;
125              
126 0         0 return $snap_dir;
127             }
128             =head2 isReservedDir
129              
130             =cut
131             sub isReservedDir {
132 0     0 0 0 my $dir = shift;
133 0         0 foreach my $rdir (@reserved_dirs) {
134 0 0       0 return 1 if ( $dir =~ /$rdir/ );
135             }
136 0         0 return 0;
137             }
138              
139             =head2 isDocFile
140              
141             =cut
142             sub isDocFile {
143 0     0 1 0 my $file = shift;
144 0         0 foreach my $dpat (@doc_pattern) {
145 0 0       0 return 1 if ( $file =~ /$dpat/ );
146             }
147 0         0 return 0;
148             }
149              
150             =head2 isConfigFile
151              
152             =cut
153             sub isConfigFile {
154 0     0 1 0 my $file = shift;
155 0         0 foreach my $cpat (@config_pattern) {
156 0 0       0 return 1 if ( $file =~ /$cpat/ );
157             }
158 0         0 return 0;
159             }
160              
161             =head2 substituteAliasDir
162              
163             =cut
164             sub substituteAliasDir {
165 0     0 1 0 my $path = shift;
166              
167             #my $not_found=1;
168 0         0 foreach my $subpath ( keys %dirAlias ) {
169              
170             #break unless ($not_found);
171 0 0       0 if ( $path =~ /^$subpath/ ) {
172 0         0 my $alias = $dirAlias{$subpath};
173 0         0 $path =~ s/^$subpath/$alias/;
174 0         0 return $path;
175             }
176             }
177 0         0 return $path;
178             }
179              
180              
181             =head2 getChangeLogs
182              
183             =cut
184             sub getChangeLogs {
185 0     0 1 0 my $specFile = shift;
186 0 0       0 return '' unless ( -f $specFile );
187 0         0 my @lines = getFileContents($specFile);
188 0         0 my @changeLogs = ();
189 0         0 my $changeLogHeaderFound = 0;
190 0         0 foreach (@lines) {
191 0 0       0 push @changeLogs, $_ if $changeLogHeaderFound == 1;
192 0 0       0 $changeLogHeaderFound = 1 if /^%changelog/;
193             }
194 0         0 return join( '', @changeLogs );
195             }
196              
197             =head2 checkVersionFormat
198              
199             =cut
200             sub checkVersionFormat {
201 0     0 1 0 my $ret=undef;
202 0         0 my $version=shift;
203 0 0       0 $ret=1 unless ( $version =~ /^[0-9][0-9\.]*$/ );
204 0         0 return $ret;
205             }
206              
207             =head2 checkReleaseFormat
208              
209             =cut
210             sub checkReleaseFormat {
211 0     0 1 0 my $ret=undef;
212 0         0 my $release=shift;
213 0 0       0 $ret=1 unless ( $release =~ /^[1-9][0-9]*$/ );
214 0         0 return $ret;
215             }
216              
217             =head2 getParameterFromConfig
218             Retrieve value from files (like .rpmmacros)
219             =cut
220             sub getParameterFromConfig {
221 1     1 1 2 my $parameter = shift;
222              
223 1         2 my $res = shift;
224 1         2 my $opened = 1;
225 1 50       20 open( MACROS, $macrosFile ) || ( $opened = 0 );
226 1 50       4 if ($opened) {
227 0         0 while () {
228 0 0       0 if (m/^\%$parameter\s+(.*)$/) {
229 0         0 $res = $1;
230             }
231             }
232              
233 0         0 close(MACROS);
234             }
235 1         3 return $res;
236             }
237              
238             =head2 getSpecTemplate
239              
240             =cut
241             sub getSpecTemplate {
242             ############################
243             # THE TEMPLATE
244             ############################
245 0     0 1   my $defaultSpecTemplate = 'Summary: <$summary>
246             Name: <$name>
247             Version: <$version>
248             Release: <$release>
249             License: GPL
250             URL: <$vendor_url>
251             Source0: %{name}-%{version}.tar.gz
252             Group: System/Administration
253             Vendor: <$vendor>
254             Packager: <$packager>
255             #Arch: <$archi>
256            
257             BuildRoot: %{_tmppath}/%{name}-%{version}-root
258             < foreach $req (@reqs) { $OUT.= "Requires: $req\n"; }>
259             %description
260             <$description>
261              
262             < if (@defConfFiles != 0) {
263             $OUT.="%package config
264             Summary: Configuration for $name
265             Group: System/Administration
266              
267             %description config
268             Configuration files for $name
269             $description";
270             } >
271            
272             $OUT.="%package doc
273             Summary: Documentation for $name
274             Group: System/Administration
275              
276             %description doc
277             Documentation files for $name
278             $description";
279             } >
280             %prep
281             #%setup -q
282             #-n %{name}-%{version}
283             %setup -c -q
284              
285             %build
286             <$build_code>
287             %install
288             rm -Rf %{buildroot}
289             mkdir -p %{buildroot}/usr/lib/debug
290              
291             #Directory installation
292             < foreach $i (@instDirs) {
293             $comment=$$i{comment};
294             $file=$$i{file};
295             $mode=$$i{mode};
296             $path=$$i{path};
297             $OUT.= "#Uncomment if needed - consider as a reserved dir\n#" if ($comment);
298             $OUT.="%{__install} -d -m $mode $file %{buildroot}$path\n";
299              
300             }>
301             #Files installation
302             < foreach $i (@instFiles) {
303             $file=$$i{file};
304             $mode=$$i{mode};
305             $path=$$i{path};
306             $OUT.= "%{__mkdir_p} `dirname %{buildroot}$path` || true\n";
307             $OUT.= "%{__install} -m $mode $file %{buildroot}$path\n";
308             }>
309             %pre
310             < if (@groups == 0 ) {
311             $OUT.="# No group Creation";
312             } else {
313             $OUT.="# Group creation";
314             foreach $i (@groups) {
315             $gid=$$i{gid};
316             $gname=$$i{name};
317             $OUT.="\ngroupadd -g $gid $gname || true";
318             }
319             }
320             if (@users == 0 ) {
321             $OUT.="\n# No User Creation";
322             } else {
323             $OUT.="\n# User creation";
324             foreach $i (@users) {
325             $uname=$$i{name};
326             $gid=$$i{gid};
327             $shell=$$i{shell};
328             $home=$$i{home};
329             $comment=$$i{comment};
330             $uid=$$i{uid};
331             $is_init=$$i{init};
332              
333             $OUT.="\nUSER_NEW=0";
334             $OUT.="\nadduser -u $uid -g $gid -s $shell -d $home -c \"$comment\" $uname && USER_NEW=1 || true";
335             if ($is_init) {
336             $OUT.="\nif [ \"\$USER_NEW\" -eq \"1\" ]; then";
337             $OUT.="\n\t# Changing password for non priviliged user";
338             $OUT.="\n\techo $uname | passwd --stdin $uname";
339             $OUT.="\nfi";
340             }
341             }
342             }>
343              
344             < $OUT.="\n$pre_code";>
345              
346             %post< foreach $i (keys %symbolic_links) {
347             $link=$i;
348             $pointee=$symbolic_links{$i};
349             $OUT.="\n#Symbolic link $i - $pointee";
350             $OUT.="\ncd `dirname $i`";
351             $OUT.="\nrm -fv `basename $i`";
352             $OUT.="\nln -fvs $pointee `basename $i`";
353             $OUT.="\ncd -";
354             }>
355             <$post_code>
356             %preun
357             <$preun_code>
358             %postun
359             <$postun_code>
360             %clean
361             rm -Rf %{buildroot}
362              
363             #Regular file and dir list
364             %files
365             < foreach $i (@listOfFiles) {
366             $mode=$$i{mode};
367             $path=$$i{r_path};
368             $comment=$$i{comment};
369             $uid=$$i{uid};
370             $gid=$$i{gid};
371             $OUT.="#Uncomment if needed !\n#" if (defined $comment);
372             $OUT.="%attr($mode $uid, $gid) ";
373             $OUT.="%dir " if ($$i{isDir});
374             $OUT.="$path\n";
375             }>
376             < if ( @listOfConfFiles != 0 ) { $OUT.="#Configuration file list"; }>
377             < if ( $multiple_packages && @listOfConfFiles != 0 ) { $OUT.= "%files config"; }>
378             < foreach $i (@listOfConfFiles) { $OUT.="%attr($$i{mode} $$i{uid}, $$i{gid}) %config $$i{path}\n"; }>
379             < if ( @listOfDocFiles != 0 ) { $OUT.= "#Documentation file list"; }>
380             < if ( $multiple_packages && @listOfDocFiles != 0 ) { $OUT.= "%files doc"; }>
381             < foreach $i (@listOfDocFiles) { $OUT.= "%doc $$i{path}\n"; }>
382             %changelog
383             * <$date> <$packager> <$name>-<$version>-<$release>
384             - <$ChangeLog>
385             - Generated version.
386              
387             <$OldChangeLogs>';
388              
389 0           my $fileName = shift;
390 0           my $res = $defaultSpecTemplate;
391 0 0         if ( $fileName ne "" ) {
392 0           my $opened = 1;
393 0 0         open( TEMPLATE, "$fileName" ) || ( $opened = 0 );
394              
395 0 0         if ($opened) {
396 0           $res = "";
397 0           while (