diff options
Diffstat (limited to 'meta/classes/webos_enhanced_submissions.bbclass')
-rw-r--r-- | meta/classes/webos_enhanced_submissions.bbclass | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/meta/classes/webos_enhanced_submissions.bbclass b/meta/classes/webos_enhanced_submissions.bbclass new file mode 100644 index 0000000000..e4ad2b856d --- /dev/null +++ b/meta/classes/webos_enhanced_submissions.bbclass @@ -0,0 +1,309 @@ +# Copyright (c) 2012-2018 LG Electronics, Inc. +# +# webos_enhanced_submissions +# +# Parse a WEBOS_VERSION in the following format: +# +# <component-version>-<enhanced-submission> +# +# where <enhanced-submission> is of the form: +# +# <submission>_<40-character-SHA-1>[;branch=<branch>] +# +# setting WEBOS_COMPONENT_VERSION, WEBOS_SUBMISSION, WEBOS_GIT_PARAM_TAG, +# WEBOS_GIT_TAG, WEBOS_GIT_PARAM_BRANCH, WEBOS_SRCREV, SRCREV, and PV. +# +# The default tag name is the webOS convention for submission tags, i.e., +# they are of the form: +# submissions/<decimal-integer> (default branch: "master") +# or, when the submission is from some permanent branch: +# submissions/<name>.<decimal-integer> (default branch: "@<name>") +# where <decimal-integer> does not contain leading zeros. +# +# <name> is the branch name without leading '@' and can have following forms: +# <decimal-integer> when the branch was created from submissions/<decimal-integer>. +# <decimal-integer>.<codename> when the branch was also created from +# submissions/<decimal-integer> tag, but for some specific <codename> release. +# <decimal-integer>.<codename>.<decimal-integer> is used for multiple levels of +# branched submissions, e.g. NN.<codename>.MM.PP is PP-th submission along the +# @NN.<codename>.MM branch. +# +# The default branch name value can be overriden by "branch" parameter in WEBOS_VERSION +# or by setting WEBOS_GIT_PARAM_BRANCH. +# +# The default tag name can be overriden by setting WEBOS_GIT_PARAM_TAG. +# +# WEBOS_SUBMISSION '0' has special meaning to disable check +# that selected SHA-1 is matching with submissions tag +# +# There is limited support for recipes with multiple git repositories in SRC_URI. +# Exactly one of them needs to have empty 'name' parameter or 'name' parameter with +# value 'main' and this one will get SRCREV set and verified by this bbclass. + +inherit webos_submissions + +def webos_enhsub_get_srcrev(d, webos_v): + webos_srcrev = webos_version_get_srcrev(webos_v) + webos_submission = d.getVar('WEBOS_SUBMISSION', True) + # submission 0 means that we're using: + # a) AUTOREV + # b) SHA-1 possibly not included in any tag or branch + # c) something else (like reference to a Gerrit review) + # + # a) and b) should be set in SRCREV + # c) should be set in WEBOS_GIT_PARAM_TAG with WEBOS_GIT_TAG enabled and let git ls-remote resolve it + # Another way to handle c) is to override WEBOS_GIT_TAG directly with ";tag=<ref>" + if webos_submission == '0': + # return only valid SRCREV or "AUTOINC", otherwise "INVALID" + if webos_srcrev == "AUTOINC" or not (len(webos_srcrev) != 40 or (False in [c in "abcdef0123456789" for c in webos_srcrev])): + return webos_srcrev + else: + return "INVALID" + if webos_srcrev == None or len(webos_srcrev) != 40 or (False in [c in "abcdef0123456789" for c in webos_srcrev]): + file = d.getVar('FILE', True) + webos_git_repo_tag = d.getVar('WEBOS_GIT_REPO_TAG', True) or "submissions/%s" % webos_submission + bb.fatal(("%s: WEBOS_VERSION needs to end with _<SHA-1> where " + + "<SHA-1> is the 40-character identifier of '%s' tag") + % (file, webos_git_repo_tag)) + # only valid SRCREVs at this point + return webos_srcrev + +def webos_enhsub_get_tag(d, webos_v): + webos_submission = d.getVar('WEBOS_SUBMISSION', True) + webos_git_repo_tag = d.getVar('WEBOS_GIT_REPO_TAG', True) or "submissions/%s" % webos_submission + return webos_git_repo_tag + +# Set WEBOS_SRCREV to value from WEBOS_VERSION. +WEBOS_SRCREV = "${@webos_enhsub_get_srcrev(d, '${WEBOS_VERSION}')}" + +# we don't include SRCPV in PV, so we have to manually include SRCREVs in do_fetch vardeps +do_fetch[vardeps] += "SRCREV_main SRCREV" +SRCREV = "${WEBOS_SRCREV}" +SRCREV_main = "${WEBOS_SRCREV}" + +# append WEBOS_PV_SUFFIX to PV when you're using 0 as WEBOS_SUBMISSION to make it clear which SHA-1 was built +WEBOS_PV_SUFFIX = "+gitr${SRCPV}" + +# srcrev is mandatory and enough, don't put tag= in SRC_URI +# to reenable you need to set WEBOS_GIT_TAG to ";tag=${WEBOS_GIT_PARAM_TAG}" +WEBOS_GIT_PARAM_TAG = "${@webos_enhsub_get_tag(d, '${WEBOS_VERSION}')}" +WEBOS_GIT_TAG = "" + +WEBOS_GIT_PARAM_BRANCH = "${@webos_version_get_branch('${WEBOS_VERSION}')}" + +# When SRCREV isn't SHA-1 show error +do_fetch[prefuncs] += "webos_enhsub_srcrev_sanity_check" + +# '0' in 'webos_submission' is used with AUTOREV or SHA-1 without matching tag +# show non-fatal ERROR to make sure that it's not accidentally merged in master +python webos_enhsub_srcrev_sanity_check() { + srcrev = d.getVar('SRCREV', True) + webos_submission = d.getVar('WEBOS_SUBMISSION', True) + if webos_submission == '0': + webos_version = d.getVar('WEBOS_VERSION', True) + pn = d.getVar('PN', True) + file = d.getVar('FILE', True) + msg = "WEBOS_VERSION '%s' for recipe '%s' (file '%s') contains submission 0, which indicates using AUTOREV or SHA-1 without matching tag and cannot be used in official builds." % (webos_version, pn, file) + package_qa_handle_error("webos-enh-sub-autorev-error", msg, d) + elif (len(srcrev) != 40 or (False in [c in "abcdef0123456789" for c in srcrev])): + file = d.getVar('FILE', True) + bb.error("%s: SRCREV needs to contain 40-character SHA1" % file) +} + +# When both SRCREV and WEBOS_SUBMISSION are defined check that they correspond +# This only compares tag and SHA-1 in local checkout (without using git ls-remote) +# This check is executed only when do_fetch is executed, that means that if someone +# moves the tag in remote repository, we won't notice it until do_fetch is re-executed. +do_unpack[postfuncs] += "submission_sanity_check" +python submission_sanity_check() { + def webos_enhsub_remote_update(d, u, pn, checkout): + """ Runs git remote update to fetch newly added tags or updated branches in case one of the checks fails + It runs git remote update twice, first in DL_DIR (e.g. downloads/git2/github.com.openwebos.librolegen/) + then in actuall checkout in WORKDIR, because we're already in do_unpack task and sanity checks are + executed in WORKDIR. + This isn't as efficient as the implementation in newer bitbake, because PREMIRROR tarballs aren't + recreated after this git remote update, so local builds will fetch the tarball and also run own + git remote update until PREMIRROR tarball is updated by fetching even newer SRCREV. + """ + bb.debug(2, "Running git remote update for pn '%s', checkout '%s'" % (pn, checkout)) + fetcher = bb.fetch2.Fetch([u], d) + localpath = fetcher.localpath(u) + bb.warn("Fetcher accessing the network, because sanity check failed %s, %s" % (u, localpath)) + cmd = "cd %s && git remote update" % (localpath) + try: + output = bb.fetch.runfetchcmd(cmd, d, quiet=True) + except bb.fetch2.FetchError: + msg = "Unable to update '%s' checkout for recipe '%s'" % (localpath, pn) + package_qa_handle_error("webos-enh-sub-error", msg, d) + # and the same in WORKDIR + cmd = "cd %s && git remote update" % (checkout) + try: + output = bb.fetch.runfetchcmd(cmd, d, quiet=True) + except bb.fetch2.FetchError: + msg = "Unable to update '%s' checkout for recipe '%s'" % (checkout, pn) + package_qa_handle_error("webos-enh-sub-error", msg, d) + + + def webos_enhsub_tag_sanity_check(d, fetcher, u, pn, tag_param, rev, webos_git_repo_tag, checkout, file, first=True): + """ Checks that tag: + 1) exists + 2) is annotated (not lightweight) + 3) uniq + 4) matches with selected SRCREV + """ + bb.debug(2, "sanity check for tag in pn '%s', tag_param '%s', rev '%s', webos_git_repo_tag '%s', checkout '%s'" % (pn, tag_param, rev, webos_git_repo_tag, checkout)) + cmd = "cd %s && git tag -l 2>/dev/null | grep '^%s$' | wc -l" % (checkout, webos_git_repo_tag) + tag_exists = bb.fetch.runfetchcmd(cmd, d).strip() + if tag_exists != "1": + if first: + webos_enhsub_remote_update(d, u, pn, checkout) + webos_enhsub_tag_sanity_check(d, fetcher, u, pn, tag_param, rev, webos_git_repo_tag, checkout, file, False) + return + else: + localpath = fetcher.localpath(u) + msg = "The tag '%s' for recipe '%s' (file '%s') doesn't exist in local checkout of SHA-1 '%s'. It's possible that the tag already exists in a remote repository, but your local checkout (or checkout downloaded as a tarball from PREMIRROR) contains the requested SHA-1 without a tag assigned to it (this cannot happen with annotated tags, because they have their own SHA-1 which either exists or not). Please update your checkout in %s by executing git fetch --tags and run again." % (webos_git_repo_tag, pn, file, rev, localpath) + package_qa_handle_error("webos-enh-sub-error", msg, d) + return + # for annotated tags there are 2 SHA-1s and we don't care which one is used (same source) + # $ git show-ref -d --tags 0.5 + # 70fb05fd340ab342c5132dc8bfa174dbe6c9d330 refs/tags/0.5 + # 215f9c884d0139c93feea940d255dc3575678218 refs/tags/0.5^{} + # prefix with 'refs/tags/' so that partial tags aren't matched, e.g. librolegen: + # $ git show-ref -d --tags 18 + # cbedc69733f65cd2f498787a621c014e219d38ab refs/tags/submissions/18 + # 9040954a24115b05219e7dd459dcf91ad05cc739 refs/tags/submissions/18^{} + # $ git show-ref -d --tags refs/tags/18 + # <nothing> + cmd = "cd %s && git show-ref -d --tags refs/tags/%s" % (checkout, webos_git_repo_tag) + tag_srcrevs = bb.fetch.runfetchcmd(cmd, d).strip().split('\n') + found_srcrev = False + if len(tag_srcrevs) > 2: + msg = "The reference refs/tags/%s is matching more than 2 entries for recipe '%s' (file '%s'):\n%s" % (webos_git_repo_tag, pn, file, '\n'.join(tag_srcrevs)) + package_qa_handle_error("webos-enh-sub-error", msg, d) + if len(tag_srcrevs) == 1: + if first: + webos_enhsub_remote_update(d, u, pn, checkout) + webos_enhsub_tag_sanity_check(d, fetcher, u, pn, tag_param, rev, webos_git_repo_tag, checkout, file, False) + return + else: + msg = "The tag '%s' for recipe '%s' (file '%s') is lightweight tag, please use annotated tag in next submission" % (webos_git_repo_tag, pn, file) + package_qa_handle_error("webos-enh-sub-error", msg, d) + for tag_srcrev in tag_srcrevs: + (sha, name) = tag_srcrev.split() + if sha == rev: + found_srcrev = True + if tag_srcrev != tag_srcrevs[0] or tag_srcrev.find("^{}") == len(tag_srcrev) - 3: + msg = "The tag '%s' for recipe '%s' (file '%s') is annotated, but WEBOS_VERSION '%s' is using SHA-1 of last commit included, not of the tag itself '%s'" % (webos_git_repo_tag, pn, file, webos_version, tag_srcrevs[0].split()[0]) + package_qa_handle_error("webos-enh-sub-error", msg, d) + + if not found_srcrev: + if first: + webos_enhsub_remote_update(d, u, pn, checkout) + webos_enhsub_tag_sanity_check(d, fetcher, u, pn, tag_param, rev, webos_git_repo_tag, checkout, file, False) + return + else: + if len(tag_srcrevs) < 1: + msg = "The SHA-1 '%s' defined in WEBOS_VERSION for recipe '%s' (file '%s') doesn't match with tag '%s', tag couldn't be found in refs/tags/" % (rev, pn, file, webos_git_repo_tag) + package_qa_handle_error("webos-enh-sub-error", msg, d) + elif len(tag_srcrevs) == 1: + msg = "The SHA-1 '%s' defined in WEBOS_VERSION for recipe '%s' (file '%s') doesn't match with tag '%s', which is seen as SHA-1 '%s'" % (rev, pn, file, webos_git_repo_tag, tag_srcrevs[0].split()[0]) + package_qa_handle_error("webos-enh-sub-error", msg, d) + else: + msg = "The SHA-1 '%s' defined in WEBOS_VERSION for recipe '%s' (file '%s') doesn't match with tag '%s', which is seen as SHA-1s:\n%s" % (rev, pn, file, webos_git_repo_tag, '\n'.join(tag_srcrevs)) + package_qa_handle_error("webos-enh-sub-error", msg, d) + + def webos_enhsub_branch_sanity_check(d, u, fetcher, branch_in_webos_version, branch_in_src_uri, pn, file, checkout, rev, first=True): + """ Checks that selected SRCREV is included in selected branch + duplicates bitbake's git fetcher functionality added in + http://git.openembedded.org/bitbake/commit/?id=89abfbc1953e3711d6c90aff793ee622c22609b1 + http://git.openembedded.org/bitbake/commit/?id=31467c0afe0346502fcd18bd376f23ea76a27d61 + http://git.openembedded.org/bitbake/commit/?id=f594cb9f5a18dd0ab2342f96ffc6dba697b35f65 + """ + bb.debug(2, "sanity check for branch in pn '%s', branch_in_webos_version '%s', branch_in_src_uri '%s', rev '%s', checkout '%s'" % (pn, branch_in_webos_version, branch_in_src_uri, rev, checkout)) + if branch_in_src_uri != branch_in_webos_version: + msg = "Branch is set in WEBOS_VERSION '%s' for recipe '%s' (file '%s') as well as in SRC_URI '%s' and they don't match" % (branch_in_webos_version, pn, file, branch_in_src_uri) + package_qa_handle_error("webos-enh-sub-error", msg, d) + cmd = "cd %s && git branch -a --contains %s --list origin/%s 2> /dev/null | wc -l" % (checkout, rev, branch_in_webos_version) + try: + output = bb.fetch.runfetchcmd(cmd, d, quiet=True) + except bb.fetch2.FetchError: + msg = "Unable to check if SHA-1 '%s' defined in WEBOS_VERSION for recipe '%s' (file '%s') is included in branch '%s'" % (rev, pn, file, branch) + package_qa_handle_error("webos-enh-sub-error", msg, d) + if len(output.split()) > 1: + msg = "Unable to check if SHA-1 '%s' defined in WEBOS_VERSION for recipe '%s' (file '%s') is included in branch '%s', unexpected output from '%s': '%s'" % (rev, pn, file, branch_in_webos_version, cmd, output) + package_qa_handle_error("webos-enh-sub-error", msg, d) + if output.split()[0] == "0": + if first: + webos_enhsub_remote_update(d, u, pn, checkout) + webos_enhsub_branch_sanity_check(d, u, fetcher, branch_in_webos_version, branch_in_src_uri, pn, file, checkout, rev, False) + return + else: + msg = "Revision '%s' defined in WEBOS_VERSION for recipe '%s' (file '%s') isn't included in branch '%s'" % (rev, pn, file, branch_in_webos_version) + package_qa_handle_error("webos-enh-sub-error", msg, d) + + src_uri = (d.getVar('SRC_URI', True) or "").split() + if len(src_uri) == 0: + return + + externalsrc = d.getVar('EXTERNALSRC', True) or "" + if len(externalsrc) != 0: + return + + found_first = False + workdir = d.getVar('WORKDIR', True) + pn = d.getVar('PN', True) + file = d.getVar('FILE', True) + fetcher = bb.fetch.Fetch(src_uri, d) + urldata = fetcher.ud + autoinc_templ = 'AUTOINC+' + for u in urldata: + tag_param = urldata[u].parm['tag'] if 'tag' in urldata[u].parm else None + name_param = urldata[u].parm['name'] if 'name' in urldata[u].parm else 'main' + if urldata[u].type == 'git' and name_param == 'main': + if found_first: + msg = "webos_enhanced_submission bbclass has limited support for recipes with multiple git repos in SRC_URI. They have to have different 'name' parameter and the one which points to repository with submissions tag should have 'name=main'. Recipe '%s' (file '%s') has multiple git repos with 'main' name or without names" % (pn, file) + package_qa_handle_error("webos-enh-sub-warning", msg, d) + break + found_first = True + destsuffix_param = urldata[u].parm['destsuffix'] if 'destsuffix' in urldata[u].parm else 'git' + webos_version = d.getVar('WEBOS_VERSION', True) + srcrev = d.getVar('SRCREV', True) + name = urldata[u].parm['name'] if 'name' in urldata[u].parm else 'default' + try: + rev = urldata[u].method.sortable_revision(urldata[u], d, name) + except TypeError: + # support old bitbake versions + rev = urldata[u].method.sortable_revision(u, urldata[u], d, name) + # Clean this up when we next bump bitbake version + if type(rev) != str: + autoinc, rev = rev + elif rev.startswith(autoinc_templ): + rev = rev[len(autoinc_templ):] + + webos_git_repo_tag = d.getVar('WEBOS_GIT_REPO_TAG', True) + webos_submission = d.getVar('WEBOS_SUBMISSION', True) + default_webos_git_repo_tag = "submissions/%s" % webos_submission + if not srcrev: + # Recipe needs to have SRCREV set one way or another + # it could be in WEBOS_VERSION, from AUTOREV or by explicit SRCREV assignment + msg = "Recipe '%s' (file '%s') doesn't contain SRCREV" % (pn, file) + package_qa_handle_error("webos-enh-sub-error", msg, d) + if not webos_git_repo_tag: + webos_git_repo_tag = default_webos_git_repo_tag + elif webos_git_repo_tag == default_webos_git_repo_tag: + msg = "Don't set WEBOS_GIT_REPO_TAG when the component is using default scheme 'submissions/${WEBOS_SUBMISSION}' in recipe '%s' (file '%s')" % (pn, file) + package_qa_handle_error("webos-enh-sub-error", msg, d) + checkout = "%s/%s" % (workdir, destsuffix_param) + + # '0' in 'webos_submission' is used with AUTOREV -> so don't check AUTOREV against submissions/0 tag + if webos_submission != '0' and webos_git_repo_tag and rev: + webos_enhsub_tag_sanity_check(d, fetcher, u, pn, tag_param, rev, webos_git_repo_tag, checkout, file) + + if not 'nobranch' in urldata[u].parm or urldata[u].parm['nobranch'] != "1": + branch_in_src_uri = urldata[u].parm['branch'] if 'branch' in urldata[u].parm else 'master' + branch_in_webos_version = d.getVar('WEBOS_GIT_PARAM_BRANCH', True) + webos_enhsub_branch_sanity_check(d, u, fetcher, branch_in_webos_version, branch_in_src_uri, pn, file, checkout, rev) + if not found_first: + msg = "Recipe '%s' (file '%s') doesn't have git repository without 'name' parameter or with 'name=main' in SRC_URI, webos_enhanced_submission bbclass shouldn't be inherited here (it has nothing to do)" % (pn, file) + package_qa_handle_error("webos-enh-sub-warning", msg, d) +} |