blob: e7e3058b7d2df8c96e5ce0344d144b91f0b07fc3 [file] [log] [blame]
Damian Królik3faca7e2022-04-12 13:48:15 +02001#!/usr/bin/env python3
2#
3# Copyright (c) 2022 Project CHIP Authors
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18import argparse
Damian Królik3faca7e2022-04-12 13:48:15 +020019import configparser
20import logging
Damian Królik3faca7e2022-04-12 13:48:15 +020021import os
Arkadiusz Bokowyd5bfb4b2023-01-09 16:15:00 +010022import subprocess
23from collections import namedtuple
Damian Królik3faca7e2022-04-12 13:48:15 +020024
25CHIP_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
26
27ALL_PLATFORMS = set([
28 'ameba',
29 'android',
30 'bl602',
wyhong0ca9aa42022-09-12 23:24:16 +080031 'bouffalolab',
Damian Królik3faca7e2022-04-12 13:48:15 +020032 'cc13x2_26x2',
abiradartif4967842022-06-28 09:19:03 -050033 'cc32xx',
Damian Królik3faca7e2022-04-12 13:48:15 +020034 'darwin',
35 'efr32',
36 'esp32',
Praveen Chandranab028392022-08-18 07:39:28 -070037 'infineon',
Damian Królik3faca7e2022-04-12 13:48:15 +020038 'k32w0',
39 'linux',
40 'mbed',
41 'nrfconnect',
Damian Królik3faca7e2022-04-12 13:48:15 +020042 'qpg',
43 'telink',
44 'tizen',
45 'webos',
nxptest2d0c5292022-06-24 19:04:49 +080046 'mw320',
pakls0168a572022-09-14 03:05:11 +080047 'genio',
Artur Tynecki83dae062022-10-22 00:45:53 +020048 'openiotsdk',
Damian Królik3faca7e2022-04-12 13:48:15 +020049])
50
51Module = namedtuple('Module', 'name path platforms')
52
53
Damian Królike80da232022-08-16 01:15:59 +020054def load_module_info() -> None:
Damian Królik3faca7e2022-04-12 13:48:15 +020055 config = configparser.ConfigParser()
56 config.read(os.path.join(CHIP_ROOT, '.gitmodules'))
57
58 for name, module in config.items():
59 if name != 'DEFAULT':
60 platforms = module.get('platforms', '').split(',')
61 platforms = set(filter(None, platforms))
62 assert not (platforms - ALL_PLATFORMS), "Submodule's platform not contained in ALL_PLATFORMS"
Damian Królik610c8e52023-01-12 15:27:59 +010063 name = name.replace('submodule "', '').replace('"', '')
Damian Królik3faca7e2022-04-12 13:48:15 +020064 yield Module(name=name, path=module['path'], platforms=platforms)
65
66
67def module_matches_platforms(module: Module, platforms: set) -> bool:
Damian Królik610c8e52023-01-12 15:27:59 +010068 # If the module is not associated with any specific platform, treat it as a match.
69 if not module.platforms:
Damian Królik3faca7e2022-04-12 13:48:15 +020070 return True
71 return bool(platforms & module.platforms)
72
73
Damian Królik610c8e52023-01-12 15:27:59 +010074def module_initialized(module: Module) -> bool:
75 return bool(os.listdir(module.path))
76
77
Damian Królike80da232022-08-16 01:15:59 +020078def make_chip_root_safe_directory() -> None:
79 # ensure no errors regarding ownership in the directory. Newer GIT seems to require this:
80 subprocess.check_call(['git', 'config', '--global', '--add', 'safe.directory', CHIP_ROOT])
81
82
jmartinez-silabs7816a692022-08-16 00:32:43 -040083def checkout_modules(modules: list, shallow: bool, force: bool, recursive: bool) -> None:
Damian Królik610c8e52023-01-12 15:27:59 +010084 names = ', '.join([module.name for module in modules])
Damian Królik3faca7e2022-04-12 13:48:15 +020085 logging.info(f'Checking out: {names}')
86
Damian Królik610c8e52023-01-12 15:27:59 +010087 cmd = ['git', '-C', CHIP_ROOT, 'submodule', '--quiet', 'update', '--init']
Damian Królik3faca7e2022-04-12 13:48:15 +020088 cmd += ['--depth', '1'] if shallow else []
Damian Królike80da232022-08-16 01:15:59 +020089 cmd += ['--force'] if force else []
jmartinez-silabs7816a692022-08-16 00:32:43 -040090 cmd += ['--recursive'] if recursive else []
Damian Królike80da232022-08-16 01:15:59 +020091 cmd += [module.path for module in modules]
92
93 subprocess.check_call(cmd)
94
95
96def deinit_modules(modules: list, force: bool) -> None:
Damian Królik610c8e52023-01-12 15:27:59 +010097 names = ', '.join([module.name for module in modules])
Damian Królike80da232022-08-16 01:15:59 +020098 logging.info(f'Deinitializing: {names}')
99
Damian Królik610c8e52023-01-12 15:27:59 +0100100 cmd = ['git', '-C', CHIP_ROOT, 'submodule', '--quiet', 'deinit']
Damian Królike80da232022-08-16 01:15:59 +0200101 cmd += ['--force'] if force else []
Damian Królik3faca7e2022-04-12 13:48:15 +0200102 cmd += [module.path for module in modules]
103
104 subprocess.check_call(cmd)
105
106
107def main():
108 logging.basicConfig(format='%(message)s', level=logging.INFO)
109
110 parser = argparse.ArgumentParser(description='Checkout or update relevant git submodules')
111 parser.add_argument('--shallow', action='store_true', help='Fetch submodules without history')
112 parser.add_argument('--platform', nargs='+', choices=ALL_PLATFORMS, default=[],
113 help='Process submodules for specific platforms only')
Damian Królike80da232022-08-16 01:15:59 +0200114 parser.add_argument('--force', action='store_true', help='Perform action despite of warnings')
115 parser.add_argument('--deinit-unmatched', action='store_true',
116 help='Deinitialize submodules for non-matching platforms')
jmartinez-silabs7816a692022-08-16 00:32:43 -0400117 parser.add_argument('--recursive', action='store_true', help='Recursive init of the listed submodules')
Damian Królik3faca7e2022-04-12 13:48:15 +0200118 args = parser.parse_args()
119
Damian Królike80da232022-08-16 01:15:59 +0200120 modules = list(load_module_info())
Damian Królik3faca7e2022-04-12 13:48:15 +0200121 selected_platforms = set(args.platform)
122 selected_modules = [m for m in modules if module_matches_platforms(m, selected_platforms)]
Damian Królik610c8e52023-01-12 15:27:59 +0100123 unmatched_modules = [m for m in modules if not module_matches_platforms(
124 m, selected_platforms) and module_initialized(m)]
Damian Królik3faca7e2022-04-12 13:48:15 +0200125
Damian Królike80da232022-08-16 01:15:59 +0200126 make_chip_root_safe_directory()
jmartinez-silabs7816a692022-08-16 00:32:43 -0400127 checkout_modules(selected_modules, args.shallow, args.force, args.recursive)
Damian Królike80da232022-08-16 01:15:59 +0200128
Damian Królik610c8e52023-01-12 15:27:59 +0100129 if args.deinit_unmatched and unmatched_modules:
Damian Królike80da232022-08-16 01:15:59 +0200130 deinit_modules(unmatched_modules, args.force)
Damian Królik3faca7e2022-04-12 13:48:15 +0200131
132
133if __name__ == '__main__':
134 main()