Thu, 17 Jul 2014 22:45:46 +0100
Merge
1.1 --- a/common/bin/hgforest.sh Thu Jul 17 18:01:58 2014 +0100 1.2 +++ b/common/bin/hgforest.sh Thu Jul 17 22:45:46 2014 +0100 1.3 @@ -1,7 +1,6 @@ 1.4 #!/bin/sh 1.5 - 1.6 # 1.7 -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. 1.8 +# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. 1.9 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.10 # 1.11 # This code is free software; you can redistribute it and/or modify it 1.12 @@ -23,165 +22,375 @@ 1.13 # questions. 1.14 # 1.15 1.16 -# Shell script for a fast parallel forest command 1.17 -command="$1" 1.18 -pull_extra_base="$2" 1.19 +# Shell script for a fast parallel forest/trees command 1.20 1.21 -if [ "" = "$command" ] ; then 1.22 - echo No command to hg supplied! 1.23 - exit 1 1.24 +usage() { 1.25 + echo "usage: $0 [-h|--help] [-q|--quiet] [-v|--verbose] [-s|--sequential] [--] <command> [commands...]" > ${status_output} 1.26 + echo "Environment variables which modify behaviour:" 1.27 + echo " HGFOREST_QUIET : (boolean) If 'true' then standard output is redirected to /dev/null" 1.28 + echo " HGFOREST_VERBOSE : (boolean) If 'true' then Mercurial asked to produce verbose output" 1.29 + echo " HGFOREST_SEQUENTIAL : (boolean) If 'true' then repos are processed sequentially. Disables concurrency" 1.30 + echo " HGFOREST_GLOBALOPTS : (string, must begin with space) Additional Mercurial global options" 1.31 + echo " HGFOREST_REDIRECT : (file path) Redirect standard output to specified file" 1.32 + echo " HGFOREST_FIFOS : (boolean) Default behaviour for FIFO detection. Does not override FIFOs disabled" 1.33 + echo " HGFOREST_CONCURRENCY: (positive integer) Number of repos to process concurrently" 1.34 + echo " HGFOREST_DEBUG : (boolean) If 'true' then temp files are retained" 1.35 + exit 1 1.36 +} 1.37 + 1.38 +global_opts="${HGFOREST_GLOBALOPTS:-}" 1.39 +status_output="${HGFOREST_REDIRECT:-/dev/stdout}" 1.40 +qflag="${HGFOREST_QUIET:-false}" 1.41 +vflag="${HGFOREST_VERBOSE:-false}" 1.42 +sflag="${HGFOREST_SEQUENTIAL:-false}" 1.43 +while [ $# -gt 0 ] 1.44 +do 1.45 + case $1 in 1.46 + -h | --help ) 1.47 + usage 1.48 + ;; 1.49 + 1.50 + -q | --quiet ) 1.51 + qflag="true" 1.52 + ;; 1.53 + 1.54 + -v | --verbose ) 1.55 + vflag="true" 1.56 + ;; 1.57 + 1.58 + -s | --sequential ) 1.59 + sflag="true" 1.60 + ;; 1.61 + 1.62 + '--' ) # no more options 1.63 + shift; break 1.64 + ;; 1.65 + 1.66 + -*) # bad option 1.67 + usage 1.68 + ;; 1.69 + 1.70 + * ) # non option 1.71 + break 1.72 + ;; 1.73 + esac 1.74 + shift 1.75 +done 1.76 + 1.77 +# silence standard output? 1.78 +if [ ${qflag} = "true" ] ; then 1.79 + global_opts="${global_opts} -q" 1.80 + status_output="/dev/null" 1.81 fi 1.82 1.83 +# verbose output? 1.84 +if [ ${vflag} = "true" ] ; then 1.85 + global_opts="${global_opts} -v" 1.86 +fi 1.87 + 1.88 +# Make sure we have a command. 1.89 +if [ $# -lt 1 -o -z "${1:-}" ] ; then 1.90 + echo "ERROR: No command to hg supplied!" 1.91 + usage 1.92 +fi 1.93 + 1.94 +command="$1"; shift 1.95 +command_args="${@:-}" 1.96 + 1.97 # Clean out the temporary directory that stores the pid files. 1.98 tmp=/tmp/forest.$$ 1.99 rm -f -r ${tmp} 1.100 mkdir -p ${tmp} 1.101 1.102 + 1.103 +if [ "${HGFOREST_DEBUG:-false}" = "true" ] ; then 1.104 + echo "DEBUG: temp files are in: ${tmp}" 1.105 +fi 1.106 + 1.107 +# Check if we can use fifos for monitoring sub-process completion. 1.108 +echo "1" > ${tmp}/read 1.109 +while_subshell=1 1.110 +while read line; do 1.111 + while_subshell=0 1.112 + break; 1.113 +done < ${tmp}/read 1.114 +rm ${tmp}/read 1.115 + 1.116 +on_windows=`uname -s | egrep -ic -e 'cygwin|msys'` 1.117 + 1.118 +if [ ${while_subshell} = "1" -o ${on_windows} = "1" ]; then 1.119 + # cygwin has (2014-04-18) broken (single writer only) FIFOs 1.120 + # msys has (2014-04-18) no FIFOs. 1.121 + # older shells create a sub-shell for redirect to while 1.122 + have_fifos="false" 1.123 +else 1.124 + have_fifos="${HGFOREST_FIFOS:-true}" 1.125 +fi 1.126 + 1.127 safe_interrupt () { 1.128 if [ -d ${tmp} ]; then 1.129 if [ "`ls ${tmp}/*.pid`" != "" ]; then 1.130 - echo "Waiting for processes ( `cat ${tmp}/*.pid | tr '\n' ' '`) to terminate nicely!" 1.131 + echo "Waiting for processes ( `cat ${tmp}/.*.pid ${tmp}/*.pid 2> /dev/null | tr '\n' ' '`) to terminate nicely!" > ${status_output} 1.132 sleep 1 1.133 # Pipe stderr to dev/null to silence kill, that complains when trying to kill 1.134 # a subprocess that has already exited. 1.135 kill -TERM `cat ${tmp}/*.pid | tr '\n' ' '` 2> /dev/null 1.136 wait 1.137 - echo Interrupt complete! 1.138 + echo "Interrupt complete!" > ${status_output} 1.139 fi 1.140 + rm -f -r ${tmp} 1.141 fi 1.142 - rm -f -r ${tmp} 1.143 - exit 1 1.144 + exit 130 1.145 } 1.146 1.147 nice_exit () { 1.148 if [ -d ${tmp} ]; then 1.149 - if [ "`ls ${tmp}`" != "" ]; then 1.150 + if [ "`ls -A ${tmp} 2> /dev/null`" != "" ]; then 1.151 wait 1.152 fi 1.153 + if [ "${HGFOREST_DEBUG:-false}" != "true" ] ; then 1.154 + rm -f -r ${tmp} 1.155 + fi 1.156 fi 1.157 - rm -f -r ${tmp} 1.158 } 1.159 1.160 trap 'safe_interrupt' INT QUIT 1.161 trap 'nice_exit' EXIT 1.162 1.163 +subrepos="corba jaxp jaxws langtools jdk hotspot nashorn" 1.164 +subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" 1.165 + 1.166 # Only look in specific locations for possible forests (avoids long searches) 1.167 pull_default="" 1.168 repos="" 1.169 repos_extra="" 1.170 -if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then 1.171 - subrepos="corba jaxp jaxws langtools jdk hotspot nashorn" 1.172 - if [ -f .hg/hgrc ] ; then 1.173 - pull_default=`hg paths default` 1.174 - if [ "${pull_default}" = "" ] ; then 1.175 - echo "ERROR: Need initial clone with 'hg paths default' defined" 1.176 - exit 1 1.177 - fi 1.178 - fi 1.179 - if [ "${pull_default}" = "" ] ; then 1.180 - echo "ERROR: Need initial repository to use this script" 1.181 +if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then 1.182 + # we must be a clone 1.183 + if [ ! -f .hg/hgrc ] ; then 1.184 + echo "ERROR: Need initial repository to use this script" > ${status_output} 1.185 exit 1 1.186 fi 1.187 + 1.188 + # the clone must know where it came from (have a default pull path). 1.189 + pull_default=`hg paths default` 1.190 + if [ "${pull_default}" = "" ] ; then 1.191 + echo "ERROR: Need initial clone with 'hg paths default' defined" > ${status_output} 1.192 + exit 1 1.193 + fi 1.194 + 1.195 + # determine which sub repos need to be cloned. 1.196 for i in ${subrepos} ; do 1.197 if [ ! -f ${i}/.hg/hgrc ] ; then 1.198 repos="${repos} ${i}" 1.199 fi 1.200 done 1.201 - if [ "${pull_extra_base}" != "" ] ; then 1.202 - subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" 1.203 - pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'` 1.204 - pull_extra="${pull_extra_base}/${pull_default_tail}" 1.205 + 1.206 + pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'` 1.207 + 1.208 + if [ -n "${command_args}" ] ; then 1.209 + # if there is an "extra sources" path then reparent "extra" repos to that path 1.210 + if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then 1.211 + echo "ERROR: Need initial clone from non-local source" > ${status_output} 1.212 + exit 1 1.213 + fi 1.214 + pull_extra="${command_args}/${pull_default_tail}" 1.215 + 1.216 + # determine which extra subrepos need to be cloned. 1.217 for i in ${subrepos_extra} ; do 1.218 if [ ! -f ${i}/.hg/hgrc ] ; then 1.219 repos_extra="${repos_extra} ${i}" 1.220 fi 1.221 done 1.222 + else 1.223 + if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then 1.224 + # local source repo. Clone the "extra" subrepos that exist there. 1.225 + for i in ${subrepos_extra} ; do 1.226 + if [ -f ${pull_default}/${i}/.hg/hgrc -a ! -f ${i}/.hg/hgrc ] ; then 1.227 + # sub-repo there in source but not here 1.228 + repos_extra="${repos_extra} ${i}" 1.229 + fi 1.230 + done 1.231 + fi 1.232 fi 1.233 - at_a_time=2 1.234 + 1.235 # Any repos to deal with? 1.236 if [ "${repos}" = "" -a "${repos_extra}" = "" ] ; then 1.237 + echo "No repositories to process." > ${status_output} 1.238 exit 1.239 fi 1.240 + 1.241 + # Repos to process concurrently. Clone does better with low concurrency. 1.242 + at_a_time="${HGFOREST_CONCURRENCY:-2}" 1.243 else 1.244 - hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg ./*/*/*/*/.hg 2>/dev/null` 1.245 - # Derive repository names from the .hg directory locations 1.246 - for i in ${hgdirs} ; do 1.247 - repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`" 1.248 + # Process command for all of the present repos 1.249 + for i in . ${subrepos} ${subrepos_extra} ; do 1.250 + if [ -d ${i}/.hg ] ; then 1.251 + repos="${repos} ${i}" 1.252 + fi 1.253 done 1.254 + 1.255 + # Any repos to deal with? 1.256 + if [ "${repos}" = "" ] ; then 1.257 + echo "No repositories to process." > ${status_output} 1.258 + exit 1.259 + fi 1.260 + 1.261 + # any of the repos locked? 1.262 + locked="" 1.263 for i in ${repos} ; do 1.264 if [ -h ${i}/.hg/store/lock -o -f ${i}/.hg/store/lock ] ; then 1.265 locked="${i} ${locked}" 1.266 fi 1.267 done 1.268 - at_a_time=8 1.269 - # Any repos to deal with? 1.270 - if [ "${repos}" = "" ] ; then 1.271 - echo "No repositories to process." 1.272 - exit 1.273 + if [ "${locked}" != "" ] ; then 1.274 + echo "ERROR: These repositories are locked: ${locked}" > ${status_output} 1.275 + exit 1 1.276 fi 1.277 - if [ "${locked}" != "" ] ; then 1.278 - echo "These repositories are locked: ${locked}" 1.279 - exit 1.280 - fi 1.281 + 1.282 + # Repos to process concurrently. 1.283 + at_a_time="${HGFOREST_CONCURRENCY:-8}" 1.284 fi 1.285 1.286 # Echo out what repositories we do a command on. 1.287 -echo "# Repositories: ${repos} ${repos_extra}" 1.288 -echo 1.289 +echo "# Repositories: ${repos} ${repos_extra}" > ${status_output} 1.290 1.291 -# Run the supplied command on all repos in parallel. 1.292 -n=0 1.293 -for i in ${repos} ${repos_extra} ; do 1.294 - n=`expr ${n} '+' 1` 1.295 - repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'` 1.296 - reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'` 1.297 - pull_base="${pull_default}" 1.298 - for j in $repos_extra ; do 1.299 - if [ "$i" = "$j" ] ; then 1.300 - pull_base="${pull_extra}" 1.301 - fi 1.302 - done 1.303 +if [ "${command}" = "serve" ] ; then 1.304 + # "serve" is run for all the repos as one command. 1.305 ( 1.306 ( 1.307 - if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then 1.308 - pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`" 1.309 - echo hg clone ${pull_newrepo} ${i} 1.310 - path="`dirname ${i}`" 1.311 - if [ "${path}" != "." ] ; then 1.312 - times=0 1.313 - while [ ! -d "${path}" ] ## nested repo, ensure containing dir exists 1.314 - do 1.315 - times=`expr ${times} '+' 1` 1.316 - if [ `expr ${times} '%' 10` -eq 0 ] ; then 1.317 - echo ${path} still not created, waiting... 1.318 + cwd=`pwd` 1.319 + serving=`basename ${cwd}` 1.320 + ( 1.321 + echo "[web]" 1.322 + echo "description = ${serving}" 1.323 + echo "allow_push = *" 1.324 + echo "push_ssl = False" 1.325 + 1.326 + echo "[paths]" 1.327 + for i in ${repos} ; do 1.328 + if [ "${i}" != "." ] ; then 1.329 + echo "/${serving}/${i} = ${i}" 1.330 + else 1.331 + echo "/${serving} = ${cwd}" 1.332 + fi 1.333 + done 1.334 + ) > ${tmp}/serve.web-conf 1.335 + 1.336 + echo "serving root repo ${serving}" > ${status_output} 1.337 + 1.338 + echo "hg${global_opts} serve" > ${status_output} 1.339 + (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 & 1.340 + ) 2>&1 | sed -e "s@^@serve: @" > ${status_output} 1.341 + ) & 1.342 +else 1.343 + # Run the supplied command on all repos in parallel. 1.344 + 1.345 + # n is the number of subprocess started or which might still be running. 1.346 + n=0 1.347 + if [ ${have_fifos} = "true" ]; then 1.348 + # if we have fifos use them to detect command completion. 1.349 + mkfifo ${tmp}/fifo 1.350 + exec 3<>${tmp}/fifo 1.351 + fi 1.352 + 1.353 + # iterate over all of the subrepos. 1.354 + for i in ${repos} ${repos_extra} ; do 1.355 + n=`expr ${n} '+' 1` 1.356 + repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'` 1.357 + reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'` 1.358 + pull_base="${pull_default}" 1.359 + 1.360 + # regular repo or "extra" repo? 1.361 + for j in ${repos_extra} ; do 1.362 + if [ "${i}" = "${j}" ] ; then 1.363 + # it's an "extra" 1.364 + pull_base="${pull_extra}" 1.365 + fi 1.366 + done 1.367 + 1.368 + # remove trailing slash 1.369 + pull_base="`echo ${pull_base} | sed -e 's@[/]*$@@'`" 1.370 + 1.371 + # execute the command on the subrepo 1.372 + ( 1.373 + ( 1.374 + if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then 1.375 + # some form of clone 1.376 + clone_newrepo="${pull_base}/${i}" 1.377 + parent_path="`dirname ${i}`" 1.378 + if [ "${parent_path}" != "." ] ; then 1.379 + times=0 1.380 + while [ ! -d "${parent_path}" ] ; do ## nested repo, ensure containing dir exists 1.381 + if [ "${sflag}" = "true" ] ; then 1.382 + # Missing parent is fatal during sequential operation. 1.383 + echo "ERROR: Missing parent path: ${parent_path}" > ${status_output} 1.384 + exit 1 1.385 + fi 1.386 + times=`expr ${times} '+' 1` 1.387 + if [ `expr ${times} '%' 10` -eq 0 ] ; then 1.388 + echo "${parent_path} still not created, waiting..." > ${status_output} 1.389 + fi 1.390 + sleep 5 1.391 + done 1.392 + fi 1.393 + # run the clone command. 1.394 + echo "hg${global_opts} clone ${clone_newrepo} ${i}" > ${status_output} 1.395 + (PYTHONUNBUFFERED=true hg${global_opts} clone ${clone_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & 1.396 + else 1.397 + # run the command. 1.398 + echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output} 1.399 + cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & 1.400 + fi 1.401 + 1.402 + echo $! > ${tmp}/${repopidfile}.pid 1.403 + ) 2>&1 | sed -e "s@^@${reponame}: @" > ${status_output} 1.404 + # tell the fifo waiter that this subprocess is done. 1.405 + if [ ${have_fifos} = "true" ]; then 1.406 + echo "${i}" >&3 1.407 + fi 1.408 + ) & 1.409 + 1.410 + if [ "${sflag}" = "true" ] ; then 1.411 + # complete this task before starting another. 1.412 + wait 1.413 + else 1.414 + if [ "${have_fifos}" = "true" ]; then 1.415 + # check on count of running subprocesses and possibly wait for completion 1.416 + if [ ${n} -ge ${at_a_time} ] ; then 1.417 + # read will block until there are completed subprocesses 1.418 + while read repo_done; do 1.419 + n=`expr ${n} '-' 1` 1.420 + if [ ${n} -lt ${at_a_time} ] ; then 1.421 + # we should start more subprocesses 1.422 + break; 1.423 fi 1.424 - sleep 5 1.425 - done 1.426 + done <&3 1.427 fi 1.428 - (PYTHONUNBUFFERED=true hg clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc )& 1.429 else 1.430 - echo "cd ${i} && hg $*" 1.431 - cd ${i} && (PYTHONUNBUFFERED=true hg "$@"; echo "$?" > ${tmp}/${repopidfile}.pid.rc )& 1.432 + # Compare completions to starts 1.433 + completed="`(ls -a1 ${tmp}/*.pid.rc 2> /dev/null | wc -l) || echo 0`" 1.434 + while [ `expr ${n} '-' ${completed}` -ge ${at_a_time} ] ; do 1.435 + # sleep a short time to give time for something to complete 1.436 + sleep 1 1.437 + completed="`(ls -a1 ${tmp}/*.pid.rc 2> /dev/null | wc -l) || echo 0`" 1.438 + done 1.439 fi 1.440 - echo $! > ${tmp}/${repopidfile}.pid 1.441 - ) 2>&1 | sed -e "s@^@${reponame}: @") & 1.442 + fi 1.443 + done 1.444 +fi 1.445 1.446 - if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then 1.447 - sleep 2 1.448 - echo Waiting 5 secs before spawning next background command. 1.449 - sleep 3 1.450 - fi 1.451 -done 1.452 -# Wait for all hg commands to complete 1.453 +# Wait for all subprocesses to complete 1.454 wait 1.455 1.456 # Terminate with exit 0 only if all subprocesses were successful 1.457 ec=0 1.458 if [ -d ${tmp} ]; then 1.459 - for rc in ${tmp}/*.pid.rc ; do 1.460 + rcfiles="`(ls -a ${tmp}/*.pid.rc 2> /dev/null) || echo ''`" 1.461 + for rc in ${rcfiles} ; do 1.462 exit_code=`cat ${rc} | tr -d ' \n\r'` 1.463 if [ "${exit_code}" != "0" ] ; then 1.464 - echo "WARNING: ${rc} exited abnormally." 1.465 + repo="`echo ${rc} | sed -e 's@^'${tmp}'@@' -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`" 1.466 + echo "WARNING: ${repo} exited abnormally (${exit_code})" > ${status_output} 1.467 ec=1 1.468 fi 1.469 done
2.1 --- a/get_source.sh Thu Jul 17 18:01:58 2014 +0100 2.2 +++ b/get_source.sh Thu Jul 17 22:45:46 2014 +0100 2.3 @@ -1,7 +1,7 @@ 2.4 #!/bin/sh 2.5 2.6 # 2.7 -# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. 2.8 +# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 2.9 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.10 # 2.11 # This code is free software; you can redistribute it and/or modify it 2.12 @@ -25,9 +25,76 @@ 2.13 # questions. 2.14 # 2.15 2.16 -# Get clones of all nested repositories 2.17 -sh ./common/bin/hgforest.sh clone "$@" || exit 1 2.18 +to_stderr() { 2.19 + echo "$@" >&2 2.20 +} 2.21 + 2.22 +error() { 2.23 + to_stderr "ERROR: $1" 2.24 + exit ${2:-126} 2.25 +} 2.26 + 2.27 +warning() { 2.28 + to_stderr "WARNING: $1" 2.29 +} 2.30 + 2.31 +version_field() { 2.32 + # rev is typically omitted for minor and major releases 2.33 + field=`echo ${1}.0 | cut -f ${2} -d .` 2.34 + if expr 1 + $field >/dev/null 2> /dev/null; then 2.35 + echo $field 2.36 + else 2.37 + echo -1 2.38 + fi 2.39 +} 2.40 + 2.41 +# Version check 2.42 + 2.43 +# required 2.44 +reqdmajor=1 2.45 +reqdminor=4 2.46 +reqdrev=0 2.47 + 2.48 +# requested 2.49 +rqstmajor=2 2.50 +rqstminor=6 2.51 +rqstrev=3 2.52 + 2.53 + 2.54 +# installed 2.55 +hgwhere="`command -v hg`" 2.56 +if [ "x$hgwhere" = "x" ]; then 2.57 + error "Could not locate Mercurial command" 2.58 +fi 2.59 + 2.60 +hgversion="`hg --version 2> /dev/null | sed -n -e 's@^Mercurial Distributed SCM (version \([^+]*\).*)\$@\1@p'`" 2.61 +if [ "x${hgversion}" = "x" ] ; then 2.62 + error "Could not determine Mercurial version of $hgwhere" 2.63 +fi 2.64 + 2.65 +hgmajor="`version_field $hgversion 1`" 2.66 +hgminor="`version_field $hgversion 2`" 2.67 +hgrev="`version_field $hgversion 3`" 2.68 + 2.69 +if [ $hgmajor -eq -1 -o $hgminor -eq -1 -o $hgrev -eq -1 ] ; then 2.70 + error "Could not determine Mercurial version of $hgwhere from \"$hgversion\"" 2.71 +fi 2.72 + 2.73 + 2.74 +# Require 2.75 +if [ $hgmajor -lt $reqdmajor -o \( $hgmajor -eq $reqdmajor -a $hgminor -lt $reqdminor \) -o \( $hgmajor -eq $reqdmajor -a $hgminor -eq $reqdminor -a $hgrev -lt $reqdrev \) ] ; then 2.76 + error "Mercurial version $reqdmajor.$reqdminor.$reqdrev or later is required. $hgwhere is version $hgversion" 2.77 +fi 2.78 + 2.79 + 2.80 +# Request 2.81 +if [ $hgmajor -lt $rqstmajor -o \( $hgmajor -eq $rqstmajor -a $hgminor -lt $rqstminor \) -o \( $hgmajor -eq $rqstmajor -a $hgminor -eq $rqstminor -a $hgrev -lt $rqstrev \) ] ; then 2.82 + warning "Mercurial version $rqstmajor.$rqstminor.$rqstrev or later is recommended. $hgwhere is version $hgversion" 2.83 +fi 2.84 + 2.85 + 2.86 +# Get clones of all absent nested repositories (harmless if already exist) 2.87 +sh ./common/bin/hgforest.sh clone "$@" || exit $? 2.88 2.89 # Update all existing repositories to the latest sources 2.90 sh ./common/bin/hgforest.sh pull -u 2.91 -