hgforest.sh revision 900:d832f6171acd
1#!/bin/sh
2
3#
4# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
5# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6#
7# This code is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 2 only, as
9# published by the Free Software Foundation.
10#
11# This code is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14# version 2 for more details (a copy is included in the LICENSE file that
15# accompanied this code).
16#
17# You should have received a copy of the GNU General Public License version
18# 2 along with this work; if not, write to the Free Software Foundation,
19# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22# or visit www.oracle.com if you need additional information or have any
23# questions.
24#
25
26# Shell script for a fast parallel forest command
27command="$1"
28pull_extra_base="$2"
29
30if [ "" = "$command" ] ; then
31  echo No command to hg supplied!
32  exit 1
33fi
34
35# Clean out the temporary directory that stores the pid files.
36tmp=/tmp/forest.$$
37rm -f -r ${tmp}
38mkdir -p ${tmp}
39
40safe_interrupt () {
41  if [ -d ${tmp} ]; then
42    if [ "`ls ${tmp}/*.pid`" != "" ]; then
43      echo "Waiting for processes ( `cat ${tmp}/*.pid | tr '\n' ' '`) to terminate nicely!"
44      sleep 1
45      # Pipe stderr to dev/null to silence kill, that complains when trying to kill
46      # a subprocess that has already exited.
47      kill -TERM `cat ${tmp}/*.pid | tr '\n' ' '` 2> /dev/null
48      wait
49      echo Interrupt complete!
50    fi
51  fi
52  rm -f -r ${tmp}
53  exit 1
54}
55
56nice_exit () {
57  if [ -d ${tmp} ]; then
58    if [ "`ls ${tmp}`" != "" ]; then
59      wait
60    fi
61  fi
62  rm -f -r ${tmp}
63}
64
65trap 'safe_interrupt' INT QUIT
66trap 'nice_exit' EXIT
67
68# Only look in specific locations for possible forests (avoids long searches)
69pull_default=""
70repos=""
71repos_extra=""
72if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
73  subrepos="corba jaxp jaxws langtools jdk hotspot nashorn"
74  if [ -f .hg/hgrc ] ; then
75    pull_default=`hg paths default`
76    if [ "${pull_default}" = "" ] ; then
77      echo "ERROR: Need initial clone with 'hg paths default' defined"
78      exit 1
79    fi
80  fi
81  if [ "${pull_default}" = "" ] ; then
82    echo "ERROR: Need initial repository to use this script"
83    exit 1
84  fi
85  for i in ${subrepos} ; do
86    if [ ! -f ${i}/.hg/hgrc ] ; then
87      repos="${repos} ${i}"
88    fi
89  done
90  if [ "${pull_extra_base}" != "" ] ; then
91    subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs"
92    pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
93    pull_extra="${pull_extra_base}/${pull_default_tail}"
94    for i in ${subrepos_extra} ; do
95      if [ ! -f ${i}/.hg/hgrc ] ; then
96        repos_extra="${repos_extra} ${i}"
97      fi
98    done
99  fi
100  at_a_time=2
101  # Any repos to deal with?
102  if [ "${repos}" = "" -a "${repos_extra}" = "" ] ; then
103    exit
104  fi
105else
106  hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg ./*/*/*/*/.hg 2>/dev/null`
107  # Derive repository names from the .hg directory locations
108  for i in ${hgdirs} ; do
109    repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`"
110  done
111  for i in ${repos} ; do
112    if [ -h ${i}/.hg/store/lock -o -f ${i}/.hg/store/lock ] ; then
113      locked="${i} ${locked}"
114    fi
115  done
116  at_a_time=8
117  # Any repos to deal with?
118  if [ "${repos}" = "" ] ; then
119    echo "No repositories to process."
120    exit
121  fi
122  if [ "${locked}" != "" ] ; then
123    echo "These repositories are locked: ${locked}"
124    exit
125  fi
126fi
127
128# Echo out what repositories we do a command on.
129echo "# Repositories: ${repos} ${repos_extra}"
130echo
131
132# Run the supplied command on all repos in parallel.
133n=0
134for i in ${repos} ${repos_extra} ; do
135  n=`expr ${n} '+' 1`
136  repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
137  reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
138  pull_base="${pull_default}"
139  for j in $repos_extra ; do
140      if [ "$i" = "$j" ] ; then
141          pull_base="${pull_extra}"
142      fi
143  done
144  (
145    (
146      if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
147        pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
148        echo hg clone ${pull_newrepo} ${i}
149        path="`dirname ${i}`"
150        if [ "${path}" != "." ] ; then
151          times=0
152          while [ ! -d "${path}" ]   ## nested repo, ensure containing dir exists
153          do
154            times=`expr ${times} '+' 1`
155            if [ `expr ${times} '%' 10` -eq 0 ] ; then
156              echo ${path} still not created, waiting...
157            fi
158            sleep 5
159          done
160        fi
161        (PYTHONUNBUFFERED=true hg clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
162      else
163        echo "cd ${i} && hg $*"
164        cd ${i} && (PYTHONUNBUFFERED=true hg "$@"; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
165      fi
166      echo $! > ${tmp}/${repopidfile}.pid
167    ) 2>&1 | sed -e "s@^@${reponame}:   @") &
168
169  if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then
170    sleep 2
171    echo Waiting 5 secs before spawning next background command.
172    sleep 3
173  fi
174done
175# Wait for all hg commands to complete
176wait
177
178# Terminate with exit 0 only if all subprocesses were successful
179ec=0
180if [ -d ${tmp} ]; then
181  for rc in ${tmp}/*.pid.rc ; do
182    exit_code=`cat ${rc} | tr -d ' \n\r'`
183    if [ "${exit_code}" != "0" ] ; then
184      echo "WARNING: ${rc} exited abnormally."
185      ec=1
186    fi
187  done
188fi
189exit ${ec}
190