Add a new traceMarker# primop for use in profiling output
[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' &&
213             $subcommand ne 'rm' &&
214             $subcommand ne 'set-branches' &&
215             $subcommand ne 'set-url') {
216             help(1);
217         }
218         while (@_ > 0 && $_[0] =~ /^-/) {
219             push(@args,shift);
220         }
221         if (($subcommand eq 'add' || $subcommand eq 'rm') && @_ < 1) {
222             help(1);
223         } elsif (@_ < 1) { # set-url
224             $branch_name = 'origin';
225         } else {
226             $branch_name = shift;
227         }
228     } elsif ($command eq 'new') {
229         if (@_ < 1) {
230             $branch_name = 'origin';
231         } else {
232             $branch_name = shift;
233         }
234     }
235
236     push(@args, @_);
237
238     # $doing is a good enough approximation to what we are doing that
239     # we can use it to check that --resume is resuming the right command
240     $doing = join(" ", ($command, @args));
241     $started = 1;
242     if ($try_to_resume && -f "resume") {
243         my $what;
244         open RESUME, "< resume"
245             or die "Can't open resume file";
246         $start_repo = <RESUME>;
247         chomp $start_repo;
248         $what = <RESUME>;
249         chomp $what;
250         close RESUME;
251         if ($what eq $doing) {
252             $started = 0;
253         }
254     }
255
256     for $line (@packages) {
257         $tag        = $$line{"tag"};
258         $scm        = $$line{"vcs"};
259         # Use the "remote" structure for bare git repositories
260         $localpath  = ($bare_flag && $scm eq "git") ?
261                       $$line{"remotepath"} : $$line{"localpath"};
262         $remotepath = ($checked_out_tree) ?
263                       $$line{"localpath"}  : $$line{"remotepath"};
264
265         if (!$started) {
266             if ($start_repo eq $localpath) {
267                 $started = 1;
268             }
269             else {
270                 next;
271             }
272         }
273
274         open RESUME, "> resume.tmp";
275         print RESUME "$localpath\n";
276         print RESUME "$doing\n";
277         close RESUME;
278         rename "resume.tmp", "resume";
279
280         # Check the SCM is OK as early as possible
281         die "Unknown SCM: $scm" if (($scm ne "darcs") and ($scm ne "git"));
282
283         # We can't create directories on GitHub, so we translate
284         # "packages/foo" into "package-foo".
285         if ($is_github_repo) {
286             $remotepath =~ s/\//-/;
287         }
288
289         # Construct the path for this package in the repo we pulled from
290         $path = "$repo_base/$remotepath";
291
292         if ($command =~ /^(?:g|ge|get)$/) {
293             # Skip any repositories we have not included the tag for
294             if (not defined($tags{$tag})) {
295                 $tags{$tag} = 0;
296             }
297             if ($tags{$tag} == 0) {
298                 next;
299             }
300
301             if (-d $localpath) {
302                 warning("$localpath already present; omitting")
303                     if $localpath ne ".";
304                 if ($scm eq "git") {
305                     scm ($localpath, $scm, "config", "core.ignorecase", "true");
306                 }
307                 next;
308             }
309
310             # Note that we use "." as the path, as $localpath
311             # doesn't exist yet.
312             if ($scm eq "darcs") {
313                 # The first time round the loop, default the get-mode
314                 if (not defined($get_mode)) {
315                     warning("adding --partial, to override use --complete");
316                     $get_mode = "--partial";
317                 }
318                 scm (".", $scm, "get", $get_mode, $path, $localpath, @args);
319             }
320             else {
321                 my @argsWithBare = @args;
322                 push @argsWithBare, $bare_flag if $bare_flag;
323                 scm (".", $scm, "clone", $path, $localpath, @argsWithBare);
324                 scm ($localpath, $scm, "config", "core.ignorecase", "true");
325             }
326             next;
327         }
328
329         my $darcs_repo_present = 1 if -d "$localpath/_darcs";
330         my $git_repo_present = 1 if -d "$localpath/.git" || ($bare_flag && -d "$localpath");
331         if ($darcs_repo_present) {
332             if ($git_repo_present) {
333                 die "Found both _darcs and .git in $localpath";
334             }
335             $scm = "darcs";
336         } elsif ($git_repo_present) {
337             $scm = "git";
338         } elsif ($tag eq "") {
339             die "Required repo $localpath is missing";
340         } else {
341              message "== $localpath repo not present; skipping";
342              next;
343         }
344
345         # Work out the arguments we should give to the SCM
346         if ($command =~ /^(?:w|wh|wha|what|whats|whatsn|whatsne|whatsnew|status)$/) {
347             if ($scm eq "darcs") {
348                 $command = "whatsnew";
349             }
350             elsif ($scm eq "git") {
351                 $command = "status";
352             }
353             else {
354                 die "Unknown scm";
355             }
356
357             # Hack around 'darcs whatsnew' failing if there are no changes
358             $ignore_failure = 1;
359             scm ($localpath, $scm, $command, @args);
360         }
361         elsif ($command =~ /^commit$/) {
362             # git fails if there is nothing to commit, so ignore failures
363             $ignore_failure = 1;
364             scm ($localpath, $scm, "commit", @args);
365         }
366         elsif ($command =~ /^(?:pus|push)$/) {
367             scm ($localpath, $scm, "push", @args);
368         }
369         elsif ($command =~ /^(?:pul|pull)$/) {
370             scm ($localpath, $scm, "pull", @args);
371         }
372         elsif ($command =~ /^(?:new-workdir)$/) {
373             gitNewWorkdir ($localpath, @args);
374         }
375         elsif ($command =~ /^(?:s|se|sen|send)$/) {
376             if ($scm eq "darcs") {
377                 $command = "send";
378             }
379             elsif ($scm eq "git") {
380                 $command = "send-email";
381             }
382             else {
383                 die "Unknown scm";
384             }
385             scm ($localpath, $scm, $command, @args);
386         }
387         elsif ($command =~ /^fetch$/) {
388             scm ($localpath, $scm, "fetch", @args);
389         }
390         elsif ($command =~ /^new$/) {
391             my @scm_args = ("log", "$branch_name..");
392             scm ($localpath, $scm, @scm_args, @args);
393         }
394         elsif ($command =~ /^log$/) {
395             scm ($localpath, $scm, "log", @args);
396         }
397         elsif ($command =~ /^remote$/) {
398             my @scm_args;
399             $ignore_failure = 1;
400             if ($subcommand eq 'add') {
401                 @scm_args = ("remote", "add", $branch_name, $path);
402             } elsif ($subcommand eq 'rm') {
403                 @scm_args = ("remote", "rm", $branch_name);
404             } elsif ($subcommand eq 'set-branches') {
405                 @scm_args = ("remote", "set-branches", $branch_name);
406             } elsif ($subcommand eq 'set-url') {
407                 @scm_args = ("remote", "set-url", $branch_name, $path);
408             }
409             scm ($localpath, $scm, @scm_args, @args);
410         }
411         elsif ($command =~ /^checkout$/) {
412             # Not all repos are necessarily branched, so ignore failure
413             $ignore_failure = 1;
414             scm ($localpath, $scm, "checkout", @args)
415                 unless $scm eq "darcs";
416         }
417         elsif ($command =~ /^grep$/) {
418             # Hack around 'git grep' failing if there are no matches
419             $ignore_failure = 1;
420             scm ($localpath, $scm, "grep", @args)
421                 unless $scm eq "darcs";
422         }
423         elsif ($command =~ /^diff$/) {
424             scm ($localpath, $scm, "diff", @args)
425                 unless $scm eq "darcs";
426         }
427         elsif ($command =~ /^clean$/) {
428             scm ($localpath, $scm, "clean", @args)
429                 unless $scm eq "darcs";
430         }
431         elsif ($command =~ /^reset$/) {
432             scm ($localpath, $scm, "reset", @args)
433                 unless $scm eq "darcs";
434         }
435         elsif ($command =~ /^branch$/) {
436             scm ($localpath, $scm, "branch", @args)
437                 unless $scm eq "darcs";
438         }
439         elsif ($command =~ /^config$/) {
440             scm ($localpath, $scm, "config", @args)
441                 unless $scm eq "darcs";
442         }
443         elsif ($command =~ /^repack$/) {
444             scm ($localpath, $scm, "repack", @args)
445                 if $scm eq "git"
446         }
447         elsif ($command =~ /^format-patch$/) {
448             scm ($localpath, $scm, "format-patch", @args)
449                 if $scm eq "git"
450         }
451         elsif ($command =~ /^gc$/) {
452             scm ($localpath, $scm, "gc", @args)
453                 unless $scm eq "darcs";
454         }
455         elsif ($command =~ /^tag$/) {
456             scm ($localpath, $scm, "tag", @args);
457         }
458         else {
459             die "Unknown command: $command";
460         }
461     }
462
463     unlink "resume";
464 }
465
466 sub help
467 {
468         my $exit = shift;
469
470         # Get the built in help
471         my $help = <<END;
472 Usage:
473
474 ./sync-all [-q] [-s] [--ignore-failure] [-r repo] [--checked-out] [--bare]
475            [--nofib] [--extra] [--testsuite] [--no-dph] [--resume]
476            cmd [git flags]
477
478 Applies the command "cmd" to each repository in the tree.
479
480 A full repository tree is obtained by first cloning the ghc
481 repository, then getting the subrepositories with "sync-all get":
482
483   \$ git clone http://darcs.haskell.org/ghc.git
484   \$ cd ghc
485   \$ ./sync-all get
486
487 After this, "./sync-all pull" will pull from the original repository
488 tree.
489
490 A remote pointing to another local repository tree can be added like
491 this:
492
493   \$ ./sync-all -r /path/to/ghc remote add otherlocal
494
495 and then we can pull from this other tree with
496
497   \$ ./sync-all pull otherlocal
498
499 -------------- Commands -----------------
500 get
501
502     Clones all sub-repositories from the same place that the ghc
503     repository was cloned from. See "which repos to use" below
504     for details of how the subrepositories are laid out.
505
506     There are various --<package-tag> options that can be given
507     before "get" that enable extra repositories. The full list is
508     given at the end of this help. For example:
509
510     ./sync-all --testsuite get
511
512     would get the testsuite repository in addition to the usual set of
513     subrepositories.
514
515 remote add <remote-name>
516 remote rm <remote-name>
517 remote set-url [--push] <remote-name>
518
519     Runs a "git remote" command on each subrepository, adjusting the
520     repository location in each case appropriately. For example, to
521     add a new remote pointing to the upstream repositories:
522
523     ./sync-all -r http://darcs.haskell.org/ remote add upstream
524
525     The -r flag points to the root of the repository tree (see "which
526     repos to use" below). For a repository on the local filesystem it
527     would point to the ghc repository, and for a remote repository it
528     points to the directory containing "ghc.git".
529
530 These commands just run the equivalent git command on each repository, passing
531 any extra arguments to git:
532
533   branch
534   checkout
535   clean
536   commit
537   config
538   diff
539   fetch
540   format-patch
541   gc
542   grep
543   log
544   new
545   new-workdir
546   pull
547   push
548   repack
549   reset
550   send
551   status
552   tag
553
554 -------------- Flags -------------------
555 These flags are given *before* the command and modify the way sync-all behaves.
556 Flags given *after* the command are passed to git.
557
558   -q says to be quiet, and -s to be silent.
559
560   --resume will restart a command that failed, from the repo at which it
561   failed. This means you don't need to wait while, e.g., "pull" goes through
562   all the repos it's just pulled, and tries to pull them again.
563
564   --ignore-failure says to ignore errors and move on to the next repository
565
566   -r repo says to use repo as the location of package repositories
567
568   --checked-out says that the remote repo is in checked-out layout, as opposed
569   to the layout used for the main repo. By default a repo on the local
570   filesystem is assumed to be checked-out, and repos accessed via HTTP or SSH
571   are assumed to be in the main repo layout; use --checked-out to override the
572   latter.
573
574   --bare says that the local repo is in bare layout, same as the main repo. It
575   also means that these repos are bare. You only have to use this flag if you
576   don't have a bare ghc.git in the current directory and would like to 'get'
577   all of the repos bare. Requires packages.conf to be present in the current
578   directory (a renamed packages file from the main ghc repo).
579
580   Note: --checked-out and --bare flags are NOT the opposite of each other.
581         --checked-out: describes the layout of the remote repository tree.
582         --bare:        describes the layout of the local repository tree.
583
584   --nofib also clones the nofib benchmark suite
585
586   --testsuite also clones the ghc testsuite 
587
588   --extra also clone some extra library packages
589
590   --no-dph avoids cloning the dph pacakges
591
592
593 ------------ Checking out a branch -------------
594 To check out a branch you can run the following command:
595
596   \$ ./sync-all checkout ghc-7.4
597
598
599 ------------ Which repos to use -------------
600 sync-all uses the following algorithm to decide which remote repos to use
601
602 It always computes the remote repos from a single base, <repo_base> How is
603 <repo_base> set? If you say "-r repo", then that's <repo_base> otherwise
604 <repo_base> is set by asking git where the ghc repo came from, and removing the
605 last component (e.g. /ghc.git/ or /ghc/).
606
607 Then sync-all iterates over the package found in the file ./packages; see that
608 file for a description of the contents.
609
610 If <repo_base> looks like a local filesystem path, or if you give the
611 --checked-out flag, sync-all works on repos of form:
612
613   <repo_base>/<local-path>
614
615 otherwise sync-all works on repos of form:
616
617   <repo_base>/<remote-path>
618
619 This logic lets you say
620   both    sync-all -r http://darcs.haskell.org/ghc-6.12 remote add ghc-6.12
621   and     sync-all -r ../working remote add working
622 The latter is called a "checked-out tree".
623
624 sync-all *ignores* the defaultrepo of all repos other than the root one. So the
625 remote repos must be laid out in one of the two formats given by <local-path>
626 and <remote-path> in the file 'packages'.
627
628 Available package-tags are:
629 END
630
631         # Collect all the tags in the packages file
632         my %available_tags;
633         open IN, "< packages.conf"
634             or open IN, "< packages" # clashes with packages directory when using --bare
635             or die "Can't open packages file (or packages.conf)";
636         while (<IN>) {
637             chomp;
638             if (/^([^# ]+) +(?:([^ ]+) +)?([^ ]+) +([^ ]+)/) {
639                 if (defined($2) && $2 ne "-") {
640                     $available_tags{$2} = 1;
641                 }
642             }
643             elsif (! /^(#.*)?$/) {
644                 die "Bad line: $_";
645             }
646         }
647         close IN;
648
649         # Show those tags and the help text
650         my @available_tags = keys %available_tags;
651         print "$help@available_tags\n\n";
652         exit $exit;
653 }
654
655 sub main {
656
657     $tags{"-"} = 1;
658     $tags{"dph"} = 1;
659
660     while ($#_ ne -1) {
661         my $arg = shift;
662         # We handle -q here as well as lower down as we need to skip over it
663         # if it comes before the source-control command
664         if ($arg eq "-q") {
665             $verbose = 1;
666         }
667         elsif ($arg eq "-s") {
668             $verbose = 0;
669         }
670         elsif ($arg eq "-r") {
671             $defaultrepo = shift;
672         }
673         elsif ($arg eq "--resume") {
674             $try_to_resume = 1;
675         }
676         elsif ($arg eq "--ignore-failure") {
677             $ignore_failure = 1;
678         }
679         elsif ($arg eq "--complete" || $arg eq "--partial") {
680             $get_mode = $arg;
681         }
682         # Use --checked-out if the _remote_ repos are a checked-out tree,
683         # rather than the master trees.
684         elsif ($arg eq "--checked-out") {
685             $checked_out_flag = 1;
686         }
687         # Use --bare if the _local_ repos are bare repos,
688         # rather than a checked-out tree.
689         elsif ($arg eq "--bare") {
690             $bare_flag = $arg;
691         }
692         elsif ($arg eq "--help") {
693             help(0);
694         }
695         # --<tag> says we grab the libs tagged 'tag' with
696         # 'get'. It has no effect on the other commands.
697         elsif ($arg =~ m/^--no-(.*)$/) {
698             $tags{$1} = 0;
699         }
700         elsif ($arg =~ m/^--(.*)$/) {
701             $tags{$1} = 1;
702         }
703         else {
704             unshift @_, $arg;
705             if (grep /^-q$/, @_) {
706                 $verbose = 1;
707             }
708             last;
709         }
710     }
711
712     # check for ghc repositories in cwd
713     my $checked_out_found = 1 if (-d ".git" && -d "compiler");
714     my $bare_found = 1 if (-d "ghc.git");
715
716     if ($bare_flag && ! $bare_found && ! $defaultrepo) {
717         die "error: bare repository ghc.git not found.\n"
718           . "       Either clone a bare ghc repo first or specify the repo location. E.g.:\n"
719           . "       ./sync-all --bare [--testsuite --nofib --extra] -r http://darcs.haskell.org/ get\n"
720     }
721     elsif ($bare_found) {
722         $bare_flag = "--bare";
723     }
724     elsif (! $bare_flag && ! $checked_out_found) {
725         die "error: sync-all must be run from the top level of the ghc tree.";
726     }
727
728     if ($#_ eq -1) {
729         help(1);
730     }
731     else {
732         # Give the command and rest of the arguments to the main loop
733         scmall @_;
734     }
735 }
736
737 END {
738     my $ec = $?;
739     my $pwd = getcwd();
740
741     message "== Checking for old haddock repo";
742     if (-d "utils/haddock/.git") {
743         chdir("utils/haddock");
744         if ((system "git log -1 87e2ca11c3d1b1bc49900fba0b5c5c6f85650718 > /dev/null 2> /dev/null") == 0) {
745             print <<EOF;
746 ============================
747 ATTENTION!
748
749 You have an old haddock repository in your GHC tree!
750
751 Please remove it (e.g. "rm -r utils/haddock"), and then run
752 "./sync-all get" to get the new repository.
753 ============================
754 EOF
755         }
756         chdir($pwd);
757     }
758
759     message "== Checking for old binary repo";
760     if (-d "libraries/binary/.git") {
761         chdir("libraries/binary");
762         if ((system "git log -1 749ac0efbde3b14901417364a872796598747aaf > /dev/null 2> /dev/null") == 0) {
763             print <<EOF;
764 ============================
765 ATTENTION!
766
767 You have an old binary repository in your GHC tree!
768
769 Please remove it (e.g. "rm -r libraries/binary"), and then run
770 "./sync-all get" to get the new repository.
771 ============================
772 EOF
773         }
774         chdir($pwd);
775     }
776
777     message "== Checking for old mtl repo";
778     if (-d "libraries/mtl/.git") {
779         chdir("libraries/mtl");
780         if ((system "git log -1 c67d8f7247c612dc35242bc67e616f7ea35eadb9 > /dev/null 2> /dev/null") == 0) {
781             print <<EOF;
782 ============================
783 ATTENTION!
784
785 You have an old mtl repository in your GHC tree!
786
787 Please remove it (e.g. "rm -r libraries/mtl"), and then run
788 "./sync-all get" to get the new repository.
789 ============================
790 EOF
791         }
792         chdir($pwd);
793     }
794
795     message "== Checking for old Cabal repo";
796     if (-d "libraries/Cabal/.git") {
797         chdir("libraries/Cabal");
798         if ((system "git log -1 c8ebd66a32865f72ae03ee0663c62df3d77f08fe > /dev/null 2> /dev/null") == 0) {
799             print <<EOF;
800 ============================
801 ATTENTION!
802
803 You have an old Cabal repository in your GHC tree!
804
805 Please remove it (e.g. "rm -r libraries/Cabal"), and then run
806 "./sync-all get" to get the new repository.
807 ============================
808 EOF
809         }
810         chdir($pwd);
811     }
812
813     $? = $ec;
814 }
815
816 main(@ARGV);
817