summaryrefslogtreecommitdiffstats
path: root/scripts/oe-setup-layers
blob: 6fbfefd656f99112237ea9e434cd23ee7e3c3fea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/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 %s rev-parse --show-toplevel" % repodir, shell=True, 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 %s rev-parse HEAD" % repodir, shell=True, 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 %s remote get-url %s" % (repodir, remote), shell=True, 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 _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['path']))
        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 = r_remote['remotes']

        print('\nSetting up source {}, revision {}, branch {}'.format(r_name, desc, branch))
        if not _is_repo_git_repo(repodir):
            cmd = 'git init -q {}'.format(repodir)
            print("Running '{}'".format(cmd))
            subprocess.check_output(cmd, shell=True)

        for remote in remotes:
            if not _is_repo_at_remote_uri(repodir, remote, remotes[remote]['uri']):
                cmd = "git remote remove {} > /dev/null 2>&1; git remote add {} {}".format(remote, remote, remotes[remote]['uri'])
                print("Running '{}' in {}".format(cmd, repodir))
                subprocess.check_output(cmd, shell=True, cwd=repodir)

                cmd = "git fetch -q {} || true".format(remote)
                print("Running '{}' in {}".format(cmd, repodir))
                subprocess.check_output(cmd, shell=True, cwd=repodir)

        if not _is_repo_at_rev(repodir, rev):
            cmd = "git fetch -q --all || true"
            print("Running '{}' in {}".format(cmd, repodir))
            subprocess.check_output(cmd, shell=True, cwd=repodir)

            cmd = 'git checkout -q {}'.format(rev)
            print("Running '{}' in {}".format(cmd, repodir))
            subprocess.check_output(cmd, shell=True, 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, shell=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)