fa661721cfa3882dd9cd006e95688e334e7d1896
[distro-functions] / src / identify-distros
1 #!/bin/bash
2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to switch
7 # its license to GPL.
8
9 # Copyright 2024 Ian Kelling
10
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
14
15 # http://www.apache.org/licenses/LICENSE-2.0
16
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
22
23 distro-name() {
24 local x
25 if [[ -f /etc/fedora-release ]]; then
26 echo fedora
27 elif [[ -e /etc/os-release ]]; then
28 sed -rn 's/^ID=(.*)/\1/p' /etc/os-release
29 elif type -p lsb_release &>/dev/null; then
30 # well, this is more standard, but it's 2 ms vs 200 ms
31 x=$(lsb_release -si); echo ${x,,}
32 else
33 echo "unknown distro"
34 return 1
35 fi
36 }
37
38 distro-name-compat() {
39 local x
40 x=$(distro-name)
41 case $x in
42 trisquel)
43 echo ubuntu
44 ;;
45 *)
46 printf "%s\n" "$x"
47 ;;
48 esac
49 }
50
51 distro-name-ver() {
52 printf "%s\n" "$(distro-name)$(debian-archive)"
53 }
54
55 distro-num() {
56 # Subshell keeps environment clean.
57 ( . /etc/os-release
58 # in ubuntu the .x matters, trisquel it doesnt
59 if [[ $ID == ubuntu ]]; then
60 echo $VERSION_ID
61 else
62 echo ${VERSION_ID%%.*}
63 fi
64 )
65 }
66
67 debian-archive() {
68 isdeb || return 0
69 local archive expression pri name highpri shortest
70 local policy="${1:-$(apt-cache policy)}" || return $?
71 # a = archive
72 # n = codename
73 # o = origin
74 # c = component (licensing component)
75 # l = label (Debian{,-Security,-Updates})
76 local d
77 d=$(distro-name)
78 # goto b for archive lines we are interested in, a for lines we arent
79 # print priority + archive name. priority is in
80 # the previous line from the archive line.
81 # case insensitive, because $d is lower and we are matching with first char upper
82 read -rd '' expression <<EOF ||:
83 /o=$d/I!b a;/l=$d/I!b a;/c=main/!b a b b;
84 : a;s/^ *([-0-9]+).*/\1/;h;b;
85 : b;s/^.*a=([^,]+).*/ \1/;H;x;s/\n//;p
86 EOF
87 while read -r pri name; do
88 # in ubuntu, we get archives like flidas, flidas-updates, all the same pri,
89 # so just pick the shortest one.
90 if [[ ! $highpri ]]; then
91 highpri=$pri;
92 shortest=$name
93 continue
94 fi
95 if [[ $pri != "$highpri" ]]; then
96 break
97 fi
98 if (( ${#shortest} > ${#name} )); then
99 shortest=$name
100 fi
101 done < <(echo "$policy" | sed -rn "$expression" | sort -rn || [[ $? == 141 ]])
102 echo "$shortest"
103 }
104
105 # formatted for use in pfile() in package-manager-abstractions
106 positive-origins() {
107 isdeb || return 0
108 local archive expression pri name highpri shortest policy
109 # In theory we might want a policy subset, we could alter this to pass
110 # it in.
111 policy="(apt-cache policy)"
112 # a = archive
113 # n = codename
114 # o = origin
115 # c = component (licensing component)
116 # l = label (Debian{,-Security,-Updates})
117 read -rd '' expression <<EOF ||:
118 /^ *([-0-9]+).*/{s/^ *([-0-9]+).*/\1/;h}
119 /^.*o=([^,]+).*/{s/^.*o=([^,]+).*/ \1/;H;x;s/\n//;p}
120 EOF
121 origins=
122 while read -r pri name; do
123 if (( pri > 0 )); then
124 if [[ ! $origins ]]; then
125 origins=$name
126 else
127 origins+=,$name
128 fi
129 fi
130 done < <(echo "$policy" | sed -rn "$expression" | sort -rn || [[ $? == 141 ]])
131 echo $origins
132 }
133
134 isdebian-testing() {
135 [[ $(debian-archive) == testing ]]
136 }
137 # I only do testing or stable.
138 isdebian-stable() {
139 [[ $(debian-archive) == stable ]]
140 }
141
142 debian-codename() {
143 isdeb || return 0
144 local policy
145 policy="$(apt-cache policy)"
146 archive=$(debian-archive "$policy")
147 printf "%s\n" "$policy" | sed -rn "s/^.*a=$archive,n=([a-z]+).*/\1/p;T;q" || [[ $? == 141 ]]
148 }
149 debian-codename-compat() {
150 local n
151 n=$(debian-codename)
152 case $n in
153 flidas)
154 echo xenial
155 ;;
156 etiona)
157 echo bionic
158 ;;
159 nabia)
160 echo focal
161 ;;
162 aramo)
163 echo jammy
164 ;;
165 *)
166 echo $n
167 ;;
168 esac
169 }
170
171 isfedora() {
172 [[ $(distro-name) == fedora ]]
173 }
174 isdebian() {
175 [[ $(distro-name) == debian ]]
176 }
177 isarch() {
178 [[ $(distro-name) == arch ]]
179 }
180 isubuntu() {
181 [[ $(distro-name) == ubuntu ]]
182 }
183 istrisquel() {
184 [[ $(distro-name) == trisquel ]]
185 }
186 # is debian/apt based
187 isdeb() { command -v apt-get &>/dev/null; }