1#!/usr/bin/python
2"""
3SPDX-License-Identifier: Apache-2.0
4Copyright (c) 2019 STMicroelectronics.
5This script will update the stm32cube module for Zephyr
6from the latest version on https://github.com/STMicroelectronics
7get the patch between initial version and latest version
8apply this patch on the zephyr module
9basic usage for a single serie update :
10   'python3 update_stm32_package.py -s <stm32_serie>'
11basic usage for all serie update at once:
12   'python3 update_stm32_package.py
13"""
14
15import os
16import sys
17import subprocess
18import argparse
19from pathlib import Path
20import serie_update
21import logging
22from genllheaders import genllheaders
23
24parser = argparse.ArgumentParser()
25parser.add_argument(
26    "-s",
27    "--stm32_serie",
28    type=str,
29    help="Update a stm32 serie. ex: stm32f1.\n"
30    + "If omitted all STM32 series will be updated,\n"
31    + "a commit is created for each serie. ",
32)
33parser.add_argument(
34    "-c",
35    "--noclean",
36    action="store_true",
37    default=False,
38    help="Do NOT clean the STM32Cube repo directory",
39)
40parser.add_argument(
41    "-r",
42    "--repo",
43    type=str,
44    help="Allows to provide path where STM32Cube repo are stored",
45)
46parser.add_argument(
47    "-v",
48    "--version",
49    default="",
50    type=str,
51    help="select to which version to update.\n",
52)
53parser.add_argument(
54    "-d",
55    "--debug",
56    action="store_true",
57    default=False,
58    help="select to which version to update.\n",
59)
60args = parser.parse_args()
61
62SCRIPT_DIR = Path(__file__).absolute().parent
63"""Script directory."""
64
65REPO_ROOT = SCRIPT_DIR / ".."
66"""Repository root (used for input/output default folders)."""
67
68
69def update_cubes():
70    """Update all STM32Cubes"""
71    module_path = REPO_ROOT / "stm32cube"
72    if not module_path.exists():
73        raise Exception("Error: cannot find ./zephyr project")
74
75    for stmyyxx in module_path.iterdir():
76        if stmyyxx.is_dir() and "common_ll" not in stmyyxx.name:
77            logging.info(
78                "%s",
79                f"***************  updating module {stmyyxx.name} *****************",
80            )
81            # Force the commit for each serie
82            update_serie = serie_update.Stm32SerieUpdate(
83                stmyyxx.name[:-2],
84                repo_path,
85                noclean=args.noclean,
86                debug=args.debug,
87                version_update="",
88            )
89            update_serie.update_stm32_hal_serie()
90
91
92################################################
93# Main
94################################################
95if args.repo:
96    repo_path = Path(args.repo)
97else:
98    repo_path = Path(os.getenv("HOME")) / "STM32Cube_repo"
99
100if args.debug:
101    print("Debug")
102    logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG)
103    std_dest = None
104else:
105    logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.INFO)
106    std_dest = subprocess.DEVNULL
107
108if not args.noclean:
109    print(
110        f"Do you want to clean downloaded repo {str(repo_path)} at the end of updates?"
111    )
112    res = input("(Enter y/n) ").lower()
113    while res not in ("y", "n"):
114        res = input("(Enter y/n) ").lower()
115    if res == "n":
116        logging.info("%s", "Add option --noclean")
117        args.noclean = True
118
119# prevent losing data in an unclean repo
120git_status = subprocess.check_output(
121    ("git", "status", "-s"),
122    cwd=SCRIPT_DIR,
123).splitlines()
124# status = [x.decode("utf-8") for x in git_status]
125for status in git_status:
126    if not status.decode("utf-8").startswith("?") and not status.decode(
127        "utf-8"
128    ).startswith("!"):
129        logging.error(
130            "%s",
131            "It seems that script repo "
132            + str(SCRIPT_DIR)
133            + "\n           is not clean:\n           git status -s:"
134            + status.decode("utf-8"),
135        )
136        logging.error("%s", "It is suggested to clean your repo first.")
137
138        print("Do you want to continue update ?")
139        res = input("(Enter y/n) ").lower()
140        while res not in ("y", "n"):
141            res = input("(Enter y/n) ").lower()
142        if res == "n":
143            sys.exit()
144        break
145
146if args.stm32_serie:
147    update = serie_update.Stm32SerieUpdate(
148        args.stm32_serie,
149        repo_path,
150        args.noclean,
151        args.version,
152        args.debug,
153    )
154    update.update_stm32_hal_serie()
155else:
156    update_cubes()
157
158logging.info("%s", "Cube update: Done")
159
160print("Do you want to autogenerate generic LL HAL headers (genllheaders.py) ?")
161res = input("(Enter y/n) ").lower()
162while res not in ("y", "n"):
163    res = input("(Enter y/n) ").lower()
164if res == "y":
165    genllheaders.main(
166        REPO_ROOT / "stm32cube",
167        REPO_ROOT / "stm32cube" / "common_ll",
168    )
169
170    genllheaders.main(REPO_ROOT / "stm32cube", REPO_ROOT / "stm32cube" / "common_ll")
171
172    # commit autogenerate generic LL HAL headers
173    commit_file_path = REPO_ROOT / "commit.msg"
174    with open(commit_file_path, "w") as commit:
175        commit.write("stm32cube: common_ll: Regeneration after cube updates\n")
176        commit.write("\n")
177        commit.write("Re - generate common_ll headers after Cube updates\n")
178
179    subprocess.check_call(
180        ("git", "commit", "-as", "-F", commit_file_path),
181        cwd=REPO_ROOT,
182    )
183
184    subprocess.check_call(
185        ("git", "rebase", "--whitespace=fix", "HEAD~1"),
186        stdout=std_dest,
187        stderr=std_dest,
188        cwd=REPO_ROOT,
189    )
190    Path(commit_file_path).unlink()
191
192    logging.info("%s", "LL HAL header update: Done")
193