Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 1 | # Copyright (c) 2022 Nordic Semiconductor ASA |
| 2 | # |
| 3 | # SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | import argparse |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 6 | import os |
| 7 | from pathlib import Path |
| 8 | import sys |
| 9 | import textwrap |
| 10 | from urllib.parse import urlparse |
| 11 | |
| 12 | from west import log |
| 13 | from west.commands import WestCommand |
| 14 | |
| 15 | from zephyr_ext_common import ZEPHYR_BASE |
| 16 | |
| 17 | sys.path.append(os.fspath(Path(__file__).parent.parent)) |
| 18 | import zephyr_module |
| 19 | |
| 20 | class Blobs(WestCommand): |
| 21 | |
Martí Bolívar | e04487c | 2022-08-18 18:25:02 -0700 | [diff] [blame] | 22 | DEFAULT_LIST_FMT = '{module} {status} {path} {type} {abspath}' |
| 23 | |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 24 | def __init__(self): |
| 25 | super().__init__( |
| 26 | 'blobs', |
| 27 | # Keep this in sync with the string in west-commands.yml. |
| 28 | 'work with binary blobs', |
| 29 | 'Work with binary blobs', |
| 30 | accepts_unknown_args=False) |
| 31 | |
| 32 | def do_add_parser(self, parser_adder): |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 33 | parser = parser_adder.add_parser( |
| 34 | self.name, |
| 35 | help=self.help, |
| 36 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 37 | description=self.description, |
| 38 | epilog=textwrap.dedent(f'''\ |
| 39 | FORMAT STRINGS |
| 40 | -------------- |
| 41 | |
| 42 | Blobs are listed using a Python 3 format string. Arguments |
| 43 | to the format string are accessed by name. |
| 44 | |
| 45 | The default format string is: |
| 46 | |
Martí Bolívar | e04487c | 2022-08-18 18:25:02 -0700 | [diff] [blame] | 47 | "{self.DEFAULT_LIST_FMT}" |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 48 | |
| 49 | The following arguments are available: |
| 50 | |
| 51 | - module: name of the module that contains this blob |
| 52 | - abspath: blob absolute path |
| 53 | - status: short status (A: present, M: hash failure, D: not present) |
| 54 | - path: blob local path from <module>/zephyr/blobs/ |
| 55 | - sha256: blob SHA256 hash in hex |
| 56 | - type: type of blob |
| 57 | - version: version string |
| 58 | - license_path: path to the license file for the blob |
| 59 | - uri: URI to the remote location of the blob |
| 60 | - description: blob text description |
| 61 | - doc-url: URL to the documentation for this blob |
| 62 | ''')) |
| 63 | |
| 64 | # Remember to update west-completion.bash if you add or remove |
| 65 | # flags |
Carles Cufi | 5524f7a | 2022-08-17 13:48:13 +0200 | [diff] [blame] | 66 | parser.add_argument('subcmd', nargs=1, |
| 67 | choices=['list', 'fetch', 'clean'], |
Martí Bolívar | 3b84dff | 2022-08-18 18:15:34 -0700 | [diff] [blame] | 68 | help='sub-command to execute') |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 69 | |
Carles Cufi | 02c95c6 | 2022-08-16 19:02:43 +0200 | [diff] [blame] | 70 | parser.add_argument('modules', metavar='MODULE', nargs='*', |
Martí Bolívar | a3f4edb | 2022-08-18 18:18:03 -0700 | [diff] [blame] | 71 | help='''zephyr modules to operate on; |
| 72 | all modules will be used if not given''') |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 73 | |
Martí Bolívar | e04487c | 2022-08-18 18:25:02 -0700 | [diff] [blame] | 74 | group = parser.add_argument_group('west blob list options') |
| 75 | group.add_argument('-f', '--format', |
| 76 | help='''format string to use to list each blob; |
| 77 | see FORMAT STRINGS below''') |
| 78 | |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 79 | return parser |
| 80 | |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 81 | def get_blobs(self, args): |
| 82 | blobs = [] |
| 83 | modules = args.modules |
| 84 | for module in zephyr_module.parse_modules(ZEPHYR_BASE, self.manifest): |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 85 | # Filter by module |
| 86 | module_name = module.meta.get('name', None) |
Carles Cufi | 389af08 | 2022-08-16 16:56:59 +0200 | [diff] [blame] | 87 | if len(modules) and module_name not in modules: |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 88 | continue |
| 89 | |
Carles Cufi | b662bc9 | 2022-08-24 15:42:55 +0200 | [diff] [blame] | 90 | blobs += zephyr_module.process_blobs(module.project, module.meta) |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 91 | |
| 92 | return blobs |
| 93 | |
| 94 | def list(self, args): |
| 95 | blobs = self.get_blobs(args) |
Carles Cufi | 25db534 | 2022-08-24 16:44:14 +0200 | [diff] [blame] | 96 | fmt = args.format or self.DEFAULT_LIST_FMT |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 97 | for blob in blobs: |
Martí Bolívar | e04487c | 2022-08-18 18:25:02 -0700 | [diff] [blame] | 98 | log.inf(fmt.format(**blob)) |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 99 | |
Carles Cufi | 0424509 | 2022-08-17 15:06:17 +0200 | [diff] [blame] | 100 | def ensure_folder(self, path): |
| 101 | path.parent.mkdir(parents=True, exist_ok=True) |
| 102 | |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 103 | def fetch_blob(self, url, path): |
| 104 | scheme = urlparse(url).scheme |
| 105 | log.dbg(f'Fetching {path} with {scheme}') |
| 106 | import fetchers |
| 107 | fetcher = fetchers.get_fetcher_cls(scheme) |
| 108 | |
| 109 | log.dbg(f'Found fetcher: {fetcher}') |
| 110 | inst = fetcher() |
Carles Cufi | 0424509 | 2022-08-17 15:06:17 +0200 | [diff] [blame] | 111 | self.ensure_folder(path) |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 112 | inst.fetch(url, path) |
| 113 | |
| 114 | def fetch(self, args): |
| 115 | blobs = self.get_blobs(args) |
| 116 | for blob in blobs: |
| 117 | if blob['status'] == 'A': |
Martí Bolívar | 21214cc | 2022-08-18 18:25:47 -0700 | [diff] [blame] | 118 | log.dbg('Blob {module}: {abspath} is up to date'.format(**blob)) |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 119 | continue |
Carles Cufi | 5524f7a | 2022-08-17 13:48:13 +0200 | [diff] [blame] | 120 | log.inf('Fetching blob {module}: {abspath}'.format(**blob)) |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 121 | self.fetch_blob(blob['url'], blob['abspath']) |
| 122 | |
Carles Cufi | 5524f7a | 2022-08-17 13:48:13 +0200 | [diff] [blame] | 123 | def clean(self, args): |
| 124 | blobs = self.get_blobs(args) |
| 125 | for blob in blobs: |
| 126 | if blob['status'] == 'D': |
Martí Bolívar | 21214cc | 2022-08-18 18:25:47 -0700 | [diff] [blame] | 127 | log.dbg('Blob {module}: {abspath} not in filesystem'.format(**blob)) |
Carles Cufi | 5524f7a | 2022-08-17 13:48:13 +0200 | [diff] [blame] | 128 | continue |
| 129 | log.inf('Deleting blob {module}: {status} {abspath}'.format(**blob)) |
| 130 | blob['abspath'].unlink() |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 131 | |
| 132 | def do_run(self, args, _): |
Carles Cufi | f033040 | 2022-08-24 15:51:44 +0200 | [diff] [blame] | 133 | log.dbg(f'subcmd: \'{args.subcmd[0]}\' modules: {args.modules}') |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 134 | |
| 135 | subcmd = getattr(self, args.subcmd[0]) |
Martí Bolívar | e04487c | 2022-08-18 18:25:02 -0700 | [diff] [blame] | 136 | |
Carles Cufi | f033040 | 2022-08-24 15:51:44 +0200 | [diff] [blame] | 137 | if args.subcmd[0] != 'list' and args.format is not None: |
Martí Bolívar | e04487c | 2022-08-18 18:25:02 -0700 | [diff] [blame] | 138 | log.die(f'unexpected --format argument; this is a "west blobs list" option') |
| 139 | |
Carles Cufi | 336aa9d | 2022-08-04 19:08:22 +0200 | [diff] [blame] | 140 | subcmd(args) |