#!/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