Исправил adb окружение для списка устройств

Этот коммит содержится в:
Виктор
2026-05-12 01:18:26 +09:00
родитель a04f096ed1
Коммит b117c275d6
+24 -32
Просмотреть файл
@@ -8,21 +8,35 @@ DATA_DIR = Path(os.getenv('DEVCONSOLE_DATA_DIR', '/var/lib/devconsole'))
PROJECTS_DIR = DATA_DIR / 'projects' PROJECTS_DIR = DATA_DIR / 'projects'
def _runtime_env_prefix() -> str:
runtime_home = os.getenv('DEVCONSOLE_RUNTIME_HOME') or os.getenv('HOME') or '/home/devconsole'
android_home = os.getenv('ANDROID_HOME') or os.getenv('ANDROID_SDK_ROOT') or f'{runtime_home}/Android'
flutter_home = os.getenv('FLUTTER_HOME') or f'{runtime_home}/flutter'
return (
f'export HOME="{runtime_home}" '
f'ANDROID_HOME="{android_home}" '
f'ANDROID_SDK_ROOT="{android_home}" '
f'PATH="{flutter_home}/bin:{android_home}/cmdline-tools/latest/bin:{android_home}/platform-tools:$PATH" && '
)
def _adb(command: str) -> str:
return f'{_runtime_env_prefix()}adb {command}'
def list_devices() -> dict: def list_devices() -> dict:
result = run_command('adb devices -l', PROJECTS_DIR.as_posix(), timeout=60) result = run_command(_adb('devices -l'), PROJECTS_DIR.as_posix(), timeout=60)
result['devices'] = parse_devices(result.get('stdout', '')) result['devices'] = parse_devices(result.get('stdout', ''))
return result return result
def _parse_adb_line_metadata(parts: list[str]) -> dict[str, str]: def _parse_adb_line_metadata(parts: list[str]) -> dict[str, str]:
metadata: dict[str, str] = {} metadata: dict[str, str] = {}
for part in parts[2:]: for part in parts[2:]:
if ':' not in part: if ':' not in part:
continue continue
key, value = part.split(':', 1) key, value = part.split(':', 1)
metadata[key.strip()] = value.strip() metadata[key.strip()] = value.strip()
return metadata return metadata
@@ -32,36 +46,25 @@ def _pretty_token(value: str) -> str:
def parse_devices(stdout: str) -> list[dict]: def parse_devices(stdout: str) -> list[dict]:
devices: list[dict] = [] devices: list[dict] = []
for line in stdout.splitlines(): for line in stdout.splitlines():
line = line.strip() line = line.strip()
if not line or line.startswith('List of devices'): if not line or line.startswith('List of devices'):
continue continue
parts = line.split() parts = line.split()
if len(parts) < 2: if len(parts) < 2:
continue continue
serial = parts[0] serial = parts[0]
state = parts[1] state = parts[1]
adb_meta = _parse_adb_line_metadata(parts) adb_meta = _parse_adb_line_metadata(parts)
if state != 'device': if state != 'device':
devices.append({ devices.append({'serial': serial, 'state': state, 'title': f'{serial} ({state})', 'subtitle': 'Устройство не готово'})
'serial': serial,
'state': state,
'title': f'{serial} ({state})',
'subtitle': 'Устройство не готово',
})
continue continue
props = get_device_props(serial) props = get_device_props(serial)
brand = props.get('brand') or adb_meta.get('product') or '' brand = props.get('brand') or adb_meta.get('product') or ''
model = props.get('model') or adb_meta.get('model') or '' model = props.get('model') or adb_meta.get('model') or ''
device = props.get('device') or adb_meta.get('device') or '' device = props.get('device') or adb_meta.get('device') or ''
android = props.get('android') or '' android = props.get('android') or ''
sdk = props.get('sdk') or '' sdk = props.get('sdk') or ''
title_parts = [] title_parts = []
if brand: if brand:
title_parts.append(_pretty_token(brand).title()) title_parts.append(_pretty_token(brand).title())
@@ -69,9 +72,7 @@ def parse_devices(stdout: str) -> list[dict]:
title_parts.append(_pretty_token(model)) title_parts.append(_pretty_token(model))
if not title_parts and device: if not title_parts and device:
title_parts.append(_pretty_token(device)) title_parts.append(_pretty_token(device))
title = ' '.join(title_parts).strip() or serial title = ' '.join(title_parts).strip() or serial
subtitle_parts = [] subtitle_parts = []
if android: if android:
subtitle_parts.append(f'Android {android}') subtitle_parts.append(f'Android {android}')
@@ -82,7 +83,6 @@ def parse_devices(stdout: str) -> list[dict]:
if adb_meta.get('transport_id'): if adb_meta.get('transport_id'):
subtitle_parts.append(f"transport {adb_meta['transport_id']}") subtitle_parts.append(f"transport {adb_meta['transport_id']}")
subtitle_parts.append(serial) subtitle_parts.append(serial)
devices.append({ devices.append({
'serial': serial, 'serial': serial,
'state': state, 'state': state,
@@ -95,28 +95,24 @@ def parse_devices(stdout: str) -> list[dict]:
'title': title, 'title': title,
'subtitle': ' · '.join(subtitle_parts), 'subtitle': ' · '.join(subtitle_parts),
}) })
return devices return devices
def get_device_props(serial: str) -> dict: def get_device_props(serial: str) -> dict:
commands = { commands = {
'brand': f'adb -s {serial} shell getprop ro.product.brand', 'brand': _adb(f'-s {serial} shell getprop ro.product.brand'),
'model': f'adb -s {serial} shell getprop ro.product.model', 'model': _adb(f'-s {serial} shell getprop ro.product.model'),
'device': f'adb -s {serial} shell getprop ro.product.device', 'device': _adb(f'-s {serial} shell getprop ro.product.device'),
'android': f'adb -s {serial} shell getprop ro.build.version.release', 'android': _adb(f'-s {serial} shell getprop ro.build.version.release'),
'sdk': f'adb -s {serial} shell getprop ro.build.version.sdk', 'sdk': _adb(f'-s {serial} shell getprop ro.build.version.sdk'),
} }
props: dict[str, str] = {} props: dict[str, str] = {}
for key, command in commands.items(): for key, command in commands.items():
try: try:
result = run_command(command, PROJECTS_DIR.as_posix(), timeout=20) result = run_command(command, PROJECTS_DIR.as_posix(), timeout=20)
props[key] = (result.get('stdout') or '').strip() props[key] = (result.get('stdout') or '').strip()
except Exception: except Exception:
props[key] = '' props[key] = ''
return props return props
@@ -135,17 +131,13 @@ def find_apks(workspace: str) -> list[str]:
def build_android(workspace: str) -> dict: def build_android(workspace: str) -> dict:
root = Path(workspace).resolve() root = Path(workspace).resolve()
if (root / 'pubspec.yaml').exists(): if (root / 'pubspec.yaml').exists():
return run_command('flutter build apk --debug', root.as_posix(), timeout=1800) return run_command('flutter build apk --debug', root.as_posix(), timeout=1800)
gradlew = root / 'gradlew' gradlew = root / 'gradlew'
if gradlew.exists(): if gradlew.exists():
return run_command('chmod +x ./gradlew && ./gradlew assembleDebug', root.as_posix(), timeout=1800) return run_command('chmod +x ./gradlew && ./gradlew assembleDebug', root.as_posix(), timeout=1800)
if (root / 'android' / 'gradlew').exists(): if (root / 'android' / 'gradlew').exists():
return run_command('cd android && chmod +x ./gradlew && ./gradlew assembleDebug', root.as_posix(), timeout=1800) return run_command('cd android && chmod +x ./gradlew && ./gradlew assembleDebug', root.as_posix(), timeout=1800)
return run_command('gradle assembleDebug', root.as_posix(), timeout=1800) return run_command('gradle assembleDebug', root.as_posix(), timeout=1800)
@@ -153,4 +145,4 @@ def install_latest_apk(workspace: str) -> dict:
apks = find_apks(workspace) apks = find_apks(workspace)
if not apks: if not apks:
raise ValueError('APK not found. Build project first.') raise ValueError('APK not found. Build project first.')
return run_command(f'adb install -r "{apks[0]}"', Path(workspace).resolve().as_posix(), timeout=600) return run_command(_adb(f'install -r "{apks[0]}"'), Path(workspace).resolve().as_posix(), timeout=600)