From 9fd47e87e66bcc90129ed548cf26cbe2d2b55674 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michael=20Schr=C3=B6der?= Date: Fri, 21 Nov 2008 14:28:45 +0000 Subject: [PATCH] - add parse method to Build::Kiwi - support kiwi product builds --- Build.pm | 2 +- Build/Kiwi.pm | 320 +++++++++++++++++++++++++++++++++++----------------------- build | 22 +++- 3 files changed, 210 insertions(+), 134 deletions(-) diff --git a/Build.pm b/Build.pm index 46ad1aa..cf470e1 100644 --- a/Build.pm +++ b/Build.pm @@ -105,7 +105,7 @@ sub read_config { my @macros = split("\n", $std_macros.$extra_macros); push @macros, "%define _target_cpu $arch"; push @macros, "%define _target_os linux"; - my $config = {'macros' => \@macros}; + my $config = {'macros' => \@macros, 'arch' => $arch}; my @config; if (ref($cfile)) { @config = @$cfile; diff --git a/Build/Kiwi.pm b/Build/Kiwi.pm index 305549e..7e5a3b3 100644 --- a/Build/Kiwi.pm +++ b/Build/Kiwi.pm @@ -2,154 +2,216 @@ package Build::Kiwi; use strict; -use Digest::MD5; -#use Device::Cdio::ISO9660; -#use Device::Cdio::ISO9660::IFS; -my $have_zlib; -eval { - require Compress::Zlib; - $have_zlib = 1; -}; - -sub parse { - my ($bconf, $fn) = @_; - my $ret; - my @control; - -print "Build::Kiwi::parse IS NOT IMPLEMENTED ! \n"; - return ; - - # get arch and os from macros - my ($arch, $os); - for (@{$bconf->{'macros'} || []}) { - $arch = $1 if /^%define _target_cpu (\S+)/; - $os = $1 if /^%define _target_os (\S+)/; +our $bootcallback; + +# worst xml parser ever, just good enough to parse those kiwi files... +# +sub parsexml { + my ($xml) = @_; + + my @nodestack; + my $node = {}; + my $c = ''; + $xml =~ s/^\s*\<\?.*?\?\>//s; + while ($xml =~ /^(.*?)\//s; + next; + } + die("bad xml\n") unless $xml =~ /(.*?\>)/s; + my $tag = $1; + $xml = substr($xml, length($tag)); + my $mode = 0; + if ($tag =~ s/^\<\///s) { + chop $tag; + $mode = 1; # end + } elsif ($tag =~ s/\/\>$//s) { + $mode = 2; # start & end + $tag = substr($tag, 1); + } else { + $tag = substr($tag, 1); + chop $tag; + } + my @tag = split(/(=(?:\"[^\"]*\"|[^\"\s]*))?\s+/, "$tag "); + $tag = shift @tag; + shift @tag; + push @tag, undef if @tag & 1; + my %atts = @tag; + for (values %atts) { + next unless defined $_; + s/^=\"([^\"]*)\"$/=$1/s; + s/^=//s; + s/<//g; + s/&/&/g; + s/"/\"/g; + } + if ($mode == 0 || $mode == 2) { + my $n = {}; + push @{$node->{$tag}}, $n; + for (sort keys %atts) { + $n->{$_} = $atts{$_}; + } + if ($mode == 0) { + push @nodestack, [ $tag, $node, $c ]; + $c = ''; + $node = $n; + } + } else { + die("element '$tag' closes without open\n") unless @nodestack; + die("element '$tag' closes, but I expected '$nodestack[-1]->[0]'\n") unless $nodestack[-1]->[0] eq $tag; + $c =~ s/^\s*//s; + $c =~ s/\s*$//s; + $node->{'_content'} = $c if $c ne ''; + $node = $nodestack[-1]->[1]; + $c = $nodestack[-1]->[2]; + pop @nodestack; + } } - # map to debian names - $os = 'linux' if !defined($os); - $arch = 'all' if !defined($arch) || $arch eq 'noarch'; - $arch = 'i386' if $arch =~ /^i[456]86$/; - $arch = 'powerpc' if $arch eq 'ppc'; - $arch = 'amd64' if $arch eq 'x86_64'; - - if (ref($fn) eq 'ARRAY') { - @control = @$fn; - } else { - local *F; - if (!open(F, '<', $fn)) { - $ret->{'error'} = "$fn: $!"; - return $ret; + $c .= $xml; + $c =~ s/^\s*//s; + $c =~ s/\s*$//s; + $node->{'_content'} = $c if $c ne ''; + return $node; +} + +sub unify { + my %h = map {$_ => 1} @_; + return grep(delete($h{$_}), @_); +} + +sub kiwiparse { + my ($xml, $arch, $count) = @_; + $count ||= 0; + die("kiwi config inclusion depth limit reached\n") if $count++ > 10; + + my @alltypes; + my @allrepos; + my @allpackages; + my @extrasources; + my $kiwi = parsexml($xml); + die("not a kiwi config\n") unless $kiwi && $kiwi->{'image'}; + $kiwi = $kiwi->{'image'}->[0]; + my $preferences = ($kiwi->{'preferences'} || [])->[0]; + $preferences ||= {}; + for my $type (@{$preferences->{'type'} || []}) { + next unless @{$preferences->{'type'}} == 1 || $type->{'primary'}; + push @alltypes, $type->{'_content'}; + push @allpackages, "kiwi-filesystem:$type->{'filesystem'}" if $type->{'filesystem'}; + if (defined $type->{'boot'}) { + if ($type->{'boot'} =~ /^obs:\/\/\/?([^\/]+)\/([^\/]+)\/?$/) { + next unless $bootcallback; + my ($bootxml, $xsrc) = $bootcallback->($1, $2); + next unless $bootxml; + push @extrasources, $xsrc if $xsrc; + my ($bootrepos, $bootpackages, $boottypes, $bootextrasources) = kiwiparse($bootxml, $arch, $count); + push @allrepos, @$bootrepos; + push @allpackages, @$bootpackages; + push @extrasources, @$bootextrasources; + } else { + die("bad boot reference: $type->{'boot'}\n") unless $type->{'boot'} =~ /^([^\/]+)\/([^\/]+)$/; + push @allpackages, "kiwi-boot:$1"; + } } - @control = ; - close F; - chomp @control; } - splice(@control, 0, 3) if @control > 3 && $control[0] =~ /^-----BEGIN/; - my $name; - my $version; - my @deps; - while (@control) { - my $c = shift @control; - last if $c eq ''; # new paragraph - my ($tag, $data) = split(':', $c, 2); - next unless defined $data; - $tag = uc($tag); - while (@control && $control[0] =~ /^\s/) { - $data .= "\n".substr(shift @control, 1); + + my $instsource = ($kiwi->{'instsource'} || [])->[0]; + if ($instsource) { + for my $repository (@{$instsource->{'instrepo'} || []}) { + my $kiwisource = ($repository->{'source'} || [])->[0]; + die("bad instsource path: $kiwisource->{'path'}\n") unless $kiwisource->{'path'} =~ /^obs:\/\/\/?([^\/]+)\/([^\/]+)\/?$/; + push @allrepos, {'project' => $1, 'repository' => $2}; } - $data =~ s/^\s+//s; - $data =~ s/\s+$//s; - if ($tag eq 'VERSION') { - $version = $data; - $version =~ s/-[^-]+$//; - } elsif ($tag eq 'SOURCE') { - $name = $data; - } elsif ($tag eq 'BUILD-DEPENDS' || $tag eq 'BUILD-CONFLICTS' || $tag eq 'BUILD-IGNORE') { - my @d = split(/,\s*/, $data); - for my $d (@d) { - if ($d =~ /^(.*?)\s*\[(.*)\]$/) { - $d = $1; - my $isneg = 0; - my $bad; - for my $q (split('[\s,]', $2)) { - $isneg = 1 if $q =~ s/^\!//; - $bad = 1 if !defined($bad) && !$isneg; - if ($isneg) { - if ($q eq $arch || $q eq "$os-$arch") { - $bad = 1; - last; - } - } elsif ($q eq $arch || $q eq "$os-$arch") { - $bad = 0; - } - } - next if $bad; - } - $d =~ s/ \(([^\)]*)\)/ $1/g; - $d =~ s/>>/>/g; - $d =~ s/<{'repopackages'} || []}) { + for my $repopackage (@{$repopackages->{'repopackage'} || []}) { + push @allpackages, $repopackage->{'name'}; } } + if ($instsource->{'metadata'}) { + for my $repopackage (@{$instsource->{'metadata'}->[0]->{'repopackage'} || []}) { + push @allpackages, $repopackage->{'name'}; + } + } } - $ret->{'name'} = $name; - $ret->{'version'} = $version; - $ret->{'deps'} = \@deps; - return $ret; -} -sub debq { - my ($fn) = @_; + for my $repository (@{$kiwi->{'repository'} || []}) { + my $kiwisource = ($repository->{'source'} || [])->[0]; + next if $kiwisource->{'path'} eq '/var/lib/empty'; # grr + die("bad path: $kiwisource->{'path'}\n") unless $kiwisource->{'path'} =~ /^obs:\/\/\/?([^\/]+)\/([^\/]+)\/?$/; + push @allrepos, {'project' => $1, 'repository' => $2}; + } + for my $packagegroup (@{$kiwi->{'packages'} || []}) { + for my $package (@{$packagegroup->{'package'} || []}) { + if ($package->{'arch'}) { + my $ma = $arch; + $ma =~ s/i[456]86/i386/; + my $pa = $package->{'arch'}; + $pa =~ s/i[456]86/i386/; + next if $ma ne $pa; + } + push @allpackages, $package->{'name'}; + } + } - print "Build::Kiwi::debq IS NOT IMPLEMENTED ! \n"; - die(); + if (!$instsource) { + my $packman = $preferences->{'packagemanager'}->[0]->{'_content'}; + push @allpackages, "kiwi-packagemanager:$packman"; + } else { + push @allpackages, "kiwi-packagemanager:instsource"; + } - return 1; + @allrepos = unify(@allrepos); + @allpackages = unify(@allpackages); + @alltypes = unify(@alltypes); + return (\@allrepos, \@allpackages, \@alltypes, \@extrasources); } -sub queryiso { - my ($handle, %opts) = @_; - -# $iso = Device::Cdio::ISO9660::IFS->new(-source=>'copying.iso'); - my $src = ''; - my $data = { - name => "DEFAULT_NAME", -# hdrmd5 => Digest::MD5::md5_hex($handle); #FIXME create real checksum from iso +sub parse { + my ($cf, $fn) = @_; + + local *F; + open(F, '<', $fn) || die("$fn: $!\n"); + my $xml = ''; + 1 while sysread(F, $xml, 4096, length($xml)) > 0; + close F; + $cf ||= {}; + my ($repos, $packages, $types, $extrasources); + eval { + ($repos, $packages, $types, $extrasources) = kiwiparse($xml, ($cf->{'arch'} || '')); }; -# $data->{'source'} = $src if $src ne ''; - if ($opts{'evra'}) { -#FIXME find out of iso: - my $arch = "i586"; - $data->{'version'} = "0.1"; - $data->{'release'} = "1"; - $data->{'type'} = "iso"; - $data->{'arch'} = $arch; + if ($@) { + my $err = $@; + $err =~ s/^\n$//s; + return {'error' => $err}; } - if ($opts{'filelist'}) { - print ("Build::KIWI query filelist not implemented !\n"); - die(); -# $data->{'filelist'} = $res{'FILENAMES'}; - } - if ($opts{'description'}) { - print ("Build::KIWI query description not implemented !\n"); - die(); -# $data->{'summary'} = $res{'SUMMARY'}->[0]; -# $data->{'description'} = $res{'DESCRIPTION'}->[0]; - } - return $data; + my $d = {'deps' => $packages, 'path' => $repos, 'imagetype' => $types}; + $d->{'extrasource'} = $extrasources if @$extrasources; + return $d; } -sub queryhdrmd5 { - my ($bin) = @_; +sub show { + my ($fn, $field, $arch) = @ARGV; + my $cf = {'arch' => $arch}; + my $d = parse($cf, $fn); + die("$d->{'error'}\n") if $d->{'error'}; + my $x = $d->{$field}; + $x = [ $x ] unless ref $x; + print "@$x\n"; +} - print "Build::Kiwi::queryhdrmd5 IS NOT IMPLEMENTED ! \n"; - die(); +sub query { + my ($handle, %opts) = @_; + return {}; +} +sub queryhdrmd5 { + my ($bin) = @_; + die("Build::Kiwi::queryhdrmd5 unimplemented.\n"); } 1; diff --git a/build b/build index 644c852..42ba881 100755 --- a/build +++ b/build @@ -1349,10 +1349,24 @@ for SPECFILE in "${SPECFILES[@]}" ; do fi rm -f $BUILD_ROOT/$TOPDIR/SOURCES/config.xml ln -s $SPECFILE $BUILD_ROOT/$TOPDIR/SOURCES/config.xml - echo "running kiwi --prepare..." - if chroot $BUILD_ROOT su -c "cd $TOPDIR/SOURCES && kiwi --prepare $TOPDIR/SOURCES --logfile terminal --root $TOPDIR/KIWIROOT" - $BUILD_USER < /dev/null ; then - echo "running kiwi --create..." - chroot $BUILD_ROOT su -c "kiwi --create $TOPDIR/KIWIROOT --logfile terminal -d $TOPDIR/KIWI" - $BUILD_USER < /dev/null && BUILD_SUCCEDED=true + imagetype=$(perl -I$BUILD_DIR -MBuild::Kiwi -e Build::Kiwi::show $BUILD_ROOT/$TOPDIR/SOURCES/$SPECFILE imagetype) + chroot $BUILD_ROOT su -c "kiwi --version" - + if test "$imagetype" = product ; then + echo "running kiwi --create-instsource..." + chroot $BUILD_ROOT su -c "kiwi --root $TOPDIR/KIWIROOT -v -v --instsource-local --logfile terminal -p $TOPDIR/SOURCES --create-instsource $TOPDIR/SOURCES" - $BUILD_USER < /dev/null && BUILD_SUCCEEDED=true + for i in "$BUILD_ROOT/$TOPDIR/KIWIROOT/main/*" ; do + test -d "$i" || continue + n="${i##*/}" + test "$n" = scripts && continue + test "$n" != "${n%0}" && continue + chroot $BUILD_ROOT su -c "suse-isolinux $TOPDIR/KIWIROOT/main/$i $TOPDIR/KIWI/$i.iso" - $BUILD_USER + done + else + echo "running kiwi --prepare..." + if chroot $BUILD_ROOT su -c "cd $TOPDIR/SOURCES && kiwi --prepare $TOPDIR/SOURCES --logfile terminal --root $TOPDIR/KIWIROOT" - $BUILD_USER < /dev/null ; then + echo "running kiwi --create..." + chroot $BUILD_ROOT su -c "kiwi --create $TOPDIR/KIWIROOT --logfile terminal -d $TOPDIR/KIWI" - $BUILD_USER < /dev/null && BUILD_SUCCEDED=true + fi fi fi -- 2.7.4