pmb.helpers.git: parse channels.cfg (MR 1912)
Prepare to base postmarketOS on Alpine stable by parsing the new channels.cfg file in pmaports.git, that describes which channel needs which branches and mirror dirs from postmarketOS and Alpine. Use the information in pmb.helpers.git.get_branches_official() first, more is coming in follow-up commits. Read the file from origin/master, so we get the latest fetched version even if the last checked out master branch is not up-to-date (think of currently checked out release branch instead of master, master will never be updated to point to latest origin/master). Allow to override the file with a new --config-channels parameter. Related: https://postmarketos.org/channels.cfg
This commit is contained in:
parent
ed16a9d080
commit
c616874443
|
@ -3,6 +3,7 @@
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import pmb.config
|
import pmb.config
|
||||||
|
import pmb.helpers.git
|
||||||
|
|
||||||
""" This file constructs the args variable, which is passed to almost all
|
""" This file constructs the args variable, which is passed to almost all
|
||||||
functions in the pmbootstrap code base. Here's a listing of the kind of
|
functions in the pmbootstrap code base. Here's a listing of the kind of
|
||||||
|
@ -131,7 +132,8 @@ def add_cache(args):
|
||||||
"find_aport": {},
|
"find_aport": {},
|
||||||
"pmb.helpers.package.depends_recurse": {},
|
"pmb.helpers.package.depends_recurse": {},
|
||||||
"pmb.helpers.package.get": {},
|
"pmb.helpers.package.get": {},
|
||||||
"pmb.helpers.repo.update": repo_update})
|
"pmb.helpers.repo.update": repo_update,
|
||||||
|
"pmb.helpers.git.parse_channels_cfg": {}})
|
||||||
|
|
||||||
|
|
||||||
def add_deviceinfo(args):
|
def add_deviceinfo(args):
|
||||||
|
@ -162,6 +164,8 @@ def init(args):
|
||||||
"pull", "shutdown", "zap"]:
|
"pull", "shutdown", "zap"]:
|
||||||
pmb.config.pmaports.read_config_into_args(args)
|
pmb.config.pmaports.read_config_into_args(args)
|
||||||
add_deviceinfo(args)
|
add_deviceinfo(args)
|
||||||
|
pmb.helpers.git.parse_channels_cfg(args)
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright 2020 Oliver Smith
|
# Copyright 2020 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
import configparser
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
@ -100,12 +101,71 @@ def get_upstream_remote(args, name_repo):
|
||||||
" repository: {}".format(name_repo, url, path))
|
" repository: {}".format(name_repo, url, path))
|
||||||
|
|
||||||
|
|
||||||
|
def parse_channels_cfg(args):
|
||||||
|
""" Parse channels.cfg from pmaports.git, origin/master branch.
|
||||||
|
Reference: https://postmarketos.org/channels.cfg
|
||||||
|
:returns: dict like: {"meta": {"recommended": "edge"},
|
||||||
|
"channels": {"edge": {"description": ...,
|
||||||
|
"branch_pmaports": ...,
|
||||||
|
"branch_aports": ...,
|
||||||
|
"mirrordir_alpine": ...},
|
||||||
|
...}} """
|
||||||
|
# Cache during one pmbootstrap run
|
||||||
|
cache_key = "pmb.helpers.git.parse_channels_cfg"
|
||||||
|
if args.cache[cache_key]:
|
||||||
|
return args.cache[cache_key]
|
||||||
|
|
||||||
|
# Read with configparser
|
||||||
|
cfg = configparser.ConfigParser()
|
||||||
|
if args.config_channels:
|
||||||
|
cfg.read([args.config_channels])
|
||||||
|
else:
|
||||||
|
remote = get_upstream_remote(args, "pmaports")
|
||||||
|
command = ["git", "show", f"{remote}/master:channels.cfg"]
|
||||||
|
stdout = pmb.helpers.run.user(args, command, args.aports,
|
||||||
|
output_return=True, check=False)
|
||||||
|
try:
|
||||||
|
cfg.read_string(stdout)
|
||||||
|
except configparser.MissingSectionHeaderError:
|
||||||
|
logging.info("NOTE: fix this by fetching your pmaports.git, e.g."
|
||||||
|
" with 'pmbootstrap pull'")
|
||||||
|
raise RuntimeError("Failed to read channels.cfg from"
|
||||||
|
f" '{remote}/master' branch of your local"
|
||||||
|
" pmaports clone")
|
||||||
|
|
||||||
|
# Meta section
|
||||||
|
ret = {"channels": {}}
|
||||||
|
ret["meta"] = {"recommended": cfg.get("channels.cfg", "recommended")}
|
||||||
|
|
||||||
|
# Channels
|
||||||
|
for channel in cfg.sections():
|
||||||
|
if channel == "channels.cfg":
|
||||||
|
continue # meta section
|
||||||
|
|
||||||
|
ret["channels"][channel] = {}
|
||||||
|
for key in ["description", "branch_pmaports", "branch_aports",
|
||||||
|
"mirrordir_alpine"]:
|
||||||
|
value = cfg.get(channel, key)
|
||||||
|
ret["channels"][channel][key] = value
|
||||||
|
|
||||||
|
args.cache[cache_key] = ret
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_branches_official(args, name_repo):
|
def get_branches_official(args, name_repo):
|
||||||
""" Get all branches that point to official release channels.
|
""" Get all branches that point to official release channels.
|
||||||
:returns: list of supported branches, e.g. ["master", "3.11"] """
|
:returns: list of supported branches, e.g. ["master", "3.11"] """
|
||||||
# More sophisticated logic to figure out the branches will be added soon:
|
# This functions gets called with pmaports and aports_upstream, because
|
||||||
# https://gitlab.com/postmarketOS/postmarketos/issues/11
|
# both are displayed in "pmbootstrap status". But it only makes sense
|
||||||
return ["master"]
|
# to display pmaports there, related code will be refactored soon (#1903).
|
||||||
|
if name_repo != "pmaports":
|
||||||
|
return ["master"]
|
||||||
|
|
||||||
|
channels_cfg = parse_channels_cfg(args)
|
||||||
|
ret = []
|
||||||
|
for channel, channel_data in channels_cfg["channels"].items():
|
||||||
|
ret.append(channel_data["branch_pmaports"])
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def pull(args, name_repo):
|
def pull(args, name_repo):
|
||||||
|
|
|
@ -342,6 +342,9 @@ def arguments():
|
||||||
default=pmb.config.defaults["config"],
|
default=pmb.config.defaults["config"],
|
||||||
help="path to pmbootstrap.cfg file (default in"
|
help="path to pmbootstrap.cfg file (default in"
|
||||||
" ~/.config/)")
|
" ~/.config/)")
|
||||||
|
parser.add_argument("--config-channels",
|
||||||
|
help="path to channels.cfg (which is by default"
|
||||||
|
" read from pmaports.git, origin/master branch)")
|
||||||
parser.add_argument("-d", "--port-distccd", dest="port_distccd")
|
parser.add_argument("-d", "--port-distccd", dest="port_distccd")
|
||||||
parser.add_argument("-mp", "--mirror-pmOS", dest="mirrors_postmarketos",
|
parser.add_argument("-mp", "--mirror-pmOS", dest="mirrors_postmarketos",
|
||||||
help="postmarketOS mirror, disable with: -mp='',"
|
help="postmarketOS mirror, disable with: -mp='',"
|
||||||
|
|
|
@ -7,6 +7,7 @@ import shutil
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pmb_test # noqa
|
import pmb_test # noqa
|
||||||
|
import pmb_test.const
|
||||||
import pmb_test.git
|
import pmb_test.git
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.logging
|
import pmb.helpers.logging
|
||||||
|
@ -16,7 +17,8 @@ import pmb.helpers.run
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def args(request):
|
def args(request):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap", "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)
|
||||||
|
@ -108,6 +110,19 @@ def test_get_upstream_remote(args, monkeypatch, tmpdir):
|
||||||
assert func(args, name_repo) == "hello"
|
assert func(args, name_repo) == "hello"
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_channels_cfg(args):
|
||||||
|
exp = {"meta": {"recommended": "edge"},
|
||||||
|
"channels": {"edge": {"description": "Rolling release channel",
|
||||||
|
"branch_pmaports": "master",
|
||||||
|
"branch_aports": "master",
|
||||||
|
"mirrordir_alpine": "edge"},
|
||||||
|
"stable": {"description": "For workgroups",
|
||||||
|
"branch_pmaports": "v20.05",
|
||||||
|
"branch_aports": "3.11-stable",
|
||||||
|
"mirrordir_alpine": "v3.11"}}}
|
||||||
|
assert pmb.helpers.git.parse_channels_cfg(args) == exp
|
||||||
|
|
||||||
|
|
||||||
def test_pull_non_existing(args):
|
def test_pull_non_existing(args):
|
||||||
assert pmb.helpers.git.pull(args, "non-existing-repo-name") == 1
|
assert pmb.helpers.git.pull(args, "non-existing-repo-name") == 1
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Reference: https://postmarketos.org/channels.cfg
|
||||||
|
[channels.cfg]
|
||||||
|
recommended=edge
|
||||||
|
|
||||||
|
[edge]
|
||||||
|
description=Rolling release channel
|
||||||
|
branch_pmaports=master
|
||||||
|
branch_aports=master
|
||||||
|
mirrordir_alpine=edge
|
||||||
|
|
||||||
|
[stable]
|
||||||
|
description=For workgroups
|
||||||
|
branch_pmaports=v20.05
|
||||||
|
branch_aports=3.11-stable
|
||||||
|
mirrordir_alpine=v3.11
|
Loading…
Reference in New Issue