Merge "build: Add download capability for external packages"
[asterisk/asterisk.git] / build_tools / download_externals
1 #!/usr/bin/env bash
2
3 if [[ ( ${BASH_VERSINFO[0]} == 4 && ${BASH_VERSINFO[1]} > 1 ) || ${BASH_VERSINFO[0]} > 4 ]] ; then
4         shopt -s compat41
5 fi
6 set -e
7
8 ASTTOPDIR=${ASTTOPDIR:-.}
9
10 module_name=$1
11
12 if [[ -z ${module_name} ]] ; then
13         echo "You must supply a module name."
14         exit 64
15 fi
16
17 tmpdir=$(mktemp -d)
18 if [[ -z "${tmpdir}" ]] ; then
19         echo "${module_name}: Unable to create temporary directory."
20         exit 1
21 fi
22 trap "rm -rf ${tmpdir}" EXIT
23
24 sed -r -e "s/^([^ =]+)\s*=\s*(.*)$/\1=\"\2\"/g" ${ASTTOPDIR}/makeopts >${tmpdir}/makeopts
25 source ${tmpdir}/makeopts
26 if [[ -z "${ASTMODDIR}" ]] ; then
27         echo "${module_name}: Unable to parse ${ASTTOPDIR}/makeopts."
28         exit 1
29 fi
30
31 XMLSTARLET=${XMLSTARLET:-xmlstarlet}
32 if [[ "${XMLSTARLET}" = ":" ]] ; then
33         echo "${module_name}: The externals downloader requires xmlstarlet to be installed."
34         exit 1
35 fi
36
37 cache_dir="${EXTERNALS_CACHE_DIR}"
38 if [[ -z ${cache_dir} ]] ; then
39         cache_dir=${tmpdir}
40 fi
41
42 version=$(${ASTTOPDIR}/build_tools/make_version ${ASTTOPDIR})
43 if [[ ! ${version} =~ ^(GIT-)?([^.-]+)[.-].* ]] ; then
44         echo "${module_name}: Couldn't parse version ${version}"
45         exit 1
46 fi
47 major_version=${BASH_REMATCH[2]}
48
49 if [[ "${major_version}" == "master" ]] ; then
50         echo "${module_name}: External module downloading is not available in the 'master' git branch.  Please disable in menuselect and download manually."
51         exit 1
52 fi
53
54 major_version=${major_version}.0
55
56 if [[ "${HOST_CPU}" = "x86_64" ]] ; then
57         host_bits=64
58 else
59         host_bits=32
60 fi
61
62 remote_url=$(${XMLSTARLET} sel -t -v "/menu/category/member[@name = '${module_name}']/member_data/downloader/@remote_url" ${ASTTOPDIR}/menuselect-tree || :)
63 if [[ -n "${remote_url}" ]] ; then
64         remote_url="${remote_url}/asterisk-${major_version}/x86-${host_bits}"
65 else
66         directory_name=$(${XMLSTARLET} sel -t -v "/menu/category/member[@name = '${module_name}']/member_data/downloader/@directory_name" ${ASTTOPDIR}/menuselect-tree || :)
67         remote_url="http://downloads.digium.com/pub/telephony/${directory_name:-${module_name}}/asterisk-${major_version}/x86-${host_bits}"
68 fi
69
70 version_convert() {
71         local v=${1##*_}
72         if [[ ${v} =~ ([0-9]+)[.]([0-9]+)[.]([0-9]+) ]] ; then
73                 v=$(( ${BASH_REMATCH[1]}<<18 | ${BASH_REMATCH[2]}<<9 | ${BASH_REMATCH[3]} ))
74         fi
75         echo ${v}
76 }
77
78 ${WGET} -q -O ${tmpdir}/manifest.xml ${remote_url}/manifest.xml || {
79         echo "${module_name}: Unable to fetch ${remote_url}/manifest.xml"
80         exit 1
81 }
82
83 rpv=$(${XMLSTARLET} sel -t -v "/package/@version" ${tmpdir}/manifest.xml)
84 rpvi=$(version_convert ${rpv})
85 echo "${module_name}: Remote package version ${rpv} (${rpvi})"
86
87 module_dir=${module_name}-${rpv}-x86_${host_bits}
88 tarball=${module_dir}.tar.gz
89 export need_install=0
90
91 if [[ -f ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml ]] ; then
92         package_arch=$(${XMLSTARLET} sel -t -v "/package/@arch" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml)
93         ipv=$(${XMLSTARLET} sel -t -v "/package/@version" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml)
94         ipvi=$(version_convert ${ipv})
95         ip_major=${ipv%_*}
96         echo "${module_name}: Installed package version ${ipv} (${ipvi})"
97         if [[ "${ip_major}" != "${major_version}" || "${package_arch}" != "x86_${host_bits}" ]] ; then
98                 echo "${module_name}: The installed package is not for this version of Asterisk.  Reinstalling."
99                 need_install=1
100         elif [[ ${rpvi} > ${ipvi} ]] ; then
101                 echo "${module_name}: A newer package is available"
102                 need_install=1
103         else
104                 sums=$(${XMLSTARLET} sel -t -m "//file" -v "@md5sum" -n ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml)
105                 for sum in ${sums} ; do
106                         install_path=$(${XMLSTARLET} sel -t -v "//file[@md5sum = '${sum}']/@install_path" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml )
107                         f=${DESTDIR}$(eval echo ${install_path})
108                         if [[ ! -f ${f} ]] ; then
109                                 echo Not found: ${f}
110                                 need_install=1
111                         else
112                                 cs=$(md5sum ${f} | cut -b1-32)
113                                 if [[ "${cs}" !=  "${sum}" ]] ; then
114                                         echo Checksum mismatch: ${f}
115                                         need_install=1
116                                 fi
117                         fi
118                 done
119         fi
120 else
121         need_install=1
122 fi
123
124 if [[ ${need_install} == 1 ]] ; then
125         if [[ ( -n "${ipvi}" ) && ${ipvi} > ${rpvi} ]] ; then
126                 echo "${module_name}: Installed package is newer than that available for download."
127                 exit 0
128         fi
129 else
130         echo "${module_name} is up to date."
131         exit 0;
132 fi
133
134 need_download=1
135 if [[ -f ${cache_dir}/${module_name}.manifest.xml ]] ; then
136         cpv=$(${XMLSTARLET} sel -t -v "/package/@version" ${cache_dir}/${module_name}.manifest.xml)
137         cpvi=$(version_convert ${cpv})
138         echo "${module_name}: Cached package version ${cpv} (${cpvi})"
139         if [[ ${cpvi} == ${rpvi} && ( -f ${cache_dir}/${tarball} ) ]] ; then
140                 echo "${module_name}: Cached version is available."
141                 need_download=0
142         fi
143 fi
144
145 if [[ ${need_download} = 1 ]] ; then
146         echo "${module_name}: Downloading ${remote_url}/${tarball}"
147         ${WGET} -q -O ${cache_dir}/${tarball} ${remote_url}/${tarball} || {
148                 echo "${module_name}: Unable to fetch ${remote_url}/${tarball}"
149                 exit 1
150         }
151         cp ${tmpdir}/manifest.xml  ${cache_dir}/${module_name}.manifest.xml
152 fi
153
154 tar -xzf ${cache_dir}/${tarball} -C ${cache_dir}
155 trap "rm -rf ${cache_dir}/${module_dir} ; rm -rf ${tmpdir}" EXIT
156
157 echo "${module_name}: Installing."
158
159 if [[ $EUID == 0 ]] ; then
160         install_params="--group=0 --owner=0"
161 fi
162
163 names=$(${XMLSTARLET} sel -t -m "//file" -v "@name" -n ${cache_dir}/${module_dir}/manifest.xml)
164 for name in ${names} ; do
165         source_path=${cache_dir}/${module_dir}/${name}
166         install_path=$(${XMLSTARLET} sel -t -v "//file[@name = '${name}']/@install_path" ${cache_dir}/${module_dir}/manifest.xml)
167         install_path=${DESTDIR}$(eval echo ${install_path})
168         executable=$(${XMLSTARLET} sel -t -v "//file[@name = '${name}']/@executable" ${cache_dir}/${module_dir}/manifest.xml || :)
169         if [[ "${executable}" = "yes" ]] ; then
170                 mode=0755
171         else
172                 mode=0644
173         fi
174
175         ${INSTALL} -Dp ${install_params} --mode=${mode} ${source_path} ${install_path}
176
177 done
178 ${INSTALL} -Dp ${install_params} --mode=0644 ${cache_dir}/${module_dir}/manifest.xml ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml
179
180 echo "${module_name}: Installed."