57c92bbf0b391c3c914eb4a2f13ad4b854fc1877
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_status / py / pw_status / update_style.py
1 #!/usr/bin/env python3
2 # Copyright 2020 The Pigweed Authors
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 # use this file except in compliance with the License. You may obtain a copy of
6 # the License at
7 #
8 #     https://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations under
14 # the License.
15 """Updates pw::Status usages from Status::CODE to Status::Code() style.
16
17 Also updates StatusWithSize.
18 """
19
20 import argparse
21 from pathlib import Path
22 import re
23 import sys
24 from typing import Iterable
25
26 from pw_presubmit import git_repo
27
28 _REMAP = {
29     'OK': 'Ok',
30     'CANCELLED': 'Cancelled',
31     'UNKNOWN': 'Unknown',
32     'INVALID_ARGUMENT': 'InvalidArgument',
33     'DEADLINE_EXCEEDED': 'DeadlineExceeded',
34     'NOT_FOUND': 'NotFound',
35     'ALREADY_EXISTS': 'AlreadyExists',
36     'PERMISSION_DENIED': 'PermissionDenied',
37     'UNAUTHENTICATED': 'Unauthenticated',
38     'RESOURCE_EXHAUSTED': 'ResourceExhausted',
39     'FAILED_PRECONDITION': 'FailedPrecondition',
40     'ABORTED': 'Aborted',
41     'OUT_OF_RANGE': 'OutOfRange',
42     'UNIMPLEMENTED': 'Unimplemented',
43     'INTERNAL': 'Internal',
44     'UNAVAILABLE': 'Unavailable',
45     'DATA_LOSS': 'DataLoss',
46 }
47
48
49 def _remap_status_with_size(match) -> str:
50     return f'StatusWithSize::{_REMAP[match.group(1)]}('
51
52
53 def _remap_codes(match) -> str:
54     return f'{match.group(1)}::{_REMAP[match.group(2)]}()'
55
56
57 _CODES = '|'.join(_REMAP.keys())
58
59 _STATUS_WITH_SIZE_CTOR = re.compile(
60     fr'\bStatusWithSize\(Status::({_CODES}),\s*')
61 _STATUS = re.compile(fr'\b(Status|StatusWithSize)::({_CODES})(?!")\b')
62
63
64 def _parse_args():
65     """Parses and return command line arguments."""
66
67     parser = argparse.ArgumentParser(description=__doc__)
68     parser.add_argument('paths',
69                         nargs='*',
70                         type=Path,
71                         help='Paths to repositories')
72     return parser.parse_args()
73
74
75 def update_status(paths: Iterable[Path]) -> None:
76     if not paths:
77         paths = [Path.cwd()]
78
79     for path in paths:
80         if git_repo.has_uncommitted_changes(path):
81             raise RuntimeError('There are pending changes in the Git repo!')
82
83         updated = 0
84
85         for file in git_repo.list_files(pathspecs=('*.h', '*.cc', '*.cpp'),
86                                         repo_path=path):
87             orig = file.read_text()
88
89             # Replace StatusAWithSize constructor
90             text = _STATUS_WITH_SIZE_CTOR.sub(_remap_status_with_size, orig)
91
92             # Replace Status and StatusAWithSize
93             text = _STATUS.sub(_remap_codes, text)
94
95             if orig != text:
96                 updated += 1
97                 file.write_text(text)
98
99     print('Updated', updated, 'files.')
100     print('Manually inspect the changes! This script is not perfect.')
101
102
103 def main():
104     return update_status(**vars(_parse_args()))
105
106
107 if __name__ == '__main__':
108     sys.exit(main())