1212from typing import Optional
1313
1414from .install import install_clang_tools , uninstall_clang_tools
15- from . import RESET_COLOR , YELLOW , MIN_VERSION , MAX_VERSION
15+ from . import RESET_COLOR , YELLOW
1616from .util import Version
1717
1818
@@ -51,6 +51,118 @@ def _wheel_install(tools: list[str], version: Optional[str]) -> int:
5151 return 0 if ok else 1
5252
5353
54+ def _validate_wheel_tool (target : str ) -> bool :
55+ """Print an error and return `False` if *target* is not a wheel tool.
56+ """
57+ if target not in WHEEL_TOOLS :
58+ print (
59+ f"{ YELLOW } Error: '{ target } ' is not available as a"
60+ f" wheel. Supported: "
61+ f"{ ', ' .join (sorted (WHEEL_TOOLS ))} { RESET_COLOR } " ,
62+ file = sys .stderr ,
63+ )
64+ return False
65+ return True
66+
67+
68+ def _handle_wheel (args : argparse .Namespace ) -> int :
69+ """Handle ``install --wheel`` subcommand."""
70+ target : str = args .target
71+ if _is_version_like (target ):
72+ return _wheel_install (args .tool , target )
73+ if not _validate_wheel_tool (target ):
74+ return 1
75+ return _wheel_install ([target ], args .explicit_version )
76+
77+
78+ def _handle_binary (args : argparse .Namespace ) -> int :
79+ """Handle ``install --binary`` subcommand."""
80+ target : str = args .target
81+ if not _is_version_like (target ):
82+ print (
83+ f"{ YELLOW } Error: --binary requires a version number"
84+ f" (got '{ target } '){ RESET_COLOR } " ,
85+ file = sys .stderr ,
86+ )
87+ return 1
88+ version = Version (target )
89+ if version .info == (0 , 0 , 0 ):
90+ print (
91+ f"{ YELLOW } The version specified is not a semantic"
92+ f" specification{ RESET_COLOR } " ,
93+ file = sys .stderr ,
94+ )
95+ return 1
96+ install_clang_tools (
97+ version ,
98+ args .tool ,
99+ args .directory ,
100+ args .overwrite ,
101+ args .no_progress_bar ,
102+ )
103+ return 0
104+
105+
106+ def _handle_auto_detect (args : argparse .Namespace ) -> int :
107+ """Handle ``install`` without --binary/--wheel (auto-detect mode)."""
108+ target : str = args .target
109+ if not _is_version_like (target ):
110+ if target not in WHEEL_TOOLS :
111+ print (
112+ f"{ YELLOW } Unknown target '{ target } '. Expected a"
113+ f" version number or one of: "
114+ f"{ ', ' .join (sorted (WHEEL_TOOLS ))} { RESET_COLOR } " ,
115+ file = sys .stderr ,
116+ )
117+ return 1
118+ return _wheel_install ([target ], args .explicit_version )
119+
120+ version = Version (target )
121+ if version .info == (0 , 0 , 0 ):
122+ print (
123+ f"{ YELLOW } The version specified is not a semantic"
124+ f" specification{ RESET_COLOR } " ,
125+ file = sys .stderr ,
126+ )
127+ return 1
128+
129+ # try binary first, fall back to wheel
130+ try :
131+ install_clang_tools (
132+ version ,
133+ args .tool ,
134+ args .directory ,
135+ args .overwrite ,
136+ args .no_progress_bar ,
137+ )
138+ return 0
139+ except (OSError , ValueError , SystemExit ) as exc :
140+ print (
141+ f"{ YELLOW } Binary install failed"
142+ f" ({ exc } ), falling back to"
143+ f" wheel...{ RESET_COLOR } " ,
144+ file = sys .stderr ,
145+ )
146+ return _wheel_install (args .tool , target )
147+
148+
149+ def _handle_install (args : argparse .Namespace ) -> int :
150+ """Dispatch ``install`` subcommand based on flags."""
151+ if args .binary and args .wheel :
152+ print (
153+ f"{ YELLOW } Error: --binary and --wheel are mutually"
154+ f" exclusive{ RESET_COLOR } " ,
155+ file = sys .stderr ,
156+ )
157+ return 1
158+
159+ if args .wheel :
160+ return _handle_wheel (args )
161+ if args .binary :
162+ return _handle_binary (args )
163+ return _handle_auto_detect (args )
164+
165+
54166def get_parser () -> argparse .ArgumentParser :
55167 """Get a parser to interpret CLI args (unified entry point)."""
56168 parser = argparse .ArgumentParser (
@@ -139,7 +251,6 @@ def main() -> int:
139251 parser = get_parser ()
140252 args = parser .parse_args ()
141253
142- # ---- No subcommand → nothing to do ----------------------------------
143254 if args .command is None :
144255 print (
145256 f"{ YELLOW } Nothing to do. Use 'install' or 'uninstall'"
@@ -149,110 +260,12 @@ def main() -> int:
149260 parser .print_help ()
150261 return 0
151262
152- # ---- ``uninstall`` subcommand ------------------------------------
153263 if args .command == "uninstall" :
154264 uninstall_clang_tools (args .version , args .tool , args .directory )
155265 return 0
156266
157- # ---- ``install`` subcommand --------------------------------------
158267 if args .command == "install" :
159- target : str = args .target
160- binary : bool = args .binary
161- wheel : bool = args .wheel
162-
163- # safety: --binary and --wheel are mutually exclusive
164- if binary and wheel :
165- print (
166- f"{ YELLOW } Error: --binary and --wheel are mutually"
167- f" exclusive{ RESET_COLOR } " ,
168- file = sys .stderr ,
169- )
170- return 1
171-
172- # ---- Case: --wheel (target may be tool name or version) -----
173- if wheel :
174- if _is_version_like (target ):
175- # ``clang-tools install 18 --wheel``
176- return _wheel_install (args .tool , target )
177- else :
178- # ``clang-tools install clang-format --wheel``
179- if target not in WHEEL_TOOLS :
180- print (
181- f"{ YELLOW } Error: '{ target } ' is not available as a"
182- f" wheel. Supported: "
183- f"{ ', ' .join (sorted (WHEEL_TOOLS ))} { RESET_COLOR } " ,
184- file = sys .stderr ,
185- )
186- return 1
187- return _wheel_install ([target ], args .explicit_version )
188-
189- # ---- Case: --binary (target must be a version) --------------
190- if binary :
191- if not _is_version_like (target ):
192- print (
193- f"{ YELLOW } Error: --binary requires a version number"
194- f" (got '{ target } '){ RESET_COLOR } " ,
195- file = sys .stderr ,
196- )
197- return 1
198- version = Version (target )
199- if version .info != (0 , 0 , 0 ):
200- install_clang_tools (
201- version ,
202- args .tool ,
203- args .directory ,
204- args .overwrite ,
205- args .no_progress_bar ,
206- )
207- return 0
208- print (
209- f"{ YELLOW } The version specified is not a semantic"
210- f" specification{ RESET_COLOR } " ,
211- file = sys .stderr ,
212- )
213- return 1
214-
215- # ---- Auto-detect (no --binary or --wheel flag) --------------
216- if _is_version_like (target ):
217- version = Version (target )
218- if version .info != (0 , 0 , 0 ):
219- # try binary first, fall back to wheel
220- try :
221- install_clang_tools (
222- version ,
223- args .tool ,
224- args .directory ,
225- args .overwrite ,
226- args .no_progress_bar ,
227- )
228- return 0
229- except Exception as exc :
230- print (
231- f"{ YELLOW } Binary install failed"
232- f" ({ exc } ), falling back to"
233- f" wheel...{ RESET_COLOR } " ,
234- file = sys .stderr ,
235- )
236- # fallback to wheel
237- return _wheel_install (args .tool , target )
238- else :
239- print (
240- f"{ YELLOW } The version specified is not a semantic"
241- f" specification{ RESET_COLOR } " ,
242- file = sys .stderr ,
243- )
244- return 1
245- else :
246- # target is a tool name → install via wheel
247- if target not in WHEEL_TOOLS :
248- print (
249- f"{ YELLOW } Unknown target '{ target } '. Expected a"
250- f" version number or one of: "
251- f"{ ', ' .join (sorted (WHEEL_TOOLS ))} { RESET_COLOR } " ,
252- file = sys .stderr ,
253- )
254- return 1
255- return _wheel_install ([target ], args .explicit_version )
268+ return _handle_install (args )
256269
257270 return 0 # unreachable
258271
0 commit comments