diff options
Diffstat (limited to 'nixpkgs/pkgs/applications/science/electronics/kicad/update.sh')
-rwxr-xr-x | nixpkgs/pkgs/applications/science/electronics/kicad/update.sh | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/applications/science/electronics/kicad/update.sh b/nixpkgs/pkgs/applications/science/electronics/kicad/update.sh new file mode 100755 index 000000000000..b47e2d84b336 --- /dev/null +++ b/nixpkgs/pkgs/applications/science/electronics/kicad/update.sh @@ -0,0 +1,260 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p coreutils git nix curl jq +# shellcheck shell=bash enable=all + +set -e +shopt -s inherit_errexit + +# this script will generate versions.nix in the right location +# this should contain the versions' revs and hashes +# the stable revs are stored only for ease of skipping + +# by default nix-prefetch-url uses XDG_RUNTIME_DIR as tmp +# which is /run/user/1000, which defaults to 10% of your RAM +# unless you have over 64GB of ram that'll be insufficient +# resulting in "tar: no space left on device" for packages3d +# hence: +export TMPDIR=/tmp + +# if something goes unrepairably wrong, run 'update.sh all clean' + +# TODO +# support parallel instances for each pname +# currently risks reusing old data +# no getting around manually checking if the build product works... +# if there is, default to commiting? +# won't work when running in parallel? +# remove items left in /nix/store? +# reuse hashes of already checked revs (to avoid redownloading testing's packages3d) + +# nixpkgs' update.nix passes in UPDATE_NIX_PNAME to indicate which package is being updated +# assigning a default value to that as shellcheck doesn't like the use of unassigned variables +: "${UPDATE_NIX_PNAME:=""}" +# update.nix can also parse JSON output of this script to formulate a commit +# this requires we collect the version string in the old versions.nix for the updated package +old_version="" +new_version="" + + +# get the latest tag that isn't an RC or *.99 +latest_tags="$(git ls-remote --tags --sort -version:refname https://gitlab.com/kicad/code/kicad.git)" +# using a scratch variable to ensure command failures get caught (SC2312) +scratch="$(grep -o 'refs/tags/[0-9]*\.[0-9]*\.[0-9]*$' <<< "${latest_tags}")" +scratch="$(grep -ve '\.99' -e '\.9\.9' <<< "${scratch}")" +scratch="$(sed -n '1p' <<< "${scratch}")" +latest_tag="$(cut -d '/' -f 3 <<< "${scratch}")" + +# get the latest branch name for testing +branches="$(git ls-remote --heads --sort -version:refname https://gitlab.com/kicad/code/kicad.git)" +scratch="$(grep -o 'refs/heads/[0-9]*\.[0-9]*$' <<< "${branches}")" +scratch="$(sed -n '1p' <<< "${scratch}")" +testing_branch="$(cut -d '/' -f 3 <<< "${scratch}")" + +# "latest_tag" and "master" directly refer to what we want +# "testing" uses "testing_branch" found above +all_versions=( "${latest_tag}" testing master ) + +prefetch="nix-prefetch-url --unpack --quiet" + +clean="" +check_stable="" +check_testing=1 +check_unstable=1 +commit="" + +for arg in "$@" "${UPDATE_NIX_PNAME}"; do + case "${arg}" in + help|-h|--help) echo "Read me!" >&2; exit 1; ;; + kicad|kicad-small|release|tag|stable|5*|6*|7*|8*) check_stable=1; check_testing=""; check_unstable="" ;; + *testing|kicad-testing-small) check_testing=1; check_unstable="" ;; + *unstable|*unstable-small|master|main) check_unstable=1; check_testing="" ;; + latest|now|today) check_unstable=1; check_testing=1 ;; + all|both|full) check_stable=1; check_testing=1; check_unstable=1 ;; + clean|fix|*fuck) check_stable=1; check_testing=1; check_unstable=1; clean=1 ;; + commit) commit=1 ;; + *) ;; + esac +done + +here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +commit_date() { + gitlab_json="$(curl -s https://gitlab.com/api/v4/projects/kicad%2Fcode%2Fkicad/repository/commits/"$1")" + commit_created="$(jq .created_at --raw-output <<< "${gitlab_json}")" + date --date="${commit_created}" --iso-8601 --utc +} + +file="${here}/versions.nix" +# just in case this runs in parallel +tmp="${here}/,versions.nix.${RANDOM}" + +libs=( symbols templates footprints packages3d ) + +get_rev() { + git ls-remote "$@" +} + +gitlab="https://gitlab.com/kicad" +# append commit hash or tag +src_pre="https://gitlab.com/api/v4/projects/kicad%2Fcode%2Fkicad/repository/archive.tar.gz?sha=" +lib_pre="https://gitlab.com/api/v4/projects/kicad%2Flibraries%2Fkicad-" +lib_mid="/repository/archive.tar.gz?sha=" + +# number of items updated +count=0 + +printf "Latest tag is %s\n" "${latest_tag}" >&2 + +if [[ ! -f ${file} ]]; then + echo "No existing file, generating from scratch" >&2 + check_stable=1; check_testing=1; check_unstable=1; clean=1 +fi + +printf "Writing %s\n" "${tmp}" >&2 + +# not a dangling brace, grouping the output to redirect to file +{ + +printf "# This file was generated by update.sh\n\n" +printf "{\n" + +for version in "${all_versions[@]}"; do + + src_version=${version}; + lib_version=${version}; + # testing is the stable branch on the main repo + # but the libraries don't have such a branch + # only the latest release tag and a master branch + if [[ ${version} == "testing" ]]; then + src_version=${testing_branch}; + lib_version=${latest_tag}; + fi + + if [[ ${version} == "master" ]]; then + pname="kicad-unstable" + elif [[ ${version} == "testing" ]]; then + pname="kicad-testing" + else + pname="kicad" + fi + + # skip a version if we don't want to check it + if [[ (-n ${check_stable} && ${version} != "master" && ${version} != "testing") \ + || (-n ${check_testing} && ${version} == "testing") \ + || (-n ${check_unstable} && ${version} == "master" ) ]]; then + + now=$(commit_date "${src_version}") + + if [[ ${version} == "master" ]]; then + pname="kicad-unstable" + new_version="${now}" + elif [[ ${version} == "testing" ]]; then + pname="kicad-testing" + new_version="${testing_branch}-${now}" + else + pname="kicad" + new_version="${version}" + fi + + printf "\nChecking %s\n" "${pname}" >&2 + + printf "%2s\"%s\" = {\n" "" "${pname}" + printf "%4skicadVersion = {\n" "" + printf "%6sversion =\t\t\t\"%s\";\n" "" "${new_version}" + printf "%6ssrc = {\n" "" + + echo "Checking src" >&2 + scratch="$(get_rev "${gitlab}"/code/kicad.git "${src_version}")" + src_rev="$(cut -f1 <<< "${scratch}")" + has_rev="$(grep -sm 1 "\"${pname}\"" -A 4 "${file}" | grep -sm 1 "${src_rev}" || true)" + has_hash="$(grep -sm 1 "\"${pname}\"" -A 5 "${file}" | grep -sm 1 "sha256" || true)" + old_version="$(grep -sm 1 "\"${pname}\"" -A 3 "${file}" | grep -sm 1 "version" | awk -F "\"" '{print $2}' || true)" + + if [[ -n ${has_rev} && -n ${has_hash} && -z ${clean} ]]; then + echo "Reusing old ${pname}.src.sha256, already latest .rev at ${old_version}" >&2 + scratch=$(grep -sm 1 "\"${pname}\"" -A 5 "${file}") + grep -sm 1 "rev" -A 1 <<< "${scratch}" + else + prefetched="$(${prefetch} "${src_pre}${src_rev}")" + printf "%8srev =\t\t\t\"%s\";\n" "" "${src_rev}" + printf "%8ssha256 =\t\t\"%s\";\n" "" "${prefetched}" + count=$((count+1)) + fi + printf "%6s};\n" "" + printf "%4s};\n" "" + + printf "%4slibVersion = {\n" "" + printf "%6sversion =\t\t\t\"%s\";\n" "" "${new_version}" + printf "%6slibSources = {\n" "" + + for lib in "${libs[@]}"; do + echo "Checking ${lib}" >&2 + url="${gitlab}/libraries/kicad-${lib}.git" + scratch="$(get_rev "${url}" "${lib_version}")" + scratch="$(cut -f1 <<< "${scratch}")" + lib_rev="$(tail -n1 <<< "${scratch}")" + has_rev="$(grep -sm 1 "\"${pname}\"" -A 19 "${file}" | grep -sm 1 "${lib_rev}" || true)" + has_hash="$(grep -sm 1 "\"${pname}\"" -A 20 "${file}" | grep -sm 1 "${lib}.sha256" || true)" + if [[ -n ${has_rev} && -n ${has_hash} && -z ${clean} ]]; then + echo "Reusing old kicad-${lib}-${new_version}.src.sha256, already latest .rev" >&2 + scratch="$(grep -sm 1 "\"${pname}\"" -A 20 "${file}")" + grep -sm 1 "${lib}" -A 1 <<< "${scratch}" + else + prefetched="$(${prefetch} "${lib_pre}${lib}${lib_mid}${lib_rev}")" + printf "%8s%s.rev =\t" "" "${lib}" + case "${lib}" in + symbols|templates) printf "\t" ;; *) ;; + esac + printf "\"%s\";\n" "${lib_rev}" + printf "%8s%s.sha256 =\t\"%s\";\n" "" "${lib}" "${prefetched}" + count=$((count+1)) + fi + done + printf "%6s};\n" "" + printf "%4s};\n" "" + printf "%2s};\n" "" + else + printf "\nReusing old %s\n" "${pname}" >&2 + grep -sm 1 "\"${pname}\"" -A 21 "${file}" + fi +done +printf "}\n" +} > "${tmp}" + +if grep '""' "${tmp}"; then + echo "empty value detected, out of space?" >&2 + exit "1" +fi + +mv "${tmp}" "${file}" + +printf "\nFinished\nMoved output to %s\n\n" "${file}" >&2 + +if [[ ${count} -gt 0 ]]; then + if [[ ${count} -gt 1 ]]; then s="s"; else s=""; fi + echo "${count} revision${s} changed" >&2 + if [[ -n ${commit} ]]; then + git commit -am "$(printf "kicad: automatic update of %s item%s\n" "${count}" "${s}")" + fi + echo "Please confirm the new versions.nix works before making a PR." >&2 +else + echo "No changes, those checked are up to date" >&2 +fi + +# using UPDATE_NIX_ATTR_PATH to detect if this is being called from update.nix +# and output JSON to describe the changes +if [[ -n ${UPDATE_NIX_ATTR_PATH} ]]; then + + if [[ ${count} -eq 0 ]]; then echo "[{}]"; exit 0; fi + + jq -n \ + --arg attrpath "${UPDATE_NIX_PNAME}" \ + --arg oldversion "${old_version}" \ + --arg newversion "${new_version}" \ + --arg file "${file}" \ +'[{ + "attrPath": $attrpath, + "oldVersion": $oldversion, + "newVersion": $newversion, + "files": [ $file ] +}]' +fi |