 23dc466969
			
		
	
	23dc466969
	
	
	
		
			
			When using apk as the package manager, imagebuilder make command
    make manifest STRIP_ABI=1
does not strip package names of their ABI-version suffix.  The ASU
server relies on this to validate builds, so many snapshot build
requests are failing.
Fix this by using the already existing package data parser in
make-index-json.py and augment it to write the result in manifest
format.
Fixes: https://github.com/openwrt/openwrt/issues/19274
Signed-off-by: Eric Fahlgren <ericfahlgren@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/19278
Signed-off-by: Robert Marko <robimarko@gmail.com>
		
	
		
			
				
	
	
		
			102 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| """
 | |
| Parse the native package index files into a json file for use by downstream
 | |
| tools.  See:
 | |
| 
 | |
|     https://github.com/openwrt/openwrt/commit/218ce40cd738f3373438aab82467807a8707fb9c
 | |
| 
 | |
| The "version 1" index.json contained ABI-versioned package names, making the
 | |
| unusable by the ASU server.  The version 2 format contains package names that
 | |
| have been stripped of their ABI version.
 | |
| """
 | |
| 
 | |
| import email.parser
 | |
| import json
 | |
| 
 | |
| 
 | |
| def removesuffix(src, suffix):
 | |
|     # For compatibility with Python < 3.9.
 | |
|     suffix_length = len(suffix)
 | |
|     return src[:-suffix_length] if suffix_length and src.endswith(suffix) else src
 | |
| 
 | |
| 
 | |
| def parse_args():
 | |
|     from argparse import ArgumentParser
 | |
| 
 | |
|     source_format = "apk", "opkg"
 | |
| 
 | |
|     parser = ArgumentParser()
 | |
|     # fmt: off
 | |
|     parser.add_argument("-a", "--architecture", required=True,
 | |
|                         help="Required device architecture: like 'x86_64' or 'aarch64_generic'")
 | |
|     parser.add_argument("-f", "--source-format", required=True, choices=source_format,
 | |
|                         help="Required source format of input: 'apk' or 'opkg'")
 | |
|     parser.add_argument("-m", "--manifest", action="store_true", default=False,
 | |
|                         help="Print output in manifest format, as package:version pairs")
 | |
|     parser.add_argument(dest="source",
 | |
|                         help="File name for input, '-' for stdin")
 | |
|     # fmt: on
 | |
|     args = parser.parse_args()
 | |
|     return args
 | |
| 
 | |
| 
 | |
| def parse_apk(text: str) -> dict:
 | |
|     packages: dict = {}
 | |
| 
 | |
|     data = json.loads(text)
 | |
|     if isinstance(data, dict) and "packages" in data:
 | |
|         # Extract 'apk adbdump' dict field to 'apk query' package list
 | |
|         data = data["packages"]
 | |
| 
 | |
|     for package in data:
 | |
|         package_name: str = package["name"]
 | |
| 
 | |
|         for tag in package.get("tags", []):
 | |
|             if tag.startswith("openwrt:abiversion="):
 | |
|                 package_abi: str = tag.split("=")[-1]
 | |
|                 package_name = removesuffix(package_name, package_abi)
 | |
|                 break
 | |
| 
 | |
|         packages[package_name] = package["version"]
 | |
| 
 | |
|     return packages
 | |
| 
 | |
| 
 | |
| def parse_opkg(text: str) -> dict:
 | |
|     packages: dict = {}
 | |
| 
 | |
|     parser: email.parser.Parser = email.parser.Parser()
 | |
|     chunks: list[str] = text.strip().split("\n\n")
 | |
|     for chunk in chunks:
 | |
|         package: dict = parser.parsestr(chunk, headersonly=True)
 | |
|         package_name: str = package["Package"]
 | |
|         package_abi = package.get("ABIVersion")
 | |
|         if package_abi:
 | |
|             package_name = removesuffix(package_name, package_abi)
 | |
| 
 | |
|         packages[package_name] = package["Version"]
 | |
| 
 | |
|     return packages
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     import sys
 | |
| 
 | |
|     args = parse_args()
 | |
| 
 | |
|     input = sys.stdin if args.source == "-" else open(args.source, "r")
 | |
|     with input:
 | |
|         text: str = input.read()
 | |
| 
 | |
|     packages = parse_apk(text) if args.source_format == "apk" else parse_opkg(text)
 | |
|     if args.manifest:
 | |
|         for name, version in packages.items():
 | |
|             print(name, version)
 | |
|     else:
 | |
|         index = {
 | |
|             "version": 2,
 | |
|             "architecture": args.architecture,
 | |
|             "packages": packages,
 | |
|         }
 | |
|         print(json.dumps(index, indent=2))
 |