Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_presubmit / py / pw_presubmit / install_hook.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 """Creates a Git hook that calls a script with certain arguments."""
16
17 import argparse
18 import logging
19 import os
20 from pathlib import Path
21 import re
22 import shlex
23 import subprocess
24 from typing import Sequence, Union
25
26 _LOG: logging.Logger = logging.getLogger(__name__)
27
28
29 def git_repo_root(path: Union[Path, str]) -> Path:
30     return Path(
31         subprocess.run(['git', '-C', path, 'rev-parse', '--show-toplevel'],
32                        check=True,
33                        stdout=subprocess.PIPE).stdout.strip().decode())
34
35
36 def install_hook(script,
37                  hook: str,
38                  args: Sequence[str] = (),
39                  repository: Union[Path, str] = '.') -> None:
40     """Installs a simple Git hook that calls a script with arguments."""
41     root = git_repo_root(repository).resolve()
42     script = os.path.relpath(script, root)
43
44     if root.joinpath('.git').is_dir():
45         hook_path = root.joinpath('.git', 'hooks', hook)
46     else:  # This repo is probably a submodule with a .git file instead
47         match = re.match('^gitdir: (.*)$', root.joinpath('.git').read_text())
48         if not match:
49             raise ValueError('Unexpected format for .git file')
50
51         hook_path = root.joinpath(match.group(1), 'hooks', hook).resolve()
52
53     hook_path.parent.mkdir(exist_ok=True)
54
55     command = ' '.join(shlex.quote(arg) for arg in (script, *args))
56
57     with hook_path.open('w') as file:
58         line = lambda *args: print(*args, file=file)
59
60         line('#!/bin/sh')
61         line(f'# {hook} hook generated by {__file__}')
62         line()
63         line(command)
64
65     hook_path.chmod(0o755)
66     logging.info('Created %s hook for %s at %s', hook, script, hook_path)
67
68
69 def argument_parser(parser=None) -> argparse.ArgumentParser:
70     if parser is None:
71         parser = argparse.ArgumentParser(description=__doc__)
72
73     def path(arg: str) -> Path:
74         if not os.path.exists(arg):
75             raise argparse.ArgumentTypeError(f'"{arg}" is not a valid path')
76
77         return Path(arg)
78
79     parser.add_argument(
80         '-r',
81         '--repository',
82         default='.',
83         type=path,
84         help='Path to the repository in which to install the hook')
85     parser.add_argument('--hook',
86                         required=True,
87                         help='Which type of Git hook to create')
88     parser.add_argument('-s',
89                         '--script',
90                         required=True,
91                         type=path,
92                         help='Path to the script to execute in the hook')
93     parser.add_argument('args',
94                         nargs='*',
95                         help='Arguments to provide to the commit hook')
96
97     return parser
98
99
100 if __name__ == '__main__':
101     logging.basicConfig(format='%(message)s', level=logging.INFO)
102     install_hook(**vars(argument_parser().parse_args()))