Rework share-log per review: subcommand, TUI confirmation, truncate large logs
This commit is contained in:
parent
995ee8a84a
commit
cd6565dc08
|
|
@ -55,7 +55,6 @@ class Arguments:
|
|||
skip_wifi_check: bool = False
|
||||
advanced: bool = False
|
||||
verbose: bool = False
|
||||
share_log: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -432,13 +431,6 @@ class ArchConfigHandler:
|
|||
default=False,
|
||||
help='Enabled verbose options',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--share-log',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Upload /var/log/archinstall/install.log to paste.rs and print the URL, then exit',
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _parse_args(self) -> Arguments:
|
||||
|
|
|
|||
|
|
@ -333,3 +333,93 @@ def log(
|
|||
|
||||
if level != logging.DEBUG:
|
||||
print(text)
|
||||
|
||||
|
||||
_PASTE_URL = 'https://paste.rs'
|
||||
_PASTE_MAX_SIZE = 10 * 1024 * 1024
|
||||
|
||||
|
||||
def share_install_log() -> int:
|
||||
from archinstall.lib.command import SysCommand
|
||||
from archinstall.lib.exceptions import SysCallError
|
||||
|
||||
log_path = logger.path
|
||||
|
||||
if not log_path.exists():
|
||||
info(f'Log file not found: {log_path}')
|
||||
return 1
|
||||
|
||||
size = log_path.stat().st_size
|
||||
if size == 0:
|
||||
info(f'Log file is empty: {log_path}')
|
||||
return 1
|
||||
|
||||
if size > _PASTE_MAX_SIZE:
|
||||
info(f'Log file exceeds {_PASTE_MAX_SIZE} bytes, uploading last {_PASTE_MAX_SIZE} bytes')
|
||||
content = log_path.read_bytes()[-_PASTE_MAX_SIZE:]
|
||||
else:
|
||||
content = log_path.read_bytes()
|
||||
|
||||
header = f'About to upload {log_path} ({len(content)} bytes) to {_PASTE_URL}\n\n'
|
||||
header += 'The log may contain hostname, mirror URLs, package list and partition layout.\n'
|
||||
header += 'The uploaded paste is public.\n\n'
|
||||
header += 'Continue?'
|
||||
|
||||
try:
|
||||
from archinstall.tui.ui.components import tui
|
||||
|
||||
confirmed: bool = tui.run(lambda: _confirm_share(header))
|
||||
except Exception:
|
||||
confirmed = False
|
||||
|
||||
if not confirmed:
|
||||
info('Cancelled.')
|
||||
return 1
|
||||
|
||||
import tempfile
|
||||
|
||||
if size > _PASTE_MAX_SIZE:
|
||||
fd, tmp_path_str = tempfile.mkstemp(suffix='.log')
|
||||
try:
|
||||
with os.fdopen(fd, 'wb') as f:
|
||||
f.write(content)
|
||||
upload_path = tmp_path_str
|
||||
except Exception:
|
||||
os.close(fd)
|
||||
raise
|
||||
else:
|
||||
upload_path = str(log_path)
|
||||
tmp_path_str = None
|
||||
|
||||
try:
|
||||
result = SysCommand(f'curl -sS --data-binary @{upload_path} {_PASTE_URL}')
|
||||
except SysCallError as e:
|
||||
info(f'Upload failed: {e}')
|
||||
return 1
|
||||
finally:
|
||||
if tmp_path_str:
|
||||
Path(tmp_path_str).unlink(missing_ok=True)
|
||||
|
||||
url = result.decode().strip()
|
||||
|
||||
if not url.startswith('http'):
|
||||
info(f'Unexpected response from {_PASTE_URL}: {url[:200]!r}')
|
||||
return 1
|
||||
|
||||
# raw print so the URL is pipe-friendly (no ANSI colors, no log prefix)
|
||||
print(url)
|
||||
return 0
|
||||
|
||||
|
||||
async def _confirm_share(header: str) -> bool:
|
||||
from archinstall.lib.menu.helpers import Confirmation
|
||||
from archinstall.tui.ui.menu_item import MenuItemGroup
|
||||
|
||||
result = await Confirmation(
|
||||
group=MenuItemGroup.yes_no(),
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
preset=False,
|
||||
).show()
|
||||
|
||||
return result.get_value()
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
import sys
|
||||
|
||||
from archinstall.lib.command import SysCommand
|
||||
from archinstall.lib.exceptions import SysCallError
|
||||
from archinstall.lib.output import logger
|
||||
|
||||
# paste.rs is a minimal text pastebin with syntax highlighting by extension.
|
||||
# 10 MiB is its documented upload limit.
|
||||
_PASTE_URL = 'https://paste.rs'
|
||||
_PASTE_MAX_SIZE = 10 * 1024 * 1024
|
||||
|
||||
|
||||
def share_install_log() -> int:
|
||||
"""Upload /var/log/archinstall/install.log to paste.rs and print the URL.
|
||||
|
||||
Intended for users to paste the URL into a GitHub issue when reporting a
|
||||
bug. Always asks for explicit confirmation - the log may contain hostname,
|
||||
mirror URLs, package list, partition layout and other system details which
|
||||
become public on upload.
|
||||
|
||||
All diagnostic output goes to stderr instead of the standard log helpers,
|
||||
so the file we are about to upload is not modified by this command.
|
||||
"""
|
||||
log_path = logger.path
|
||||
|
||||
if not log_path.exists():
|
||||
print(f'Log file not found: {log_path}', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
size = log_path.stat().st_size
|
||||
if size == 0:
|
||||
print(f'Log file is empty: {log_path}', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if size > _PASTE_MAX_SIZE:
|
||||
print(
|
||||
f'Log file is too large to share: {size} bytes (limit: {_PASTE_MAX_SIZE} bytes). Trim it or upload manually.',
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
print(f'About to upload {log_path} ({size} bytes) to {_PASTE_URL}', file=sys.stderr)
|
||||
print(
|
||||
'The log may contain hostname, mirror URLs, package list and partition layout. The uploaded paste is public.',
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
try:
|
||||
answer = input('Continue? [y/N]: ').strip().lower()
|
||||
except EOFError, KeyboardInterrupt:
|
||||
print(file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if answer not in ('y', 'yes'):
|
||||
print('Cancelled.', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
try:
|
||||
result = SysCommand(f'curl -sS --data-binary @{log_path} {_PASTE_URL}')
|
||||
except SysCallError as e:
|
||||
print(f'Upload failed: {e}', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
url = result.decode().strip()
|
||||
|
||||
if not url.startswith('http'):
|
||||
print(f'Unexpected response from {_PASTE_URL}: {url[:200]!r}', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print(url)
|
||||
return 0
|
||||
|
|
@ -13,10 +13,9 @@ from archinstall.lib.disk.utils import disk_layouts
|
|||
from archinstall.lib.hardware import SysInfo
|
||||
from archinstall.lib.network.wifi_handler import WifiHandler
|
||||
from archinstall.lib.networking import ping
|
||||
from archinstall.lib.output import debug, error, info, warn
|
||||
from archinstall.lib.output import debug, error, info, share_install_log, warn
|
||||
from archinstall.lib.packages.util import check_version_upgrade
|
||||
from archinstall.lib.pacman.pacman import Pacman
|
||||
from archinstall.lib.share_log import share_install_log
|
||||
from archinstall.lib.translationhandler import tr, translation_handler
|
||||
from archinstall.lib.utils.util import running_from_iso
|
||||
from archinstall.tui.ui.components import tui
|
||||
|
|
@ -80,6 +79,9 @@ def run() -> int:
|
|||
OR straight as a module: python -m archinstall
|
||||
In any case we will be attempting to load the provided script to be run from the scripts/ folder
|
||||
"""
|
||||
if 'share-log' in sys.argv:
|
||||
return share_install_log()
|
||||
|
||||
arch_config_handler = ArchConfigHandler()
|
||||
|
||||
if '--help' in sys.argv or '-h' in sys.argv:
|
||||
|
|
@ -96,9 +98,6 @@ def run() -> int:
|
|||
print(tr('Archinstall requires root privileges to run. See --help for more.'))
|
||||
return 1
|
||||
|
||||
if arch_config_handler.args.share_log:
|
||||
return share_install_log()
|
||||
|
||||
translation_handler.save_console_font()
|
||||
|
||||
_log_sys_info()
|
||||
|
|
@ -146,7 +145,7 @@ def _error_message(exc: Exception) -> None:
|
|||
https://github.com/archlinux/archinstall and include the log file "/var/log/archinstall/install.log".
|
||||
|
||||
Hint: To upload the log and get a shareable URL, run
|
||||
archinstall --share-log
|
||||
archinstall share-log
|
||||
"""
|
||||
)
|
||||
warn(text)
|
||||
|
|
|
|||
Loading…
Reference in New Issue