]> rtime.felk.cvut.cz Git - l4.git/blob - repomgr
fiasco: drivers-frst: Get this code back to default state. Port interference problem...
[l4.git] / repomgr
1 #! /usr/bin/perl -W
2
3 use strict;
4
5 my %modules =
6  (
7    repomgr => { paths => [ qw(repomgr) ] },
8
9    bid => { paths => [ qw(l4/Makefile
10                           l4/BENCHMARKING
11                           l4/COPYING-GPL-2
12                           l4/COPYING-LGPL-2.1
13                           l4/LICENSING
14                           l4/mk
15                           l4/conf
16                           l4/pkg/Makefile
17                           l4/pkg/README
18                           l4/tool/Makefile
19                           l4/tool/gendep
20                           l4/tool/kconfig
21                           l4/tool/vim
22                           l4/tool/lib
23                           l4/tool/elf-patcher
24                           l4/tool/gen_dopecode
25                          ) ]
26           },
27
28    toolbin => { paths => [ map { "l4/tool/bin/$_" }
29                            qw(isocreator qemu-x86-launch ux-launch
30                               gengrub1iso gengrub2iso entry-selector
31                               mkspafs genexportpack gen_kconfig
32                              ) ]
33               },
34
35    l4re => { paths => [ map { "l4/pkg/$_" } qw(
36                          bootstrap l4re-core/libgcc
37                          l4re-core/libgcc-pure
38                          l4re-core/crtn l4re-core/cxx l4re-core/cxx_libc_io
39                          l4re-core/ldscripts
40                          l4re-core/l4re/ l4re-core/l4re_c/
41                          l4re-core/l4re_kernel/ l4re-core/l4re_vfs/
42                          l4re-core/l4sys/ l4re-core/l4util/
43                          l4re-core/ldso/
44                          l4re-core/libc_backends l4re-core/libkproxy/
45                          l4re-core/libloader/
46                          l4re-core/libsigma0/
47                          l4re-core/libstdc++-headers/ l4re-core/libstdc++-v3/
48                          l4re-core/libstdc++-v3-minimal
49                          l4re-core/libsupc++ l4re-core/libsupc++-minimal
50                          l4re-core/prj-config
51                          l4re-core/moe l4re-core/ned/ l4re-core/sigma0/
52                          l4re-core/uclibc l4re-core/uclibc-minimal/
53                          l4re-core/uclibc-headers/
54                          l4re-core/lua/
55                          io
56                          cxx_thread drivers-frst hello
57                          acpica libvcpu loader log
58                         ) ],
59              pub_module => 1,
60              modules => [ qw(bid toolbin) ],
61            },
62
63
64    # ./mk/pkgdeps -A mk/aliases.d pkgdeps pkg ...
65    l4linux_requirements
66         => { paths => [ map { "l4/pkg/$_" } qw(
67                         libedid lxfuxlibc rtc shmc
68                         drivers fb-drv x86emu input libirq
69                         ) ],
70                     pub_module => 1,
71                     modules => [ qw(l4re) ],
72                   },
73
74    examples_core => {
75      paths => [ qw(l4/pkg/hello),
76                 map { "l4/pkg/examples/$_" }
77                 qw(Makefile
78                    Control
79                    sys
80                    clntsrv
81                    misc/Makefile
82                    misc/cat
83                    misc/shared-hello
84                    libs/Makefile
85                    libs/l4re
86                  ) ],
87    },
88
89
90    examples_all => {
91      modules => [ qw(examples_core) ],
92      paths => [ qw(l4/pkg/hello),
93                 map { "l4/pkg/examples/$_" }
94                 qw(
95                    fb/Makefile
96                    fb/spectrum
97                    misc/eb_leds
98                    misc/fortran-hello
99                    misc/reboot
100                    libs/inputtst
101                    libs/libc_thread_safe
102                    libs/libgomp
103                    libs/libio
104                    libs/libirq
105                    libs/libpng
106                    libs/rtc
107                    libs/shmc
108                  ) ],
109    },
110
111    doc => { paths => [ qw(l4/doc/Makefile l4/doc/source) ], },
112
113    l4re_snapshot =>  {
114      paths => [ map { "l4/pkg/$_" }
115                 qw(ankh
116                    boost-lite
117                    cons
118                    cunit
119                    dash
120                    demangle
121                    dde
122                    dde-libinput
123                    dope
124                    drivers
125                    expat2
126                    fb-drv
127                    fbterminal
128                    ferret
129                    fuxfprov
130                    gnu-efi
131                    hello
132                    input
133                    l4con
134                    l4virtio
135                    lib_vt100
136                    libbsd
137                    libedid
138                    libevent
139                    libc_be_stdin
140                    libcrypto
141                    libevent
142                    libgfxbitmap
143                    libgfortran
144                    libgomp
145                    libfdt
146                    libiniparser
147                    libirq
148                    libjpeg
149                    libpng
150                    libsdl
151                    libsdl-image
152                    libquadmath
153                    linux-26-headers
154                    lwip
155                    lxfuxlibc
156                    mag
157                    mag-gfx
158                    ocaml
159                    plr
160                    python
161                    readline
162                    rtc
163                    scout
164                    scout-gfx
165                    serial-drv
166                    shmc
167                    slab
168                    spafs
169                    sqlite
170                    tlsf
171                    tmpfs
172                    udis86
173                    valgrind
174                    vmm
175                    x86emu
176                    zlib
177                    ) ],
178      modules => [ qw(l4re examples_all doc toolbin) ] },
179
180    l4re_all => { paths   => [ qw(l4/pkg l4/tool) ],
181                  modules => [ qw(l4re_snapshot) ] },
182
183    fiasco => {
184       pub_module => 1,
185       paths   => [ qw(kernel/fiasco/BENCHMARKING
186                       kernel/fiasco/COPYING
187                       kernel/fiasco/MAINTAINER
188                       kernel/fiasco/Makefile
189                       kernel/fiasco/README
190                       kernel/fiasco/src
191                       kernel/fiasco/tool
192                      ) ],
193    },
194
195    kernel => {
196       paths => [ qw(kernel/Makefile) ],
197    },
198
199    grub => {
200       paths => [ qw(grub) ],
201    },
202
203    remote_repo_l4re => {
204       modules => [ qw(l4re_snapshot) ],
205    },
206
207    remote_repo => { modules => [ qw(fiasco remote_repo_l4re) ] },
208
209    all => {
210       modules => [ qw(remote_repo) ],
211    },
212
213
214    # those are going away, we need to keep them to get the
215    # dirs updated and thus removed
216    __prev => {
217      paths => [ map { "l4/pkg/$_" }
218                 qw(ferret io libio libio-io libio-direct ocaml_toys
219                    libstdc++-v3_r libsupc++_r uclibc_r
220                    
221                    boehm_gc libgcc libgcc-pure libbsd-full
222                    crtn cxx cxx_libc_io cxx_thread
223                    ldscripts
224                    l4re/ l4re_c l4re_kernel l4re_vfs l4sys l4util
225                    ldscripts ldso
226                    libc_backends libkproxy libloader
227                    libsigma0
228                    libstdc++-headers libstdc++-v3 libstdc++-v3-minimal
229                    libsupc++ libsupc++-minimal
230                    libvbus lua moe ned sigma0
231                    uclibc uclibc-minimal uclibc-headers
232                  
233                  ) ],
234    },
235  );
236
237 my %commands;
238 my $svnrev = $ENV{REPOMGR_SVN_REV} || 'HEAD';
239
240 sub get_root_url()
241 {
242   my $o = `svn info -r '$svnrev' --xml .`;
243   die "Failed 'svn info'." if $?;
244   $o =~ /<root>(.+)<\/root>/m;
245   $1;
246 }
247
248 sub merge_modules
249 {
250   my %paths;
251
252   sub do_merge
253   {
254     my $pathsref = shift;
255     my $count = shift;
256
257     die "Possible looping in modules structure detected!" unless $count;
258
259     foreach my $m (@_)
260       {
261         die "Unknown module '$m' referenced!" unless defined $modules{$m};
262         $$pathsref{$_} = 1 foreach @{$modules{$m}{paths}};
263         do_merge($pathsref, $count - 1, @{$modules{$m}{modules}});
264       }
265   }
266
267   do_merge(\%paths, 20, scalar @_ ? @_ : 'all');
268
269   sort keys %paths;
270 }
271
272 sub show_pub_modules()
273 {
274   print "Available modules:\n";
275   foreach (sort keys %modules)
276     {
277        print "  $_\n" if $modules{$_}{pub_module};
278     }
279 }
280
281 sub usage
282 {
283   my $command = shift;
284
285   # check alias
286   $command = $commands{$command}{alias}
287     if defined $command and defined $commands{$command}{alias};
288
289   if (!defined $command or $command eq 'help')
290     {
291       print "$0 command [option]\n";
292
293       print "Available commands, use '$0 help command' for help on the command:\n";
294       foreach (sort keys %commands)
295         {
296           print "  $_\n" if defined $commands{$_}{public};
297         }
298     }
299   elsif ($command eq 'update')
300     {
301       print "  'update' will update in the following way:\n".
302             "      update itself and re-exec if necessary\n".
303             "      call 'make update' in l4/pkg\n".
304             "      call 'svn update' every directory in kernel\n";
305     }
306   elsif ($command eq 'checkout')
307     {
308       print "  'checkout' will check out the given modules.\n";
309       show_pub_modules();
310     }
311   elsif ($command eq 'modules')
312     {
313       show_pub_modules();
314     }
315   else
316     {
317       print "  No such command '$command'.\n";
318     }
319 }
320
321 sub check_module_structure()
322 {
323   # make sure the paths look ok
324   foreach (merge_modules())
325     {
326       #die "Trailing /'s in modules structure" if /\/$/;
327       die "Double // detected in modules structure" if /\/\//;
328     }
329 }
330
331 sub command_help
332 {
333   usage(@_);
334 }
335
336 sub command_update
337 {
338   print "XXX: todo\n";
339 }
340
341 sub command_root
342 {
343   my $url = shift;
344   my $dirname = shift;
345   die "Need to give URL" unless defined $url and defined $dirname;
346   system("svn co -r '$svnrev' $url --depth empty $dirname");
347 }
348
349 sub init_config($)
350 {
351   my $config_blob = shift;
352   $config_blob = '{}' unless defined $config_blob;
353   my $c;
354   unless ($c = eval($config_blob))
355     {
356       die "Couldn't parse config file: $@" if $@;
357       die "Couldn't do config file: $!" if $!;
358       die "Couldn't run config file";
359     }
360
361   my %a = %$c;
362
363   $a{base} = "trunk" unless defined $a{base};
364
365   return %a;
366 }
367
368 sub convert_path($$%)
369 {
370   my $p = shift;
371   my $partmatch = shift;
372   my %path_roots = @_;
373
374   $p =~ s/^\.\///;
375   $p .= '/';
376   foreach my $key (keys %path_roots)
377     {
378       my $r = $key;
379       $r .= '/' unless $r =~ /\/$/;
380       if ($partmatch)
381         {
382           # for partly matches we also need to return the modified path
383           # because otherwise we can't really know
384           if ($p =~ /^($r)(.*)$/)
385             {
386                my $s = $path_roots{$key}.'/'.$2;
387                # strip off last / again, it's just used for matching
388                return substr($s, 0, length($s) - 1);
389             }
390         }
391       else
392         {
393           return $path_roots{$key} if $p =~ /^$r$/;
394         }
395     }
396   undef;
397 }
398
399 sub do_checkout(%)
400 {
401   my %args = @_;
402   unless (defined ${$args{mods}}[0])
403     {
404       print "Supply module to check out.\n";
405       usage("checkout");
406       exit 1;
407     }
408
409   die "Current directory is no SVN WC" unless -d ".svn";
410
411   my $root_url = get_root_url();
412
413   my @paths = merge_modules(@{$args{mods}});
414
415   foreach my $paths (@paths)
416     {
417       my @path_elems = split /\/+/, $paths;
418       my $last_elem = pop @path_elems;
419       my $path = '.';
420
421       foreach my $pe (@path_elems)
422         {
423           if (! -d "$path/$pe")
424             {
425               # if we find something from path_roots then switch to that
426               my $changed_path = convert_path("$path/$pe", 0,
427                                               %{$args{conf}{path_roots}});
428
429               print "Creating $path/$pe\n";
430               print "   from $changed_path\n" if defined $changed_path;
431
432               # there's some other little problem with the 'depth' thing
433               # when we do checkout some specific list of files (and dirs),
434               # we need to use depth=empty so that we only get those
435               # specific files out of the directory, on the other side we'd
436               # (probably) like to have updates on the directory contents
437               # when we do 'svn up' which would would with depth=files (or
438               # infinite)
439               # As the first thing is merely only needed when doing a
440               # checkout for another repo... let's have a config option.
441               my $depth = 'files';
442               $depth = 'empty' if defined $ENV{REPOMGR_EXACT_CHECKOUT};
443
444               if (defined $changed_path)
445                   {
446                     my $cmd = "cd $path && svn co -r '$svnrev' --depth empty $root_url/$changed_path $pe";
447                     #print "cmd: $cmd\n";
448                     system($cmd);
449                     die "svn co failed" if $?;
450                   }
451                 else
452                   {
453                     my $cmd = "cd $path && svn update -q -r '$svnrev' --depth empty $pe";
454                     #print "cmd: $cmd\n";
455                     system($cmd);
456                     die "svn update failed" if $?;
457                   }
458             }
459           $path .= '/'.$pe;
460         }
461     }
462
463   print "Getting sources\n";
464   my $c = "svn update -r '$svnrev' --set-depth infinity ".join(' ', map { s/^\/+//; $_; } @paths);
465   #print "cmd: $c\n";
466   system($c);
467   die "svn update failed" if $?;
468 }
469
470 sub read_file($)
471 {
472   my $fn = shift;
473   return undef unless defined $fn;
474   my $blob;
475   if ($fn =~ /^(file|svn|ssh\+svn):\/\//)
476     {
477       $blob = `svn -r '$svnrev' cat $fn`;
478       undef $blob if $?;
479     }
480   elsif (open(A, $fn))
481     {
482       local undef $/;
483       $blob = <A>;
484       close A;
485     }
486   $blob;
487 }
488
489 sub command_checkout
490 {
491   my %conf = init_config(read_file("l4/conf/repomgr.conf"));
492   do_checkout(conf => { %conf }, mods => [ @_ ]);
493 }
494
495 sub fix_repomgr_path(%)
496 {
497   my %conf = @_;
498   # fix the path to the repomgr...
499   @{$modules{repomgr}{paths}} = map { "$conf{repomgr_prefix}/$_" } @{$modules{repomgr}{paths}}
500     if defined $conf{repomgr_prefix};
501 }
502
503 sub command_init
504 {
505   my $repo_root = shift;
506   my $repo_conf = '';
507   my $localdir  = 'src';
508
509   while (defined $_[0] && ($_[0] eq '-c' or $_[0] eq '-l'))
510     {
511       if ($_[0] eq '-c')
512         {
513           $repo_conf = $_[1];
514           shift; shift;
515         }
516       elsif ($_[0] eq '-l')
517         {
518           $localdir = $_[1];
519           shift; shift;
520         }
521     }
522
523   die "Usage: $0 init <REPOROOTURL> [-c <REPOCONFPATH>] [-l <LOCALDIR>] modules..."
524     if    not defined $repo_root or not defined $repo_conf
525        or not defined $localdir;
526
527   # for absolute path we assume a local config file, good for testing
528   my $confblob;
529   if ($repo_conf ne '')
530     {
531       if ($repo_conf =~ /^\//)
532         {
533           $confblob = read_file($repo_conf);
534           die "Cannot open '$repo_conf': $!" unless defined $confblob;
535         }
536       else
537         {
538           my $cmd = "svn cat -r '$svnrev' $repo_root\/$repo_conf";
539           $confblob = `$cmd`;
540           die "Command '$cmd' failed" if $?;
541         }
542     }
543
544   my %conf = init_config($confblob);
545
546   ($localdir = $conf{base}) =~ s/.*\/// unless defined $localdir;
547   print "localdir: $localdir\n";
548
549   my $cmd = "svn co -r '$svnrev' --depth empty $repo_root/$conf{base} $localdir";
550   system($cmd);
551   die "Command '$cmd' failed" if $?;
552   chdir $localdir;
553
554   fix_repomgr_path(%conf);
555   do_checkout(conf => { %conf }, mods => [ "repomgr", @_ ]);
556 }
557
558 sub command_modules
559 {
560   foreach (sort keys %modules)
561     {
562       print "$_\n" if defined $modules{$_}{pub_module};
563     }
564 }
565
566 sub command_list
567 {
568   print "$_\n" foreach merge_modules(@_);
569 }
570
571 sub command_listmapped
572 {
573   my $blob = read_file(shift);
574   die "Need config" unless defined $blob;
575   my %conf = init_config($blob);
576   fix_repomgr_path(%conf);
577   print join("\n", map {
578                          my $p = convert_path($_, 1, %{$conf{path_roots}});
579                          defined $p ? $p : $_;
580                        } merge_modules(@_));
581   print "\n";
582 }
583
584 %commands =
585  (
586    help      => { func => \&command_help, },
587    init      => { func => \&command_init, },
588    update    => { func => \&command_update, },
589    up        => { func => \&command_update, alias => 'update' },
590    checkout  => { func => \&command_checkout, public => 1},
591    co        => { func => \&command_checkout, alias => 'checkout'},
592    modules   => { func => \&command_modules, public => 1},
593    list      => { func => \&command_list, },
594    listmapped=> { func => \&command_listmapped, },
595    root      => { func => \&command_root, },
596  );
597
598 # ----------------------------------------------------------------
599
600 check_module_structure();
601
602 my $command = shift;
603
604 unless (defined $command)
605   {
606     usage();
607     exit 1;
608   }
609
610 if (defined $commands{$command})
611   {
612     &{$commands{$command}{func}}(@ARGV);
613   }
614 else
615   {
616     print "Unknown command '$command'.\n";
617     usage();
618     exit 1;
619   }