1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Add version information to poky.yaml based upon current git branch/tags 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Copyright Linux Foundation 6*4882a593Smuzhiyun# Author: Richard Purdie <richard.purdie@linuxfoundation.org> 7*4882a593Smuzhiyun# 8*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 9*4882a593Smuzhiyun# 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun 12*4882a593Smuzhiyunimport subprocess 13*4882a593Smuzhiyunimport collections 14*4882a593Smuzhiyunimport sys 15*4882a593Smuzhiyunimport os 16*4882a593Smuzhiyunimport itertools 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunourversion = None 19*4882a593Smuzhiyunif len(sys.argv) == 2: 20*4882a593Smuzhiyun ourversion = sys.argv[1] 21*4882a593Smuzhiyun 22*4882a593Smuzhiyunourversion = None 23*4882a593Smuzhiyunif len(sys.argv) == 2: 24*4882a593Smuzhiyun ourversion = sys.argv[1] 25*4882a593Smuzhiyun 26*4882a593Smuzhiyunactivereleases = ["kirkstone", "honister", "hardknott", "dunfell"] 27*4882a593Smuzhiyundevbranch = "langdale" 28*4882a593Smuzhiyunltsseries = ["kirkstone", "dunfell"] 29*4882a593Smuzhiyun 30*4882a593Smuzhiyunrelease_series = collections.OrderedDict() 31*4882a593Smuzhiyunrelease_series["langdale"] = "4.1" 32*4882a593Smuzhiyunrelease_series["kirkstone"] = "4.0" 33*4882a593Smuzhiyunrelease_series["honister"] = "3.4" 34*4882a593Smuzhiyunrelease_series["hardknott"] = "3.3" 35*4882a593Smuzhiyunrelease_series["gatesgarth"] = "3.2" 36*4882a593Smuzhiyunrelease_series["dunfell"] = "3.1" 37*4882a593Smuzhiyunrelease_series["zeus"] = "3.0" 38*4882a593Smuzhiyunrelease_series["warrior"] = "2.7" 39*4882a593Smuzhiyunrelease_series["thud"] = "2.6" 40*4882a593Smuzhiyunrelease_series["sumo"] = "2.5" 41*4882a593Smuzhiyunrelease_series["rocko"] = "2.4" 42*4882a593Smuzhiyunrelease_series["pyro"] = "2.3" 43*4882a593Smuzhiyunrelease_series["morty"] = "2.2" 44*4882a593Smuzhiyunrelease_series["krogoth"] = "2.1" 45*4882a593Smuzhiyunrelease_series["jethro"] = "2.0" 46*4882a593Smuzhiyunrelease_series["jethro-pre"] = "1.9" 47*4882a593Smuzhiyunrelease_series["fido"] = "1.8" 48*4882a593Smuzhiyunrelease_series["dizzy"] = "1.7" 49*4882a593Smuzhiyunrelease_series["daisy"] = "1.6" 50*4882a593Smuzhiyunrelease_series["dora"] = "1.5" 51*4882a593Smuzhiyunrelease_series["dylan"] = "1.4" 52*4882a593Smuzhiyunrelease_series["danny"] = "1.3" 53*4882a593Smuzhiyunrelease_series["denzil"] = "1.2" 54*4882a593Smuzhiyunrelease_series["edison"] = "1.1" 55*4882a593Smuzhiyunrelease_series["bernard"] = "1.0" 56*4882a593Smuzhiyunrelease_series["laverne"] = "0.9" 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun 59*4882a593Smuzhiyunbitbake_mapping = { 60*4882a593Smuzhiyun "langdale" : "2.2", 61*4882a593Smuzhiyun "kirkstone" : "2.0", 62*4882a593Smuzhiyun "honister" : "1.52", 63*4882a593Smuzhiyun "hardknott" : "1.50", 64*4882a593Smuzhiyun "gatesgarth" : "1.48", 65*4882a593Smuzhiyun "dunfell" : "1.46", 66*4882a593Smuzhiyun} 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun# 3.4 onwards doesn't have poky version 69*4882a593Smuzhiyun# Early 3.4 release docs do reference it though 70*4882a593Smuzhiyunpoky_mapping = { 71*4882a593Smuzhiyun "3.4" : "26.0", 72*4882a593Smuzhiyun "3.3" : "25.0", 73*4882a593Smuzhiyun "3.2" : "24.0", 74*4882a593Smuzhiyun "3.1" : "23.0", 75*4882a593Smuzhiyun} 76*4882a593Smuzhiyun 77*4882a593Smuzhiyunourseries = None 78*4882a593Smuzhiyunourbranch = None 79*4882a593Smuzhiyunbitbakeversion = None 80*4882a593Smuzhiyundocconfver = None 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun# Test tags exist and inform the user to fetch if not 83*4882a593Smuzhiyuntry: 84*4882a593Smuzhiyun subprocess.run(["git", "show", "yocto-3.4.2"], capture_output=True, check=True) 85*4882a593Smuzhiyunexcept subprocess.CalledProcessError: 86*4882a593Smuzhiyun sys.exit("Please run 'git fetch --tags' before building the documentation") 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun# Try and figure out what we are 89*4882a593Smuzhiyuntags = subprocess.run(["git", "tag", "--points-at", "HEAD"], capture_output=True, text=True).stdout 90*4882a593Smuzhiyunfor t in tags.split(): 91*4882a593Smuzhiyun if t.startswith("yocto-"): 92*4882a593Smuzhiyun ourversion = t[6:] 93*4882a593Smuzhiyun 94*4882a593Smuzhiyunif ourversion: 95*4882a593Smuzhiyun # We're a tagged release 96*4882a593Smuzhiyun components = ourversion.split(".") 97*4882a593Smuzhiyun baseversion = components[0] + "." + components[1] 98*4882a593Smuzhiyun docconfver = ourversion 99*4882a593Smuzhiyun for i in release_series: 100*4882a593Smuzhiyun if release_series[i] == baseversion: 101*4882a593Smuzhiyun ourseries = i 102*4882a593Smuzhiyun ourbranch = i 103*4882a593Smuzhiyun if i in bitbake_mapping: 104*4882a593Smuzhiyun bitbakeversion = bitbake_mapping[i] 105*4882a593Smuzhiyunelse: 106*4882a593Smuzhiyun # We're floating on a branch 107*4882a593Smuzhiyun branch = subprocess.run(["git", "branch", "--show-current"], capture_output=True, text=True).stdout.strip() 108*4882a593Smuzhiyun ourbranch = branch 109*4882a593Smuzhiyun if branch != "master" and branch not in release_series: 110*4882a593Smuzhiyun # We're not on a known release branch so we have to guess. Compare the numbers of commits 111*4882a593Smuzhiyun # from each release branch and assume the smallest number of commits is the one we're based off 112*4882a593Smuzhiyun possible_branch = None 113*4882a593Smuzhiyun branch_count = 0 114*4882a593Smuzhiyun for b in itertools.chain(release_series.keys(), ["master"]): 115*4882a593Smuzhiyun result = subprocess.run(["git", "log", "--format=oneline", "HEAD..origin/" + b], capture_output=True, text=True) 116*4882a593Smuzhiyun if result.returncode == 0: 117*4882a593Smuzhiyun count = result.stdout.count('\n') 118*4882a593Smuzhiyun if not possible_branch or count < branch_count: 119*4882a593Smuzhiyun print("Branch %s has count %s" % (b, count)) 120*4882a593Smuzhiyun possible_branch = b 121*4882a593Smuzhiyun branch_count = count 122*4882a593Smuzhiyun if possible_branch: 123*4882a593Smuzhiyun branch = possible_branch 124*4882a593Smuzhiyun else: 125*4882a593Smuzhiyun branch = "master" 126*4882a593Smuzhiyun print("Nearest release branch estimated to be %s" % branch) 127*4882a593Smuzhiyun if branch == "master": 128*4882a593Smuzhiyun ourseries = devbranch 129*4882a593Smuzhiyun docconfver = "dev" 130*4882a593Smuzhiyun bitbakeversion = "dev" 131*4882a593Smuzhiyun elif branch in release_series: 132*4882a593Smuzhiyun ourseries = branch 133*4882a593Smuzhiyun if branch in bitbake_mapping: 134*4882a593Smuzhiyun bitbakeversion = bitbake_mapping[branch] 135*4882a593Smuzhiyun else: 136*4882a593Smuzhiyun sys.exit("Unknown series for branch %s" % branch) 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun previoustags = subprocess.run(["git", "tag", "--merged", "HEAD"], capture_output=True, text=True).stdout 139*4882a593Smuzhiyun previoustags = [t[6:] for t in previoustags.split() if t.startswith("yocto-" + release_series[ourseries])] 140*4882a593Smuzhiyun futuretags = subprocess.run(["git", "tag", "--merged", ourbranch], capture_output=True, text=True).stdout 141*4882a593Smuzhiyun futuretags = [t[6:] for t in futuretags.split() if t.startswith("yocto-" + release_series[ourseries])] 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun # Append .999 against the last known version 144*4882a593Smuzhiyun if len(previoustags) != len(futuretags): 145*4882a593Smuzhiyun ourversion = previoustags[-1] + ".999" 146*4882a593Smuzhiyun else: 147*4882a593Smuzhiyun ourversion = release_series[ourseries] + ".999" 148*4882a593Smuzhiyun if not docconfver: 149*4882a593Smuzhiyun docconfver = ourversion 150*4882a593Smuzhiyun 151*4882a593Smuzhiyunseries = [k for k in release_series] 152*4882a593Smuzhiyunpreviousseries = series[series.index(ourseries)+1:] or [""] 153*4882a593Smuzhiyunlastlts = [k for k in previousseries if k in ltsseries] or "dunfell" 154*4882a593Smuzhiyun 155*4882a593Smuzhiyunprint("Version calculated to be %s" % ourversion) 156*4882a593Smuzhiyunprint("Release series calculated to be %s" % ourseries) 157*4882a593Smuzhiyun 158*4882a593Smuzhiyunreplacements = { 159*4882a593Smuzhiyun "DISTRO" : ourversion, 160*4882a593Smuzhiyun "DISTRO_NAME_NO_CAP" : ourseries, 161*4882a593Smuzhiyun "DISTRO_NAME" : ourseries.capitalize(), 162*4882a593Smuzhiyun "DISTRO_NAME_NO_CAP_MINUS_ONE" : previousseries[0], 163*4882a593Smuzhiyun "DISTRO_NAME_NO_CAP_LTS" : lastlts[0], 164*4882a593Smuzhiyun "YOCTO_DOC_VERSION" : ourversion, 165*4882a593Smuzhiyun "DISTRO_REL_TAG" : "yocto-" + ourversion, 166*4882a593Smuzhiyun "DOCCONF_VERSION" : docconfver, 167*4882a593Smuzhiyun "BITBAKE_SERIES" : bitbakeversion, 168*4882a593Smuzhiyun} 169*4882a593Smuzhiyun 170*4882a593Smuzhiyunif release_series[ourseries] in poky_mapping: 171*4882a593Smuzhiyun pokyversion = poky_mapping[release_series[ourseries]] 172*4882a593Smuzhiyun if ourversion != release_series[ourseries]: 173*4882a593Smuzhiyun pokyversion = pokyversion + "." + ourversion.rsplit(".", 1)[1] 174*4882a593Smuzhiyun else: 175*4882a593Smuzhiyun pokyversion = pokyversion + ".0" 176*4882a593Smuzhiyun replacements["POKYVERSION"] = pokyversion 177*4882a593Smuzhiyun 178*4882a593Smuzhiyunif os.path.exists("poky.yaml.in"): 179*4882a593Smuzhiyun with open("poky.yaml.in", "r") as r, open("poky.yaml", "w") as w: 180*4882a593Smuzhiyun lines = r.readlines() 181*4882a593Smuzhiyun for line in lines: 182*4882a593Smuzhiyun data = line.split(":") 183*4882a593Smuzhiyun k = data[0].strip() 184*4882a593Smuzhiyun if k in replacements: 185*4882a593Smuzhiyun w.write("%s : \"%s\"\n" % (k, replacements[k])) 186*4882a593Smuzhiyun else: 187*4882a593Smuzhiyun w.write(line) 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun print("poky.yaml generated from poky.yaml.in") 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun 192*4882a593Smuzhiyun# In the switcher list of versions we display: 193*4882a593Smuzhiyun# - latest dev 194*4882a593Smuzhiyun# - latest stable release 195*4882a593Smuzhiyun# - latest LTS 196*4882a593Smuzhiyun# - latest for each releases listed as active 197*4882a593Smuzhiyun# - latest doc version in current series 198*4882a593Smuzhiyun# - current doc version 199*4882a593Smuzhiyun# (with duplicates removed) 200*4882a593Smuzhiyun 201*4882a593Smuzhiyunversions = [] 202*4882a593Smuzhiyunwith open("sphinx-static/switchers.js.in", "r") as r, open("sphinx-static/switchers.js", "w") as w: 203*4882a593Smuzhiyun lines = r.readlines() 204*4882a593Smuzhiyun for line in lines: 205*4882a593Smuzhiyun if "ALL_RELEASES_PLACEHOLDER" in line: 206*4882a593Smuzhiyun w.write(str(list(release_series.keys()))) 207*4882a593Smuzhiyun continue 208*4882a593Smuzhiyun if "VERSIONS_PLACEHOLDER" in line: 209*4882a593Smuzhiyun w.write(" 'dev': { 'title': 'dev (%s)', 'obsolete': false,},\n" % release_series[devbranch]) 210*4882a593Smuzhiyun for branch in activereleases + ([ourseries] if ourseries not in activereleases else []): 211*4882a593Smuzhiyun if branch == devbranch: 212*4882a593Smuzhiyun continue 213*4882a593Smuzhiyun branch_versions = subprocess.run('git tag --list yocto-%s*' % (release_series[branch]), shell=True, capture_output=True, text=True).stdout.split() 214*4882a593Smuzhiyun branch_versions = sorted([v.replace("yocto-" + release_series[branch] + ".", "").replace("yocto-" + release_series[branch], "0") for v in branch_versions], key=int) 215*4882a593Smuzhiyun if not branch_versions: 216*4882a593Smuzhiyun continue 217*4882a593Smuzhiyun version = release_series[branch] 218*4882a593Smuzhiyun if branch_versions[-1] != "0": 219*4882a593Smuzhiyun version = version + "." + branch_versions[-1] 220*4882a593Smuzhiyun versions.append(version) 221*4882a593Smuzhiyun w.write(" '%s': {'title': '%s', 'obsolete': %s,},\n" % (version, version, str(branch not in activereleases).lower())) 222*4882a593Smuzhiyun if ourversion not in versions and ourseries != devbranch: 223*4882a593Smuzhiyun w.write(" '%s': {'title': '%s', 'obsolete': %s,},\n" % (ourversion, ourversion, str(ourseries not in activereleases).lower())) 224*4882a593Smuzhiyun else: 225*4882a593Smuzhiyun w.write(line) 226*4882a593Smuzhiyun 227*4882a593Smuzhiyunprint("switchers.js generated from switchers.js.in") 228*4882a593Smuzhiyun 229