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