Tools: generate_manifest.py: allow generation of features.json file

This commit is contained in:
Peter Barker 2022-07-29 15:19:37 +10:00 committed by Peter Barker
parent 71d1c050b3
commit 459af5ec9b
2 changed files with 101 additions and 32 deletions

View File

@ -20,7 +20,6 @@ import string
import subprocess
import sys
import traceback
import gzip
# local imports
import generate_manifest
@ -621,21 +620,9 @@ is bob we will attempt to checkout bob-AVR'''
base_url = 'https://firmware.ardupilot.org'
generator = generate_manifest.ManifestGenerator(self.binaries,
base_url)
content = generator.json()
new_json_filepath = os.path.join(self.binaries, "manifest.json.new")
self.write_string_to_filepath(content, new_json_filepath)
# provide a pre-compressed manifest. For reference, a 7M manifest
# "gzip -9"s to 300k in 1 second, "xz -e"s to 80k in 26 seconds
new_json_filepath_gz = os.path.join(self.binaries,
"manifest.json.gz.new")
with gzip.open(new_json_filepath_gz, 'wb') as gf:
if running_python3:
content = bytes(content, 'ascii')
gf.write(content)
json_filepath = os.path.join(self.binaries, "manifest.json")
json_filepath_gz = os.path.join(self.binaries, "manifest.json.gz")
shutil.move(new_json_filepath, json_filepath)
shutil.move(new_json_filepath_gz, json_filepath_gz)
generator.run()
generator.write_manifest_json(os.path.join(self.binaries, "manifest.json"))
self.progress("Manifest generation successful")
self.progress("Generating stable releases")

View File

@ -2,18 +2,26 @@
from __future__ import print_function
import sys
import copy
import fnmatch
import gen_stable
import gzip
import json
import os
import re
import fnmatch
import gen_stable
import subprocess
import shutil
import sys
if sys.version_info[0] < 3:
running_python3 = False
running_python310 = False
elif sys.version_info[1] < 10:
running_python3 = True
running_python310 = False
else:
running_python3 = True
running_python310 = True
FIRMWARE_TYPES = ["AntennaTracker", "Copter", "Plane", "Rover", "Sub", "AP_Periph", "Blimp"]
RELEASE_TYPES = ["beta", "latest", "stable", "stable-*", "dirty"]
@ -394,8 +402,14 @@ class ManifestGenerator():
frame = vehicletype # e.g. Plane
platform = platformdir # e.g. apm2
# also gather information from any features.txt files present:
features_text = None
features_filepath = os.path.join(some_dir, "features.txt")
if os.path.exists(features_filepath):
features_text = sorted(open(features_filepath).read().rstrip().split("\n"))
for filename in os.listdir(some_dir):
if filename in ["git-version.txt", "firmware-version.txt", "files.html"]:
if filename in ["git-version.txt", "firmware-version.txt", "files.html", "features.txt"]:
continue
if filename.startswith("."):
continue
@ -446,6 +460,8 @@ class ManifestGenerator():
firmware["format"] = firmware_format
firmware["firmware-version"] = firmware_version
firmware["features"] = features_text
firmware_data.append(firmware)
def valid_release_type(self, tag):
@ -506,6 +522,8 @@ class ManifestGenerator():
# convert from ardupilot-naming conventions to common JSON format:
firmware_json = []
features_json = [] # a structure containing summarised features per firmware
for firmware in firmwares:
filepath = firmware["filepath"]
# replace the base directory with the base URL
@ -524,6 +542,7 @@ class ManifestGenerator():
"latest": firmware["latest"],
"format": firmware["format"],
})
if firmware["firmware-version"]:
try:
(major, minor, patch, release_type) = self.parse_fw_version(
@ -543,22 +562,83 @@ class ManifestGenerator():
#print(some_json['url'])
firmware_json.append(some_json)
# now the features the firmware supports...
try:
features = firmware["features"]
# check apj here in case we're creating bin and apj etc:
if (firmware["format"] == "apj" and
features is not None and
bool(firmware["latest"])):
x = dict({
"vehicletype": firmware["vehicletype"],
"platform": firmware["platform"],
"git-sha": firmware["git_sha"],
"latest": firmware["latest"],
})
x["features"] = features
features_json.append(x)
except KeyError:
pass
ret = {
"format-version": "1.0.0", # semantic versioning
"firmware": firmware_json
}
return ret
features_ret = {
"format-version": "1.0.0", # semantic versioning
"features": features_json
}
def json(self):
'''walk directory supplied in constructor, return json string'''
return ret, features_ret
def run(self):
'''walk directory supplied in constructor, record results in self'''
if not self.looks_like_binaries_directory(self.basedir):
print("Warning: this does not look like a binaries directory",
file=sys.stderr)
structure = self.walk_directory(self.basedir)
return json.dumps(structure, indent=4, separators=(',', ': '))
self.structure, self.features_structure = self.walk_directory(self.basedir)
def json(self):
'''returns JSON string for version information for all firmwares'''
if getattr(self, 'structure', None) is None:
self.run()
return json.dumps(self.structure, indent=4, separators=(',', ': '))
def json_features(self):
'''returns JSON string for supported features for all firmwares.
run() method must have been called already'''
return json.dumps(self.features_structure, indent=4, separators=(',', ': '))
def write_string_to_filepath(self, string, filepath):
'''writes the entirety of string to filepath'''
with open(filepath, "w") as x:
x.write(string)
def write_json(self, content, path):
'''write content to path, also creating a compress .gz version'''
new_json_filepath = path + ".new"
self.write_string_to_filepath(content, new_json_filepath)
# provide a pre-compressed version. For reference, a 7M manifest
# "gzip -9"s to 300k in 1 second, "xz -e"s to 80k in 26 seconds
new_json_filepath_gz = path + ".gz.new"
with gzip.open(new_json_filepath_gz, 'wb') as gf:
if running_python3:
content = bytes(content, 'ascii')
gf.write(content)
gf.close()
shutil.move(new_json_filepath, path)
shutil.move(new_json_filepath_gz, path + ".gz")
def write_manifest_json(self, path):
'''write generated JSON content to path'''
self.write_json(self.json(), path)
def write_features_json(self, path):
'''write generated features JSON content to path'''
self.write_json(self.json_features(), path)
def usage():
return '''Usage:
@ -570,6 +650,7 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description='generate manifest.json')
parser.add_argument('--outfile', type=str, default=None, help='output file, default stdout')
parser.add_argument('--outfile-features-json', type=str, default=None, help='output file for features json file')
parser.add_argument('--baseurl', type=str, default="https://firmware.ardupilot.org", help='base binaries directory')
parser.add_argument('basedir', type=str, default="-", help='base binaries directory')
@ -579,12 +660,13 @@ if __name__ == "__main__":
gen_stable.make_all_stable(args.basedir)
generator = ManifestGenerator(args.basedir, args.baseurl)
generator.run()
content = generator.json()
if args.outfile is None:
print(generator.json())
print(content)
else:
f = open(args.outfile, "w")
content = generator.json()
if running_python3:
content = bytes(content, 'ascii')
f.write(content)
f.close()
generator.write_manifest_json(args.outfile)
if args.outfile_features_json is not None:
generator.write_features_json(args.outfile_features_json)