Skip to content

Commit 788275d

Browse files
committed
Improve support for deb822 source files
1 parent be38e7a commit 788275d

1 file changed

Lines changed: 179 additions & 28 deletions

File tree

src/scripts/tools/ppa.sh

Lines changed: 179 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,23 @@ update_lists_helper() {
5050
update_lists() {
5151
local ppa=${1:-}
5252
local ppa_search=${2:-}
53+
local status_token=${3:-$ppa_search}
5354
local list=
54-
status_file=/tmp/os_lists
55+
local status_file=/tmp/os_lists
56+
local hash_cmd
5557
if [[ -n "$ppa" && -n "$ppa_search" ]]; then
56-
list="$list_dir"/"$(basename "$(grep -lr "$ppa_search" "$list_dir")")"
57-
status_file=/tmp/"$(echo -n "$ppa_search" | shasum -a 256 | cut -d ' ' -f 1)"
58-
elif [ -e "$list_file" ] && grep -Eq '^deb |^Types deb' "$list_file"; then
58+
if [ -f "$ppa_search" ]; then
59+
list="$ppa_search"
60+
else
61+
list="$(grep -Elr "$ppa_search" "$list_dir" 2>/dev/null | head -n 1)"
62+
fi
63+
hash_cmd="$(command -v sha256sum || command -v shasum)"
64+
if [ -n "$status_token" ] && [ -n "$hash_cmd" ]; then
65+
status_file=/tmp/os_lists_"$(echo -n "$status_token" | $hash_cmd | awk '{print $1}')"
66+
elif [ -n "$status_token" ]; then
67+
status_file=/tmp/os_lists_$(date +%s)
68+
fi
69+
elif [ -e "$list_file" ] && grep -Eq '^deb |^Types: *deb' "$list_file"; then
5970
list="$list_file"
6071
fi
6172
if [ ! -e "$status_file" ]; then
@@ -64,6 +75,67 @@ update_lists() {
6475
fi
6576
}
6677

78+
# Determine whether deb822 sources are the default on this system.
79+
get_sources_format() {
80+
if [ -n "$sources_format" ]; then
81+
echo "$sources_format"
82+
return
83+
fi
84+
sources_format=deb
85+
if [ -e "$list_dir"/ubuntu.sources ] || [ -e "$list_dir"/debian.sources ]; then
86+
sources_format="deb822"
87+
elif ! [[ "$ID" =~ ubuntu|debian ]]; then
88+
find "$list_dir" -type f -name '*.sources' | grep -q . && sources_format="deb822"
89+
fi
90+
echo "$sources_format"
91+
}
92+
93+
escape_regex() {
94+
printf '%s' "$1" | sed -e 's/[][\.^$*+?{}()|\/]/\\&/g'
95+
}
96+
97+
merge_components() {
98+
local out=() t
99+
for t in $1 $2; do [[ $t && " ${out[*]} " != *" $t "* ]] && out+=("$t"); done
100+
printf '%s\n' "${out[*]}"
101+
}
102+
103+
merge_components_from_file() {
104+
local path=$1
105+
local incoming=$2
106+
local current=
107+
if [ -n "$path" ] && [ -e "$path" ]; then
108+
current="$(grep -E '^Components:' "$path" | head -n 1 | cut -d ':' -f 2 | xargs)"
109+
fi
110+
local merged
111+
merged="$(merge_components "$current" "$incoming")"
112+
if [ -z "$merged" ] || [ "$merged" = "$current" ]; then
113+
return 1
114+
fi
115+
printf '%s\n' "$merged"
116+
}
117+
118+
# Function to get repo patterns based on format.
119+
get_repo_patterns() {
120+
local list_format=$1
121+
local ppa_url=$2
122+
local package_dist=$3
123+
local branches=$4
124+
local escaped_url
125+
local escaped_dist
126+
local escaped_branches
127+
escaped_url="$(escape_regex "$ppa_url")"
128+
escaped_dist="$(escape_regex "$package_dist")"
129+
escaped_branches="$(escape_regex "$branches")"
130+
local deb_pattern="^deb .*${escaped_url} ${escaped_dist} .*${escaped_branches}$"
131+
local deb822_pattern="^URIs: ${escaped_url}$"
132+
if [ "$list_format" = "deb822" ]; then
133+
printf '%s|%s\n' "$deb822_pattern" "$deb_pattern"
134+
else
135+
printf '%s|%s\n' "$deb_pattern" "$deb822_pattern"
136+
fi
137+
}
138+
67139
# Function to get fingerprint from an Ubuntu PPA.
68140
ubuntu_fingerprint() {
69141
ppa="$1"
@@ -104,19 +176,78 @@ add_key() {
104176
fi
105177
}
106178

179+
handle_existing_list() {
180+
local ppa=$1
181+
local list_format=$2
182+
branches=$3
183+
[[ "$list_format" = "deb822" && -n "$check_lists_file" ]] || {
184+
echo "Repository $ppa ($branches) already exists"
185+
return 1
186+
}
187+
[[ "$check_lists_file" = *.list ]] && {
188+
sudo rm -f "$check_lists_file"
189+
return 0
190+
}
191+
local merged_components
192+
merged_components="$(merge_components_from_file "$check_lists_file" "$branches")" && {
193+
sudo rm -f "$check_lists_file"
194+
branches="$merged_components"
195+
return 0
196+
}
197+
echo "Repository $ppa ($branches) already exists"
198+
return 1
199+
}
200+
201+
# Function to write a list file.
202+
write_list() {
203+
local type=$1
204+
local ppa=$2
205+
local url=$3
206+
local suite=$4
207+
local components=$5
208+
local key_file=$6
209+
local list_basename="${ppa%%/*}"-"$ID"-"${ppa#*/}"-"$suite"
210+
local arch
211+
arch="$(dpkg --print-architecture)"
212+
sudo rm -f "$list_dir"/"${ppa/\//-}".list "$list_dir"/"${ppa/\//-}".sources "$list_dir"/"$list_basename".list "$list_dir"/"$list_basename".sources || true
213+
if [ "$type" = "deb822" ]; then
214+
cat <<EOF | sudo tee "$list_dir"/"$list_basename".sources >/dev/null
215+
Types: deb
216+
URIs: $url
217+
Suites: $suite
218+
Components: $components
219+
Architectures: $arch
220+
Signed-By: $key_file
221+
EOF
222+
else
223+
echo "deb [arch=$arch signed-by=$key_file] $url $suite $components" | sudo tee "$list_dir"/"$list_basename".list >/dev/null 2>&1
224+
fi
225+
}
226+
107227
# Function to check if a PPA and its lists exist
108228
check_lists() {
109-
ppa=$1
110-
ppa_search=$2
111-
if grep -Eqr "$ppa_search" "$list_dir"; then
229+
local ppa=$1
230+
local primary=${2:-}
231+
local secondary=${3:-}
232+
local status_token=${4:-$primary}
233+
local match_file=
234+
check_lists_file=
235+
if [ -n "$primary" ]; then
236+
match_file=$(grep -Elr "$primary" "$list_dir" 2>/dev/null | head -n 1)
237+
fi
238+
if [ -z "$match_file" ] && [ -n "$secondary" ]; then
239+
match_file=$(grep -Elr "$secondary" "$list_dir" 2>/dev/null | head -n 1)
240+
fi
241+
if [ -n "$match_file" ]; then
242+
local list_count
112243
list_count="$(sudo find /var/lib/apt/lists -type f -name "*${ppa/\//_}*" | wc -l)"
113244
if [ "$list_count" = "0" ]; then
114-
update_lists "$ppa" "$ppa_search"
245+
update_lists "$ppa" "$match_file" "$status_token"
115246
fi
116-
return 0;
117-
else
118-
return 1;
247+
check_lists_file="$match_file"
248+
return 0
119249
fi
250+
return 1
120251
}
121252

122253
# Function to add a sources list.
@@ -126,19 +257,24 @@ add_list() {
126257
key_source=${3:-"$ppa_url"}
127258
package_dist=${4:-"$VERSION_CODENAME"}
128259
branches=${5:-main}
129-
ppa_search="deb .*$ppa_url $package_dist .*$branches$"
130-
if check_lists "$ppa" "$ppa_search"; then
131-
echo "Repository $ppa already exists";
132-
return 1;
133-
else
134-
arch=$(dpkg --print-architecture)
135-
[ -e "$key_source" ] && key_file=$key_source || key_file="$key_dir"/"${ppa/\//-}"-keyring.gpg
136-
add_key "$ppa" "$ppa_url" "$package_dist" "$key_source" "$key_file"
137-
sudo rm -rf "$list_dir"/"${ppa/\//-}".list || true
138-
echo "deb [arch=$arch signed-by=$key_file] $ppa_url $package_dist $branches" | sudo tee -a "$list_dir"/"${ppa%%/*}"-"$ID"-"${ppa#*/}"-"$package_dist".list >/dev/null 2>&1
139-
update_lists "$ppa" "$ppa_search"
140-
. /etc/os-release
260+
local list_format
261+
list_format="$(get_sources_format)"
262+
local status_token
263+
status_token="${ppa_url}|${package_dist}|${branches}"
264+
local list_path=
265+
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
266+
if check_lists "$ppa" "$primary_pattern" "$secondary_pattern" "$status_token"; then
267+
list_path="$check_lists_file"
268+
handle_existing_list "$ppa" "$list_format" "$branches" || return 1;
269+
check_lists_file=
270+
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
271+
status_token="${ppa_url}|${package_dist}|${branches}"
141272
fi
273+
[ -e "$key_source" ] && key_file=$key_source || key_file="$key_dir"/"${ppa/\//-}"-keyring.gpg
274+
add_key "$ppa" "$ppa_url" "$package_dist" "$key_source" "$key_file"
275+
write_list "$list_format" "$ppa" "$ppa_url" "$package_dist" "$branches" "$key_file"
276+
update_lists "$ppa" "$primary_pattern" "$status_token"
277+
. /etc/os-release
142278
return 0;
143279
}
144280

@@ -148,8 +284,12 @@ check_ppa() {
148284
ppa_url=${2:-"$lpc_ppa/$ppa/ubuntu"}
149285
package_dist=${3:-"$VERSION_CODENAME"}
150286
branches=${4:-main}
151-
ppa_search="deb .*$ppa_url $package_dist .*$branches$"
152-
if check_lists "$ppa" "$ppa_search"; then
287+
local list_format
288+
list_format="$(get_sources_format)"
289+
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
290+
local status_token
291+
status_token="${ppa_url}|${package_dist}|${branches}"
292+
if check_lists "$ppa" "$primary_pattern" "$secondary_pattern" "$status_token"; then
153293
return 0;
154294
else
155295
return 1;
@@ -163,7 +303,7 @@ remove_list() {
163303
for ppa_url in "${ppa_urls[@]}"; do
164304
grep -lr "$ppa_url" "$list_dir" | xargs -n1 sudo rm -f
165305
done
166-
sudo rm -f "$key_dir"/"${ppa/\//-}"-keyring || true
306+
sudo rm -f "$key_dir"/"${ppa/\//-}"-keyring /tmp/os_lists* || true
167307
}
168308

169309
# Function to check if ubuntu ppa is up
@@ -213,12 +353,23 @@ update_ppa() {
213353
ppa_url=${2:-"$lpc_ppa/$ppa/ubuntu"}
214354
package_dist=${4:-"$VERSION_CODENAME"}
215355
branches=${5:-main}
216-
ppa_search="deb .*$ppa_url $package_dist .*$branches"
217-
update_lists "$ppa" "$ppa_search"
356+
local list_format
357+
list_format="$(get_sources_format)"
358+
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
359+
local list_path
360+
list_path="$(grep -Elr "$primary_pattern" "$list_dir" 2>/dev/null | head -n 1)"
361+
if [ -z "$list_path" ] && [ -n "$secondary_pattern" ]; then
362+
list_path="$(grep -Elr "$secondary_pattern" "$list_dir" 2>/dev/null | head -n 1)"
363+
fi
364+
local status_token
365+
status_token="${ppa_url}|${package_dist}|${branches}"
366+
update_lists "$ppa" "${list_path:-$primary_pattern}" "$status_token"
218367
. /etc/os-release
219368
}
220369

221370
# Variables
371+
sources_format=
372+
check_lists_file=
222373
list_dir='/etc/apt/sources.list.d'
223374
list_file="/etc/apt/sources.list.d/$ID.sources"
224375
[ -e "$list_file" ] || list_file='/etc/apt/sources.list'

0 commit comments

Comments
 (0)