# Utility function definitions for the various COIN scripts. # Copyright (c) 2010 Lou Hafer Simon Fraser University # All Rights Reserved. # This file is distributed under the Eclipse Public License. # It is part of the BuildTools project in COIN-OR (www.coin-or.org) # # $Id$ # Functions to disassemble svn URLs and extract relevant bits, and utilities # to find the best (most recent) stable and release URLs, calculate libtool # version numbers, and compare URLs for compatibility based on major and minor # version. Complicated because we have to account for trunk/stable/release and # for the variant syntax of Data and ThirdParty URLs. For your normal project, # it's # https://projects.coin-or.org/svn/ProjName/trunk # https://projects.coin-or.org/svn/ProjName/stable/M.m # https://projects.coin-or.org/svn/ProjName/releases/M.m.r # with the proviso that sometimes it's # https://projects.coin-or.org/svn/ProjName/SubProj/trunk # etc. # For ThirdParty, it's just like a normal project, except the prefix string # is longer: # https://projects.coin-or.org/svn/BuildTools/ThirdParty/ProjName # Data is the real pain. Prior to 20101103 (1.0.x series), it had this form: # https://projects.coin-or.org/svn/Data/trunk/ProjName # https://projects.coin-or.org/svn/Data/stable/M.m/ProjName # https://projects.coin-or.org/svn/Data/releases/M.m.r/ProjName # After 20101103 (1.1 and subsequent), it uses the same layout as ThirdParty, # namely /Data/Projname/. Macros below # will cope, but really you should be using pre-1.1 Data anyway. # Extract the COIN base from the URL, up to svn. Just in case it ever changes. # usage: baseURL=`extractBaseURL $svnURL` extractBaseURL () { exbu_baseURL=`echo $1 | sed -n -e 's|\(.*/svn\)/.*$|\1|p'` echo "$exbu_baseURL" } # Extract branch type (trunk/stable/release) from the URL. # usage: branchType=`extractTypeFromURL $svnURL` extractTypeFromURL () { etfu_type="invalid" case "$1" in */trunk* ) etfu_type=trunk ;; */stable/* ) etfu_type=stable ;; */releases/* ) etfu_type=release ;; esac echo $etfu_type } # Determine if this is a `normal' URL, defined as not Data, ThirdParty, or # BuildTools itself. ThirdParty lives in BuildTools as of 100628, so the # condition is redundant. Returns yes or no. # 101105 Exclude CoinBazaar, which follows the Data pattern. May not be the # correct choice if any CoinBazaar projects use BuildTools # usage: isNormal=`isNormalURL $svnURL` isNormalURL () { case $1 in */BuildTools/* | */ThirdParty/* | */Data/* | */CoinBazaar/* ) echo "no" ;; *) echo "yes" ;; esac } # Extract the project from a svn URL. The trick, for `normal' projects, is to # handle CHiPPS, which has CHiPPS/Alps, Bcps, Blis. We can't assume the # project name does not contain '/'. The heuristic is to look for everything # between svn and one of trunk, stable, releases, or end of line. # usage: projName=`extractProjFromURL $svnURL` extractProjFromURL () { epfu_URL="$1" epfu_projPat='\([^/][^/]*\)' epfu_sfxPat='.*$' case "$epfu_URL" in */Data/trunk/* ) epfu_pfxPat=svn/Data/trunk/ ;; */Data/stable/* | */Data/releases/* ) epfu_pfxPat='svn/Data/[^/][^/]*/[0-9][0-9.]*/' ;; */Data/* ) epfu_pfxPat='svn/Data/' ;; */ThirdParty/* ) epfu_pfxPat=svn/BuildTools/ThirdParty/ ;; *) epfu_type=`extractTypeFromURL $epfu_URL` epfu_pfxPat='svn/' epfu_projPat='\(.*\)' case $epfu_type in trunk | stable | release ) epfu_sfxPat=$epfu_type'.*$' ;; * ) epfu_sfxPat='$' ;; esac ;; esac epfu_projName=`echo $epfu_URL | sed -n -e 's|.*/'$epfu_pfxPat$epfu_projPat$epfu_sfxPat'|\1|p'` epfu_projName=`echo $epfu_projName | sed -e 's|/$||'` echo "$epfu_projName" } # Extract the tail (directory) from a URL that specifies an external. Relevant # only for normal projects, where the external will be a subdirectory # of the project. Returns null for Data / ThirdParty / BuildTools. # usage: projName=`extractTailFromExt $extURL` extractTailFromExt () { etfe_tail= case "$1" in */Data/* ) ;; */BuildTools/ThirdParty/* ) ;; */BuildTools/* ) ;; */CoinBazaar/* ) ;; *) etfe_pfxPat= case "$1" in */trunk/* ) etfe_pfxPat='.*/trunk/' ;; */stable/* ) etfe_pfxPat='.*/stable/[0-9][0-9.]*/' ;; */releases/* ) etfe_pfxPat='.*/releases/[0-9][0-9.]*/' ;; esac etfe_tail=`echo $1 | sed -n -e 's|'$etfe_pfxPat'\(.*\)|\1|p'` ;; esac echo "$etfe_tail" } # CppAD uses a version string of the form YYYMMDD.rr. What a pain in the ass. # Hence the scattered exceptions below. # Extract the entire version string from a stable or release URL. Returns a # null string if handed a trunk URL or if there's no version in the URL. The # version number must have at least major.minor to match. # usage: version=`extractVersionFromURL $svnURL` extractVersionFromURL () { evfu_URL="$1" if expr "$evfu_URL" : '.*/stable/.*' >/dev/null 2>&1 || expr "$evfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then if expr "$evfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then evfu_verPat='\([0-9][0-9.]*\)' else evfu_verPat='\([0-9][0-9]*\.[0-9][0-9.]*\)' fi evfu_sfxPat='.*$' evfu_proj=`extractProjFromURL $evfu_URL` case "$evfu_URL" in */Data/stable/* | */Data/releases/* ) evfu_pfxPat='svn/Data/[^/][^/]*/' ;; */ThirdParty/* ) evfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/' ;; */Data/* ) evfu_pfxPat='svn/Data/'$evfu_proj'/[^/][^/]*/' ;; *) evfu_pfxPat='svn/'$evfu_proj'/[^/][^/]*/' ;; esac evfu_verVer=`echo $1 | sed -n -e 's|.*/'$evfu_pfxPat$evfu_verPat$evfu_sfxPat'|\1|p'` echo "$evfu_verVer" else echo "" fi } # Replace the entire version string from a stable or release URL. A trunk # URL will be unmodified. newRev will not be accessed unless the URL is a # release. The version must have at least major.minor to match. # usage: newURL=`replaceVersionInURL $oldURL $newMajor $newMinor $newRev` # and just for CppAD, # usage: newURL=`replaceVersionInURL $oldURL $newMajor $newRev` replaceVersionInURL () { if expr "$1" : '.*/CppAD/.*' >/dev/null 2>&1 ; then isCppAD=yes else isCppAD=no fi if test $isCppAD = no ; then rviu_verPat='[0-9][0-9]*\.[0-9][0-9.]*' else rviu_verPat='[0-9][0-9.]*' fi if expr "$1" : '.*/stable/.*' >/dev/null 2>&1 ; then if test $isCppAD = no ; then rviu_newVersion=$2.$3 else rviu_newVersion=$2 fi elif expr "$1" : '.*/releases/.*' >/dev/null 2>&1 ; then if test $isCppAD = no ; then rviu_newVersion=$2.$3.$4 else rviu_newVersion=$2.$3 fi else rviu_newVersion= rviu_newURL=$1 fi if test -n "$rviu_newVersion" ; then rviu_newURL=`echo $1 | sed -n -e 's|^\(.*\)/'$rviu_verPat'\(.*\)$|\1/'$rviu_newVersion'\2|p'` fi echo $rviu_newURL } # Extract the major version number from a stable or release URL. Returns -1 if # handed a trunk URL or if there's no version in the URL # usage: majVer=`extractMajorFromURL $svnURL` extractMajorFromURL () { ejfu_URL="$1" if expr "$ejfu_URL" : '.*/stable/.*' >/dev/null 2>&1 || expr "$ejfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then ejfu_majPat='\([0-9][0-9]*\)' if expr "$ejfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then ejfu_sfxPat='.*$' else ejfu_sfxPat='\.[0-9][0-9]*.*$' fi ejfu_proj=`extractProjFromURL $ejfu_URL` case "$ejfu_URL" in */Data/stable/* | */Data/releases/* ) ejfu_pfxPat='svn/Data/[^/][^/]*/' ;; */ThirdParty/* ) ejfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/' ;; */Data/* ) ejfu_pfxPat='svn/Data/'$ejfu_proj'/[^/][^/]*/' ;; *) ejfu_pfxPat='svn/'$ejfu_proj'/[^/][^/]*/' ;; esac ejfu_majVer=`echo $ejfu_URL | sed -n -e 's|.*/'$ejfu_pfxPat$ejfu_majPat$ejfu_sfxPat'|\1|p'` echo "$ejfu_majVer" else echo "-1" fi } # Extract the minor version number from a stable or release URL. Returns -1 if # handed a trunk URL or if there's no version in the URL. # The CppAD form (YYYYMMDD.rr) doesn't have a minor version number. # usage: minVer=`extractMinorFromURL $svnURL` extractMinorFromURL () { emfu_URL="$1" if expr "$emfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then echo "-1" elif expr "$emfu_URL" : '.*/stable/.*' >/dev/null 2>&1 || expr "$emfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then emfu_minPat='[0-9][0-9]*\.\([0-9][0-9]*\)' emfu_sfxPat='.*$' emfu_proj=`extractProjFromURL $emfu_URL` case "$emfu_URL" in */Data/stable/* | */Data/releases/* ) emfu_pfxPat='svn/Data/[^/][^/]*/' ;; */ThirdParty/* ) emfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/' ;; */Data/* ) emfu_pfxPat='svn/Data/'$emfu_proj'/[^/][^/]*/' ;; *) emfu_pfxPat='svn/'$emfu_proj'/[^/][^/]*/' ;; esac emfu_minVer=`echo $emfu_URL | sed -n -e 's|.*/'$emfu_pfxPat$emfu_minPat$emfu_sfxPat'|\1|p'` echo "$emfu_minVer" else echo "-1" fi } # Extract the release (revision) number from a release URL. Returns -1 if # handed a trunk or stable URL # usage: minVer=`extractReleaseFromURL $svnURL` extractReleaseFromURL () { erfu_URL="$1" if expr "$erfu_URL" : '.*/releases/.*' >/dev/null 2>&1 ; then if expr "$erfu_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then erfu_relPat='[0-9][0-9]*\.\([0-9][0-9]*\)' else erfu_relPat='[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)' fi erfu_sfxPat='.*$' erfu_proj=`extractProjFromURL $erfu_URL` case "$erfu_URL" in */Data/releases/* ) erfu_pfxPat='svn/Data/[^/][^/]*/' ;; */ThirdParty/* ) erfu_pfxPat='svn/BuildTools/ThirdParty/[^/][^/]*/[^/][^/]*/' ;; */Data/*) erfu_pfxPat='svn/Data/'$erfu_proj'/[^/][^/]*/' ;; *) erfu_pfxPat='svn/'$erfu_proj'/[^/][^/]*/' ;; esac erfu_relVer=`echo $erfu_URL | sed -n -e 's|.*/'$erfu_pfxPat$erfu_relPat$erfu_sfxPat'|\1|p'` echo "$erfu_relVer" else echo "-1" fi } # Now some functions to locate the highest-numbered stable or release. # Return the URL of the most recent stable branch matching the parameters. # A value of -1 for major version is interpreted as `highest number' # Returns an empty string if no suitable stable branch exists. # usage: stableURL=`bestStable ` bestStable () { bstb_URL=$1 bstb_majVer=$2 # Construct a URL to send to the repository to list the stable branches. bstb_baseURL=`extractBaseURL $bstb_URL` bstb_proj=`extractProjFromURL $bstb_URL` case "$bstb_URL" in */Data/trunk/* ) bstb_listURL=$bstb_baseURL/Data/stable ;; */Data/* ) bstb_listURL=$bstb_baseURL/Data/$bstb_proj/stable ;; */ThirdParty/* ) bstb_listURL=$bstb_baseURL/BuildTools/ThirdParty/$bstb_proj/stable ;; * ) bstb_listURL=$bstb_baseURL/$bstb_proj/stable ;; esac bstb_rawls=`svn list $bstb_listURL | sort -nr -t. -k1,1 -k2,2` # echo "Raw ls: $bstb_rawls" # Filter the list of stable branches to remove any that do not match the # requested major version. Note that there's a / at the end of each URL. if test "$bstb_majVer" = "-1" ; then bstb_verPat='[0-9][0-9.]*/' elif expr "$bstb_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then bstb_verPat=$bstb_majVer'/' else bstb_verPat=$bstb_majVer'\.[0-9][0-9]*' fi bstb_filter= for bstb_ver in $bstb_rawls ; do if expr "$bstb_ver" : $bstb_verPat >/dev/null 2>&1 ; then bstb_filter="$bstb_filter $bstb_ver" fi done # echo "Filtered ls: $bstb_filter" # If there are any candidates left ... bstb_bestURL= if test -n "$bstb_filter" ; then # If we're dealing with old-style Data, we have to work a bit harder # to find our project. See if any of the filtered candidates contain # the correct project. case "$bstb_URL" in */Data/trunk/* | */Data/stable/* | */Data/releases/* ) bstb_projPat='.*'$bstb_proj'/.*' # echo "Pattern: $bstb_projPat" for bstb_ver in $bstb_filter ; do if expr "$bstb_ver" : $bstb_verPat >/dev/null 2>&1 ; then # echo " url: $bstb_listURL/$bstb_ver" bstb_svnls2="`svn list $bstb_listURL/$bstb_ver`" # echo " result: $bstb_svnls2" if expr "$bstb_svnls2" : $bstb_projPat >/dev/null 2>&1 ; then bstb_best=$bstb_ver # echo " best: $bstb_best" break fi fi done bstb_bestURL=$bstb_listURL/$bstb_best$bstb_proj ;; *) bstb_bestURL=`echo $bstb_filter | sed -n -e 's|\([^/]*/\).*$|\1|p'` bstb_bestURL=$bstb_listURL/$bstb_bestURL ;; esac fi echo $bstb_bestURL } # Return the URL of the most recent release matching the parameters. Returns # null if no suitable release exists. # A value of -1 for major or minor version is interpreted as `highest number' # A value of -1 for major version means that minor version is ignored. # usage: releaseURL=`bestRelease ` bestRelease () { bstb_URL=$1 bstb_majVer=$2 bstb_minVer=$3 # Construct a URL to send to the repository to list the releases. bstb_baseURL=`extractBaseURL $bstb_URL` bstb_proj=`extractProjFromURL $bstb_URL` case "$bstb_URL" in */Data/* ) bstb_listURL=$bstb_baseURL/Data/$bstb_proj/releases ;; */ThirdParty/* ) bstb_listURL=$bstb_baseURL/BuildTools/ThirdParty/$bstb_proj/releases ;; * ) bstb_listURL=$bstb_baseURL/$bstb_proj/releases ;; esac bstb_rawls=`svn list $bstb_listURL | sort -nr -t. -k1,1 -k2,2 -k3,3` # echo "Raw ls: $bstb_rawls" # Filter the list of releases to remove any that do not match the # requested major and minor version. if expr "$bstb_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then isCppAD=yes else isCppAD=no fi if test "$bstb_majVer" = "-1" ; then bstb_verPat='[0-9][0-9.]*/' else bstb_verPat=$bstb_majVer if test $isCppAD = no && test "$bstb_minVer" != "-1" ; then bstb_verPat="${bstb_verPat}\.$bstb_minVer" fi bstb_verPat="${bstb_verPat}"'\.[0-9][0-9]*/' fi # echo "Version pattern: $bstb_verPat" bstb_filter= for bstb_ver in $bstb_rawls ; do if expr "$bstb_ver" : $bstb_verPat >/dev/null 2>&1 ; then bstb_filter="$bstb_filter $bstb_ver" fi done # echo "Filtered ls: $bstb_filter" # If there are any candidates left ... bstb_bestURL= if test -n "$bstb_filter" ; then # If we're dealing with old-style Data, we have to work a bit harder to find our # project. See if any of the filtered candidates contain the correct # project. case "$bstb_URL" in */Data/trunk/* | */Data/stable/* | */Data/releases/* ) bstb_projPat='.*'$bstb_proj'/.*' # echo "Pattern: $bstb_projPat" for bstb_ver in $bstb_filter ; do if expr "$bstb_ver" : $bstb_verPat >/dev/null 2>&1 ; then # echo " url: $bstb_listURL/$bstb_ver" bstb_svnls2="`svn list $bstb_listURL/$bstb_ver`" # echo " result: $bstb_svnls2" if expr "$bstb_svnls2" : $bstb_projPat >/dev/null 2>&1 ; then bstb_best=$bstb_ver # echo " best: $bstb_best" break fi fi done bstb_bestURL=$bstb_listURL/$bstb_best$bstb_proj ;; *) bstb_bestURL=`echo $bstb_filter | sed -n -e 's|\([^/]*/\).*$|\1|p'` bstb_bestURL=$bstb_listURL/$bstb_bestURL ;; esac fi echo $bstb_bestURL } # Count the total number of stable branches for the project for the specified # major version number, up to the specified minor version number (libtool age). # Returns 0 if handed a trunk url, or if the url is Data or BuildTools itself. # usage: calcLibtoolAge calcLibtoolAge () { cltc_URL=$1 cltc_majVer=$2 cltc_minVer=$3 # Construct a URL to send to the repository to list the stable branches. cltc_baseURL=`extractBaseURL $cltc_URL` cltc_proj=`extractProjFromURL $cltc_URL` case "$cltc_URL" in */Data/* ) cltc_listURL= ;; */ThirdParty/* ) cltc_listURL=$cltc_baseURL/BuildTools/ThirdParty/$cltc_proj/stable ;; */BuildTools/* ) cltc_listURL= ;; * ) cltc_listURL=$cltc_baseURL/$cltc_proj/stable ;; esac # Run an ls and filter for standard stable branches (M.m or YYYYMMDD) if test -n "$cltc_listURL" ; then cltc_rawls=`svn list $cltc_listURL | sed -n -e '/[0-9][0-9.]/p'` # echo "Raw ls: $cltc_rawls" # Filter the list of stable branches to remove any that do not match the # requested major version. if expr "$cltc_URL" : '.*/CppAD/.*' >/dev/null 2>&1 ; then cltc_verPat=$cltc_majVer else cltc_verPat=$cltc_majVer'\.[0-9][0-9]*/' fi cltc_majfilter= for cltc_ver in $cltc_rawls ; do if expr "$cltc_ver" : $cltc_verPat >/dev/null 2>&1 ; then cltc_majfilter="$cltc_majfilter $cltc_ver" fi done # echo "Filtered ls (major version): $cltc_majfilter" # For the specific major version, filter the list that matched on major # version to remove any that exceed the minor version. cltc_minfilter= for cltc_ver in $cltc_majfilter ; do cltc_min=`echo $cltc_ver | sed -e 's/[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/'` if expr $cltc_min '<=' $cltc_minVer >/dev/null 2>&1 ; then cltc_minfilter="$cltc_minfilter $cltc_ver" fi done # echo "Filtered ls (minor version): $cltc_minfilter" cltc_cnt=`echo $cltc_minfilter | wc -w | sed -e 's/ //g'` else cltc_cnt=0 fi echo $cltc_cnt } # Count the total number of stable branches for the project up to the # specified major.minor version number (libtool current). Returns 0 if # handed a trunk url, or if the url is Data or BuildTools itself. # usage: calcLibtoolCurrent calcLibtoolCurrent () { cltc_URL=$1 cltc_majVer=$2 cltc_minVer=$3 # Construct a URL to send to the repository to list the stable branches. cltc_baseURL=`extractBaseURL $cltc_URL` cltc_proj=`extractProjFromURL $cltc_URL` case "$cltc_URL" in */Data/* ) cltc_listURL= ;; */ThirdParty/* ) cltc_listURL=$cltc_baseURL/BuildTools/ThirdParty/$cltc_proj/stable ;; */BuildTools/* ) cltc_listURL= ;; * ) cltc_listURL=$cltc_baseURL/$cltc_proj/stable ;; esac # Run an ls and filter for standard stable branches (M.m or YYYYMMDD) if test -n "$cltc_listURL" ; then cltc_rawls=`svn list $cltc_listURL | sed -n -e '/[0-9][0-9.]/p'` # echo "Raw ls: $cltc_rawls" # Filter the list of stable branches to find those with standard version # numbers. cltc_verPat='[0-9][0-9.]*/' cltc_stdfilter= for cltc_ver in $cltc_rawls ; do if expr "$cltc_ver" : $cltc_verPat >/dev/null 2>&1 ; then cltc_stdfilter="$cltc_stdfilter $cltc_ver" fi done # echo "Filtered ls (standard): $cltc_stdfilter" # Filter to remove major versions that exceed the specified version. cltc_majfilter= for cltc_ver in $cltc_stdfilter ; do cltc_maj=`echo $cltc_ver | sed -e 's/\([0-9][0-9]*\)\.[0-9].*/\1/'` if expr $cltc_maj '<=' $cltc_majVer >/dev/null 2>&1 ; then cltc_majfilter="$cltc_majfilter $cltc_ver" fi done # echo "Filtered ls (major version): $cltc_majfilter" # For the specific major version, filter the list that matched on major # version to remove any that exceed the minor version. cltc_minfilter= cltc_verPat='s/'$cltc_majVer'\.\([0-9][0-9]*\).*/\1/' for cltc_ver in $cltc_majfilter ; do cltc_min=`echo $cltc_ver | sed -e $cltc_verPat` if expr $cltc_min '<=' $cltc_minVer >/dev/null 2>&1 ; then cltc_minfilter="$cltc_minfilter $cltc_ver" fi done # echo "Filtered ls (minor version): $cltc_minfilter" cltc_cnt=`echo $cltc_minfilter | wc -w | sed -e 's/ //g'` else cltc_cnt=0 fi echo $cltc_cnt } # Function to compare the versions in a pair of URLs for equality. The criteria # is that the major and minor versions match. In theory, the release should # not matter. Probably should be a parameter. # usage: compareURLVersions compareURLVersions () { url1_major=`extractMajorFromURL $1` url1_minor=`extractMinorFromURL $1` url2_major=`extractMajorFromURL $2` url2_minor=`extractMinorFromURL $2` if test $url1_major = $url2_major && test $url1_minor = $url2_minor ; then echo "yes" else echo "no" fi }