source: trunk/scripts/feeds

Last change on this file was 49267, checked in by blogic, 4 weeks ago

scripts: avoid hard-coded paths in scripts

Signed-off-by: Iblis Lin <e196819@…>

  • Property svn:executable set to *
File size: 19.7 KB
Line 
1#!/usr/bin/env perl
2use Getopt::Std;
3use FindBin;
4use Cwd;
5use lib "$FindBin::Bin";
6use metadata;
7use warnings;
8use strict;
9use Cwd 'abs_path';
10
11chdir "$FindBin::Bin/..";
12$ENV{TOPDIR}=getcwd();
13$ENV{GIT_CONFIG_PARAMETERS}="'core.autocrlf=false'";
14$ENV{GREP_OPTIONS}="";
15
16my $mk=`which gmake 2>/dev/null`;       # select the right 'make' program
17chomp($mk);             # trim trailing newline
18$mk or $mk = "make";    # default to 'make'
19
20# check version of make
21my @mkver = split /\s+/, `$mk -v`, 4;
22my $valid_mk = 1;
23$mkver[0] =~ /^GNU/ or $valid_mk = 0;
24$mkver[1] =~ /^Make/ or $valid_mk = 0;
25$mkver[2] >= "3.81" or $valid_mk = 0;
26$valid_mk or die "Unsupported version of make found: $mk\n";
27
28my @feeds;
29my %build_packages;
30my %installed;
31my %installed_targets;
32my %feed_cache;
33
34my $feed_package = {};
35my $feed_src = {};
36my $feed_target = {};
37
38sub parse_config() {
39        my $line = 0;
40        my %name;
41
42        open FEEDS, "feeds.conf" or
43                open FEEDS, "feeds.conf.default" or
44                die "Unable to open feeds configuration";
45        while (<FEEDS>) {
46                chomp;
47                s/#.+$//;
48                next unless /\S/;
49                my @line = split /\s+/, $_, 3;
50                my @src;
51                $line++;
52
53                my $valid = 1;
54                $line[0] =~ /^src-[\w-]+$/ or $valid = 0;
55                $line[1] =~ /^\w+$/ or $valid = 0;
56                @src = split /\s+/, $line[2];
57                $valid or die "Syntax error in feeds.conf, line: $line\n";
58
59                $name{$line[1]} and die "Duplicate feed name '$line[1]', line: $line\n";
60                $name{$line[1]} = 1;
61
62                push @feeds, [$line[0], $line[1], \@src];
63        }
64        close FEEDS;
65}
66
67sub update_location($$)
68{
69        my $name = shift;
70        my $url  = shift;
71        my $old_url;
72
73        -d "./feeds/$name.tmp" or mkdir "./feeds/$name.tmp" or return 1;
74
75        if( open LOC, "< ./feeds/$name.tmp/location" )
76        {
77                chomp($old_url = readline LOC);
78                close LOC;
79        }
80
81        if( !$old_url || $old_url ne $url )
82        {
83                if( open LOC, "> ./feeds/$name.tmp/location" )
84                {
85                        print LOC $url, "\n";
86                        close LOC;
87                }
88                return $old_url ? 1 : 0;
89        }
90
91        return 0;
92}
93
94sub update_index($)
95{
96        my $name = shift;
97
98        -d "./feeds/$name.tmp" or mkdir "./feeds/$name.tmp" or return 1;
99        -d "./feeds/$name.tmp/info" or mkdir "./feeds/$name.tmp/info" or return 1;
100
101        system("$mk -s prepare-mk OPENWRT_BUILD= TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\"");
102        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\"");
103        system("$mk -s -f include/scan.mk IS_TTY=1 SCAN_TARGET=\"targetinfo\" SCAN_DIR=\"feeds/$name\" SCAN_NAME=\"target\" SCAN_DEPS=\"profiles/*.mk $ENV{TOPDIR}/include/target.mk\" SCAN_DEPTH=5 SCAN_EXTRA=\"\" SCAN_MAKEOPTS=\"TARGET_BUILD=1\" TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\"");
104        system("ln -sf $name.tmp/.packageinfo ./feeds/$name.index");
105        system("ln -sf $name.tmp/.targetinfo ./feeds/$name.targetindex");
106
107        return 0;
108}
109
110my %update_method = (
111        'src-svn' => {
112                'init'          => "svn checkout '%s' '%s'",
113                'update'        => "svn update",
114                'controldir'    => ".svn",
115                'revision'      => "svn info | grep 'Revision' | cut -d ' ' -f 2 | tr -d '\n'"},
116        'src-cpy' => {
117                'init'          => "cp -Rf '%s' '%s'",
118                'update'        => "",
119                'revision'      => "echo -n 'local'"},
120        'src-link' => {
121                'init'          => "ln -s '%s' '%s'",
122                'update'        => "",
123                'revision'      => "echo -n 'local'"},
124        'src-git' => {
125                'init'          => "git clone --depth 1 '%s' '%s'",
126                'init_branch'   => "git clone --depth 1 --branch '%s' '%s' '%s'",
127                'init_commit'   => "git clone '%s' '%s' && cd '%s' && git checkout -b '%s' '%s' && cd -",
128                'update'        => "git pull --ff",
129                'controldir'    => ".git",
130                'revision'      => "git show --abbrev-commit HEAD | head -n 1 | cut -d ' ' -f 2 | tr -d '\n'"},
131        'src-git-full' => {
132                'init'          => "git clone '%s' '%s'",
133                'init_branch'   => "git clone --branch '%s' '%s' '%s'",
134                'init_commit'   => "git clone '%s' '%s' && cd '%s' && git checkout -b '%s' '%s' && cd -",
135                'update'        => "git pull --ff",
136                'controldir'    => ".git",
137                'revision'      => "git show --abbrev-commit HEAD | head -n 1 | cut -d ' ' -f 2 | tr -d '\n'"},
138        'src-gitsvn' => {
139                'init'  => "git svn clone -r HEAD '%s' '%s'",
140                'update'        => "git svn rebase",
141                'controldir'    => ".git",
142                'revision'      => "git show --abbrev-commit HEAD | head -n 1 | cut -d ' ' -f 2 | tr -d '\n'"},
143        'src-bzr' => {
144                'init'          => "bzr checkout --lightweight '%s' '%s'",
145                'update'        => "bzr update",
146                'controldir'    => ".bzr"},
147        'src-hg' => {
148                'init'          => "hg clone '%s' '%s'",
149                'update'        => "hg pull --update",
150                'controldir'    => ".hg"},
151        'src-darcs' => {
152                'init'    => "darcs get '%s' '%s'",
153                'update'  => "darcs pull -a",
154                'controldir' => "_darcs"},
155);
156
157# src-git: pull broken
158# src-cpy: broken if `basename $src` != $name
159
160sub update_feed_via($$$$) {
161        my $type = shift;
162        my $name = shift;
163        my $src = shift;
164        my $relocate = shift;
165
166        my $m = $update_method{$type};
167        my $localpath = "./feeds/$name";
168        my $safepath = $localpath;
169        $safepath =~ s/'/'\\''/;
170        my ($base_branch, $branch) = split(/;/, $src, 2);
171        my ($base_commit, $commit) = split(/\^/, $src, 2);
172
173        if( $relocate || !$m->{'update'} || !-d "$localpath/$m->{'controldir'}" ) {
174                system("rm -rf '$safepath'");
175                if ($m->{'init_branch'} and $branch) {
176                        system(sprintf($m->{'init_branch'}, $branch, $base_branch, $safepath)) == 0 or return 1;
177                } elsif ($m->{'init_commit'} and $commit) {
178                        system(sprintf($m->{'init_commit'}, $base_commit, $safepath, $safepath, $commit, $commit)) == 0 or return 1;
179                } else {
180                        system(sprintf($m->{'init'}, $src, $safepath)) == 0 or return 1;
181                }
182        } elsif ($m->{'init_commit'} and $commit) {
183                # in case git hash has been provided don't update the feed
184        } else {
185                system("cd '$safepath'; $m->{'update'}") == 0 or return 1;
186        }
187
188        return 0;
189}
190
191sub get_targets($) {
192        my $file = shift;
193        my @target = parse_target_metadata($file);
194        my %target;
195        foreach my $target (@target) {
196                $target{$target->{id}} = $target;
197        }
198        return %target
199}
200
201sub get_feed($) {
202        my $feed = shift;
203
204        if (!defined($feed_cache{$feed})) {
205                my $file = "./feeds/$feed.index";
206
207                clear_packages();
208                -f $file or do {
209                        print "Ignoring feed '$feed' - index missing\n";
210                        return;
211                };
212                parse_package_metadata($file) or return;
213                my %target = get_targets("./feeds/$feed.targetindex");
214
215                $feed_cache{$feed} = [ { %package }, { %srcpackage }, { %target } ];
216        }
217
218        $feed_package = $feed_cache{$feed}->[0];
219        $feed_src = $feed_cache{$feed}->[1];
220        $feed_target = $feed_cache{$feed}->[2];
221        return $feed_cache{$feed}->[0];
222}
223
224sub get_installed() {
225        system("$mk -s prepare-tmpinfo OPENWRT_BUILD=");
226        clear_packages();
227        parse_package_metadata("./tmp/.packageinfo");
228        %installed = %package;
229        %installed_targets = get_targets("./tmp/.targetinfo");
230}
231
232sub search_feed {
233        my $feed = shift;
234        my @substr = @_;
235        my $display;
236
237        return unless @substr > 0;
238        get_feed($feed);
239        foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
240                my $pkg = $feed_package->{$name};
241                my $substr;
242                my $pkgmatch = 1;
243
244                next if $pkg->{vdepends};
245                foreach my $substr (@substr) {
246                        my $match;
247                        foreach my $key (qw(name title description src)) {
248                                $pkg->{$key} and $substr and $pkg->{$key} =~ m/$substr/i and $match = 1;
249                        }
250                        $match or undef $pkgmatch;
251                };
252                $pkgmatch and do {
253                        $display or do {
254                                print "Search results in feed '$feed':\n";
255                                $display = 1;
256                        };
257                        printf "\%-25s\t\%s\n", $pkg->{name}, $pkg->{title};
258                };
259        }
260
261        foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_target) {
262                my $target = $feed_target->{$name};
263                my $targetmatch = 1;
264
265                foreach my $substr (@substr) {
266                        my $match;
267                        foreach my $key (qw(id name description)) {
268                                $target->{$key} and $substr and $target->{$key} =~ m/$substr/i and $match = 1;
269                        }
270                        $match or undef $targetmatch;
271                };
272                $targetmatch and do {
273                        $display or do {
274                                print "Search results in feed '$feed':\n";
275                                $display = 1;
276                        };
277                        printf "TARGET: \%-17s\t\%s\n", $target->{id}, $target->{name};
278                };
279        }
280        return 0;
281}
282
283sub search {
284        my %opts;
285
286        getopt('r:', \%opts);
287        foreach my $feed (@feeds) {
288                search_feed($feed->[1], @ARGV) if (!defined($opts{r}) or $opts{r} eq $feed->[1]);
289        }
290}
291
292sub list_feed {
293        my $feed = shift;
294
295        get_feed($feed);
296        foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
297                my $pkg = $feed_package->{$name};
298                next if $pkg->{vdepends};
299                if($pkg->{name}) {
300                        printf "\%-32s\t\%s\n", $pkg->{name}, $pkg->{title};
301                }
302        }
303
304        foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_target) {
305                my $target = $feed_target->{$name};
306                if($target->{name}) {
307                        printf "TARGET: \%-24s\t\%s\n", $target->{id}, $target->{name};
308                }
309        }
310
311        return 0;
312}
313
314sub list {
315        my %opts;
316
317        getopts('r:d:nshf', \%opts);
318        if ($opts{h}) {
319                usage();
320                return 0;
321        }
322        if ($opts{n}) {
323                foreach my $feed (@feeds) {
324                        printf "%s\n", $feed->[1];
325                }
326                return 0;
327        }
328        if ($opts{s}) {
329                foreach my $feed (@feeds) {
330                        my $localpath = "./feeds/$feed->[1]";
331                        my $m = $update_method{$feed->[0]};
332                        my $revision;
333                        if( !$m->{'revision'} ) {
334                                $revision = "X";
335                        }
336                        elsif( $m->{'controldir'} && -d "$localpath/$m->{'controldir'}" ) {
337                                $revision = `cd '$localpath'; $m->{'revision'}`;
338                        }
339                        else {
340                                $revision = "local";
341                        }
342                        if ($opts{d}) {
343                                printf "%s%s%s%s%s%s%s\n", $feed->[1], $opts{d}, $feed->[0], $opts{d}, $revision, $opts{d}, join(", ", @{$feed->[2]});
344                        }
345                        elsif ($opts{f}) {
346                                my $uri = join(", ", @{$feed->[2]});
347                                if ($revision ne "local" && $revision ne "X") {
348                                        $uri =~ s/[;^].*//;
349                                        $uri .= "^" . $revision;
350                                }
351                                printf "%s %s %s\n", $feed->[0], $feed->[1], $uri;
352                        }
353                        else {
354                                printf "\%-8s \%-8s \%-8s \%s\n", $feed->[1], $feed->[0], $revision, join(", ", @{$feed->[2]});
355                        }
356                }
357                return 0;
358        }
359        foreach my $feed (@feeds) {
360                list_feed($feed->[1], @ARGV) if (!defined($opts{r}) or $opts{r} eq $feed->[1]);
361        }
362        return 0;
363}
364
365sub do_install_package($$) {
366        my $feed = shift;
367        my $pkg = shift;
368        my $path = $pkg->{makefile};
369
370        if($path) {
371                $path =~ s/\/Makefile$//;
372
373                -d "./package/feeds" or mkdir "./package/feeds";
374                -d "./package/feeds/$feed->[1]" or mkdir "./package/feeds/$feed->[1]";
375                system("ln -sf ../../../$path ./package/feeds/$feed->[1]/");
376        } else {
377                warn "Package is not valid\n";
378                return 1;
379        }
380
381        return 0;
382}
383
384sub do_install_target($) {
385        my $target = shift;
386        my $path = $target->{makefile};
387
388        if ($path) {
389                $path =~ s/\/Makefile$//;
390                my $name = $path;
391                $name =~ s/.*\///;
392                my $dest = "./target/linux/$name";
393
394                -e $dest and do {
395                        warn "Path $dest already exists";
396                        return 1;
397                };
398
399                system("ln -sf ../../$path ./target/linux/");
400        } else {
401                warn "Target is not valid\n";
402                return 1;
403        }
404
405        return 0;
406}
407
408sub lookup_package($$) {
409        my $feed = shift;
410        my $package = shift;
411
412        foreach my $feed ($feed, @feeds) {
413                next unless $feed->[1];
414                next unless $feed_cache{$feed->[1]};
415                $feed_cache{$feed->[1]}->[0]->{$package} and return $feed;
416        }
417        return;
418}
419
420sub lookup_target($$) {
421        my $feed = shift;
422        my $target = shift;
423
424        foreach my $feed ($feed, @feeds) {
425                next unless $feed->[1];
426                next unless $feed_cache{$feed->[1]};
427                $feed_cache{$feed->[1]}->[2]->{$target} and return $feed;
428        }
429        return;
430}
431
432sub is_core_package($) {
433        my $package = shift;
434        foreach my $file ("tmp/info/.packageinfo-$package", glob("tmp/info/.packageinfo-*_$package")) {
435                next unless index($file, "tmp/info/.packageinfo-feeds_");
436                return 1 if -s $file;
437        }
438        return 0;
439}
440
441sub install_target {
442        my $feed = shift;
443        my $name = shift;
444
445        $feed = $feed_cache{$feed->[1]}->[2];
446        $feed or return 0;
447
448        my $target = $feed->{$name};
449        $target or return 0;
450
451        warn "Installing target '$name'\n";
452        return do_install_target($target);
453}
454
455sub install_package {
456        my $feed = shift;
457        my $name = shift;
458        my $force = shift;
459        my $ret = 0;
460
461        my $this_feed_target = lookup_target($feed, $name);
462        $this_feed_target and do {
463                $installed_targets{$name} and return 0;
464                install_target($this_feed_target, $name);
465                return 0;
466        };
467
468        $feed = lookup_package($feed, $name);
469        $feed or do {
470                $installed{$name} and return 0;
471                # TODO: check if it's already installed within ./package directory
472                $feed_src->{$name} or is_core_package($name) or warn "WARNING: No feed for package '$name' found, maybe it's already part of the standard packages?\n";
473                return 0;
474        };
475
476        # switch to the metadata for the selected feed
477        my $cur = get_feed($feed->[1]);
478
479        my $pkg = $cur->{$name} or return 1;
480        $pkg->{name} or do {
481                $installed{$name} and return 0;
482                # TODO: check if this is an alias package, maybe it's known by another name
483                warn "WARNING: Package '$name' is not available in feed $feed->[1].\n";
484                return 0;
485        };
486        my $src = $pkg->{src};
487        my $type = $feed->[0];
488        $src or $src = $name;
489
490        # If it's a core package and we don't want to override, just return
491        !$force and is_core_package($src) and return 0;
492
493        # previously installed packages set the runtime package
494        # newly installed packages set the source package to 1
495        $installed{$src} and $installed{$src} == 1 and return 0;
496
497        # we'll trigger the override only with the 3 conditions below:
498        # - override is allowed by command line (-f)
499        # - a package with the same src exists in the core packages list
500        # - the package previously installed is not from a feed
501        my $override = 1 if ($force and is_core_package($src) and !$installed{$name}->{feed});
502
503        # check previously installed packages
504        $installed{$name} and !$override and return 0;
505        $installed{$src} = 1;
506
507        defined($override) and $override == 1
508                and warn "Overriding core package '$src' with version from $feed->[1]\n"
509                or warn "Installing package '$src' from $feed->[1]\n";
510
511        do_install_package($feed, $pkg) == 0 or do {
512                warn "failed.\n";
513                return 1;
514        };
515
516        # install all dependencies referenced from the source package
517        foreach my $vpkg (@{$feed_src->{$src}}) {
518                foreach my $dep (@{$vpkg->{depends}}, @{$vpkg->{builddepends}}, @{$vpkg->{"builddepends/host"}}) {
519                        next if $dep =~ /@/;
520                        $dep =~ s/^\+//;
521                        $dep =~ s/^.+://;
522                        $dep =~ s/\/.+$//;
523                        next unless $dep;
524                        install_package($feed, $dep, 0) == 0 or $ret = 1;
525                }
526        }
527
528        return $ret;
529}
530
531sub refresh_config {
532        my $default = shift;
533
534        # workaround for timestamp check
535        system("rm -f tmp/.packageinfo");
536
537        # refresh the config
538        if ($default) {
539                system("$mk oldconfig CONFDEFAULT=\"$default\" Config.in >/dev/null 2>/dev/null");
540        } else {
541                system("$mk defconfig Config.in >/dev/null 2>/dev/null");
542        }
543}
544
545sub install {
546        my $name;
547        my %opts;
548        my $feed;
549        my $ret = 0;
550
551        getopts('ap:d:fh', \%opts);
552
553        if ($opts{h}) {
554                usage();
555                return 0;
556        }
557
558        get_installed();
559
560        foreach my $f (@feeds) {
561                # fetch all feeds
562                get_feed($f->[1]);
563
564                # look up the preferred feed
565                $opts{p} and $f->[1] eq $opts{p} and $feed = $f;
566        }
567
568        if($opts{a}) {
569                foreach my $f (@feeds) {
570                        if (!defined($opts{p}) or $opts{p} eq $f->[1]) {
571                                printf "Installing all packages from feed %s.\n", $f->[1];
572                                get_feed($f->[1]);
573                                foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
574                                        my $p = $feed_package->{$name};
575                                        next if $p->{vdepends};
576                                        if( $p->{name} ) {
577                                                install_package($feed, $p->{name}, exists($opts{f})) == 0 or $ret = 1;
578                                                get_feed($f->[1]);
579                                        }
580                                }
581                        }
582                }
583        } else {
584                while ($name = shift @ARGV) {
585                        install_package($feed, $name, exists($opts{f})) == 0 or $ret = 1;
586                }
587        }
588
589        # workaround for timestamp check
590
591        # set the defaults
592        if ($opts{d} and $opts{d} =~ /^[ymn]$/) {
593                refresh_config($opts{d});
594        }
595
596        return $ret;
597}
598
599sub uninstall_target($) {
600        my $dir = shift;
601        my $name = $dir;
602        $name =~ s/.*\///g;
603
604        my $dest = readlink $dir;
605        return unless $dest =~ /..\/..\/feeds/;
606        warn "Uninstalling target '$name'\n";
607        unlink "$dir";
608}
609
610sub uninstall {
611        my %opts;
612        my $name;
613        my $uninstall;
614
615        getopts('ah', \%opts);
616
617        if ($opts{h}) {
618                usage();
619                return 0;
620        }
621
622        if ($opts{a}) {
623                system("rm -rvf ./package/feeds");
624                foreach my $dir (glob "target/linux/*") {
625                        next unless -l $dir;
626                        uninstall_target($dir);
627                }
628                $uninstall = 1;
629        } else {
630                if($#ARGV == -1) {
631                        warn "WARNING: no package to uninstall\n";
632                        return 0;
633                }
634                get_installed();
635                while ($name = shift @ARGV) {
636                        my $target = "target/linux/$name";
637                        -l "$target" and do {
638                                uninstall_target($target);
639                                $uninstall = 1;
640                                next;
641                        };
642
643                        my $pkg = $installed{$name};
644                        $pkg or do {
645                                warn "WARNING: $name not installed\n";
646                                next;
647                        };
648                        $pkg->{src} and $name = $pkg->{src};
649                        warn "Uninstalling package '$name'\n";
650                        system("rm -f ./package/feeds/*/$name");
651                        $uninstall = 1;
652                }
653        }
654        $uninstall and refresh_config();
655        return 0;
656}
657
658sub update_feed($$$$)
659{
660        my $type=shift;
661        my $name=shift;
662        my $src=shift;
663        my $perform_update=shift;
664        my $force_relocate=update_location( $name, "@$src" );
665
666        if( $force_relocate ) {
667                warn "Source of feed $name has changed, replacing copy\n";
668        }
669        $update_method{$type} or do {
670                warn "Unknown type '$type' in feed $name\n";
671                return 1;
672        };
673        $perform_update and do {
674                my $failed = 1;
675                foreach my $feedsrc (@$src) {
676                        warn "Updating feed '$name' from '$feedsrc' ...\n";
677                        next unless update_feed_via($type, $name, $feedsrc, $force_relocate) == 0;
678                        $failed = 0;
679                        last;
680                }
681                $failed and do {
682                        warn "failed.\n";
683                        return 1;
684                };
685        };
686        warn "Create index file './feeds/$name.index' \n";
687        update_index($name) == 0 or do {
688                warn "failed.\n";
689                return 1;
690        };
691        return 0;
692}
693
694sub update {
695        my %opts;
696        my $feed_name;
697        my $perform_update=1;
698        my $failed=0;
699
700        $ENV{SCAN_COOKIE} = $$;
701        $ENV{OPENWRT_VERBOSE} = 's';
702
703        getopts('ahi', \%opts);
704
705        if ($opts{h}) {
706                usage();
707                return 0;
708        }
709
710        if ($opts{i}) {
711                # don't update from (remote) repository
712                # only re-create index information
713                $perform_update=0;
714        }
715
716        -d "feeds" or do {
717                        mkdir "feeds" or die "Unable to create the feeds directory";
718                };
719
720        if ( ($#ARGV == -1) or $opts{a}) {
721                foreach my $feed (@feeds) {
722                        my ($type, $name, $src) = @$feed;
723                        update_feed($type, $name, $src, $perform_update) == 0 or $failed=1;
724                }
725        } else {
726                while ($feed_name = shift @ARGV) {
727                        foreach my $feed (@feeds) {
728                                my ($type, $name, $src) = @$feed;
729                                if($feed_name ne $name) {
730                                        next;
731                                }
732                                update_feed($type, $name, $src, $perform_update) == 0 or $failed=1;
733                        }
734                }
735        }
736
737        refresh_config();
738
739        return $failed;
740}
741
742sub feed_config() {
743        foreach my $feed (@feeds) {
744                my $installed = (-f "feeds/$feed->[1].index");
745
746                printf "\tconfig FEED_%s\n", $feed->[1];
747                printf "\t\tbool \"Enable feed %s\"\n", $feed->[1];
748                printf "\t\tdepends on PER_FEED_REPO\n";
749                printf "\t\tdefault y\n" if $installed;
750                printf "\t\thelp\n";
751                printf "\t\t Enable the \\\"%s\\\" feed at %s.\n", $feed->[1], $feed->[2][0];
752                printf "\n";
753        }
754
755        return 0;
756}
757
758sub usage() {
759        print <<EOF;
760Usage: $0 <command> [options]
761
762Commands:
763        list [options]: List feeds, their content and revisions (if installed)
764        Options:
765            -n :            List of feed names.
766            -s :            List of feed names and their URL.
767            -r <feedname>:  List packages of specified feed.
768            -d <delimiter>: Use specified delimiter to distinguish rows (default: spaces)
769            -f :            List feeds in feeds.conf compatible format (when using -s).
770
771        install [options] <package>: Install a package
772        Options:
773            -a :           Install all packages from all feeds or from the specified feed using the -p option.
774            -p <feedname>: Prefer this feed when installing packages.
775            -d <y|m|n>:    Set default for newly installed packages.
776            -f :           Install will be forced even if the package exists in core OpenWrt (override)
777
778        search [options] <substring>: Search for a package
779        Options:
780            -r <feedname>: Only search in this feed
781
782        uninstall -a|<package>: Uninstall a package
783        Options:
784            -a :           Uninstalls all packages.
785
786        update -a|<feedname(s)>: Update packages and lists of feeds in feeds.conf .
787        Options:
788            -a :           Update all feeds listed within feeds.conf. Otherwise the specified feeds will be updated.
789            -i :           Recreate the index only. No feed update from repository is performed.
790
791        clean:             Remove downloaded/generated files.
792
793EOF
794        exit(1);
795}
796
797my %commands = (
798        'list' => \&list,
799        'update' => \&update,
800        'install' => \&install,
801        'search' => \&search,
802        'uninstall' => \&uninstall,
803        'feed_config' => \&feed_config,
804        'clean' => sub {
805                system("rm -rf ./feeds ./package/feeds");
806        }
807);
808
809my $arg = shift @ARGV;
810$arg or usage();
811parse_config;
812foreach my $cmd (keys %commands) {
813        $arg eq $cmd and do {
814                exit(&{$commands{$cmd}}());
815        };
816}
817usage();
Note: See TracBrowser for help on using the repository browser.