common/bin/hgforest.sh

changeset 1144
e16a393ee5e3
parent 1143
e3ae43560332
child 1145
3c596cad39e6
equal deleted inserted replaced
1143:e3ae43560332 1144:e16a393ee5e3
70 usage() { 70 usage() {
71 echo "usage: $0 [-q|--quiet] [-v|--verbose] [-s|--sequential] [--] <command> [commands...]" > ${status_output} 71 echo "usage: $0 [-q|--quiet] [-v|--verbose] [-s|--sequential] [--] <command> [commands...]" > ${status_output}
72 exit 1 72 exit 1
73 } 73 }
74 74
75
76 if [ "x" = "x$command" ] ; then 75 if [ "x" = "x$command" ] ; then
77 echo "ERROR: No command to hg supplied!" 76 echo "ERROR: No command to hg supplied!"
78 usage 77 usage
78 fi
79
80 # Check if we can use fifos for monitoring sub-process completion.
81 on_windows=`uname -s | egrep -ic -e 'cygwin|msys'`
82 if [ ${on_windows} = "1" ]; then
83 # cygwin has (2014-04-18) broken (single writer only) FIFOs
84 # msys has (2014-04-18) no FIFOs.
85 have_fifos="false"
86 else
87 have_fifos="true"
79 fi 88 fi
80 89
81 # Clean out the temporary directory that stores the pid files. 90 # Clean out the temporary directory that stores the pid files.
82 tmp=/tmp/forest.$$ 91 tmp=/tmp/forest.$$
83 rm -f -r ${tmp} 92 rm -f -r ${tmp}
208 (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 & 217 (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
209 ) 2>&1 | sed -e "s@^@serve: @" > ${status_output} 218 ) 2>&1 | sed -e "s@^@serve: @" > ${status_output}
210 ) & 219 ) &
211 else 220 else
212 # Run the supplied command on all repos in parallel. 221 # Run the supplied command on all repos in parallel.
222
223 # n is the number of subprocess started or which might still be running.
213 n=0 224 n=0
225 if [ $have_fifos = "true" ]; then
226 # if we have fifos use them to detect command completion.
227 mkfifo ${tmp}/fifo
228 exec 3<>${tmp}/fifo
229 if [ "${sflag}" = "true" ] ; then
230 # force sequential
231 at_a_time=1
232 fi
233 fi
234
214 for i in ${repos} ${repos_extra} ; do 235 for i in ${repos} ${repos_extra} ; do
215 n=`expr ${n} '+' 1` 236 n=`expr ${n} '+' 1`
216 repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'` 237 repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
217 reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'` 238 reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
218 pull_base="${pull_default}" 239 pull_base="${pull_default}"
219 for j in $repos_extra ; do 240 for j in $repos_extra ; do
220 if [ "$i" = "$j" ] ; then 241 if [ "$i" = "$j" ] ; then
221 pull_base="${pull_extra}" 242 pull_base="${pull_extra}"
222 fi 243 fi
223 done 244 done
245 pull_base="`echo ${pull_base} | sed -e 's@[/]*$@@'`"
224 ( 246 (
225 ( 247 (
226 if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then 248 if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then
227 pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`" 249 pull_newrepo="${pull_base}/${i}"
228 path="`dirname ${i}`" 250 path="`dirname ${i}`"
229 if [ "${path}" != "." ] ; then 251 if [ "${path}" != "." ] ; then
230 times=0 252 times=0
231 while [ ! -d "${path}" ] ## nested repo, ensure containing dir exists 253 while [ ! -d "${path}" ] ## nested repo, ensure containing dir exists
232 do 254 do
235 echo "${path} still not created, waiting..." > ${status_output} 257 echo "${path} still not created, waiting..." > ${status_output}
236 fi 258 fi
237 sleep 5 259 sleep 5
238 done 260 done
239 fi 261 fi
240 echo "hg clone ${pull_newrepo} ${i}" > ${status_output} 262 echo "hg${global_opts} clone ${pull_newrepo} ${i}" > ${status_output}
241 (PYTHONUNBUFFERED=true hg${global_opts} clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & 263 (PYTHONUNBUFFERED=true hg${global_opts} clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
242 else 264 else
243 echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output} 265 echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output}
244 cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & 266 cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
245 fi 267 fi
246 268
247 echo $! > ${tmp}/${repopidfile}.pid 269 echo $! > ${tmp}/${repopidfile}.pid
248 ) 2>&1 | sed -e "s@^@${reponame}: @" > ${status_output} 270 ) 2>&1 | sed -e "s@^@${reponame}: @" > ${status_output}
271 if [ $have_fifos = "true" ]; then
272 echo "${reponame}" >&3
273 fi
249 ) & 274 ) &
250 275
251 if [ `expr ${n} '%' ${at_a_time}` -eq 0 -a "${sflag}" = "false" ] ; then 276 if [ $have_fifos = "true" ]; then
252 sleep 2 277 # check on count of running subprocesses and possibly wait for completion
253 echo "Waiting 5 secs before spawning next background command." > ${status_output} 278 if [ ${at_a_time} -lt ${n} ] ; then
254 sleep 3 279 # read will block until there are completed subprocesses
255 fi 280 while read repo_done; do
256 281 n=`expr ${n} '-' 1`
257 if [ "${sflag}" = "true" ] ; then 282 if [ ${n} -lt ${at_a_time} ] ; then
283 # we should start more subprocesses
284 break;
285 fi
286 done <&3
287 fi
288 else
289 if [ "${sflag}" = "false" ] ; then
290 # Compare completions to starts
291 completed="`(ls -1 ${tmp}/*.pid.rc 2> /dev/null | wc -l) || echo 0`"
292 while [ ${at_a_time} -lt `expr ${n} '-' ${completed}` ] ; do
293 # sleep a short time to give time for something to complete
294 sleep 1
295 completed="`(ls -1 ${tmp}/*.pid.rc 2> /dev/null | wc -l) || echo 0`"
296 done
297 else
298 # complete this task before starting another.
258 wait 299 wait
259 fi 300 fi
260 done 301 fi
261 fi 302 done
262 303 fi
263 # Wait for all hg commands to complete 304
305 # Wait for all subprocesses to complete
264 wait 306 wait
265 307
266 # Terminate with exit 0 only if all subprocesses were successful 308 # Terminate with exit 0 only if all subprocesses were successful
267 ec=0 309 ec=0
268 if [ -d ${tmp} ]; then 310 if [ -d ${tmp} ]; then
269 for rc in ${tmp}/*.pid.rc ; do 311 for rc in ${tmp}/*.pid.rc ; do
270 exit_code=`cat ${rc} | tr -d ' \n\r'` 312 exit_code=`cat ${rc} | tr -d ' \n\r'`
271 if [ "${exit_code}" != "0" ] ; then 313 if [ "${exit_code}" != "0" ] ; then
272 repo="`echo ${rc} | sed -e s@^${tmp}@@ -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`" 314 repo="`echo ${rc} | sed -e s@^${tmp}@@ -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`"
273 echo "WARNING: ${repo} exited abnormally." > ${status_output} 315 echo "WARNING: ${repo} exited abnormally ($exit_code)" > ${status_output}
274 ec=1 316 ec=1
275 fi 317 fi
276 done 318 done
277 fi 319 fi
278 exit ${ec} 320 exit ${ec}

mercurial