pmb.helpers.git.clone: use git from host system (!1845)

Do not install git in the native chroot and use it from there. Remove the
chown_to_user argument from pmb.helpers.git.clone(), the resulting dir
is now always owned by the user. While at it, refactor the function and
display the clone URL.

Previously we had cloned aports_upstream (from Alpine) with
chown_to_user=False (legacy) and pmaports with chown_to_user=True.
pmb.helpers.git.rev_parse() would only work after chown_to_user=True.

Check if git is installed in "pmbootstrap init", and remove the same
check from rev_parse(). Add a new work dir version, that checks for git
and changes ownership of already checked out aports_upstream to the
host system's user.

When creating a new work dir, create cache_git instead of cache_http.
cache_http is created on demand already, with proper permissions. But
cache_git must be created, otherwise pmb.helpers.mount.bind will create it
as root.

This is in preparation for the "pmbootstrap pull" feature, as it allows
using the host system's git in all new code paths. We will be able to
handle repositories even if they were cloned outside of the work dir
(which we do in a few CI scripts for example).

Related: #1858
This commit is contained in:
Oliver Smith 2019-12-22 12:11:21 +01:00
parent cba37d5d79
commit 02e514f4d3
No known key found for this signature in database
GPG Key ID: 5AE7F5513E0885CB
7 changed files with 54 additions and 47 deletions

View File

@ -14,6 +14,7 @@ Package build scripts live in the [`pmaports`](https://gitlab.com/postmarketOS/p
* [Linux kernel 3.17 or higher](https://postmarketos.org/oldkernel)
* Python 3.4+
* OpenSSL
* git
## Usage Examples
Please refer to the [postmarketOS wiki](https://wiki.postmarketos.org) for in-depth coverage of topics such as [porting to a new device](https://wiki.postmarketos.org/wiki/Porting_to_a_new_device) or [installation](https://wiki.postmarketos.org/wiki/Installation_guide). The help output (`pmbootstrap -h`) has detailed usage instructions for every command. Read on for some generic examples of what can be done with `pmbootstrap`.

View File

@ -206,9 +206,8 @@ def get_upstream_aport(args, pkgname):
# APKBUILD < binary
if compare == -1:
raise RuntimeError("You can update your local checkout with:"
" 'pmbootstrap chroot --add=git --user -- git -C"
" /mnt/pmbootstrap-git/aports_upstream pull'")
raise RuntimeError("You can update your local checkout with: 'git -C"
"\"{}\" pull'".format(aports_upstream_path))
# APKBUILD > binary
raise RuntimeError("You can force an update of your binary package"
" APKINDEX files with: 'pmbootstrap update'")

View File

@ -45,12 +45,12 @@ pmaports_min_version = "4"
# Version of the work folder (as asked during 'pmbootstrap init'). Increase
# this number, whenever migration is required and provide the migration code,
# see migrate_work_folder()).
work_version = 3
work_version = 4
# Programs that pmbootstrap expects to be available from the host system. Keep
# in sync with README.md, and try to keep the list as small as possible. The
# idea is to run almost everything in Alpine chroots.
required_programs = ["openssl", "ps"]
required_programs = ["git", "openssl", "ps"]
# Keys saved in the config file (mostly what we ask in 'pmbootstrap init')
config_keys = ["ccache_size", "device", "extra_packages", "hostname", "jobs",

View File

@ -78,8 +78,9 @@ def ask_for_work_path(args):
with open(work + "/version", "w") as handle:
handle.write(str(pmb.config.work_version) + "\n")
# Make sure, that we can write into it
os.makedirs(work + "/cache_http", 0o700, True)
# Create cache_git dir, so it is owned by the host system's user
# (otherwise pmb.helpers.mount.bind would create it as root)
os.makedirs(work + "/cache_git", 0o700, True)
return (work, exists)
except OSError:
logging.fatal("ERROR: Could not create this folder, or write"

View File

@ -49,7 +49,7 @@ def clone(args):
" recipes (pmaports)...")
# Set up the native chroot and clone pmaports
pmb.helpers.git.clone(args, "pmaports", False, True)
pmb.helpers.git.clone(args, "pmaports", False)
def symlink(args):

View File

@ -18,7 +18,6 @@ along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
"""
import logging
import os
import shutil
import pmb.build
import pmb.chroot.apk
@ -26,55 +25,37 @@ import pmb.config
import pmb.helpers.run
def clone(args, name_repo, shallow=True, chown_to_user=False):
def clone(args, name_repo, shallow=True):
""" Clone a git repository to $WORK/cache_git/$name_repo.
:param name_repo: short alias used for the repository name, from
pmb.config.git_repos (e.g. "aports_upstream",
"pmaports")
:param shallow: only clone the last revision of the repository, instead
of the entire repository (faster, saves bandwith) """
# Check for repo name in the config
if name_repo not in pmb.config.git_repos:
raise ValueError("No git repository configured for " + name_repo)
# Skip if already checked out
if os.path.exists(args.work + "/cache_git/" + name_repo):
path = args.work + "/cache_git/" + name_repo
if os.path.exists(path):
return
# Check out to temp folder
name_temp = name_repo + ".temp"
if not os.path.exists(args.work + "/cache_git/" + name_temp):
# Set up chroot and install git
pmb.chroot.apk.install(args, ["git"])
logging.info("(native) git clone " + pmb.config.git_repos[name_repo])
# Build git command
url = pmb.config.git_repos[name_repo]
command = ["git", "clone"]
if shallow:
command += ["--depth=1"]
command += [url, path]
# git options
options = []
if shallow:
options += ["--depth=1"]
# Run the command
pmb.chroot.user(args, ["git", "clone"] + options +
[pmb.config.git_repos[name_repo], name_temp],
working_dir="/home/pmos/git/", check=False,
output="stdout")
if not os.path.exists(args.work + "/cache_git/" + name_temp):
logging.info("NOTE: cloning from git is known to fail when the"
" host linux kernel is older than 3.17:"
" <https://postmarketos.org/oldkernel>")
raise RuntimeError("git clone failed!")
# Chown to user's UID and GID
if chown_to_user:
uid_gid = "{}:{}".format(os.getuid(), os.getgid())
pmb.helpers.run.root(args, ["chown", "-R", uid_gid, args.work +
"/cache_git/" + name_temp])
# Rename the temp folder
pmb.helpers.run.root(args, ["mv", name_temp, name_repo],
args.work + "/cache_git")
# Create parent dir and clone
logging.info("Clone git repository: " + url)
os.makedirs(args.work + "/cache_git", exist_ok=True)
pmb.helpers.run.user(args, command, output="stdout")
def rev_parse(args, revision="HEAD"):
if shutil.which("git") is None:
logging.warning("WARNING: Cannot determine revision of git " +
"repository at " + args.aports + ". Command 'git' " +
"not found.")
return ""
rev = pmb.helpers.run.user(args, ["git", "rev-parse", revision],
args.aports, output_return=True, check=False)
if rev is None:

View File

@ -21,6 +21,7 @@ import os
import re
import pmb.chroot
import pmb.config
import pmb.config.init
import pmb.helpers.pmaports
import pmb.helpers.run
@ -154,6 +155,30 @@ def migrate_work_folder(args):
migrate_success(args, 3)
current = 3
if current == 3:
# Ask for confirmation
path = args.work + "/cache_git"
logging.info("Changelog:")
logging.info("* pmbootstrap clones repositories with host system's")
logging.info(" 'git' instead of using it from an Alpine chroot")
logging.info("Migration will do the following:")
logging.info("* Check if 'git' is installed")
logging.info("* Change ownership to your user: " + path)
if not pmb.helpers.cli.confirm(args):
raise RuntimeError("Aborted.")
# Require git, set cache_git ownership
pmb.config.init.require_programs()
if os.path.exists(path):
uid_gid = "{}:{}".format(os.getuid(), os.getgid())
pmb.helpers.run.root(args, ["chown", "-R", uid_gid, path])
else:
os.makedirs(path, 0o700, True)
# Update version file
migrate_success(args, 4)
current = 4
# Can't migrate, user must delete it
if current != required:
raise RuntimeError("Sorry, we can't migrate that automatically. Please"