| #!/usr/bin/env python3 | |
| # | |
| # Copyright OpenEmbedded Contributors | |
| # | |
| # SPDX-License-Identifier: MIT | |
| # | |
| # This file was copied from poky(or oe-core)/scripts/oe-setup-layers by running | |
| # | |
| # bitbake-layers create-layers-setup destdir | |
| # | |
| # It is recommended that you do not modify this file directly, but rather re-run the above command to get the freshest upstream copy. | |
| # | |
| # This script is idempotent. Subsequent runs only change what is necessary to | |
| # ensure your layers match your configuration. | |
| import argparse | |
| import json | |
| import os | |
| import subprocess | |
| def _is_repo_git_repo(repodir): | |
| try: | |
| curr_toplevel = subprocess.check_output(['git', '-C', repodir, 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL) | |
| if curr_toplevel.strip().decode("utf-8") == repodir: | |
| return True | |
| except subprocess.CalledProcessError: | |
| pass | |
| return False | |
| def _is_repo_at_rev(repodir, rev): | |
| try: | |
| curr_rev = subprocess.check_output(['git', '-C', repodir, 'rev-parse', 'HEAD'], stderr=subprocess.DEVNULL) | |
| if curr_rev.strip().decode("utf-8") == rev: | |
| return True | |
| except subprocess.CalledProcessError: | |
| pass | |
| return False | |
| def _is_repo_at_remote_uri(repodir, remote, uri): | |
| try: | |
| curr_uri = subprocess.check_output(['git', '-C', repodir, 'remote', 'get-url', remote], stderr=subprocess.DEVNULL) | |
| if curr_uri.strip().decode("utf-8") == uri: | |
| return True | |
| except subprocess.CalledProcessError: | |
| pass | |
| return False | |
| def _contains_submodules(repodir): | |
| return os.path.exists(os.path.join(repodir,".gitmodules")) | |
| def _write_layer_list(dest, repodirs): | |
| layers = [] | |
| for r in repodirs: | |
| for root, dirs, files in os.walk(r): | |
| if os.path.basename(root) == 'conf' and 'layer.conf' in files: | |
| layers.append(os.path.relpath(os.path.dirname(root), dest)) | |
| layers_f = os.path.join(dest, ".oe-layers.json") | |
| print("Writing list of layers into {}".format(layers_f)) | |
| with open(layers_f, 'w') as f: | |
| json.dump({"version":"1.0","layers":layers}, f, sort_keys=True, indent=4) | |
| def _get_remotes(r_remote): | |
| remotes = {} | |
| if not 'remotes' in r_remote and not 'uri' in r_remote: | |
| raise Exception("Expected key(s): 'remotes', 'uri'") | |
| if 'remotes' in r_remote: | |
| remotes = r_remote['remotes'].copy() | |
| if 'uri' in r_remote: | |
| r_name = '' | |
| if 'remotes' in r_remote: | |
| if not 'origin' in r_remote['remotes']: | |
| r_name = 'origin' | |
| else: | |
| import itertools | |
| for i in itertools.count(start=1): | |
| if not 'origin-{}'.format(i) in r_remote['remotes']: | |
| r_name = 'origin-{}'.format(i) | |
| break | |
| else: | |
| r_name = 'origin' | |
| remotes.update({r_name: {'uri': r_remote['uri']}}) | |
| return remotes | |
| def _do_checkout(args, json): | |
| repos = json['sources'] | |
| repodirs = [] | |
| oesetupbuild = None | |
| for r_name in repos: | |
| r_data = repos[r_name] | |
| repodir = os.path.abspath(os.path.join(args['destdir'], r_data.get('path', r_name))) | |
| repodirs.append(repodir) | |
| if 'contains_this_file' in r_data.keys(): | |
| force_arg = 'force_bootstraplayer_checkout' | |
| if not args[force_arg]: | |
| print('Note: not checking out source {repo}, use {repoflag} to override.'.format(repo=r_name, repoflag='--force-bootstraplayer-checkout')) | |
| continue | |
| r_remote = r_data['git-remote'] | |
| rev = r_remote['rev'] | |
| desc = r_remote['describe'] | |
| if not desc: | |
| desc = rev[:10] | |
| branch = r_remote['branch'] | |
| remotes = _get_remotes(r_remote) | |
| print('\nSetting up source {}, revision {}, branch {}'.format(r_name, desc, branch)) | |
| if not _is_repo_git_repo(repodir): | |
| cmd = ['git', 'init', '-q', repodir] | |
| print("Running '{}'".format(cmd)) | |
| subprocess.check_output(cmd) | |
| for remote in remotes: | |
| if not _is_repo_at_remote_uri(repodir, remote, remotes[remote]['uri']): | |
| cmd = ['git', 'remote', 'remove', remote] | |
| # Ignore errors | |
| subprocess.run(cmd, cwd=repodir) | |
| cmd = ['git', 'remote', 'add', remote, remotes[remote]['uri']] | |
| print("Running '{}' in {}".format(cmd, repodir)) | |
| subprocess.check_output(cmd, cwd=repodir) | |
| cmd = ['git', 'fetch', '-q', remote] | |
| print("Running '{}' in {}".format(cmd, repodir)) | |
| # Ignore errors | |
| subprocess.run(cmd, cwd=repodir) | |
| if not _is_repo_at_rev(repodir, rev): | |
| cmd = ['git', 'fetch', '-q', '--all'] | |
| print("Running '{}' in {}".format(cmd, repodir)) | |
| # Ignore errors | |
| subprocess.run(cmd, cwd=repodir) | |
| cmd = ['git', 'checkout', '-q', rev] | |
| print("Running '{}' in {}".format(cmd, repodir)) | |
| subprocess.check_output(cmd, cwd=repodir) | |
| if _contains_submodules(repodir): | |
| print("Repo {} contains submodules, use 'git submodule update' to ensure they are up to date".format(repodir)) | |
| if os.path.exists(os.path.join(repodir, 'scripts/oe-setup-build')): | |
| oesetupbuild = os.path.join(repodir, 'scripts/oe-setup-build') | |
| _write_layer_list(args['destdir'], repodirs) | |
| if oesetupbuild: | |
| oesetupbuild_symlink = os.path.join(args['destdir'], 'setup-build') | |
| if os.path.exists(oesetupbuild_symlink): | |
| os.remove(oesetupbuild_symlink) | |
| os.symlink(os.path.relpath(oesetupbuild,args['destdir']),oesetupbuild_symlink) | |
| print("\nRun '{}' to list available build configuration templates and set up a build from one of them.".format(oesetupbuild_symlink)) | |
| parser = argparse.ArgumentParser(description="A self contained python script that fetches all the needed layers and sets them to correct revisions using data in a json format from a separate file. The json data can be created from an active build directory with 'bitbake-layers create-layers-setup destdir' and there's a sample file and a schema in meta/files/") | |
| parser.add_argument('--force-bootstraplayer-checkout', action='store_true', | |
| help='Force the checkout of the layer containing this file (by default it is presumed that as this script is in it, the layer is already in place).') | |
| try: | |
| defaultdest = os.path.dirname(subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], universal_newlines=True, cwd=os.path.dirname(__file__))) | |
| except subprocess.CalledProcessError as e: | |
| defaultdest = os.path.abspath(".") | |
| parser.add_argument('--destdir', default=defaultdest, help='Where to check out the layers (default is {defaultdest}).'.format(defaultdest=defaultdest)) | |
| parser.add_argument('--jsondata', default=__file__+".json", help='File containing the layer data in json format (default is {defaultjson}).'.format(defaultjson=__file__+".json")) | |
| args = parser.parse_args() | |
| with open(args.jsondata) as f: | |
| json_f = json.load(f) | |
| supported_versions = ["1.0"] | |
| if json_f["version"] not in supported_versions: | |
| raise Exception("File {} has version {}, which is not in supported versions: {}".format(args.jsondata, json_f["version"], supported_versions)) | |
| _do_checkout(vars(args), json_f) |