repo 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. #!/usr/bin/env bash
  2. # Drop unsupported releases
  3. drop_unsupported_releases() {
  4. if [[ "$1" == "all" ]]; then
  5. echo "Cleanup: dropping published repositories" | sudo tee -a "${DEBUGFILE}"
  6. BUILD_FW=()
  7. else
  8. echo "Cleanup: dropping unsupported" | sudo tee -a "${DEBUGFILE}"
  9. BUILD_FW=($(grep -rw config/distributions/*/support -ve 'eos' | cut -d"/" -f3))
  10. fi
  11. REPO=($(aptly publish list -config="${CONFIG}" --raw | sed "s/. //g"))
  12. DROP=()
  13. for i in "${REPO[@]}"; do
  14. skip=
  15. for j in "${BUILD_FW[@]}"; do
  16. [[ $i == $j ]] && { skip=1; break ; }
  17. done
  18. [[ -n $skip ]] || DROP+=("$i")
  19. done
  20. # drop
  21. for i in "${DROP[@]}"; do
  22. aptly publish drop -config="${CONFIG}" "${i}" | sudo tee -a "${DEBUGFILE}" >/dev/null
  23. done
  24. }
  25. # Display repository content
  26. #
  27. showall(){
  28. echo "Displaying common repository contents"
  29. aptly repo show -with-packages -config="${CONFIG}" common | tail -n +7
  30. for release in "${DISTROS[@]}"; do
  31. echo "Displaying repository contents for $release-utils"
  32. aptly repo show -with-packages -config="${CONFIG}" "${release}-utils" | tail -n +7
  33. echo "Displaying repository contents for $release-desktop"
  34. aptly repo show -with-packages -config="${CONFIG}" "${release}-desktop" | tail -n +7
  35. done
  36. }
  37. # Adding package
  38. #
  39. # @arg $1 string component
  40. # @arg $2 string incoming folder
  41. # @arg $3 string description
  42. # @arg $4 input folder
  43. #
  44. adding_packages() {
  45. # add deb files to repository if they are not already there
  46. if ! find "${4}${2}" -maxdepth 1 -type f -name "*.deb" 2> /dev/null | grep -q .; then
  47. return 0
  48. fi
  49. for f in "${4}${2}"/*.deb; do
  50. # If we have a list of last known working kernels, repack BSP files to prevent upgrade to kernel that breaks
  51. if [[ -f userpatches/last-known-good.map ]]; then
  52. PACKAGE_NAME=$(dpkg-deb -W $f | awk '{ print $1 }')
  53. for g in $(cat userpatches/last-known-good-kernel-pkg.map); do
  54. # Read values from file
  55. BOARD=$(echo $g | cut -d"|" -f1);
  56. BRANCH=$(echo $g | cut -d"|" -f2);
  57. LINUXFAMILY=$(echo $g | cut -d"|" -f3)
  58. LASTKERNEL=$(echo $g | cut -d"|" -f4);
  59. if [[ ${PACKAGE_NAME} == "armbian-bsp-cli-${BOARD}-${BRANCH}" ]]; then
  60. echo "Setting last kernel upgrade for $BOARD to linux-image-$BRANCH-$BOARD=${LASTKERNEL}"
  61. tempdir=$(mktemp -d)
  62. dpkg-deb -R $f $tempdir
  63. sed -i '/^Replaces:/ s/$/, linux-image-'$BRANCH'-'$LINUXFAMILY' (>> '$LASTKERNEL'), linux-dtb-'$BRANCH'-'$LINUXFAMILY' (>> '$LASTKERNEL')/' $tempdir/DEBIAN/control
  64. dpkg-deb -b $tempdir ${f} >/dev/null
  65. fi
  66. done
  67. fi
  68. aptly repo add -remove-files -force-replace -config="${CONFIG}" "${1}" "${f}"
  69. done
  70. }
  71. # publishing repository
  72. #
  73. # $1: Input folder
  74. # $2: Output folder
  75. # $3: Command
  76. # $4: GPG password
  77. # $5: jammy,sid
  78. publishing(){
  79. # this repository contains packages that are the same in all releases.
  80. if [[ -z $(aptly repo list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep common) ]]; then
  81. aptly repo create -config="${CONFIG}" -distribution="common" -component="main" -comment="Armbian common packages" "common" | sudo tee -a "${DEBUGFILE}" >/dev/null
  82. fi
  83. # add packages from main folder
  84. adding_packages "common" "" "main" "$1"
  85. # create snapshot
  86. UNIQUE_NAME=$(date +%s)
  87. if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "common") ]]; then
  88. aptly -config="${CONFIG}" snapshot drop common | sudo tee -a "${DEBUGFILE}" >/dev/null
  89. fi
  90. aptly -config="${CONFIG}" snapshot create common from repo common | sudo tee -a "${DEBUGFILE}" >/dev/null
  91. # make it for all that exists. It costs little extra time
  92. local distributions=($(grep -rw config/distributions/*/support -ve '' | cut -d"/" -f3))
  93. for release in "${distributions[@]}"; do
  94. # create for each one
  95. if [[ -z $(aptly repo list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
  96. aptly repo create -config="${CONFIG}" -component="${release}-utils" -distribution="${release}" -comment="Armbian ${release}-utils repository" "${release}-utils" | sudo tee -a "${DEBUGFILE}" >/dev/null
  97. fi
  98. if [[ -z $(aptly repo list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
  99. aptly repo create -config="${CONFIG}" -component="${release}-desktop" -distribution="${release}" -comment="Armbian ma${release}-desktop repository" "${release}-desktop" | sudo tee -a "${DEBUGFILE}" >/dev/null
  100. fi
  101. adding_packages "${release}-utils" "/extra/${release}-utils" "release utils" "$1"
  102. adding_packages "${release}-desktop" "/extra/${release}-desktop" "release desktop" "$1"
  103. # drop release utils snapshot
  104. if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
  105. aptly -config="${CONFIG}" snapshot drop ${release}-utils | sudo tee -a "${DEBUGFILE}" 2>/dev/null
  106. fi
  107. # drop release desktop snapshot
  108. if [[ -n $(aptly snapshot list -config="${CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
  109. aptly -config="${CONFIG}" snapshot drop ${release}-desktop | sudo tee -a "${DEBUGFILE}" 2>/dev/null
  110. fi
  111. aptly -config="${CONFIG}" snapshot create ${release}-utils from repo ${release}-utils | sudo tee -a "${DEBUGFILE}" >/dev/null
  112. aptly -config="${CONFIG}" snapshot create ${release}-desktop from repo ${release}-desktop | sudo tee -a "${DEBUGFILE}" >/dev/null
  113. echo "Publishing $release"
  114. aptly publish \
  115. -architectures="armhf,arm64,amd64,riscv64,i386,all" \
  116. -passphrase="${4}" \
  117. -origin="Armbian" \
  118. -label="Armbian" \
  119. -config="${CONFIG}" \
  120. -component=main,${release}-utils,${release}-desktop \
  121. -distribution="${release}" snapshot common ${release}-utils ${release}-desktop > /dev/null
  122. done
  123. # cleanup
  124. aptly db cleanup -config="${CONFIG}"
  125. # key
  126. mkdir -p "${2}"/public/
  127. cp config/armbian.key "${2}"/public/
  128. # write repo sync control file
  129. sudo date +%s > ${2}/public/control
  130. # display what we have
  131. showall
  132. }
  133. #
  134. # $1: Input folder
  135. # $2: Output folder
  136. # $3: Command
  137. # $4: GPG password
  138. # $5: jammy,sid
  139. # $6: list of packages to delete
  140. repo-manipulate() {
  141. # read comma delimited distros into array
  142. IFS=', ' read -r -a DISTROS <<< "$5"
  143. case $3 in
  144. serve)
  145. sudo aptly serve -listen=$(ip -f inet addr | grep -Po 'inet \K[\d.]+' | grep -v 127.0.0.1 | head -1):80 -config="${CONFIG}"
  146. return 0
  147. ;;
  148. html)
  149. cat tools/repository/header.html
  150. for release in "${DISTROS[@]}"; do
  151. echo "<thead><tr><td colspan=3><h2>$release</h2></tr><tr><th>Main</th><th>Utils</th><th>Desktop</th></tr></thead>"
  152. echo "<tbody><tr><td width=33% valing=top>"
  153. aptly repo show -with-packages -config="${CONFIG}" "${release}-utils" | tail -n +7 | sed 's/.*/&<br>/'
  154. echo "</td><td width=33% valign=top>" | sudo tee -a ${filename}
  155. aptly repo show -with-packages -config="${CONFIG}" "${release}-desktop" | tail -n +7 | sed 's/.*/&<br>/'
  156. echo "</td></tr></tbody>"
  157. done
  158. cat tools/repository/footer.html
  159. return 0
  160. ;;
  161. delete)
  162. echo "Deleting $6 from common"
  163. aptly -config="${CONFIG}" repo remove common "$6"
  164. for release in "${DISTROS[@]}"; do
  165. echo "Deleting $6 from $release-utils"
  166. aptly -config="${CONFIG}" repo remove "${release}-utils" "$6"
  167. echo "Deleting $6 from $release-desktop"
  168. aptly -config="${CONFIG}" repo remove "${release}-desktop" "$6"
  169. done
  170. return 0
  171. ;;
  172. show)
  173. showall
  174. return 0
  175. ;;
  176. unique)
  177. # which package should be removed from all repositories
  178. IFS=$'\n'
  179. while true; do
  180. LIST=()
  181. LIST+=($(aptly repo show -with-packages -config="${CONFIG}" common | tail -n +7))
  182. for release in "${DISTROS[@]}"; do
  183. LIST+=($(aptly repo show -with-packages -config="${CONFIG}" "${release}-utils" | tail -n +7))
  184. LIST+=($(aptly repo show -with-packages -config="${CONFIG}" "${release}-desktop" | tail -n +7))
  185. done
  186. LIST=($(echo "${LIST[@]}" | tr ' ' '\n' | sort -u))
  187. new_list=()
  188. # create a human readable menu
  189. for ((n = 0; n < $((${#LIST[@]})); n++)); do
  190. new_list+=("${LIST[$n]}")
  191. new_list+=("")
  192. done
  193. LIST=("${new_list[@]}")
  194. LIST_LENGTH=$((${#LIST[@]} / 2))
  195. exec 3>&1
  196. TARGET_VERSION=$(dialog --cancel-label "Cancel" --backtitle "BACKTITLE" --no-collapse --title \
  197. "Remove packages from repositories" --clear --menu "Delete" $((9 + LIST_LENGTH)) 82 65 "${LIST[@]}" 2>&1 1>&3)
  198. exitstatus=$?
  199. exec 3>&-
  200. if [[ $exitstatus -eq 0 ]]; then
  201. aptly repo remove -config="${CONFIG}" "common" "$TARGET_VERSION"
  202. for release in "${DISTROS[@]}"; do
  203. aptly repo remove -config="${CONFIG}" "${release}-utils" "$TARGET_VERSION"
  204. aptly repo remove -config="${CONFIG}" "${release}-desktop" "$TARGET_VERSION"
  205. done
  206. else
  207. return 1
  208. fi
  209. aptly db cleanup -config="${CONFIG}" > /dev/null 2>&1
  210. # remove empty folders
  211. find $2/public -type d -empty -print -exec rm -rf {} \;
  212. done
  213. ;;
  214. update)
  215. # remove old releases from publishing
  216. drop_unsupported_releases "all"
  217. publishing "$1" "$2" "$3" "$4" "$5"
  218. ;;
  219. *)
  220. echo -e "Unknown command"
  221. return 1
  222. ;;
  223. esac
  224. }
  225. # defaults
  226. input="output/debs-beta"
  227. output="output/repository"
  228. command="show"
  229. releases=$(grep -rw config/distributions/*/support -ve 'eos' | cut -d"/" -f3 | xargs | sed -e 's/ /,/g')
  230. help()
  231. {
  232. echo "Armbian wrapper for Aptly v1.0
  233. (c) Igor Pecovnik, igor@armbian.com
  234. License: (MIT) <https://mit-license.org/>
  235. Usage: $0 [ -short | --long ]
  236. -h --help displays this
  237. -i --input [input folder]
  238. -o --output [output folder]
  239. -p --password [GPG password]
  240. -r --repository [jammy,sid,bullseye,...]
  241. -l --list [\"Name (% linux*)|armbian-config\"]
  242. -c --command
  243. [show] displays packages in each repository
  244. [html] displays packages in each repository in html form
  245. [serve] serve repository - useful for local diagnostics
  246. [unique] manually select which package should be removed from all repositories
  247. [update] search for packages in input folder
  248. [delete] delete package from -l LIST of packages
  249. "
  250. exit 2
  251. }
  252. SHORT=i:,l:,o:,c:,p:,r:,h
  253. LONG=input:,list:,output:,command:,password:,releases:,help
  254. OPTS=$(getopt -a -n repo --options $SHORT --longoptions $LONG -- "$@")
  255. DEBUGFILE="/var/log/repo-management.log"
  256. VALID_ARGUMENTS=$# # Returns the count of arguments that are in short or long options
  257. eval set -- "$OPTS"
  258. while :
  259. do
  260. case "$1" in
  261. -i | --input )
  262. input="$2"
  263. shift 2
  264. ;;
  265. -o | --output )
  266. output="$2"
  267. shift 2
  268. ;;
  269. -c | --command )
  270. command="$2"
  271. shift 2
  272. ;;
  273. -p | --password )
  274. password="$2"
  275. shift 2
  276. ;;
  277. -r | --releases )
  278. releases="$2"
  279. shift 2
  280. ;;
  281. -l | --list )
  282. list="$2"
  283. shift 2
  284. ;;
  285. -h | --help)
  286. help
  287. ;;
  288. --)
  289. shift;
  290. break
  291. ;;
  292. *)
  293. echo "Unexpected option: $1"
  294. help
  295. ;;
  296. esac
  297. done
  298. # redefine output folder in Aptly
  299. TempDir="$(mktemp -d || exit 1)"
  300. sed 's|"rootDir": ".*"|"rootDir": "'$output'"|g' tools/repository/aptly.conf > "${TempDir}"/aptly.conf
  301. CONFIG="${TempDir}/aptly.conf"
  302. # main
  303. repo-manipulate "$input" "$output" "$command" "$password" "$releases" "$list"
  304. RETURN=$?
  305. exit $RETURN