about summary refs log tree commit diff
path: root/nixpkgs/pkgs/applications/science/electronics/kicad/update.sh
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/applications/science/electronics/kicad/update.sh')
-rwxr-xr-xnixpkgs/pkgs/applications/science/electronics/kicad/update.sh260
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