192b42cb3SPatrick Williams#!/usr/bin/env python3 292b42cb3SPatrick Williams# 392b42cb3SPatrick Williams# Copyright OpenEmbedded Contributors 492b42cb3SPatrick Williams# 592b42cb3SPatrick Williams# SPDX-License-Identifier: MIT 692b42cb3SPatrick Williams# 792b42cb3SPatrick Williams 892b42cb3SPatrick Williams# This file was copied from poky(or oe-core)/scripts/oe-setup-layers by running 992b42cb3SPatrick Williams# 1092b42cb3SPatrick Williams# bitbake-layers create-layers-setup destdir 1192b42cb3SPatrick Williams# 1292b42cb3SPatrick Williams# It is recommended that you do not modify this file directly, but rather re-run the above command to get the freshest upstream copy. 13c5535c91SAndrew Geissler# 14c5535c91SAndrew Geissler# This script is idempotent. Subsequent runs only change what is necessary to 15c5535c91SAndrew Geissler# ensure your layers match your configuration. 1692b42cb3SPatrick Williams 1792b42cb3SPatrick Williamsimport argparse 1892b42cb3SPatrick Williamsimport json 1992b42cb3SPatrick Williamsimport os 2092b42cb3SPatrick Williamsimport subprocess 2192b42cb3SPatrick Williams 226aa7eec5SAndrew Geisslerdef _is_repo_git_repo(repodir): 23c5535c91SAndrew Geissler try: 2420137395SAndrew Geissler curr_toplevel = subprocess.check_output("git -C %s rev-parse --show-toplevel" % repodir, shell=True, stderr=subprocess.DEVNULL) 2520137395SAndrew Geissler if curr_toplevel.strip().decode("utf-8") == repodir: 2620137395SAndrew Geissler return True 27c5535c91SAndrew Geissler except subprocess.CalledProcessError: 2820137395SAndrew Geissler pass 29c5535c91SAndrew Geissler return False 30c5535c91SAndrew Geissler 316aa7eec5SAndrew Geisslerdef _is_repo_at_rev(repodir, rev): 32c5535c91SAndrew Geissler try: 336aa7eec5SAndrew Geissler curr_rev = subprocess.check_output("git -C %s rev-parse HEAD" % repodir, shell=True, stderr=subprocess.DEVNULL) 34c5535c91SAndrew Geissler if curr_rev.strip().decode("utf-8") == rev: 35c5535c91SAndrew Geissler return True 36c5535c91SAndrew Geissler except subprocess.CalledProcessError: 37c5535c91SAndrew Geissler pass 38c5535c91SAndrew Geissler return False 39c5535c91SAndrew Geissler 406aa7eec5SAndrew Geisslerdef _is_repo_at_remote_uri(repodir, remote, uri): 41c5535c91SAndrew Geissler try: 426aa7eec5SAndrew Geissler curr_uri = subprocess.check_output("git -C %s remote get-url %s" % (repodir, remote), shell=True, stderr=subprocess.DEVNULL) 43c5535c91SAndrew Geissler if curr_uri.strip().decode("utf-8") == uri: 44c5535c91SAndrew Geissler return True 45c5535c91SAndrew Geissler except subprocess.CalledProcessError: 46c5535c91SAndrew Geissler pass 47c5535c91SAndrew Geissler return False 48c5535c91SAndrew Geissler 496aa7eec5SAndrew Geisslerdef _contains_submodules(repodir): 506aa7eec5SAndrew Geissler return os.path.exists(os.path.join(repodir,".gitmodules")) 5192b42cb3SPatrick Williams 52*73bd93f1SPatrick Williamsdef _write_layer_list(dest, repodirs): 53*73bd93f1SPatrick Williams layers = [] 54*73bd93f1SPatrick Williams for r in repodirs: 55*73bd93f1SPatrick Williams for root, dirs, files in os.walk(r): 56*73bd93f1SPatrick Williams if os.path.basename(root) == 'conf' and 'layer.conf' in files: 57*73bd93f1SPatrick Williams layers.append(os.path.relpath(os.path.dirname(root), dest)) 58*73bd93f1SPatrick Williams layers_f = os.path.join(dest, ".oe-layers.json") 59*73bd93f1SPatrick Williams print("Writing list of layers into {}".format(layers_f)) 60*73bd93f1SPatrick Williams with open(layers_f, 'w') as f: 61*73bd93f1SPatrick Williams json.dump({"version":"1.0","layers":layers}, f, sort_keys=True, indent=4) 62*73bd93f1SPatrick Williams 636aa7eec5SAndrew Geisslerdef _do_checkout(args, json): 646aa7eec5SAndrew Geissler repos = json['sources'] 65*73bd93f1SPatrick Williams repodirs = [] 66*73bd93f1SPatrick Williams oesetupbuild = None 676aa7eec5SAndrew Geissler for r_name in repos: 686aa7eec5SAndrew Geissler r_data = repos[r_name] 696aa7eec5SAndrew Geissler repodir = os.path.abspath(os.path.join(args['destdir'], r_data['path'])) 70*73bd93f1SPatrick Williams repodirs.append(repodir) 716aa7eec5SAndrew Geissler 726aa7eec5SAndrew Geissler if 'contains_this_file' in r_data.keys(): 7392b42cb3SPatrick Williams force_arg = 'force_bootstraplayer_checkout' 7492b42cb3SPatrick Williams if not args[force_arg]: 756aa7eec5SAndrew Geissler print('Note: not checking out source {repo}, use {repoflag} to override.'.format(repo=r_name, repoflag='--force-bootstraplayer-checkout')) 7692b42cb3SPatrick Williams continue 776aa7eec5SAndrew Geissler r_remote = r_data['git-remote'] 786aa7eec5SAndrew Geissler rev = r_remote['rev'] 796aa7eec5SAndrew Geissler desc = r_remote['describe'] 8092b42cb3SPatrick Williams if not desc: 8192b42cb3SPatrick Williams desc = rev[:10] 826aa7eec5SAndrew Geissler branch = r_remote['branch'] 836aa7eec5SAndrew Geissler remotes = r_remote['remotes'] 8492b42cb3SPatrick Williams 856aa7eec5SAndrew Geissler print('\nSetting up source {}, revision {}, branch {}'.format(r_name, desc, branch)) 866aa7eec5SAndrew Geissler if not _is_repo_git_repo(repodir): 876aa7eec5SAndrew Geissler cmd = 'git init -q {}'.format(repodir) 8892b42cb3SPatrick Williams print("Running '{}'".format(cmd)) 8992b42cb3SPatrick Williams subprocess.check_output(cmd, shell=True) 9092b42cb3SPatrick Williams 9192b42cb3SPatrick Williams for remote in remotes: 926aa7eec5SAndrew Geissler if not _is_repo_at_remote_uri(repodir, remote, remotes[remote]['uri']): 9392b42cb3SPatrick Williams cmd = "git remote remove {} > /dev/null 2>&1; git remote add {} {}".format(remote, remote, remotes[remote]['uri']) 946aa7eec5SAndrew Geissler print("Running '{}' in {}".format(cmd, repodir)) 956aa7eec5SAndrew Geissler subprocess.check_output(cmd, shell=True, cwd=repodir) 9692b42cb3SPatrick Williams 9792b42cb3SPatrick Williams cmd = "git fetch -q {} || true".format(remote) 986aa7eec5SAndrew Geissler print("Running '{}' in {}".format(cmd, repodir)) 996aa7eec5SAndrew Geissler subprocess.check_output(cmd, shell=True, cwd=repodir) 10092b42cb3SPatrick Williams 1016aa7eec5SAndrew Geissler if not _is_repo_at_rev(repodir, rev): 102c5535c91SAndrew Geissler cmd = "git fetch -q --all || true" 1036aa7eec5SAndrew Geissler print("Running '{}' in {}".format(cmd, repodir)) 1046aa7eec5SAndrew Geissler subprocess.check_output(cmd, shell=True, cwd=repodir) 105c5535c91SAndrew Geissler 10692b42cb3SPatrick Williams cmd = 'git checkout -q {}'.format(rev) 1076aa7eec5SAndrew Geissler print("Running '{}' in {}".format(cmd, repodir)) 1086aa7eec5SAndrew Geissler subprocess.check_output(cmd, shell=True, cwd=repodir) 1096aa7eec5SAndrew Geissler 1106aa7eec5SAndrew Geissler if _contains_submodules(repodir): 1116aa7eec5SAndrew Geissler print("Repo {} contains submodules, use 'git submodule update' to ensure they are up to date".format(repodir)) 112*73bd93f1SPatrick Williams if os.path.exists(os.path.join(repodir, 'scripts/oe-setup-build')): 113*73bd93f1SPatrick Williams oesetupbuild = os.path.join(repodir, 'scripts/oe-setup-build') 114*73bd93f1SPatrick Williams 115*73bd93f1SPatrick Williams _write_layer_list(args['destdir'], repodirs) 116*73bd93f1SPatrick Williams 117*73bd93f1SPatrick Williams if oesetupbuild: 118*73bd93f1SPatrick Williams oesetupbuild_symlink = os.path.join(args['destdir'], 'setup-build') 119*73bd93f1SPatrick Williams if os.path.exists(oesetupbuild_symlink): 120*73bd93f1SPatrick Williams os.remove(oesetupbuild_symlink) 121*73bd93f1SPatrick Williams os.symlink(os.path.relpath(oesetupbuild,args['destdir']),oesetupbuild_symlink) 122*73bd93f1SPatrick Williams print("\nRun '{}' to list available build configuration templates and set up a build from one of them.".format(oesetupbuild_symlink)) 12392b42cb3SPatrick Williams 12492b42cb3SPatrick Williamsparser = 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/") 12592b42cb3SPatrick Williams 12692b42cb3SPatrick Williamsparser.add_argument('--force-bootstraplayer-checkout', action='store_true', 12792b42cb3SPatrick Williams 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).') 12892b42cb3SPatrick Williams 12992b42cb3SPatrick Williamstry: 13092b42cb3SPatrick Williams defaultdest = os.path.dirname(subprocess.check_output('git rev-parse --show-toplevel', universal_newlines=True, shell=True, cwd=os.path.dirname(__file__))) 13192b42cb3SPatrick Williamsexcept subprocess.CalledProcessError as e: 13292b42cb3SPatrick Williams defaultdest = os.path.abspath(".") 13392b42cb3SPatrick Williams 13492b42cb3SPatrick Williamsparser.add_argument('--destdir', default=defaultdest, help='Where to check out the layers (default is {defaultdest}).'.format(defaultdest=defaultdest)) 13592b42cb3SPatrick Williamsparser.add_argument('--jsondata', default=__file__+".json", help='File containing the layer data in json format (default is {defaultjson}).'.format(defaultjson=__file__+".json")) 13692b42cb3SPatrick Williams 13792b42cb3SPatrick Williamsargs = parser.parse_args() 13892b42cb3SPatrick Williams 13992b42cb3SPatrick Williamswith open(args.jsondata) as f: 1406aa7eec5SAndrew Geissler json_f = json.load(f) 14192b42cb3SPatrick Williams 14292b42cb3SPatrick Williamssupported_versions = ["1.0"] 1436aa7eec5SAndrew Geisslerif json_f["version"] not in supported_versions: 1446aa7eec5SAndrew Geissler raise Exception("File {} has version {}, which is not in supported versions: {}".format(args.jsondata, json_f["version"], supported_versions)) 14592b42cb3SPatrick Williams 1466aa7eec5SAndrew Geissler_do_checkout(vars(args), json_f) 147