Fix truncated package metadata in additional packages preview (#3580)

This commit is contained in:
Softer 2026-05-01 13:15:11 +03:00
parent 6fefa3b6f5
commit 652ec9616f
3 changed files with 41 additions and 10 deletions

View File

@ -1,3 +1,5 @@
import os
import textwrap
from dataclasses import dataclass, field
from enum import Enum
from functools import cached_property
@ -134,13 +136,32 @@ class AvailablePackage(BaseModel):
# return all package info line by line
def info(self) -> str:
output = ''
for key, value in self.model_dump().items():
key = key.replace('_', ' ').capitalize()
key = key.ljust(self.longest_key)
output += f'{key} : {value}\n'
# Preview pane occupies roughly half the terminal width when shown
# alongside the option list. Wrap each value to fit so long fields
# (Description, Optional Deps, etc.) do not produce horizontal scroll.
try:
cols = os.get_terminal_size().columns
except OSError:
cols = 80
preview_width = max(40, cols // 2 - 5)
indent = ' ' * (self.longest_key + 3)
return output
lines: list[str] = []
for key, value in self.model_dump().items():
key_label = key.replace('_', ' ').capitalize().ljust(self.longest_key)
prefix = f'{key_label} : '
lines.append(
textwrap.fill(
str(value),
width=preview_width,
initial_indent=prefix,
subsequent_indent=indent,
break_long_words=False,
break_on_hyphens=False,
),
)
return '\n'.join(lines) + '\n'
@cached_property
def get_depends_on(self) -> list[str]:

View File

@ -9,6 +9,12 @@ from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
# Force pacman to emit untruncated single-line field values. With the default
# pty width of 80 columns, pacman wraps long fields like Description across
# multiple lines, and our line-based parser ends up dropping the continuation
# lines after they get pre-stripped of their leading whitespace. See #3580.
_WIDE_PACMAN_ENV = {'COLUMNS': '500'}
def installed_package(package: str) -> LocalPackage | None:
try:
@ -52,7 +58,7 @@ def package_group_info(package: str) -> PackageGroup | None:
def available_package(package: str) -> AvailablePackage | None:
try:
package_info: list[str] = []
for line in Pacman.run(f'-S --info {package}'):
for line in Pacman.run(f'-S --info {package}', environment_vars=_WIDE_PACMAN_ENV):
package_info.append(line.decode().strip())
return _parse_package_output(package_info, AvailablePackage)
@ -78,7 +84,7 @@ def list_available_packages(
except Exception as e:
debug(f'Failed to sync Arch Linux package database: {e}')
for line in Pacman.run('-S --info'):
for line in Pacman.run('-S --info', environment_vars=_WIDE_PACMAN_ENV):
dec_line = line.decode().strip()
current_package.append(dec_line)

View File

@ -18,7 +18,11 @@ class Pacman:
self.target = target
@staticmethod
def run(args: str, default_cmd: str = 'pacman') -> SysCommand:
def run(
args: str,
default_cmd: str = 'pacman',
environment_vars: dict[str, str] | None = None,
) -> SysCommand:
"""
A centralized function to call `pacman` from.
It also protects us from colliding with other running pacman sessions (if used locally).
@ -37,7 +41,7 @@ class Pacman:
error(tr('Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall.'))
sys.exit(1)
return SysCommand(f'{default_cmd} {args}')
return SysCommand(f'{default_cmd} {args}', environment_vars=environment_vars)
def ask(self, error_message: str, bail_message: str, func: Callable, *args, **kwargs) -> None: # type: ignore[no-untyped-def, type-arg]
while True: