Skip to content

Commit fb159a8

Browse files
authored
Fix 3081 - Local mirrorlist parsing bug (#3104)
* Fix 3081 - shortcircuit on empty mirror options * Update * Update
1 parent c9bdaa2 commit fb159a8

File tree

7 files changed

+128
-11
lines changed

7 files changed

+128
-11
lines changed

archinstall/lib/mirrors.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,11 @@ def run(self) -> MirrorConfiguration:
322322

323323
def select_mirror_regions(preset: list[MirrorRegion]) -> list[MirrorRegion]:
324324
mirror_list_handler.load_mirrors()
325-
326325
available_regions = mirror_list_handler.get_mirror_regions()
326+
327+
if not available_regions:
328+
return []
329+
327330
preset_regions = [region for region in available_regions if region in preset]
328331

329332
items = [MenuItem(region.name, value=region) for region in available_regions]

archinstall/lib/models/mirrors.py

+18-10
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ def __eq__(self, other: object) -> bool:
145145

146146

147147
class MirrorListHandler:
148-
def __init__(self) -> None:
148+
def __init__(
149+
self,
150+
local_mirrorlist: Path = Path('/etc/pacman.d/mirrorlist'),
151+
) -> None:
152+
self._local_mirrorlist = local_mirrorlist
149153
self._status_mappings: dict[str, list[MirrorStatusEntryV3]] | None = None
150154

151155
def _mappings(self) -> dict[str, list[MirrorStatusEntryV3]]:
@@ -190,7 +194,7 @@ def load_remote_mirrors(self) -> bool:
190194
return False
191195

192196
def load_local_mirrors(self) -> None:
193-
with Path('/etc/pacman.d/mirrorlist').open('r') as fp:
197+
with self._local_mirrorlist.open('r') as fp:
194198
mirrorlist = fp.read()
195199
self._status_mappings = self._parse_locale_mirrors(mirrorlist)
196200

@@ -236,23 +240,26 @@ def _parse_locale_mirrors(self, mirrorlist: str) -> dict[str, list[MirrorStatusE
236240
lines = mirrorlist.splitlines()
237241

238242
# remove empty lines
239-
lines = [line for line in lines if line]
243+
# lines = [line for line in lines if line]
240244

241245
mirror_list: dict[str, list[MirrorStatusEntryV3]] = {}
242246

243247
current_region = ''
244-
for idx, line in enumerate(lines):
248+
249+
for line in lines:
245250
line = line.strip()
246251

247-
if line.lower().startswith('server'):
252+
if line.startswith('## '):
253+
current_region = line.replace('## ', '').strip()
254+
mirror_list.setdefault(current_region, [])
255+
256+
if line.startswith('Server = '):
248257
if not current_region:
249-
for i in range(idx - 1, 0, -1):
250-
if lines[i].startswith('##'):
251-
current_region = lines[i].replace('#', '').strip()
252-
mirror_list.setdefault(current_region, [])
253-
break
258+
current_region = 'Local'
259+
mirror_list.setdefault(current_region, [])
254260

255261
url = line.removeprefix('Server = ')
262+
256263
mirror_entry = MirrorStatusEntryV3(
257264
url=url.removesuffix('$repo/os/$arch'),
258265
protocol=urllib.parse.urlparse(url).scheme,
@@ -267,6 +274,7 @@ def _parse_locale_mirrors(self, mirrorlist: str) -> dict[str, list[MirrorStatusE
267274
ipv6=True,
268275
details='Locally defined mirror',
269276
)
277+
270278
mirror_list[current_region].append(mirror_entry)
271279

272280
return mirror_list

tests/conftest.py

+15
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,18 @@ def config_fixture() -> Path:
1111
@pytest.fixture(scope='session')
1212
def creds_fixture() -> Path:
1313
return Path(__file__).parent / 'data' / 'test_creds.json'
14+
15+
16+
@pytest.fixture(scope='session')
17+
def mirrorlist_no_country_fixture() -> Path:
18+
return Path(__file__).parent / 'data' / 'mirrorlists' / 'test_no_country'
19+
20+
21+
@pytest.fixture(scope='session')
22+
def mirrorlist_with_country_fixture() -> Path:
23+
return Path(__file__).parent / 'data' / 'mirrorlists' / 'test_with_country'
24+
25+
26+
@pytest.fixture(scope='session')
27+
def mirrorlist_multiple_countries_fixture() -> Path:
28+
return Path(__file__).parent / 'data' / 'mirrorlists' / 'test_multiple_countries'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
################################################################################
2+
################# Arch Linux mirrorlist generated by Reflector #################
3+
################################################################################
4+
5+
# With: reflector @/etc/xdg/reflector/reflector.conf
6+
# When: 2025-01-11 05:37:57 UTC
7+
# From: https://archlinux.org/mirrors/status/json/
8+
# Retrieved: 2025-01-11 05:37:17 UTC
9+
# Last Check: 2025-01-11 05:17:17 UTC
10+
11+
## United States
12+
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
13+
Server = https://america.mirror.pkgbuild.com/$repo/os/$arch
14+
15+
## Australia
16+
Server = https://au.mirror.pkgbuild.com/$repo/os/$arch
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
################################################################################
2+
################# Arch Linux mirrorlist generated by Reflector #################
3+
################################################################################
4+
5+
# With: reflector @/etc/xdg/reflector/reflector.conf
6+
# When: 2025-01-11 05:37:57 UTC
7+
# From: https://archlinux.org/mirrors/status/json/
8+
# Retrieved: 2025-01-11 05:37:17 UTC
9+
# Last Check: 2025-01-11 05:17:17 UTC
10+
11+
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
12+
Server = https://america.mirror.pkgbuild.com/$repo/os/$arch
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
################################################################################
2+
################# Arch Linux mirrorlist generated by Reflector #################
3+
################################################################################
4+
5+
# With: reflector @/etc/xdg/reflector/reflector.conf
6+
# When: 2025-01-11 05:37:57 UTC
7+
# From: https://archlinux.org/mirrors/status/json/
8+
# Retrieved: 2025-01-11 05:37:17 UTC
9+
# Last Check: 2025-01-11 05:17:17 UTC
10+
11+
## United States
12+
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
13+
Server = https://america.mirror.pkgbuild.com/$repo/os/$arch

tests/test_mirrorlist.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from pathlib import Path
2+
3+
from archinstall.lib.models.mirrors import MirrorListHandler
4+
5+
6+
def test_mirrorlist_no_country(mirrorlist_no_country_fixture: Path) -> None:
7+
handler = MirrorListHandler(local_mirrorlist=mirrorlist_no_country_fixture)
8+
handler.load_local_mirrors()
9+
10+
regions = handler.get_mirror_regions()
11+
12+
assert len(regions) == 1
13+
assert regions[0].name == 'Local'
14+
assert regions[0].urls == [
15+
'https://geo.mirror.pkgbuild.com/$repo/os/$arch',
16+
'https://america.mirror.pkgbuild.com/$repo/os/$arch'
17+
]
18+
19+
20+
def test_mirrorlist_with_country(mirrorlist_with_country_fixture: Path) -> None:
21+
handler = MirrorListHandler(local_mirrorlist=mirrorlist_with_country_fixture)
22+
handler.load_local_mirrors()
23+
24+
regions = handler.get_mirror_regions()
25+
26+
assert len(regions) == 1
27+
assert regions[0].name == 'United States'
28+
assert regions[0].urls == [
29+
'https://geo.mirror.pkgbuild.com/$repo/os/$arch',
30+
'https://america.mirror.pkgbuild.com/$repo/os/$arch'
31+
]
32+
33+
34+
def test_mirrorlist_multiple_countries(mirrorlist_multiple_countries_fixture: Path) -> None:
35+
handler = MirrorListHandler(local_mirrorlist=mirrorlist_multiple_countries_fixture)
36+
handler.load_local_mirrors()
37+
38+
regions = handler.get_mirror_regions()
39+
40+
assert len(regions) == 2
41+
assert regions[0].name == 'United States'
42+
assert regions[0].urls == [
43+
'https://geo.mirror.pkgbuild.com/$repo/os/$arch',
44+
'https://america.mirror.pkgbuild.com/$repo/os/$arch'
45+
]
46+
47+
assert regions[1].name == 'Australia'
48+
assert regions[1].urls == [
49+
'https://au.mirror.pkgbuild.com/$repo/os/$arch'
50+
]

0 commit comments

Comments
 (0)