2018-11-15 07:30:49 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
"""
|
2019-01-02 08:31:20 +00:00
|
|
|
Copyright 2019 Oliver Smith
|
2018-11-15 07:30:49 +00:00
|
|
|
|
|
|
|
This file is part of pmbootstrap.
|
|
|
|
|
|
|
|
pmbootstrap is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
pmbootstrap is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
"""
|
|
|
|
|
new action: 'pmbootstrap repo_missing'
Add a new action that lists all aports, for which no binary packages
exist. Only list packages that can be built for the relevant arch
(specified with --arch). This works recursively: when a package can be
built for a certain arch, but one of its dependencies
(or their depends) can not be built for that arch, then don't list it.
This action will be used for the new sr.ht based build infrastructure,
to figure out which packages need to be built ahead of time (so we can
trigger each of them as single build job). Determining the order of the
packages to be built is not determined with pmbootstrap, the serverside
code of build.postmarketos.org takes care of that.
For testing purposes, a single package can also be specified and the
action will list if it can be built for that arch with its
dependencies, and what needs to be built exactly.
Add pmb/helpers/package.py to hold functions that work on both pmaports
and (binary package) repos - in contrary to the existing
pmb/helpers/pmaports.py (see previous commit) and pmb/helpers/repo.py,
which only work with one of those.
Refactoring:
* pmb/helpers/pmaports.py: add a get_list() function, which lists all
aports and use it instead of writing the same glob loop over and over
* add pmb.helpers.pmaports.get(), which finds an APKBUILD and parses it
in one step.
* rename pmb.build._package.check_arch to ...check_arch_abort to
distinguish it from the other check_arch function
2018-11-15 07:36:39 +00:00
|
|
|
"""
|
|
|
|
Functions that work only on pmaports. See also:
|
|
|
|
- pmb/helpers/repo.py (only work on binary package repos)
|
|
|
|
- pmb/helpers/package.py (work on both)
|
|
|
|
"""
|
|
|
|
|
2018-11-15 07:30:49 +00:00
|
|
|
import glob
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
|
|
|
|
import pmb.parse
|
|
|
|
|
|
|
|
|
new action: 'pmbootstrap repo_missing'
Add a new action that lists all aports, for which no binary packages
exist. Only list packages that can be built for the relevant arch
(specified with --arch). This works recursively: when a package can be
built for a certain arch, but one of its dependencies
(or their depends) can not be built for that arch, then don't list it.
This action will be used for the new sr.ht based build infrastructure,
to figure out which packages need to be built ahead of time (so we can
trigger each of them as single build job). Determining the order of the
packages to be built is not determined with pmbootstrap, the serverside
code of build.postmarketos.org takes care of that.
For testing purposes, a single package can also be specified and the
action will list if it can be built for that arch with its
dependencies, and what needs to be built exactly.
Add pmb/helpers/package.py to hold functions that work on both pmaports
and (binary package) repos - in contrary to the existing
pmb/helpers/pmaports.py (see previous commit) and pmb/helpers/repo.py,
which only work with one of those.
Refactoring:
* pmb/helpers/pmaports.py: add a get_list() function, which lists all
aports and use it instead of writing the same glob loop over and over
* add pmb.helpers.pmaports.get(), which finds an APKBUILD and parses it
in one step.
* rename pmb.build._package.check_arch to ...check_arch_abort to
distinguish it from the other check_arch function
2018-11-15 07:36:39 +00:00
|
|
|
def get_list(args):
|
|
|
|
""" :returns: list of all pmaport pkgnames (["hello-world", ...]) """
|
|
|
|
ret = []
|
|
|
|
for apkbuild in glob.glob(args.aports + "/*/*/APKBUILD"):
|
|
|
|
ret.append(os.path.basename(os.path.dirname(apkbuild)))
|
|
|
|
ret.sort()
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2018-11-15 07:30:49 +00:00
|
|
|
def guess_main(args, subpkgname):
|
|
|
|
"""
|
|
|
|
Find the main package by assuming it is a prefix of the subpkgname.
|
|
|
|
We do that, because in some APKBUILDs the subpkgname="" variable gets
|
|
|
|
filled with a shell loop and the APKBUILD parser in pmbootstrap can't
|
|
|
|
parse this right. (Intentionally, we don't want to implement a full shell
|
|
|
|
parser.)
|
|
|
|
|
|
|
|
:param subpkgname: subpackage name (e.g. "u-boot-some-device")
|
|
|
|
:returns: * full path to the aport, e.g.:
|
|
|
|
"/home/user/code/pmbootstrap/aports/main/u-boot"
|
|
|
|
* None when we couldn't find a main package
|
|
|
|
"""
|
|
|
|
# Iterate until the cut up subpkgname is gone
|
|
|
|
words = subpkgname.split("-")
|
|
|
|
while len(words) > 1:
|
|
|
|
# Remove one dash-separated word at a time ("a-b-c" -> "a-b")
|
|
|
|
words.pop()
|
|
|
|
pkgname = "-".join(words)
|
|
|
|
|
|
|
|
# Look in pmaports
|
|
|
|
paths = glob.glob(args.aports + "/*/" + pkgname)
|
|
|
|
if paths:
|
|
|
|
logging.debug(subpkgname + ": guessed to be a subpackage of " +
|
|
|
|
pkgname)
|
|
|
|
return paths[0]
|
|
|
|
|
|
|
|
|
|
|
|
def find(args, package, must_exist=True):
|
|
|
|
"""
|
new action: 'pmbootstrap repo_missing'
Add a new action that lists all aports, for which no binary packages
exist. Only list packages that can be built for the relevant arch
(specified with --arch). This works recursively: when a package can be
built for a certain arch, but one of its dependencies
(or their depends) can not be built for that arch, then don't list it.
This action will be used for the new sr.ht based build infrastructure,
to figure out which packages need to be built ahead of time (so we can
trigger each of them as single build job). Determining the order of the
packages to be built is not determined with pmbootstrap, the serverside
code of build.postmarketos.org takes care of that.
For testing purposes, a single package can also be specified and the
action will list if it can be built for that arch with its
dependencies, and what needs to be built exactly.
Add pmb/helpers/package.py to hold functions that work on both pmaports
and (binary package) repos - in contrary to the existing
pmb/helpers/pmaports.py (see previous commit) and pmb/helpers/repo.py,
which only work with one of those.
Refactoring:
* pmb/helpers/pmaports.py: add a get_list() function, which lists all
aports and use it instead of writing the same glob loop over and over
* add pmb.helpers.pmaports.get(), which finds an APKBUILD and parses it
in one step.
* rename pmb.build._package.check_arch to ...check_arch_abort to
distinguish it from the other check_arch function
2018-11-15 07:36:39 +00:00
|
|
|
Find the aport path, that provides a certain subpackage.
|
|
|
|
If you want the parsed APKBUILD instead, use pmb.helpers.pmaports.get().
|
2018-11-15 07:30:49 +00:00
|
|
|
|
|
|
|
:param must_exist: Raise an exception, when not found
|
|
|
|
:returns: the full path to the aport folder
|
|
|
|
"""
|
|
|
|
# Try to get a cached result first (we assume, that the aports don't change
|
|
|
|
# in one pmbootstrap call)
|
|
|
|
ret = None
|
|
|
|
if package in args.cache["find_aport"]:
|
|
|
|
ret = args.cache["find_aport"][package]
|
|
|
|
else:
|
|
|
|
# Sanity check
|
|
|
|
if "*" in package:
|
|
|
|
raise RuntimeError("Invalid pkgname: " + package)
|
|
|
|
|
|
|
|
# Search in packages
|
|
|
|
paths = glob.glob(args.aports + "/*/" + package)
|
|
|
|
if len(paths) > 1:
|
|
|
|
raise RuntimeError("Package " + package + " found in multiple"
|
|
|
|
" aports subfolders. Please put it only in one"
|
|
|
|
" folder.")
|
|
|
|
elif len(paths) == 1:
|
|
|
|
ret = paths[0]
|
|
|
|
|
2018-12-10 19:48:57 +00:00
|
|
|
# Search in subpackages and provides
|
2018-11-15 07:30:49 +00:00
|
|
|
if not ret:
|
|
|
|
for path_current in glob.glob(args.aports + "/*/*/APKBUILD"):
|
|
|
|
apkbuild = pmb.parse.apkbuild(args, path_current)
|
2018-12-10 19:48:57 +00:00
|
|
|
found = False
|
|
|
|
|
|
|
|
# Subpackages
|
|
|
|
for subpackage_i in apkbuild["subpackages"]:
|
|
|
|
if package == subpackage_i.split(":", 1)[0]:
|
|
|
|
found = True
|
|
|
|
break
|
|
|
|
|
|
|
|
# Provides (cut off before equals sign for entries like
|
|
|
|
# "mkbootimg=0.0.1")
|
|
|
|
if not found:
|
|
|
|
for provides_i in apkbuild["provides"]:
|
|
|
|
if package == provides_i.split("=", 1)[0]:
|
|
|
|
found = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if found:
|
2018-11-15 07:30:49 +00:00
|
|
|
ret = os.path.dirname(path_current)
|
|
|
|
break
|
|
|
|
|
|
|
|
# Guess a main package
|
|
|
|
if not ret:
|
|
|
|
ret = guess_main(args, package)
|
|
|
|
|
|
|
|
# Crash when necessary
|
|
|
|
if ret is None and must_exist:
|
|
|
|
raise RuntimeError("Could not find aport for package: " +
|
|
|
|
package)
|
|
|
|
|
|
|
|
# Save result in cache
|
|
|
|
args.cache["find_aport"][package] = ret
|
|
|
|
return ret
|
new action: 'pmbootstrap repo_missing'
Add a new action that lists all aports, for which no binary packages
exist. Only list packages that can be built for the relevant arch
(specified with --arch). This works recursively: when a package can be
built for a certain arch, but one of its dependencies
(or their depends) can not be built for that arch, then don't list it.
This action will be used for the new sr.ht based build infrastructure,
to figure out which packages need to be built ahead of time (so we can
trigger each of them as single build job). Determining the order of the
packages to be built is not determined with pmbootstrap, the serverside
code of build.postmarketos.org takes care of that.
For testing purposes, a single package can also be specified and the
action will list if it can be built for that arch with its
dependencies, and what needs to be built exactly.
Add pmb/helpers/package.py to hold functions that work on both pmaports
and (binary package) repos - in contrary to the existing
pmb/helpers/pmaports.py (see previous commit) and pmb/helpers/repo.py,
which only work with one of those.
Refactoring:
* pmb/helpers/pmaports.py: add a get_list() function, which lists all
aports and use it instead of writing the same glob loop over and over
* add pmb.helpers.pmaports.get(), which finds an APKBUILD and parses it
in one step.
* rename pmb.build._package.check_arch to ...check_arch_abort to
distinguish it from the other check_arch function
2018-11-15 07:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get(args, pkgname, must_exist=True):
|
|
|
|
""" Find and parse an APKBUILD file.
|
|
|
|
Run 'pmbootstrap apkbuild_parse hello-world' for a full output example.
|
|
|
|
Relevant variables are defined in pmb.config.apkbuild_attributes.
|
|
|
|
|
|
|
|
:param pkgname: the package name to find
|
|
|
|
:param must_exist: raise an exception when it can't be found
|
|
|
|
:returns: relevant variables from the APKBUILD as dictionary, e.g.:
|
|
|
|
{ "pkgname": "hello-world",
|
|
|
|
"arch": ["all"],
|
|
|
|
"pkgrel": "4",
|
|
|
|
"pkgrel": "1",
|
|
|
|
"options": [],
|
|
|
|
... }
|
|
|
|
"""
|
|
|
|
aport = find(args, pkgname, must_exist)
|
|
|
|
if aport:
|
|
|
|
return pmb.parse.apkbuild(args, aport + "/APKBUILD")
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def get_repo(args, pkgname, must_exist=True):
|
|
|
|
""" Get the repository folder of an aport.
|
|
|
|
|
|
|
|
:pkgname: package name
|
|
|
|
:must_exist: raise an exception when it can't be found
|
|
|
|
:returns: a string like "main", "device", "cross", ...
|
|
|
|
or None when the aport could not be found """
|
|
|
|
aport = find(args, pkgname, must_exist)
|
|
|
|
if not aport:
|
|
|
|
return None
|
|
|
|
return os.path.basename(os.path.dirname(aport))
|
2019-04-19 23:20:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
def check_arches(arches, arch):
|
|
|
|
""" Check if building for a certain arch is allowed.
|
|
|
|
|
|
|
|
:param arches: list of all supported arches, as it can be found in the
|
|
|
|
arch="" line of APKBUILDS (including all, noarch,
|
|
|
|
!arch, ...). For example: ["x86_64", "x86", "!armhf"]
|
|
|
|
:param arch: the architecture to check for
|
|
|
|
:returns: True when building is allowed, False otherwise
|
|
|
|
"""
|
|
|
|
if "!" + arch in arches:
|
|
|
|
return False
|
|
|
|
for value in [arch, "all", "noarch"]:
|
|
|
|
if value in arches:
|
|
|
|
return True
|
|
|
|
return False
|