X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=blobdiff_plain;f=scripts%2Ffeeds;h=b1bdee597ea0f2e1a8c5da5553bd9064737cb949;hp=78e65ad1d5c184584d34a122bd8376751885141d;hb=83cb1f8cf7bd8d4d460cfa7037ade5b94b12c306;hpb=1457c8fbb46be316ae15bd3d9057bb555f598357 diff --git a/scripts/feeds b/scripts/feeds index 78e65ad1d5..b1bdee597e 100755 --- a/scripts/feeds +++ b/scripts/feeds @@ -10,114 +10,188 @@ use Cwd 'abs_path'; chdir "$FindBin::Bin/.."; $ENV{TOPDIR}=getcwd(); +$ENV{GIT_CONFIG_PARAMETERS}="'core.autocrlf=false'"; + +my $mk=`which gmake 2>/dev/null`; # select the right 'make' program +chomp($mk); # trim trailing newline +$mk or $mk = "make"; # default to 'make' + +# check version of make +my @mkver = split /\s+/, `$mk -v`, 4; +my $valid_mk = 1; +$mkver[0] =~ /^GNU/ or $valid_mk = 0; +$mkver[1] =~ /^Make/ or $valid_mk = 0; +$mkver[2] >= "3.81" or $valid_mk = 0; +$valid_mk or die "Unsupported version of make found: $mk\n"; my @feeds; my %build_packages; my %installed; +my %feed_cache; + +my $feed_package = {}; +my $feed_src = {}; sub parse_config() { my $line = 0; my %name; - open FEEDS, "feeds.conf"; + open FEEDS, "feeds.conf" or + open FEEDS, "feeds.conf.default" or + die "Unable to open feeds configuration"; while () { chomp; s/#.+$//; next unless /\S/; my @line = split /\s+/, $_, 3; + my @src; $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"; + @src = split /\s+/, $line[2]; + $valid or die "Syntax error in feeds.conf, line: $line\n"; $name{$line[1]} and die "Duplicate feed name '$line[1]', line: $line\n"; $name{$line[1]} = 1; - push @feeds, [@line]; + push @feeds, [$line[0], $line[1], \@src]; } close FEEDS; } -sub update_index($) +sub update_location($$) { my $name = shift; + my $url = shift; + my $old_url; -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 update_svn($$) { - my $name = shift; - my $src = shift; + if( open LOC, "< ./feeds/$name.tmp/location" ) + { + chomp($old_url = readline LOC); + close LOC; + } - if (-d "./feeds/$name/.svn" ) { - system("(cd \"./feeds/$name\"; svn up)") == 0 or return 1; - } else { - system("rm -rf \"./feeds/$name\""); - system("svn co $src \"./feeds/$name\"") == 0 or return 1; + if( !$old_url || $old_url ne $url ) + { + if( open LOC, "> ./feeds/$name.tmp/location" ) + { + print LOC $url, "\n"; + close LOC; + } + return $old_url ? 1 : 0; } return 0; } -sub update_cpy($$) { +sub update_index($) +{ my $name = shift; - my $src = shift; - system("mkdir -p ./feeds/$name"); - system("cp -Rf $src ./feeds"); + -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("$mk -s prepare-mk OPENWRT_BUILD= TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\""); + system("$mk -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=5 SCAN_EXTRA=\"\" TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\""); + system("ln -sf $name.tmp/.packageinfo ./feeds/$name.index"); return 0; } -sub update_link($$) { - my $name = shift; - my $src = abs_path(shift); - - system("rm -f ./feeds/$name; ln -s $src ./feeds/$name"); +my %update_method = ( + 'src-svn' => { + 'init' => "svn checkout '%s' '%s'", + 'update' => "svn update", + 'controldir' => ".svn", + 'revision' => "svn info | grep 'Revision' | cut -d ' ' -f 2 | tr -d '\n'"}, + 'src-cpy' => { + 'init' => "cp -Rf '%s' '%s'", + 'update' => "", + 'revision' => "echo -n 'local'"}, + 'src-link' => { + 'init' => "ln -s '%s' '%s'", + 'update' => "", + 'revision' => "echo -n 'local'"}, + 'src-git' => { + 'init' => "git clone --depth 1 '%s' '%s'", + 'init_branch' => "git clone --depth 1 --branch '%s' '%s' '%s'", + 'update' => "git pull", + 'controldir' => ".git", + 'revision' => "git show --abbrev-commit HEAD | head -n 1 | cut -d ' ' -f 2 | tr -d '\n'"}, + 'src-gitsvn' => { + 'init' => "git svn clone -r HEAD '%s' '%s'", + 'update' => "git svn rebase", + 'controldir' => ".git", + 'revision' => "git show --abbrev-commit HEAD | head -n 1 | cut -d ' ' -f 2 | tr -d '\n'"}, + 'src-bzr' => { + 'init' => "bzr checkout --lightweight '%s' '%s'", + 'update' => "bzr update", + 'controldir' => ".bzr"}, + 'src-hg' => { + 'init' => "hg clone '%s' '%s'", + 'update' => "hg pull --update", + 'controldir' => ".hg"}, + 'src-darcs' => { + 'init' => "darcs get '%s' '%s'", + 'update' => "darcs pull -a", + 'controldir' => "_darcs"}, +); - return 0; -} +# src-git: pull broken +# src-cpy: broken if `basename $src` != $name -sub update_git($$) { +sub update_feed_via($$$$) { + my $type = shift; my $name = shift; my $src = shift; - - if (-d "./feeds/$name/.git" ) { - system("GIT_DIR=./feeds/$name/.git git pull") == 0 or return 1; + my $relocate = shift; + + my $m = $update_method{$type}; + my $localpath = "./feeds/$name"; + my $safepath = $localpath; + $safepath =~ s/'/'\\''/; + my ($base, $branch) = split(/;/, $src, 2); + + if( $relocate || !$m->{'update'} || !-d "$localpath/$m->{'controldir'}" ) { + system("rm -rf '$safepath'"); + if ($m->{'init_branch'} and $branch) { + system(sprintf($m->{'init_branch'}, $branch, $base, $safepath)) == 0 or return 1; + } else { + system(sprintf($m->{'init'}, $src, $safepath)) == 0 or return 1; + } } else { - system("rm -rf \"./feeds/$name\""); - system("git-clone --depth 1 $src ./feeds/$name") == 0 or return 1; + system("cd '$safepath'; $m->{'update'}") == 0 or return 1; } - + return 0; } sub get_feed($) { my $feed = shift; - my $file = "./feeds/$feed.index"; - clear_packages(); + if (!defined($feed_cache{$feed})) { + my $file = "./feeds/$feed.index"; - -f $file or do { - print "Ignoring feed '$feed' - index missing\n"; - return; - }; - parse_package_metadata($file) or return; - return { %package }; + clear_packages(); + -f $file or do { + print "Ignoring feed '$feed' - index missing\n"; + return; + }; + parse_package_metadata($file) or return; + $feed_cache{$feed} = [ { %package }, { %srcpackage } ]; + } + + $feed_package = $feed_cache{$feed}->[0]; + $feed_src = $feed_cache{$feed}->[1]; + return $feed_cache{$feed}->[0]; } sub get_installed() { - system("make -s prepare-tmpinfo"); + system("$mk -s prepare-tmpinfo OPENWRT_BUILD="); clear_packages(); parse_package_metadata("./tmp/.packageinfo"); %installed = %package; @@ -130,14 +204,15 @@ sub search_feed { return unless @substr > 0; get_feed($feed); - foreach my $name (sort { lc($a) cmp lc($b) } keys %package) { - my $pkg = $package{$name}; + foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) { + my $pkg = $feed_package->{$name}; my $substr; my $pkgmatch = 1; + next if $pkg->{vdepends}; foreach my $substr (@substr) { my $match; - foreach my $key (qw(name title description)) { + foreach my $key (qw(name title description src)) { $pkg->{$key} and $substr and $pkg->{$key} =~ m/$substr/i and $match = 1; } $match or undef $pkgmatch; @@ -166,8 +241,9 @@ sub list_feed { my $feed = shift; get_feed($feed); - foreach my $name (sort { lc($a) cmp lc($b) } keys %package) { - my $pkg = $package{$name}; + foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) { + my $pkg = $feed_package->{$name}; + next if $pkg->{vdepends}; if($pkg->{name}) { printf "\%-32s\t\%s\n", $pkg->{name}, $pkg->{title}; } @@ -179,14 +255,31 @@ sub list_feed { sub list { my %opts; - getopts('r:sh', \%opts); + getopts('r:d:sh', \%opts); if ($opts{h}) { usage(); return 0; } if ($opts{s}) { foreach my $feed (@feeds) { - printf "\%-32s\tURL: %s\n", $feed->[1], $feed->[2]; + my $localpath = "./feeds/$feed->[1]"; + my $m = $update_method{$feed->[0]}; + my $revision; + if( !$m->{'revision'} ) { + $revision = "X"; + } + elsif( $m->{'controldir'} && -d "$localpath/$m->{'controldir'}" ) { + $revision = `cd '$localpath'; $m->{'revision'}`; + } + else { + $revision = "local"; + } + if ($opts{d}) { + printf "%s%s%s%s%s%s%s\n", $feed->[1], $opts{d}, $feed->[0], $opts{d}, $revision, $opts{d}, join(", ", @{$feed->[2]}); + } + else { + printf "\%-8s \%-8s \%-8s \%s\n", $feed->[1], $feed->[0], $revision, join(", ", @{$feed->[2]}); + } } return 0; } @@ -220,6 +313,10 @@ my %install_method = ( 'src-cpy' => \&install_generic, 'src-link' => \&install_generic, 'src-git' => \&install_generic, + 'src-gitsvn' => \&install_generic, + 'src-bzr' => \&install_generic, + 'src-hg' => \&install_generic, + 'src-darcs' => \&install_generic, ); my %feed; @@ -245,10 +342,13 @@ sub install_package { $feed or do { $installed{$name} and return 0; # TODO: check if it's already installed within ./package directory - warn "WARNING: No feed for package '$name' found, maybe it's already part of the standard packages?\n"; + $feed_src->{$name} or -d "./package/$name" or warn "WARNING: No feed for package '$name' found, maybe it's already part of the standard packages?\n"; return 0; }; + # switch to the metadata for the selected feed + get_feed($feed->[1]); + my $pkg = $feed{$feed->[1]}->{$name} or return 1; $pkg->{name} or do { $installed{$name} and return 0; @@ -279,11 +379,16 @@ sub install_package { return 1; }; - # install all dependencies - foreach my $dep (@{$pkg->{depends}}, @{$pkg->{builddepends}}) { - next if $dep =~ /@/; - $dep =~ s/^\+//; - install_package($feed, $dep) == 0 or $ret = 1; + # install all dependencies referenced from the source package + foreach my $vpkg (@{$feed_src->{$src}}) { + foreach my $dep (@{$vpkg->{depends}}, @{$vpkg->{builddepends}}, @{$vpkg->{"builddepends/host"}}) { + next if $dep =~ /@/; + $dep =~ s/^\+//; + $dep =~ s/^.+://; + $dep =~ s/\/.+$//; + next unless $dep; + install_package($feed, $dep) == 0 or $ret = 1; + } } return $ret; @@ -296,10 +401,10 @@ sub refresh_config { system("rm -f tmp/.packageinfo"); # refresh the config - if ($default) { - system("make oldconfig CONFDEFAULT=\"$default\" Config.in >/dev/null 2>/dev/null"); + if ($default) { + system("$mk oldconfig CONFDEFAULT=\"$default\" Config.in >/dev/null 2>/dev/null"); } else { - system("make defconfig Config.in >/dev/null 2>/dev/null"); + system("$mk defconfig Config.in >/dev/null 2>/dev/null"); } } @@ -331,10 +436,12 @@ sub install { if (!defined($opts{p}) or $opts{p} eq $f->[1]) { printf "Installing all packages from feed %s.\n", $f->[1]; get_feed($f->[1]); - foreach my $name (sort { lc($a) cmp lc($b) } keys %package) { - my $p = $package{$name}; + foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) { + my $p = $feed_package->{$name}; + next if $p->{vdepends}; if( $p->{name} ) { install_package($feed, $p->{name}) == 0 or $ret = 1; + get_feed($f->[1]); } } } @@ -392,27 +499,30 @@ sub uninstall { return 0; } -my %update_method = ( - 'src-svn' => \&update_svn, - 'src-cpy' => \&update_cpy, - 'src-link' => \&update_link, - 'src-git' => \&update_git -); - sub update_feed($$$$) { my $type=shift; my $name=shift; my $src=shift; my $perform_update=shift; + my $force_relocate=update_location( $name, "@$src" ); + if( $force_relocate ) { + warn "Source of feed $name has changed, replacing copy\n"; + } $update_method{$type} or do { warn "Unknown type '$type' in feed $name\n"; return 1; }; $perform_update and do { - warn "Updating feed '$name' from '$src' ...\n"; - &{$update_method{$type}}($name, $src) == 0 or do { + my $failed = 1; + foreach my $feedsrc (@$src) { + warn "Updating feed '$name' from '$feedsrc' ...\n"; + next unless update_feed_via($type, $name, $feedsrc, $force_relocate) == 0; + $failed = 0; + last; + } + $failed and do { warn "failed.\n"; return 1; }; @@ -431,7 +541,7 @@ sub update { my $perform_update=1; $ENV{SCAN_COOKIE} = $$; - $ENV{KBUILD_VERBOSE} = 99; + $ENV{OPENWRT_VERBOSE} = 's'; getopts('ahi', \%opts); @@ -477,10 +587,11 @@ sub usage() { Usage: $0 [options] Commands: - list [options]: List feeds and their content + list [options]: List feeds, their content and revisions (if installed) Options: - -s : List of feed names and their URL. - -r : List packages of specified feed. + -s : List of feed names and their URL. + -r : List packages of specified feed. + -d : Use specified delimiter to distinguish rows (default: spaces) install [options] : Install a package Options: @@ -498,7 +609,7 @@ Commands: update -a|: Update packages and lists of feeds in feeds.conf . Options: - -a : Update all feeds listed within feeds.conf. Otherwise the spezified feeds will be updated. + -a : Update all feeds listed within feeds.conf. Otherwise the specified feeds will be updated. -i : Recreate the index only. No feed update from repository is performed. clean: Remove downloaded/generated files.