Merge branch 'master' of http://darcs.haskell.org/ghc
[ghc-hetmet.git] / sync-all
old mode 100644 (file)
new mode 100755 (executable)
index cfc44ea..9b0706e
--- a/sync-all
+++ b/sync-all
@@ -3,6 +3,64 @@
 use strict;
 use Cwd;
 
+# Usage:
+#
+# ./sync-all [-q] [-s] [--ignore-failure] [-r repo]
+#            [--nofib] [--testsuite] [--checked-out] cmd [git flags]
+#
+# Applies the command "cmd" to each repository in the tree.
+# sync-all will try to do the right thing for both git and darcs repositories.
+#
+# e.g.
+#      ./sync-all -r http://darcs.haskell.org/ghc get
+#          To get any repos which do not exist in the local tree
+#
+#      ./sync-all pull
+#          To pull everything from the default repos
+#
+# -------------- Flags -------------------
+#   -q says to be quite, and -s to be silent.
+#
+#   --ignore-failure says to ignore errors and move on to the next repository
+#
+#   -r repo says to use repo as the location of package repositories
+#
+#   --checked-out says that the remote repo is in checked-out layout, as
+#   opposed to the layout used for the main repo.  By default a repo on
+#   the local filesystem is assumed to be checked-out, and repos accessed
+#   via HTTP or SSH are assumed to be in the main repo layout; use
+#   --checked-out to override the latter.
+#
+#   --nofib, --testsuite also get the nofib and testsuite repos respectively
+#
+# ------------ Which repos to use -------------
+# sync-all uses the following algorithm to decide which remote repos to use
+#
+#  It always computes the remote repos from a single base, $repo_base
+#  How is $repo_base set?  
+#    If you say "-r repo", then that's $repo_base
+#    otherwise $repo_base is set by asking git where the ghc repo came
+#    from, and removing the last component (e.g. /ghc.git/ of /ghc/).
+#
+#  Then sync-all iterates over the package found in the file
+#  ./packages; see that file for a description of the contents.
+# 
+#    If $repo_base looks like a local filesystem path, or if you give
+#    the --checked-out flag, sync-all works on repos of form
+#          $repo_base/<local-path>
+#    otherwise sync-all works on repos of form
+#          $repo_base/<remote-path>
+#    This logic lets you say
+#      both    sync-all -r http://darcs.haskell.org/ghc-6.12 pull
+#      and     sync-all -r ../HEAD pull
+#    The latter is called a "checked-out tree".
+
+# NB: sync-all *ignores* the defaultrepo of all repos other than the
+# root one.  So the remote repos must be laid out in one of the two
+# formats given by <local-path> and <remote-path> in the file 'packages'.
+
+$| = 1; # autoflush stdout after each print, to avoid output after die
+
 my $defaultrepo;
 my @packages;
 my $verbose = 2;
@@ -79,7 +137,7 @@ sub parsePackages {
     my @repos;
     my $lineNum;
 
-    open IN, "< packages.git" or die "Can't open packages file";
+    open IN, "< packages" or die "Can't open packages file";
     @repos = <IN>;
     close IN;
 
@@ -116,12 +174,25 @@ sub warning {
 }
 
 sub scm {
+    my $dir = shift;
     my $scm = shift;
-    
-    message "== running $scm @_";
+    my $pwd;
+
+    if ($dir eq '.') {
+        message "== running $scm @_";
+    } else {
+        message "== $dir: running $scm @_";
+        $pwd = getcwd();
+        chdir($dir);
+    }
+
     system ($scm, @_) == 0
         or $ignore_failure
         or die "$scm failed: $?";
+
+    if ($dir ne '.') {
+        chdir($pwd);
+    }
 }
 
 sub repoexists {
@@ -150,6 +221,8 @@ sub scmall {
 
     my @scm_args;
 
+    my $pwd;
+
     my ($repo_base, $checked_out_tree) = getrepo();
 
     parsePackages;
@@ -223,6 +296,19 @@ sub scmall {
                           or ($scm eq "git" and "send-email"));
                 $want_remote_repo = 1;
             }
+            elsif ($command =~ /^set-origin$/) {
+                @scm_args = ("remote", "set-url", "origin", $path);
+            }
+            elsif ($command =~ /^set-push$/) {
+                @scm_args = ("remote", "set-url", "--push", "origin", $path);
+                print "foo\n", @scm_args;
+            }
+            elsif ($command =~ /^fetch$/) {
+                @scm_args = ("fetch", "origin");
+            }
+            elsif ($command =~ /^new$/) {
+                @scm_args = ("log", "origin..");
+            }
             else {
                 die "Unknown command: $command";
             }
@@ -231,19 +317,20 @@ sub scmall {
             if (repoexists ($scm, $localpath)) {
                 if ($want_remote_repo) {
                     if ($scm eq "darcs") {
-                        scm ($scm, @scm_args, @_, "--repodir=$localpath", $path);
+                        scm (".", $scm, @scm_args, @_, "--repodir=$localpath", $path);
                     } else {
                         # git pull doesn't like to be used with --work-dir
-                        scm ($scm, "--git-dir=$localpath/.git", @scm_args, @_, $path, "master");
+                        # I couldn't find an alternative to chdir() here
+                        scm ($localpath, $scm, @scm_args, @_, $path, "master");
                     }
                 } else {
                     # git status *must* be used with --work-dir, if we don't chdir() to the dir
-                    scm ($scm, "--git-dir=$localpath/.git", "--work-tree=$localpath", @scm_args, @_);
+                    scm ($localpath, $scm, @scm_args, @_);
                 }
             }
             elsif ($local_repo_unnecessary) {
                 # Don't bother to change directory in this case
-                scm ($scm, @scm_args, @_);
+                scm (".", $scm, @scm_args, @_);
             }
             elsif ($tag eq "") {
                 message "== Required repo $localpath is missing! Skipping";
@@ -314,7 +401,11 @@ Supported commands:
   * --<package-tag>
   * --complete
   * --partial
+ * fetch
  * send
+ * set-origin
+ * set-push
+ * new
 
 Available package-tags are:
 END