shellcheck fixes, including real bug
[distro-functions] / src / identify-distros
index 0d7a8fe1a9a1eff9b93a178efbe4839871c40c41..fa661721cfa3882dd9cd006e95688e334e7d1896 100644 (file)
@@ -1,5 +1,12 @@
 #!/bin/bash
-# Copyright (C) 2014 Ian Kelling
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to switch
+# its license to GPL.
+
+# Copyright 2024 Ian Kelling
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-distro_name() {
-    if [[ -f /etc/fedora-release ]]; then
-        echo fedora
+distro-name() {
+  local x
+  if [[ -f /etc/fedora-release ]]; then
+    echo fedora
+  elif [[ -e /etc/os-release ]]; then
+    sed -rn 's/^ID=(.*)/\1/p' /etc/os-release
+  elif type -p lsb_release &>/dev/null; then
+    # well, this is more standard, but it's 2 ms vs 200 ms
+    x=$(lsb_release -si); echo ${x,,}
+  else
+    echo "unknown distro"
+    return 1
+  fi
+}
+
+distro-name-compat() {
+  local x
+  x=$(distro-name)
+  case $x in
+    trisquel)
+      echo ubuntu
+      ;;
+    *)
+      printf "%s\n" "$x"
+      ;;
+  esac
+}
+
+distro-name-ver() {
+  printf "%s\n" "$(distro-name)$(debian-archive)"
+}
+
+distro-num() {
+  # Subshell keeps environment clean.
+  ( . /etc/os-release
+    # in ubuntu the .x matters, trisquel it doesnt
+    if [[ $ID == ubuntu ]]; then
+      echo $VERSION_ID
     else
-        grep "^ID=.*" /etc/os-release | sed 's/^ID=//'
+      echo ${VERSION_ID%%.*}
+    fi
+  )
+}
+
+debian-archive() {
+  isdeb || return 0
+  local archive expression pri name highpri shortest
+  local policy="${1:-$(apt-cache policy)}" || return $?
+  # a = archive
+  # n = codename
+  # o = origin
+  # c = component (licensing component)
+  # l = label (Debian{,-Security,-Updates})
+  local d
+  d=$(distro-name)
+  # goto b for archive lines we are interested in, a for lines we arent
+  # print priority + archive name. priority is in
+  # the previous line from the archive line.
+  # case insensitive, because $d is lower and we are matching with first char upper
+  read -rd '' expression <<EOF ||:
+/o=$d/I!b a;/l=$d/I!b a;/c=main/!b a b b;
+: a;s/^ *([-0-9]+).*/\1/;h;b;
+: b;s/^.*a=([^,]+).*/ \1/;H;x;s/\n//;p
+EOF
+  while read -r pri name; do
+    # in ubuntu, we get archives like flidas, flidas-updates, all the same pri,
+    # so just pick the shortest one.
+    if [[ ! $highpri ]]; then
+      highpri=$pri;
+      shortest=$name
+      continue
+    fi
+    if [[ $pri != "$highpri" ]]; then
+      break
+    fi
+    if (( ${#shortest} > ${#name} )); then
+      shortest=$name
     fi
+  done < <(echo "$policy" | sed -rn "$expression" | sort -rn || [[ $? == 141 ]])
+  echo "$shortest"
 }
+
+# formatted for use in pfile() in package-manager-abstractions
+positive-origins() {
+  isdeb || return 0
+  local archive expression pri name highpri shortest policy
+  # In theory we might want a policy subset, we could alter this to pass
+  # it in.
+  policy="(apt-cache policy)"
+  # a = archive
+  # n = codename
+  # o = origin
+  # c = component (licensing component)
+  # l = label (Debian{,-Security,-Updates})
+  read -rd '' expression <<EOF ||:
+/^ *([-0-9]+).*/{s/^ *([-0-9]+).*/\1/;h}
+/^.*o=([^,]+).*/{s/^.*o=([^,]+).*/ \1/;H;x;s/\n//;p}
+EOF
+  origins=
+  while read -r pri name; do
+    if (( pri > 0 )); then
+      if [[ ! $origins ]]; then
+        origins=$name
+      else
+        origins+=,$name
+      fi
+    fi
+  done < <(echo "$policy" | sed -rn "$expression" | sort -rn || [[ $? == 141 ]])
+  echo $origins
+}
+
+isdebian-testing() {
+  [[ $(debian-archive) == testing ]]
+}
+# I only do testing or stable.
+isdebian-stable() {
+  [[ $(debian-archive) == stable ]]
+}
+
+debian-codename() {
+  isdeb || return 0
+  local policy
+  policy="$(apt-cache policy)"
+  archive=$(debian-archive "$policy")
+  printf "%s\n" "$policy" | sed -rn "s/^.*a=$archive,n=([a-z]+).*/\1/p;T;q" || [[ $? == 141 ]]
+}
+debian-codename-compat() {
+  local n
+  n=$(debian-codename)
+  case $n in
+    flidas)
+      echo xenial
+      ;;
+    etiona)
+      echo bionic
+      ;;
+    nabia)
+      echo focal
+      ;;
+    aramo)
+      echo jammy
+      ;;
+    *)
+      echo $n
+      ;;
+  esac
+}
+
 isfedora() {
-    local d=$(distro_name)
-    [[ $d == fedora ]] || return 1
+  [[ $(distro-name) == fedora ]]
 }
 isdebian() {
-    local d=$(distro_name)
-    [[ $d == debian ]] || return 1
+  [[ $(distro-name) == debian ]]
 }
-isdeb() {
-    local d=$(distro_name)
-    [[ $d == debian || $d == ubuntu ]] || return 1
+isarch() {
+  [[ $(distro-name) == arch ]]
 }
 isubuntu() {
-    local d=$(distro_name)
-    [[ $d == ubuntu ]] || return 1
+  [[ $(distro-name) == ubuntu ]]
+}
+istrisquel() {
+  [[ $(distro-name) == trisquel ]]
 }
+# is debian/apt based
+isdeb() { command -v apt-get &>/dev/null; }