add initial version of a package feeds management script

SVN-Revision: 8973
This commit is contained in:
Felix Fietkau 2007-09-23 02:39:01 +00:00
parent d7502c446b
commit f8dfc57573
7 changed files with 484 additions and 130 deletions

2
feeds.conf Normal file
View File

@ -0,0 +1,2 @@
src-svn packages https://svn.openwrt.org/openwrt/packages
src-svn xwrt http://svn.berlios.de/svnroot/repos/xwrt/trunk/package

View File

@ -1,15 +1,15 @@
include $(TOPDIR)/include/verbose.mk
TMP_DIR:=$(TOPDIR)/tmp
all: tmp/.$(SCAN_TARGET)
all: $(TMP_DIR)/.$(SCAN_TARGET)
include $(TOPDIR)/include/host.mk
SCAN_TARGET ?= packageinfo
SCAN_NAME ?= package
SCAN_DIR ?= package
TARGET_STAMP:=tmp/info/.files-$(SCAN_TARGET).stamp
FILELIST:=tmp/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)
TARGET_STAMP:=$(TMP_DIR)/info/.files-$(SCAN_TARGET).stamp
FILELIST:=$(TMP_DIR)/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)
ifeq ($(IS_TTY),1)
define progress
@ -22,8 +22,8 @@ else
endif
define PackageDir
tmp/.$(SCAN_TARGET): tmp/info/.$(SCAN_TARGET)-$(1)
tmp/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(1)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(1)/$(DEP))))
$(TMP_DIR)/.$(SCAN_TARGET): $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1)
$(TMP_DIR)/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(1)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(1)/$(DEP))))
{ \
$$(call progress,Collecting $(SCAN_NAME) info: $(SCAN_DIR)/$(2)) \
echo Source-Makefile: $(SCAN_DIR)/$(2)/Makefile; \
@ -33,10 +33,10 @@ define PackageDir
endef
$(FILELIST):
rm -f tmp/info/.files-$(SCAN_TARGET)-*
rm -f $(TMP_DIR)/info/.files-$(SCAN_TARGET)-*
$(call FIND_L, $(SCAN_DIR)) $(SCAN_EXTRA) -mindepth 1 $(if $(SCAN_DEPTH),-maxdepth $(SCAN_DEPTH)) -name Makefile | xargs grep -HE 'call (Build/DefaultTargets|Build(Package|Target)|.+Package)' | sed -e 's#^$(SCAN_DIR)/##' -e 's#/Makefile:.*##' | uniq > $@
tmp/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
$(TMP_DIR)/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
( \
cat $< | awk '{print "$(SCAN_DIR)/" $$0 "/Makefile" }' | xargs grep -HE '^ *SCAN_DEPS *= *' | awk -F: '{ gsub(/^.*DEPS *= */, "", $$2); print "DEPS_" $$1 "=" $$2 }'; \
awk -v deps="$$DEPS" '{ \
@ -47,7 +47,7 @@ tmp/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
true; \
) > $@
-include tmp/info/.files-$(SCAN_TARGET).mk
-include $(TMP_DIR)/info/.files-$(SCAN_TARGET).mk
$(TARGET_STAMP):
( \
@ -60,9 +60,9 @@ $(TARGET_STAMP):
} \
)
tmp/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP)
$(TMP_DIR)/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP)
$(call progress,Collecting $(SCAN_NAME) info: merging...)
cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "tmp/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@
cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@
$(call progress,Collecting $(SCAN_NAME) info: done)
echo

View File

@ -30,15 +30,17 @@ endif
SCAN_COOKIE?=$(shell echo $$$$)
export SCAN_COOKIE
prepare-mk: FORCE ;
prepare-tmpinfo: FORCE
mkdir -p tmp/info
+$(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(TOPDIR)/include/package*.mk" SCAN_DEPTH=4 SCAN_EXTRA=""
+$(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk $(TOPDIR)/include/kernel*.mk" SCAN_DEPTH=2 SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1"
for type in package target; do \
f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \
[ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config < "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \
[ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \
done
./scripts/metadata.pl package_mk < tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
touch $(TOPDIR)/tmp/.build
.config: ./scripts/config/conf prepare-tmpinfo
@ -64,7 +66,7 @@ defconfig: scripts/config/conf prepare-tmpinfo FORCE
$< -D .config Config.in
oldconfig: scripts/config/conf prepare-tmpinfo FORCE
$< -o Config.in
$< -$(if $(CONFDEFAULT),$(CONFDEFAULT),o) Config.in
menuconfig: scripts/config/mconf prepare-tmpinfo FORCE
if [ \! -f .config -a -e $(HOME)/.openwrt/defconfig ]; then \

View File

@ -579,28 +579,11 @@ int main(int ac, char **av)
}
case ask_all:
case ask_new:
conf_read(NULL);
break;
case set_no:
case set_mod:
case set_yes:
case set_random:
name = getenv("KCONFIG_ALLCONFIG");
if (name && !stat(name, &tmpstat)) {
conf_read_simple(name);
break;
}
switch (input_mode) {
case set_no: name = "allno.config"; break;
case set_mod: name = "allmod.config"; break;
case set_yes: name = "allyes.config"; break;
case set_random: name = "allrandom.config"; break;
default: break;
}
if (!stat(name, &tmpstat))
conf_read_simple(name);
else if (!stat("all.config", &tmpstat))
conf_read_simple("all.config");
conf_read(NULL);
break;
default:
break;

322
scripts/feeds Executable file
View File

@ -0,0 +1,322 @@
#!/usr/bin/perl
use Getopt::Std;
use FindBin;
use Cwd;
use lib "$FindBin::Bin";
use metadata;
use warnings;
use strict;
chdir "$FindBin::Bin/..";
$ENV{TOPDIR}=getcwd();
my @feeds;
my %build_packages;
my %installed;
sub parse_config() {
my $line = 0;
my %name;
open FEEDS, "feeds.conf";
while (<FEEDS>) {
chomp;
s/#.+$//;
next unless /\S/;
my @line = split /\s+/, $_, 3;
$line++;
my $valid = 1;
$line[0] =~ /^src-\w+$/ or $valid = 0;
$line[1] =~ /^\w+$/ or $valid = 0;
$line[2] =~ /\s/ and $valid = 0;
$valid or die "Syntax error in feeds.list, line: $line\n";
$name{$line[1]} and die "Duplicate feed name '$line[1]', line: $line\n";
$name{$line[1]} = 1;
push @feeds, [@line];
}
close FEEDS;
}
sub update_svn($$) {
my $name = shift;
my $src = shift;
system("svn co $src ./feeds/$name") == 0 or return 1;
-d "./feeds/$name.tmp" or mkdir "./feeds/$name.tmp" or return 1;
-d "./feeds/$name.tmp/info" or mkdir "./feeds/$name.tmp/info" or return 1;
system("make -s prepare-mk TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\"");
system("make -s -f include/scan.mk IS_TTY=1 SCAN_TARGET=\"packageinfo\" SCAN_DIR=\"feeds/$name\" SCAN_NAME=\"package\" SCAN_DEPS=\"$ENV{TOPDIR}/include/package*.mk\" SCAN_DEPTH=4 SCAN_EXTRA=\"\" TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\"");
system("ln -sf $name.tmp/.packageinfo ./feeds/$name.index");
return 0;
}
sub get_feed($) {
my $feed = shift;
clear_packages();
parse_package_metadata("./feeds/$feed.index") or return;
return { %package };
}
sub get_installed() {
system("make -s prepare-tmpinfo");
clear_packages();
parse_package_metadata("./tmp/.packageinfo");
%installed = %package;
}
sub search_feed {
my $feed = shift;
my @substr = @_;
my $display;
return unless @substr > 0;
get_feed($feed);
foreach my $name (sort { lc($a) cmp lc($b) } keys %package) {
my $pkg = $package{$name};
my $substr;
my $pkgmatch = 1;
foreach my $substr (@substr) {
my $match;
foreach my $key (qw(name title description)) {
$substr and $pkg->{$key} =~ m/$substr/i and $match = 1;
}
$match or undef $pkgmatch;
};
$pkgmatch and do {
$display or do {
print "Search results in feed '$feed':\n";
$display = 1;
};
printf "\%-25s\t\%s\n", $pkg->{name}, $pkg->{title};
};
}
return 0;
}
sub search {
my %opts;
getopt('r:', \%opts);
foreach my $feed (@feeds) {
search_feed($feed->[1], @ARGV) if (!defined($opts{r}) or $opts{r} eq $feed->[1]);
}
}
sub install_svn() {
my $feed = shift;
my $pkg = shift;
my $path = $pkg->{makefile};
$path =~ s/\/Makefile$//;
-d "./package/feeds" or mkdir "./package/feeds";
-d "./package/feeds/$feed->[1]" or mkdir "./package/feeds/$feed->[1]";
system("ln -sf ../../../$path ./package/feeds/$feed->[1]/");
return 0;
}
my %install_method = (
'src-svn' => \&install_svn
);
my %feed;
sub lookup_package($$) {
my $feed = shift;
my $package = shift;
foreach my $feed ($feed, @feeds) {
next unless $feed->[1];
next unless $feed{$feed->[1]};
$feed{$feed->[1]}->{$package} and return $feed;
}
return;
}
sub install_package {
my $feed = shift;
my $name = shift;
my $ret = 0;
$feed = lookup_package($feed, $name);
$feed or do {
$installed{$name} and return 0;
warn "WARNING: Package '$name' is not available.\n";
return 1;
};
my $pkg = $feed{$feed->[1]}->{$name} or return 1;
my $src = $pkg->{src};
my $type = $feed->[0];
$src or $src = $name;
# previously installed packages set the runtime package
# newly installed packages set the source package
$installed{$src} and return 0;
# install all dependencies
foreach my $dep (@{$pkg->{depends}}) {
next if $dep =~ /@/;
$dep =~ s/^\+//;
install_package($feed, $dep) == 0 or $ret = 1;
}
# check previously installed packages
$installed{$name} and return 0;
$installed{$src} = 1;
warn "Installing package '$src'\n";
$install_method{$type} or do {
warn "Unknown installation method: '$type'\n";
return 1;
};
&{$install_method{$type}}($feed, $pkg) == 0 or do {
warn "failed.\n";
return 1;
};
return $ret;
}
sub refresh_config {
my $default = shift;
$default or $default = "o";
# workaround for timestamp check
system("rm -f tmp/.packageinfo");
# refresh the config
system("make oldconfig CONFDEFAULT=\"$default\" Config.in >/dev/null 2>/dev/null");
}
sub install {
my $name;
my %opts;
my $feed;
my $ret = 0;
getopt('p:d:', \%opts);
get_installed();
foreach my $f (@feeds) {
# index all feeds
$feed{$f->[1]} = get_feed($f->[1]);
# look up the preferred feed
$opts{p} and $f->[1] eq $opts{p} and $feed = $f;
}
while ($name = shift @ARGV) {
install_package($feed, $name) == 0 or $ret = 1;
}
# workaround for timestamp check
# set the defaults
if ($opts{d} and $opts{d} =~ /^[ymn]$/) {
refresh_config($opts{d});
}
return $ret;
}
sub uninstall {
my $name;
my $uninstall;
if ($ARGV[0] eq '-a') {
system("rm -rf ./package/feeds");
$uninstall = 1;
} else {
get_installed();
while ($name = shift @ARGV) {
my $pkg = $installed{$name};
$pkg or do {
warn "WARNING: $name not installed\n";
next;
};
$pkg->{src} and $name = $pkg->{src};
warn "Uninstalling package '$name'\n";
system("rm -f ./package/feeds/*/$name");
$uninstall = 1;
}
}
$uninstall and refresh_config();
return 0;
}
sub usage() {
print <<EOF;
Usage: $0 <command> [options]
Commands:
install [options] <package>: Install a package
Options:
-p <feedname>: Prefer this feed when installing packages
-d <y|m|n>: Set default for newly installed packages
search [options] <substring>: Search for a package
Options:
-r <feedname>: Only search in this feed
uninstall -a|<package>: Uninstall a package
-a uninstalls all packages
update: Update packages and lists of feeds in feeds.list
clean: Remove downloaded/generated files
EOF
exit(1);
}
my %update_method = (
'src-svn' => \&update_svn
);
my %commands = (
'update' => sub {
-d "feeds" or do {
mkdir "feeds" or die "Unable to create the feeds directory";
};
$ENV{SCAN_COOKIE} = $$;
$ENV{KBUILD_VERBOSE} = 99;
foreach my $feed (@feeds) {
my ($type, $name, $src) = @$feed;
$update_method{$type} or do {
warn "Unknown type '$type' in feed $name\n";
next;
};
warn "Updating feed '$name'...\n";
&{$update_method{$type}}($name, $src) == 0 or do {
warn "failed.\n";
return 1;
};
}
return 0;
},
'install' => \&install,
'search' => \&search,
'uninstall' => \&uninstall,
'clean' => sub {
system("rm -rf feeds");
}
);
my $arg = shift @ARGV;
$arg or usage();
parse_config;
foreach my $cmd (keys %commands) {
$arg eq $cmd and do {
exit(&{$commands{$cmd}}());
};
}
usage();

View File

@ -1,24 +1,11 @@
#!/usr/bin/perl
use FindBin;
use lib "$FindBin::Bin";
use strict;
my %preconfig;
my %package;
my %srcpackage;
my %category;
my %subdir;
use metadata;
my %board;
sub get_multiline {
my $prefix = shift;
my $str;
while (<>) {
last if /^@@/;
s/^\s*//g;
$str .= (($_ and $prefix) ? $prefix . $_ : $_);
}
return $str;
}
sub confstr($) {
my $conf = shift;
$conf =~ tr#/\.\-/#___#;
@ -26,8 +13,13 @@ sub confstr($) {
}
sub parse_target_metadata() {
my ($target, @target, $profile);
while (<>) {
my $file = shift @ARGV;
my ($target, @target, $profile);
open FILE, "<$file" or do {
warn "Can't open file '$file': $!\n";
return;
};
while (<FILE>) {
chomp;
/^Target:\s*(.+)\s*$/ and do {
$target = {
@ -46,7 +38,7 @@ sub parse_target_metadata() {
/^Target-Path:\s*(.+)\s*$/ and $target->{path} = $1;
/^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1;
/^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ];
/^Target-Description:/ and $target->{desc} = get_multiline();
/^Target-Description:/ and $target->{desc} = get_multiline(*FILE);
/^Linux-Version:\s*(.+)\s*$/ and $target->{version} = $1;
/^Linux-Release:\s*(.+)\s*$/ and $target->{release} = $1;
/^Linux-Kernel-Arch:\s*(.+)\s*$/ and $target->{karch} = $1;
@ -61,10 +53,11 @@ sub parse_target_metadata() {
};
/^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1;
/^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ];
/^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline();
/^Target-Profile-Config:/ and $profile->{config} = get_multiline("\t");
/^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(*FILE);
/^Target-Profile-Config:/ and $profile->{config} = get_multiline(*FILE, "\t");
/^Target-Profile-Kconfig:/ and $profile->{kconfig} = 1;
}
close FILE;
foreach my $target (@target) {
@{$target->{profiles}} > 0 or $target->{profiles} = [
{
@ -77,78 +70,6 @@ sub parse_target_metadata() {
return @target;
}
sub parse_package_metadata() {
my $pkg;
my $makefile;
my $preconfig;
my $subdir;
my $src;
while (<>) {
chomp;
/^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do {
$makefile = $1;
$subdir = $2;
$src = $3;
$subdir =~ s/^package\///;
$subdir{$src} = $subdir;
$srcpackage{$src} = [];
undef $pkg;
};
/^Package:\s*(.+?)\s*$/ and do {
$pkg = {};
$pkg->{src} = $src;
$pkg->{makefile} = $makefile;
$pkg->{name} = $1;
$pkg->{default} = "m if ALL";
$pkg->{depends} = [];
$pkg->{builddepends} = [];
$pkg->{subdir} = $subdir;
$package{$1} = $pkg;
push @{$srcpackage{$src}}, $pkg;
};
/^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
/^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
/^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
/^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
/^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
/^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
/^Provides: \s*(.+)\s*$/ and do {
my @vpkg = split /\s+/, $1;
foreach my $vpkg (@vpkg) {
$package{$vpkg} or $package{$vpkg} = { vdepends => [] };
push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
}
};
/^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ];
/^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ];
/^Category: \s*(.+)\s*$/ and do {
$pkg->{category} = $1;
defined $category{$1} or $category{$1} = {};
defined $category{$1}->{$src} or $category{$1}->{$src} = [];
push @{$category{$1}->{$src}}, $pkg;
};
/^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline("\t\t ");
/^Config: \s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline();
/^Prereq-Check:/ and $pkg->{prereq} = 1;
/^Preconfig:\s*(.+)\s*$/ and do {
my $pkgname = $pkg->{name};
$preconfig{$pkgname} or $preconfig{$pkgname} = {};
if (exists $preconfig{$pkgname}->{$1}) {
$preconfig = $preconfig{$pkgname}->{$1};
} else {
$preconfig = {
id => $1
};
$preconfig{$pkgname}->{$1} = $preconfig;
}
};
/^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1;
/^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1;
/^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1;
}
return %category;
}
sub gen_kconfig_overrides() {
my %config;
my %kconfig;
@ -318,20 +239,31 @@ EOF
print "endchoice\n";
}
sub find_package_dep($$) {
my %dep_check;
sub __find_package_dep($$) {
my $pkg = shift;
my $name = shift;
my $deps = ($pkg->{vdepends} or $pkg->{depends});
return 0 unless defined $deps;
foreach my $dep (@{$deps}) {
next if $dep_check{$dep};
$dep_check{$dep} = 1;
return 1 if $dep eq $name;
return 1 if ($package{$dep} and (find_package_dep($package{$dep},$name) == 1));
return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
}
return 0;
}
# wrapper to avoid infinite recursion
sub find_package_dep($$) {
my $pkg = shift;
my $name = shift;
%dep_check = ();
return __find_package_dep($pkg, $name);
}
sub package_depends($$) {
my $a = shift;
my $b = shift;
@ -452,7 +384,7 @@ sub print_package_config_category($) {
}
sub gen_package_config() {
parse_package_metadata();
parse_package_metadata($ARGV[0]) or exit 1;
print "menuconfig UCI_PRECONFIG\n\tbool \"Image configuration\"\n";
foreach my $preconfig (keys %preconfig) {
foreach my $cfg (keys %{$preconfig{$preconfig}}) {
@ -478,7 +410,7 @@ sub gen_package_mk() {
my %dep;
my $line;
parse_package_metadata();
parse_package_metadata($ARGV[0]) or exit 1;
foreach my $name (sort {uc($a) cmp uc($b)} keys %package) {
my $config;
my $pkg = $package{$name};

113
scripts/metadata.pm Normal file
View File

@ -0,0 +1,113 @@
package metadata;
use base 'Exporter';
use strict;
use warnings;
our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig clear_packages parse_package_metadata get_multiline);
our %package;
our %preconfig;
our %srcpackage;
our %category;
our %subdir;
sub get_multiline {
my $fh = shift;
my $prefix = shift;
my $str;
while (<$fh>) {
last if /^@@/;
s/^\s*//g;
$str .= (($_ and $prefix) ? $prefix . $_ : $_);
}
return $str ? $str : "";
}
sub clear_packages() {
%subdir = ();
%preconfig = ();
%package = ();
%srcpackage = ();
%category = ();
}
sub parse_package_metadata($) {
my $file = shift;
my $pkg;
my $makefile;
my $preconfig;
my $subdir;
my $src;
open FILE, "<$file" or do {
warn "Cannot open '$file': $!\n";
return undef;
};
while (<FILE>) {
chomp;
/^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do {
$makefile = $1;
$subdir = $2;
$src = $3;
$subdir =~ s/^package\///;
$subdir{$src} = $subdir;
$srcpackage{$src} = [];
undef $pkg;
};
/^Package:\s*(.+?)\s*$/ and do {
$pkg = {};
$pkg->{src} = $src;
$pkg->{makefile} = $makefile;
$pkg->{name} = $1;
$pkg->{default} = "m if ALL";
$pkg->{depends} = [];
$pkg->{builddepends} = [];
$pkg->{subdir} = $subdir;
$package{$1} = $pkg;
push @{$srcpackage{$src}}, $pkg;
};
/^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
/^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
/^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
/^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
/^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
/^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
/^Provides: \s*(.+)\s*$/ and do {
my @vpkg = split /\s+/, $1;
foreach my $vpkg (@vpkg) {
$package{$vpkg} or $package{$vpkg} = { vdepends => [] };
push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
}
};
/^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ];
/^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ];
/^Category: \s*(.+)\s*$/ and do {
$pkg->{category} = $1;
defined $category{$1} or $category{$1} = {};
defined $category{$1}->{$src} or $category{$1}->{$src} = [];
push @{$category{$1}->{$src}}, $pkg;
};
/^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline(*FILE, "\t\t ");
/^Config: \s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(*FILE);
/^Prereq-Check:/ and $pkg->{prereq} = 1;
/^Preconfig:\s*(.+)\s*$/ and do {
my $pkgname = $pkg->{name};
$preconfig{$pkgname} or $preconfig{$pkgname} = {};
if (exists $preconfig{$pkgname}->{$1}) {
$preconfig = $preconfig{$pkgname}->{$1};
} else {
$preconfig = {
id => $1
};
$preconfig{$pkgname}->{$1} = $preconfig;
}
};
/^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1;
/^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1;
/^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1;
}
close FILE;
return %category;
}
1;