forked from Mirror/pmbootstrap
pmbootstrap init: ask for release channel (MR 1912)
Ask for release channel and switch pmaports branch to the related branch defined in channels.cfg. Store in pmbootstrap.cfg whether the user chose a channel (boolean). If the user did not choose a channel yet, suggest the recommended channel from channels.cfg (currently "edge").
This commit is contained in:
parent
261e8595ad
commit
17f3b3c2f0
5 changed files with 132 additions and 1 deletions
|
@ -42,6 +42,7 @@ config_keys = ["aports",
|
||||||
"device",
|
"device",
|
||||||
"extra_packages",
|
"extra_packages",
|
||||||
"hostname",
|
"hostname",
|
||||||
|
"is_default_channel",
|
||||||
"jobs",
|
"jobs",
|
||||||
"kernel",
|
"kernel",
|
||||||
"keymap",
|
"keymap",
|
||||||
|
@ -61,6 +62,7 @@ defaults = {
|
||||||
"alpine_version": "edge", # alternatively: latest-stable
|
"alpine_version": "edge", # alternatively: latest-stable
|
||||||
"aports": "$WORK/cache_git/pmaports",
|
"aports": "$WORK/cache_git/pmaports",
|
||||||
"ccache_size": "5G",
|
"ccache_size": "5G",
|
||||||
|
"is_default_channel": True,
|
||||||
# aes-xts-plain64 would be better, but this is not supported on LineageOS
|
# aes-xts-plain64 would be better, but this is not supported on LineageOS
|
||||||
# kernel configs
|
# kernel configs
|
||||||
"cipher": "aes-cbc-plain64",
|
"cipher": "aes-cbc-plain64",
|
||||||
|
|
|
@ -72,6 +72,39 @@ def ask_for_work_path(args):
|
||||||
" inside it! Please try again.")
|
" inside it! Please try again.")
|
||||||
|
|
||||||
|
|
||||||
|
def ask_for_channel(args):
|
||||||
|
""" Ask for the postmarketOS release channel. The channel dictates, which
|
||||||
|
pmaports branch pmbootstrap will check out, and which repository URLs
|
||||||
|
will be used when initializing chroots.
|
||||||
|
:returns: channel name (e.g. "edge", "stable") """
|
||||||
|
channels_cfg = pmb.helpers.git.parse_channels_cfg(args)
|
||||||
|
count = len(channels_cfg["channels"])
|
||||||
|
|
||||||
|
# List channels
|
||||||
|
logging.info("Choose the postmarketOS release channel.")
|
||||||
|
logging.info(f"Available ({count}):")
|
||||||
|
for channel, channel_data in channels_cfg["channels"].items():
|
||||||
|
logging.info(f"* {channel}: {channel_data['description']}")
|
||||||
|
|
||||||
|
# Default for first run: "recommended" from channels.cfg
|
||||||
|
# Otherwise, if valid: channel from pmaports.cfg of current branch
|
||||||
|
# The actual channel name is not saved in pmbootstrap.cfg, because then we
|
||||||
|
# would need to sync it with what is checked out in pmaports.git.
|
||||||
|
default = pmb.config.pmaports.read_config(args)["channel"]
|
||||||
|
choices = channels_cfg["channels"].keys()
|
||||||
|
if args.is_default_channel or default not in choices:
|
||||||
|
default = channels_cfg["meta"]["recommended"]
|
||||||
|
|
||||||
|
# Ask until user gives valid channel
|
||||||
|
while True:
|
||||||
|
ret = pmb.helpers.cli.ask(args, "Channel", None, default,
|
||||||
|
complete=choices)
|
||||||
|
if ret in choices:
|
||||||
|
return ret
|
||||||
|
logging.fatal("ERROR: Invalid channel specified, please type in one"
|
||||||
|
" from the list above.")
|
||||||
|
|
||||||
|
|
||||||
def ask_for_ui(args):
|
def ask_for_ui(args):
|
||||||
ui_list = pmb.helpers.ui.list(args)
|
ui_list = pmb.helpers.ui.list(args)
|
||||||
logging.info("Available user interfaces (" +
|
logging.info("Available user interfaces (" +
|
||||||
|
@ -365,6 +398,11 @@ def frontend(args):
|
||||||
# Clone pmaports
|
# Clone pmaports
|
||||||
pmb.config.pmaports.init(args)
|
pmb.config.pmaports.init(args)
|
||||||
|
|
||||||
|
# Choose release channel, possibly switch pmaports branch
|
||||||
|
channel = ask_for_channel(args)
|
||||||
|
pmb.config.pmaports.switch_to_channel_branch(args, channel)
|
||||||
|
cfg["pmbootstrap"]["is_default_channel"] = "False"
|
||||||
|
|
||||||
# Device
|
# Device
|
||||||
device, device_exists, kernel, nonfree = ask_for_device(args)
|
device, device_exists, kernel, nonfree = ask_for_device(args)
|
||||||
cfg["pmbootstrap"]["device"] = device
|
cfg["pmbootstrap"]["device"] = device
|
||||||
|
|
|
@ -124,3 +124,38 @@ def init(args):
|
||||||
clone(args)
|
clone(args)
|
||||||
symlink(args)
|
symlink(args)
|
||||||
read_config(args)
|
read_config(args)
|
||||||
|
|
||||||
|
|
||||||
|
def switch_to_channel_branch(args, channel_new):
|
||||||
|
""" Checkout the channel's branch in pmaports.git.
|
||||||
|
:channel_new: channel name (e.g. "edge", "stable")
|
||||||
|
:returns: True if another branch was checked out, False otherwise """
|
||||||
|
# Check current pmaports branch channel
|
||||||
|
channel_current = read_config(args)["channel"]
|
||||||
|
if channel_current == channel_new:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# List current and new branches/channels
|
||||||
|
channels_cfg = pmb.helpers.git.parse_channels_cfg(args)
|
||||||
|
branch_new = channels_cfg["channels"][channel_new]["branch_pmaports"]
|
||||||
|
branch_current = pmb.helpers.git.rev_parse(args, args.aports,
|
||||||
|
extra_args=["--abbrev-ref"])
|
||||||
|
logging.info(f"Currently checked out branch '{branch_current}' of"
|
||||||
|
f" pmaports.git is on channel '{channel_current}'.")
|
||||||
|
logging.info(f"Switching to branch '{branch_new}' on channel"
|
||||||
|
f" '{channel_new}'...")
|
||||||
|
|
||||||
|
# Attempt to switch branch (git gives a nice error message, mentioning
|
||||||
|
# which files need to be committed/stashed, so just pass it through)
|
||||||
|
if pmb.helpers.run.user(args, ["git", "checkout", branch_new],
|
||||||
|
args.aports, "interactive", check=False):
|
||||||
|
raise RuntimeError("Failed to switch branch. Go to your pmaports and"
|
||||||
|
" fix what git complained about, then try again: "
|
||||||
|
f"{args.aports}")
|
||||||
|
|
||||||
|
# Invalidate all caches
|
||||||
|
pmb.helpers.args.add_cache(args)
|
||||||
|
|
||||||
|
# Verify pmaports.cfg on new branch
|
||||||
|
read_config(args)
|
||||||
|
return True
|
||||||
|
|
50
test/test_config_pmaports.py
Normal file
50
test/test_config_pmaports.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Copyright 2020 Oliver Smith
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
""" Test pmb/config/pmaports.py """
|
||||||
|
import pytest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import pmb_test
|
||||||
|
import pmb_test.const
|
||||||
|
import pmb_test.git
|
||||||
|
import pmb.config
|
||||||
|
import pmb.config.workdir
|
||||||
|
import pmb.config.pmaports
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def args(request):
|
||||||
|
import pmb.parse
|
||||||
|
cfg = f"{pmb_test.const.testdata}/channels.cfg"
|
||||||
|
sys.argv = ["pmbootstrap.py", "--config-channels", cfg, "init"]
|
||||||
|
args = pmb.parse.arguments()
|
||||||
|
args.log = args.work + "/log_testsuite.txt"
|
||||||
|
pmb.helpers.logging.init(args)
|
||||||
|
request.addfinalizer(args.logfd.close)
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def test_switch_to_channel_branch(args, monkeypatch, tmpdir):
|
||||||
|
path, run_git = pmb_test.git.prepare_tmpdir(args, monkeypatch, tmpdir)
|
||||||
|
args.aports = path
|
||||||
|
|
||||||
|
# Pretend to have channel=edge in pmaports.cfg
|
||||||
|
def read_config(args):
|
||||||
|
return {"channel": "edge"}
|
||||||
|
monkeypatch.setattr(pmb.config.pmaports, "read_config", read_config)
|
||||||
|
|
||||||
|
# Success: Channel does not change
|
||||||
|
func = pmb.config.pmaports.switch_to_channel_branch
|
||||||
|
assert func(args, "edge") is False
|
||||||
|
|
||||||
|
# Fail: git error (could be any error, but here: branch does not exist)
|
||||||
|
with pytest.raises(RuntimeError) as e:
|
||||||
|
func(args, "stable")
|
||||||
|
assert str(e.value).startswith("Failed to switch branch")
|
||||||
|
|
||||||
|
# Success: switch channel and change branch
|
||||||
|
run_git(["checkout", "-b", "v20.05"])
|
||||||
|
run_git(["checkout", "master"])
|
||||||
|
assert func(args, "stable") is True
|
||||||
|
branch = pmb.helpers.git.rev_parse(args, path, extra_args=["--abbrev-ref"])
|
||||||
|
assert branch == "v20.05"
|
|
@ -16,7 +16,8 @@ import pmb.helpers.logging
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def args(tmpdir, request):
|
def args(tmpdir, request):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap.py", "init"]
|
cfg = f"{pmb_test.const.testdata}/channels.cfg"
|
||||||
|
sys.argv = ["pmbootstrap.py", "--config-channels", cfg, "init"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = args.work + "/log_testsuite.txt"
|
args.log = args.work + "/log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
|
@ -287,3 +288,8 @@ def test_questions_hostname(args, monkeypatch):
|
||||||
# Device name: empty string
|
# Device name: empty string
|
||||||
fake_answers(monkeypatch, [device])
|
fake_answers(monkeypatch, [device])
|
||||||
assert func(args, device) == ""
|
assert func(args, device) == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_questions_channel(args, monkeypatch):
|
||||||
|
fake_answers(monkeypatch, ["invalid-channel", "stable"])
|
||||||
|
assert pmb.config.init.ask_for_channel(args) == "stable"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue