summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2007-09-23 02:39:01 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2007-09-23 02:39:01 +0000
commitd29153dc010840afa45e70ced91c5e558fca6bb6 (patch)
treed42029d0592cba445fd6249f039834b3625a4f2e /scripts
parent23334c52818e113da1174eeb747f2cb3fc6b1055 (diff)
add initial version of a package feeds management script
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@8973 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'scripts')
-rw-r--r--scripts/config/conf.c19
-rwxr-xr-xscripts/feeds322
-rwxr-xr-xscripts/metadata.pl130
-rw-r--r--scripts/metadata.pm113
4 files changed, 467 insertions, 117 deletions
diff --git a/scripts/config/conf.c b/scripts/config/conf.c
index cb2093691e..6589aee451 100644
--- a/scripts/config/conf.c
+++ b/scripts/config/conf.c
@@ -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;
diff --git a/scripts/feeds b/scripts/feeds
new file mode 100755
index 0000000000..d62e8e79dd
--- /dev/null
+++ b/scripts/feeds
@@ -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();
diff --git a/scripts/metadata.pl b/scripts/metadata.pl
index 03041f97c4..f3d6e9df2c 100755
--- a/scripts/metadata.pl
+++ b/scripts/metadata.pl
@@ -1,23 +1,10 @@
#!/usr/bin/perl
+use FindBin;
+use lib "$FindBin::Bin";
use strict;
-my %preconfig;
-my %package;
-my %srcpackage;
-my %category;
-my %subdir;
-my %board;
-
-sub get_multiline {
- my $prefix = shift;
- my $str;
- while (<>) {
- last if /^@@/;
- s/^\s*//g;
- $str .= (($_ and $prefix) ? $prefix . $_ : $_);
- }
+use metadata;
- return $str;
-}
+my %board;
sub confstr($) {
my $conf = shift;
@@ -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};
diff --git a/scripts/metadata.pm b/scripts/metadata.pm
new file mode 100644
index 0000000000..f90446298a
--- /dev/null
+++ b/scripts/metadata.pm
@@ -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;