hgforest.sh revision 966:76533a3f52ce
1#!/bin/sh 2 3# 4# Copyright (c) 2009, 2014, 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="closed 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