Follow upstream mtl and Cabal, add transformers package (#5958)
[ghc.git] / sync-all
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Cwd;
5
6 $| = 1; # autoflush stdout after each print, to avoid output after die
7
8 my $defaultrepo;
9 my @packages;
10 my $verbose = 2;
11 my $try_to_resume = 0;
12 my $ignore_failure = 0;
13 my $checked_out_flag = 0; # NOT the opposite of bare_flag (describes remote repo state)
14 my $get_mode;
15 my $bare_flag = ""; # NOT the opposite of checked_out_flag (describes local repo state)
16
17 my %tags;
18
19 # Figure out where to get the other repositories from.
20 sub getrepo {
21     my $repo;
22
23     if (defined($defaultrepo)) {
24         $repo = $defaultrepo;
25         chomp $repo;
26     } else {
27         # Figure out where to get the other repositories from,
28         # based on where this GHC repo came from.
29         my $git_dir = $bare_flag ? "--git-dir=ghc.git" : "";
30         my $branch  = `git $git_dir branch | grep "\* " | sed "s/^\* //"`; chomp $branch;
31         my $remote  = `git $git_dir config branch.$branch.remote`;         chomp $remote;
32         if ($remote eq "") {
33             # remotes are not mandatory for branches (e.g. not recorded by default for bare repos)
34             $remote = "origin";
35         }
36         $repo       = `git $git_dir config remote.$remote.url`;            chomp $repo;
37     }
38
39     my $repo_base;
40     my $checked_out_tree;
41
42     if ($repo =~ /^...*:/) {
43         # HTTP or SSH
44         # Above regex says "at least two chars before the :", to avoid
45         # catching Win32 drives ("C:\").
46         $repo_base = $repo;
47
48         # --checked-out is needed if you want to use a checked-out repo
49         # over SSH or HTTP
50         if ($checked_out_flag) {
51             $checked_out_tree = 1;
52         } else {
53             $checked_out_tree = 0;
54         }
55
56         # Don't drop the last part of the path if specified with -r, as
57         # it expects repos of the form:
58         #
59         #   http://darcs.haskell.org
60         #
61         # rather than
62         #
63         #   http://darcs.haskell.org/ghc
64         #
65         if (!$defaultrepo) {
66             $repo_base =~ s#/[^/]+/?$##;
67         }
68     }
69     elsif ($repo =~ /^\/|\.\.\/|.:(\/|\\)/) {
70         # Local filesystem, either absolute (C:/ or /) or relative (../) path
71         $repo_base = $repo;
72         if (-f "$repo/HEAD") {
73             # assume a local mirror:
74             $checked_out_tree = 0;
75             $repo_base =~ s#/[^/]+/?$##;
76         } elsif (-d "$repo/ghc.git") {
77             # assume a local mirror:
78             $checked_out_tree = 0;
79         } else {
80             # assume a checked-out tree:
81             $checked_out_tree = 1;
82         }
83     }
84     else {
85         die "Couldn't work out repo";
86     }
87
88     return $repo_base, $checked_out_tree;
89 }
90
91 sub parsePackages {
92     my @repos;
93     my $lineNum;
94
95     open IN, "< packages.conf"
96         or open IN, "< packages" # clashes with packages directory when using --bare
97         or die "Can't open packages file (or packages.conf)";
98     @repos = <IN>;
99     close IN;
100
101     @packages = ();
102     $lineNum = 0;
103     foreach (@repos) {
104         chomp;
105         $lineNum++;
106         if (/^([^# ]+) +([^ ]+) +([^ ]+) +([^ ]+)$/) {
107             my %line;
108             $line{"localpath"}  = $1;
109             $line{"tag"}        = $2;
110             $line{"remotepath"} = $3;
111             $line{"vcs"}        = $4;
112             push @packages, \%line;
113         }
114         elsif (! /^(#.*)?$/) {
115             die "Bad content on line $lineNum of packages file: $_";
116         }
117     }
118 }
119
120 sub message {
121     if ($verbose >= 2) {
122         print "@_\n";
123     }
124 }
125
126 sub warning {
127     if ($verbose >= 1) {
128         print "warning: @_\n";
129     }
130 }
131
132 sub gitNewWorkdir {
133     my $dir = shift;
134     my $target = shift;
135     my $target_dir = "$target/$dir";
136     my $pwd;
137
138     if ($dir eq '.') {
139         message "== running git-new-workdir . $target_dir @_";
140     } else {
141         message "== $dir: running git-new-workdir . $target_dir @_";
142         $pwd = getcwd();
143         chdir($dir);
144     }
145
146     system ("git-new-workdir", ".", $target_dir, @_) == 0
147         or $ignore_failure
148         or die "git-new-workdir failed: $?";
149
150     if ($dir ne '.') {
151         chdir($pwd);
152     }
153 }
154
155 sub scm {
156     my $dir = shift;
157     my $scm = shift;
158     my $pwd;
159
160     if ($dir eq '.') {
161         message "== running $scm @_";
162     } else {
163         message "== $dir: running $scm @_";
164         $pwd = getcwd();
165         chdir($dir);
166     }
167
168     system ($scm, @_) == 0
169         or $ignore_failure
170         or die "$scm failed: $?";
171
172     if ($dir ne '.') {
173         chdir($pwd);
174     }
175 }
176
177 sub scmall {
178     my $command = shift;
179
180     my $localpath;
181     my $tag;
182     my $remotepath;
183     my $scm;
184     my $line;
185     my $branch_name;
186     my $subcommand;
187
188     my $path;
189     my $wd_before = getcwd;
190
191     my $pwd;
192     my @args;
193
194     my $started;
195     my $doing;
196     my $start_repo;
197
198     my ($repo_base, $checked_out_tree) = getrepo();
199
200     my $is_github_repo = $repo_base =~ m/(git@|git:\/\/|https:\/\/)github.com/;
201
202     parsePackages;
203
204     @args = ();
205
206     if ($command =~ /^remote$/) {
207         while (@_ > 0 && $_[0] =~ /^-/) {
208             push(@args,shift);
209         }
210         if (@_ < 1) { help(1); }
211         $subcommand = shift;
212         if ($subcommand ne 'add' && $subcommand ne 'rm' && $subcommand ne 'set-url') {
213             help(1);
214         }
215         while (@_ > 0 && $_[0] =~ /^-/) {
216             push(@args,shift);
217         }
218         if (($subcommand eq 'add' || $subcommand eq 'rm') && @_ < 1) {
219             help(1);
220         } elsif (@_ < 1) { # set-url
221             $branch_name = 'origin';
222         } else {
223             $branch_name = shift;
224         }
225     } elsif ($command eq 'new') {
226         if (@_ < 1) {
227             $branch_name = 'origin';
228         } else {
229             $branch_name = shift;
230         }
231     }
232
233     push(@args, @_);
234
235     # $doing is a good enough approximation to what we are doing that
236     # we can use it to check that --resume is resuming the right command
237     $doing = join(" ", ($command, @args));
238     $started = 1;
239     if ($try_to_resume && -f "resume") {
240         my $what;
241         open RESUME, "< resume"
242             or die "Can't open resume file";
243         $start_repo = <RESUME>;
244         chomp $start_repo;
245         $what = <RESUME>;
246         chomp $what;
247         close RESUME;
248         if ($what eq $doing) {
249             $started = 0;
250         }
251     }
252
253     for $line (@packages) {
254         $tag        = $$line{"tag"};
255         $scm        = $$line{"vcs"};
256         # Use the "remote" structure for bare git repositories
257         $localpath  = ($bare_flag && $scm eq "git") ?
258                       $$line{"remotepath"} : $$line{"localpath"};
259         $remotepath = ($checked_out_tree) ?
260                       $$line{"localpath"}  : $$line{"remotepath"};
261
262         if (!$started) {
263             if ($start_repo eq $localpath) {
264                 $started = 1;
265             }
266             else {
267                 next;
268             }
269         }
270
271         open RESUME, "> resume.tmp";
272         print RESUME "$localpath\n";
273         print RESUME "$doing\n";
274         close RESUME;
275         rename "resume.tmp", "resume";
276
277         # Check the SCM is OK as early as possible
278         die "Unknown SCM: $scm" if (($scm ne "darcs") and ($scm ne "git"));
279
280         # We can't create directories on GitHub, so we translate
281         # "packages/foo" into "package-foo".
282         if ($is_github_repo) {
283             $remotepath =~ s/\//-/;
284         }
285
286         # Construct the path for this package in the repo we pulled from
287         $path = "$repo_base/$remotepath";
288
289         if ($command =~ /^(?:g|ge|get)$/) {
290             # Skip any repositories we have not included the tag for
291             if (not defined($tags{$tag})) {
292                 $tags{$tag} = 0;
293             }
294             if ($tags{$tag} == 0) {
295                 next;
296             }
297
298             if (-d $localpath) {
299                 warning("$localpath already present; omitting")
300                     if $localpath ne ".";
301                 if ($scm eq "git") {
302                     scm ($localpath, $scm, "config", "core.ignorecase", "true");
303                 }
304                 next;
305             }
306
307             # Note that we use "." as the path, as $localpath
308             # doesn't exist yet.
309             if ($scm eq "darcs") {
310                 # The first time round the loop, default the get-mode
311                 if (not defined($get_mode)) {
312                     warning("adding --partial, to override use --complete");
313                     $get_mode = "--partial";
314                 }
315                 scm (".", $scm, "get", $get_mode, $path, $localpath, @args);
316             }
317             else {
318                 my @argsWithBare = @args;
319                 push @argsWithBare, $bare_flag if $bare_flag;
320                 scm (".", $scm, "clone", $path, $localpath, @argsWithBare);
321                 scm ($localpath, $scm, "config", "core.ignorecase", "true");
322             }
323             next;
324         }
325
326         my $darcs_repo_present = 1 if -d "$localpath/_darcs";
327         my $git_repo_present = 1 if -d "$localpath/.git" || ($bare_flag && -d "$localpath");
328         if ($darcs_repo_present) {
329             if ($git_repo_present) {
330                 die "Found both _darcs and .git in $localpath";
331             }
332             $scm = "darcs";
333         } elsif ($git_repo_present) {
334             $scm = "git";
335         } elsif ($tag eq "") {
336             die "Required repo $localpath is missing";
337         } else {
338              message "== $localpath repo not present; skipping";
339              next;
340         }
341
342         # Work out the arguments we should give to the SCM
343         if ($command =~ /^(?:w|wh|wha|what|whats|whatsn|whatsne|whatsnew|status)$/) {
344             if ($scm eq "darcs") {
345                 $command = "whatsnew";
346             }
347             elsif ($scm eq "git") {
348                 $command = "status";
349             }
350             else {
351                 die "Unknown scm";
352             }
353
354             # Hack around 'darcs whatsnew' failing if there are no changes
355             $ignore_failure = 1;
356             scm ($localpath, $scm, $command, @args);
357         }
358         elsif ($command =~ /^commit$/) {
359             # git fails if there is nothing to commit, so ignore failures
360             $ignore_failure = 1;
361             scm ($localpath, $scm, "commit", @args);
362         }
363         elsif ($command =~ /^(?:pus|push)$/) {
364             scm ($localpath, $scm, "push", @args);
365         }
366         elsif ($command =~ /^(?:pul|pull)$/) {
367             scm ($localpath, $scm, "pull", @args);
368         }
369         elsif ($command =~ /^(?:new-workdir)$/) {
370             gitNewWorkdir ($localpath, @args);
371         }
372         elsif ($command =~ /^(?:s|se|sen|send)$/) {
373             if ($scm eq "darcs") {
374                 $command = "send";
375             }
376             elsif ($scm eq "git") {
377                 $command = "send-email";
378             }
379             else {
380                 die "Unknown scm";
381             }
382             scm ($localpath, $scm, $command, @args);
383         }
384         elsif ($command =~ /^fetch$/) {
385             scm ($localpath, $scm, "fetch", @args);
386         }
387         elsif ($command =~ /^new$/) {
388             my @scm_args = ("log", "$branch_name..");
389             scm ($localpath, $scm, @scm_args, @args);
390         }
391         elsif ($command =~ /^log$/) {
392             scm ($localpath, $scm, "log", @args);
393         }
394         elsif ($command =~ /^remote$/) {
395             my @scm_args;
396             $ignore_failure = 1;
397             if ($subcommand eq 'add') {
398                 @scm_args = ("remote", "add", $branch_name, $path);
399             } elsif ($subcommand eq 'rm') {
400                 @scm_args = ("remote", "rm", $branch_name);
401             } elsif ($subcommand eq 'set-url') {
402                 @scm_args = ("remote", "set-url", $branch_name, $path);
403             }
404             scm ($localpath, $scm, @scm_args, @args);
405         }
406         elsif ($command =~ /^checkout$/) {
407             # Not all repos are necessarily branched, so ignore failure
408             $ignore_failure = 1;
409             scm ($localpath, $scm, "checkout", @args)
410                 unless $scm eq "darcs";
411         }
412         elsif ($command =~ /^grep$/) {
413             # Hack around 'git grep' failing if there are no matches
414             $ignore_failure = 1;
415             scm ($localpath, $scm, "grep", @args)
416                 unless $scm eq "darcs";
417         }
418         elsif ($command =~ /^diff$/) {
419             scm ($localpath, $scm, "diff", @args)
420                 unless $scm eq "darcs";
421         }
422         elsif ($command =~ /^clean$/) {
423             scm ($localpath, $scm, "clean", @args)
424                 unless $scm eq "darcs";
425         }
426         elsif ($command =~ /^reset$/) {
427             scm ($localpath, $scm, "reset", @args)
428                 unless $scm eq "darcs";
429         }
430         elsif ($command =~ /^branch$/) {
431             scm ($localpath, $scm, "branch", @args)
432                 unless $scm eq "darcs";
433         }
434         elsif ($command =~ /^config$/) {
435             scm ($localpath, $scm, "config", @args)
436                 unless $scm eq "darcs";
437         }
438         elsif ($command =~ /^repack$/) {
439             scm ($localpath, $scm, "repack", @args)
440                 if $scm eq "git"
441         }
442         elsif ($command =~ /^format-patch$/) {
443             scm ($localpath, $scm, "format-patch", @args)
444                 if $scm eq "git"
445         }
446         elsif ($command =~ /^gc$/) {
447             scm ($localpath, $scm, "gc", @args)
448                 unless $scm eq "darcs";
449         }
450         elsif ($command =~ /^tag$/) {
451             scm ($localpath, $scm, "tag", @args);
452         }
453         else {
454             die "Unknown command: $command";
455         }
456     }
457
458     unlink "resume";
459 }
460
461 sub help
462 {
463         my $exit = shift;
464
465         # Get the built in help
466         my $help = <<END;
467 Usage:
468
469 ./sync-all [-q] [-s] [--ignore-failure] [-r repo] [--checked-out] [--bare]
470            [--nofib] [--extra] [--testsuite] [--no-dph] [--resume]
471            cmd [git flags]
472
473 Applies the command "cmd" to each repository in the tree.
474
475 A full repository tree is obtained by first cloning the ghc
476 repository, then getting the subrepositories with "sync-all get":
477
478   \$ git clone http://darcs.haskell.org/ghc.git
479   \$ cd ghc
480   \$ ./sync-all get
481
482 After this, "./sync-all pull" will pull from the original repository
483 tree.
484
485 A remote pointing to another local repository tree can be added like
486 this:
487
488   \$ ./sync-all -r /path/to/ghc remote add otherlocal
489
490 and then we can pull from this other tree with
491
492   \$ ./sync-all pull otherlocal
493
494 -------------- Commands -----------------
495 get
496
497     Clones all sub-repositories from the same place that the ghc
498     repository was cloned from. See "which repos to use" below
499     for details of how the subrepositories are laid out.
500
501     There are various --<package-tag> options that can be given
502     before "get" that enable extra repositories. The full list is
503     given at the end of this help. For example:
504
505     ./sync-all --testsuite get
506
507     would get the testsuite repository in addition to the usual set of
508     subrepositories.
509
510 remote add <remote-name>
511 remote rm <remote-name>
512 remote set-url [--push] <remote-name>
513
514     Runs a "git remote" command on each subrepository, adjusting the
515     repository location in each case appropriately. For example, to
516     add a new remote pointing to the upstream repositories:
517
518     ./sync-all -r http://darcs.haskell.org/ remote add upstream
519
520     The -r flag points to the root of the repository tree (see "which
521     repos to use" below). For a repository on the local filesystem it
522     would point to the ghc repository, and for a remote repository it
523     points to the directory containing "ghc.git".
524
525 These commands just run the equivalent git command on each repository, passing
526 any extra arguments to git:
527
528   branch
529   checkout
530   clean
531   commit
532   config
533   diff
534   fetch
535   format-patch
536   gc
537   grep
538   log
539   new
540   new-workdir
541   pull
542   push
543   repack
544   reset
545   send
546   status
547   tag
548
549 -------------- Flags -------------------
550 These flags are given *before* the command and modify the way sync-all behaves.
551 Flags given *after* the command are passed to git.
552
553   -q says to be quiet, and -s to be silent.
554
555   --resume will restart a command that failed, from the repo at which it
556   failed. This means you don't need to wait while, e.g., "pull" goes through
557   all the repos it's just pulled, and tries to pull them again.
558
559   --ignore-failure says to ignore errors and move on to the next repository
560
561   -r repo says to use repo as the location of package repositories
562
563   --checked-out says that the remote repo is in checked-out layout, as opposed
564   to the layout used for the main repo. By default a repo on the local
565   filesystem is assumed to be checked-out, and repos accessed via HTTP or SSH
566   are assumed to be in the main repo layout; use --checked-out to override the
567   latter.
568
569   --bare says that the local repo is in bare layout, same as the main repo. It
570   also means that these repos are bare. You only have to use this flag if you
571   don't have a bare ghc.git in the current directory and would like to 'get'
572   all of the repos bare. Requires packages.conf to be present in the current
573   directory (a renamed packages file from the main ghc repo).
574
575   Note: --checked-out and --bare flags are NOT the opposite of each other.
576         --checked-out: describes the layout of the remote repository tree.
577         --bare:        describes the layout of the local repository tree.
578
579   --nofib also clones the nofib benchmark suite
580
581   --testsuite also clones the ghc testsuite 
582
583   --extra also clone some extra library packages
584
585   --no-dph avoids cloning the dph pacakges
586
587
588 ------------ Checking out a branch -------------
589 To check out a branch you can run the following command:
590
591   \$ ./sync-all checkout ghc-7.4
592
593
594 ------------ Which repos to use -------------
595 sync-all uses the following algorithm to decide which remote repos to use
596
597 It always computes the remote repos from a single base, <repo_base> How is
598 <repo_base> set? If you say "-r repo", then that's <repo_base> otherwise
599 <repo_base> is set by asking git where the ghc repo came from, and removing the
600 last component (e.g. /ghc.git/ or /ghc/).
601
602 Then sync-all iterates over the package found in the file ./packages; see that
603 file for a description of the contents.
604
605 If <repo_base> looks like a local filesystem path, or if you give the
606 --checked-out flag, sync-all works on repos of form:
607
608   <repo_base>/<local-path>
609
610 otherwise sync-all works on repos of form:
611
612   <repo_base>/<remote-path>
613
614 This logic lets you say
615   both    sync-all -r http://darcs.haskell.org/ghc-6.12 remote add ghc-6.12
616   and     sync-all -r ../working remote add working
617 The latter is called a "checked-out tree".
618
619 sync-all *ignores* the defaultrepo of all repos other than the root one. So the
620 remote repos must be laid out in one of the two formats given by <local-path>
621 and <remote-path> in the file 'packages'.
622
623 Available package-tags are:
624 END
625
626         # Collect all the tags in the packages file
627         my %available_tags;
628         open IN, "< packages.conf"
629             or open IN, "< packages" # clashes with packages directory when using --bare
630             or die "Can't open packages file (or packages.conf)";
631         while (<IN>) {
632             chomp;
633             if (/^([^# ]+) +(?:([^ ]+) +)?([^ ]+) +([^ ]+)/) {
634                 if (defined($2) && $2 ne "-") {
635                     $available_tags{$2} = 1;
636                 }
637             }
638             elsif (! /^(#.*)?$/) {
639                 die "Bad line: $_";
640             }
641         }
642         close IN;
643
644         # Show those tags and the help text
645         my @available_tags = keys %available_tags;
646         print "$help@available_tags\n\n";
647         exit $exit;
648 }
649
650 sub main {
651
652     $tags{"-"} = 1;
653     $tags{"dph"} = 1;
654
655     while ($#_ ne -1) {
656         my $arg = shift;
657         # We handle -q here as well as lower down as we need to skip over it
658         # if it comes before the source-control command
659         if ($arg eq "-q") {
660             $verbose = 1;
661         }
662         elsif ($arg eq "-s") {
663             $verbose = 0;
664         }
665         elsif ($arg eq "-r") {
666             $defaultrepo = shift;
667         }
668         elsif ($arg eq "--resume") {
669             $try_to_resume = 1;
670         }
671         elsif ($arg eq "--ignore-failure") {
672             $ignore_failure = 1;
673         }
674         elsif ($arg eq "--complete" || $arg eq "--partial") {
675             $get_mode = $arg;
676         }
677         # Use --checked-out if the _remote_ repos are a checked-out tree,
678         # rather than the master trees.
679         elsif ($arg eq "--checked-out") {
680             $checked_out_flag = 1;
681         }
682         # Use --bare if the _local_ repos are bare repos,
683         # rather than a checked-out tree.
684         elsif ($arg eq "--bare") {
685             $bare_flag = $arg;
686         }
687         elsif ($arg eq "--help") {
688             help(0);
689         }
690         # --<tag> says we grab the libs tagged 'tag' with
691         # 'get'. It has no effect on the other commands.
692         elsif ($arg =~ m/^--no-(.*)$/) {
693             $tags{$1} = 0;
694         }
695         elsif ($arg =~ m/^--(.*)$/) {
696             $tags{$1} = 1;
697         }
698         else {
699             unshift @_, $arg;
700             if (grep /^-q$/, @_) {
701                 $verbose = 1;
702             }
703             last;
704         }
705     }
706
707     # check for ghc repositories in cwd
708     my $checked_out_found = 1 if (-d ".git" && -d "compiler");
709     my $bare_found = 1 if (-d "ghc.git");
710
711     if ($bare_flag && ! $bare_found && ! $defaultrepo) {
712         die "error: bare repository ghc.git not found.\n"
713           . "       Either clone a bare ghc repo first or specify the repo location. E.g.:\n"
714           . "       ./sync-all --bare [--testsuite --nofib --extra] -r http://darcs.haskell.org/ get\n"
715     }
716     elsif ($bare_found) {
717         $bare_flag = "--bare";
718     }
719     elsif (! $bare_flag && ! $checked_out_found) {
720         die "error: sync-all must be run from the top level of the ghc tree.";
721     }
722
723     if ($#_ eq -1) {
724         help(1);
725     }
726     else {
727         # Give the command and rest of the arguments to the main loop
728         scmall @_;
729     }
730 }
731
732 END {
733     my $ec = $?;
734     my $pwd = getcwd();
735
736     message "== Checking for old haddock repo";
737     if (-d "utils/haddock/.git") {
738         chdir("utils/haddock");
739         if ((system "git log -1 87e2ca11c3d1b1bc49900fba0b5c5c6f85650718 > /dev/null 2> /dev/null") == 0) {
740             print <<EOF;
741 ============================
742 ATTENTION!
743
744 You have an old haddock repository in your GHC tree!
745
746 Please remove it (e.g. "rm -r utils/haddock"), and then run
747 "./sync-all get" to get the new repository.
748 ============================
749 EOF
750         }
751         chdir($pwd);
752     }
753
754     message "== Checking for old binary repo";
755     if (-d "libraries/binary/.git") {
756         chdir("libraries/binary");
757         if ((system "git log -1 749ac0efbde3b14901417364a872796598747aaf > /dev/null 2> /dev/null") == 0) {
758             print <<EOF;
759 ============================
760 ATTENTION!
761
762 You have an old binary repository in your GHC tree!
763
764 Please remove it (e.g. "rm -r libraries/binary"), and then run
765 "./sync-all get" to get the new repository.
766 ============================
767 EOF
768         }
769         chdir($pwd);
770     }
771
772     message "== Checking for old mtl repo";
773     if (-d "libraries/mtl/.git") {
774         chdir("libraries/mtl");
775         if ((system "git log -1 c67d8f7247c612dc35242bc67e616f7ea35eadb9 > /dev/null 2> /dev/null") == 0) {
776             print <<EOF;
777 ============================
778 ATTENTION!
779
780 You have an old mtl repository in your GHC tree!
781
782 Please remove it (e.g. "rm -r libraries/mtl"), and then run
783 "./sync-all get" to get the new repository.
784 ============================
785 EOF
786         }
787         chdir($pwd);
788     }
789
790     message "== Checking for old Cabal repo";
791     if (-d "libraries/Cabal/.git") {
792         chdir("libraries/Cabal");
793         if ((system "git log -1 c8ebd66a32865f72ae03ee0663c62df3d77f08fe > /dev/null 2> /dev/null") == 0) {
794             print <<EOF;
795 ============================
796 ATTENTION!
797
798 You have an old Cabal repository in your GHC tree!
799
800 Please remove it (e.g. "rm -r libraries/Cabal"), and then run
801 "./sync-all get" to get the new repository.
802 ============================
803 EOF
804         }
805         chdir($pwd);
806     }
807
808     $? = $ec;
809 }
810
811 main(@ARGV);
812