#!/bin/sh # This file is a part of Julia. License is MIT: https://julialang.org/license # build-time mini version of WinRPM, usage: # ./winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_13.2/ mingw64-zlib1 # depends on curl, xmllint, gunzip, sort -V, sha256sum, and p7zip set -e setglobal url = $1 setglobal toinstall = $2 for i in [curl xmllint gunzip sort sha256sum 7z] { if test -z $[which $i !2 >/dev/null] { echo "error: this script requires having $i installed" > !2 exit 1 } } # there is a curl --retry flag but it wasn't working here for some reason proc retry_curl { for i in [$[seq 10]] { curl -fLsS $1 && return #sleep 2 } echo "error: failed to download $1" > !2 exit 1 } setglobal xp = '"xmllint --xpath'" # the local-name() complication here is due to xml namespaces setglobal loc = '"local-name()='" eval $[retry_curl $url/repodata/repomd.xml | $xp "/*[$loc'repomd'] \ /*[$loc'data'][@type='primary']/*[$loc'location']/@href" -] match $href { with *.gz setglobal primary = $[retry_curl $url/$href | gunzip] with * setglobal primary = $[retry_curl $url/$href] } # outputs xml string for newest version # don't include arch=src packages, those will list build-time dependencies proc rpm_select { setglobal candidates = ""$[echo $primary | $xp "//*[$loc'package'] \ [./*[$loc'name' and .='$1']][./*[$loc'arch' and .='noarch']]" - \ !2 >/dev/null | sed -e 's|"" # remove rpm namespacing so output can be parsed by xmllint later if test $candidates = "" { echo "error: no package candidates found for $1" > !2 exit 1 } setglobal epochs = ''"" for i in [$[echo $candidates | $xp "/c/package/version/@epoch" -]] { eval $i setglobal epochs = ""$epochs $epoch"" } setglobal maxepoch = $[echo $epochs | sed 's/ /\n/g' | sort -V -u | tail -n 1] setglobal vers = ''"" for i in [$[echo $candidates | $xp "/c/package/version \ [@epoch='$maxepoch']/@ver" -]] { eval $i setglobal vers = ""$vers $ver"" } setglobal maxver = $[echo $vers | sed 's/ /\n/g' | sort -V -u | tail -n 1] setglobal rels = ''"" for i in [$[echo $candidates | $xp "/c/package/version \ [@epoch='$maxepoch'][@ver='$maxver']/@rel" -]] { eval $i setglobal rels = ""$rels $rel"" } setglobal maxrel = $[echo $rels | sed 's/ /\n/g' | sort -V -u | tail -n 1] setglobal repeats = $[echo $rels | sed 's/ /\n/g' | sort -V | uniq -d | tail -n 1] if test $repeats = $maxrel { echo "warning: multiple candidates found for $1 with same version:" > !2 echo "epoch $maxepoch, ver $maxver, rel $maxrel, picking at random" > !2 } echo $candidates | $xp "/c/package[version[@epoch='$maxepoch'] \ [@ver='$maxver'][@rel='$maxrel']][1]" - } for i in [$toinstall] { # fail if no available candidates for requested packages if test -z $[rpm_select $i] { exit 1 } } # outputs package and dll names, e.g. mingw64(zlib1.dll) proc rpm_requires { for i in [$[rpm_select $1 | \ $xp "/package/format/requires/entry/@name" - !2 >/dev/null]] { eval $i echo $name } } # outputs package name, warns if multiple providers with different names proc rpm_provides { setglobal providers = $[echo $primary | $xp "//*[$loc'package'][./*[$loc'format'] \ /*[$loc'provides']/*[$loc'entry'][@name='$1']]/*[$loc'name']" - | \ sed -e 's|||g' -e 's||\n|g' | sort -u] if test $[echo $providers | wc -w] -gt 1 { echo "warning: found multiple providers $providers for $1, adding all" > !2 } echo $providers } setglobal newpkgs = $toinstall setglobal allrequires = ''"" while test -n $newpkgs { setglobal newrequires = ''"" for i in [$newpkgs] { for j in [$[rpm_requires $i]] { # leading and trailing spaces to ensure word match match " $allrequires $newrequires " { with *" $j "* # already on list with * setglobal newrequires = ""$newrequires $j"" } } } setglobal allrequires = ""$allrequires $newrequires"" setglobal newpkgs = ''"" for i in [$newrequires] { setglobal provides = $[rpm_provides $i] match " $toinstall $newpkgs " { with *" $provides "* # already on list with * setglobal newpkgs = ""$newpkgs $provides"" } } setglobal toinstall = ""$toinstall $newpkgs"" } mkdir -p noarch for i in [$toinstall] { setglobal pkgi = $[rpm_select $i] setglobal checksum = $[echo $pkgi | $xp "/package/checksum/text()" -] eval $[echo $pkgi | $xp "/package/location/@href" -] echo "downloading $href" $[dirname $0]/../../deps/tools/jldownload $href $url/$href echo "$checksum *$href" | sha256sum -c 7z x -y $href setglobal cpiofile = $[basename $href | sed 's/.rpm$/.cpio/] rm $href 7z x -y $cpiofile rm $cpiofile } rmdir --ignore-fail-on-non-empty noarch