Skip to content

Commit e1f8994

Browse files
author
Trong Nhan Mai
committed
feat: add cli build command patcher
Signed-off-by: Trong Nhan Mai <[email protected]>
1 parent 8203dae commit e1f8994

File tree

2 files changed

+698
-0
lines changed

2 files changed

+698
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Copyright (c) 2025 - 2025, Oracle and/or its affiliates. All rights reserved.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
3+
4+
"""This module contains the implementation of the build command patching."""
5+
6+
import logging
7+
from collections.abc import Mapping, Sequence
8+
9+
from macaron.build_spec_generator.cli_command_parser import CLICommand, CLICommandParser, PatchCommandBuildTool
10+
from macaron.build_spec_generator.cli_command_parser.gradle_cli_parser import (
11+
GradleCLICommandParser,
12+
GradleOptionPatchValueType,
13+
)
14+
from macaron.build_spec_generator.cli_command_parser.maven_cli_parser import (
15+
CommandLineParseError,
16+
MavenCLICommandParser,
17+
MavenOptionPatchValueType,
18+
PatchBuildCommandError,
19+
)
20+
from macaron.build_spec_generator.cli_command_parser.unparsed_cli_command import UnparsedCLICommand
21+
22+
logger: logging.Logger = logging.getLogger(__name__)
23+
24+
MVN_CLI_PARSER = MavenCLICommandParser()
25+
GRADLE_CLI_PARSER = GradleCLICommandParser()
26+
27+
PatchValueType = GradleOptionPatchValueType | MavenOptionPatchValueType
28+
29+
30+
def _patch_commands(
31+
cmds_sequence: Sequence[list[str]],
32+
cli_parsers: Sequence[CLICommandParser],
33+
patches: Mapping[
34+
PatchCommandBuildTool,
35+
Mapping[str, PatchValueType | None],
36+
],
37+
) -> list[CLICommand] | None:
38+
"""Patch the sequence of build commands, using the provided CLICommandParser instances.
39+
40+
For each command in `cmds_sequence`, it will be checked against all CLICommandParser instances until there is
41+
one that can parse it, then a patch from ``patches`` is applied for this command if provided.
42+
43+
If a command doesn't have any corresponding ``CLICommandParser`` instance it will be parsed as UnparsedCLICommand,
44+
which just holds the original command as a list of string, without any changes.
45+
"""
46+
result: list[CLICommand] = []
47+
for cmds in cmds_sequence:
48+
effective_cli_parser = None
49+
for cli_parser in cli_parsers:
50+
if cli_parser.is_build_tool(cmds[0]):
51+
effective_cli_parser = cli_parser
52+
break
53+
54+
if not effective_cli_parser:
55+
result.append(UnparsedCLICommand(original_cmds=cmds))
56+
continue
57+
58+
try:
59+
cli_command = effective_cli_parser.parse(cmds)
60+
except CommandLineParseError as error:
61+
logger.error(
62+
"Failed to parse the mvn command %s. Error %s.",
63+
" ".join(cmds),
64+
error,
65+
)
66+
return None
67+
68+
patch = patches.get(effective_cli_parser.build_tool, None)
69+
if not patch:
70+
result.append(cli_command)
71+
continue
72+
73+
try:
74+
new_cli_command = effective_cli_parser.apply_patch(
75+
cli_command=cli_command,
76+
options_patch=patch,
77+
)
78+
except PatchBuildCommandError as error:
79+
logger.error(
80+
"Failed to patch the mvn command %s. Error %s.",
81+
" ".join(cmds),
82+
error,
83+
)
84+
return None
85+
86+
result.append(new_cli_command)
87+
88+
return result
89+
90+
91+
def patch_commands(
92+
cmds_sequence: Sequence[list[str]],
93+
patches: Mapping[
94+
PatchCommandBuildTool,
95+
Mapping[str, PatchValueType | None],
96+
],
97+
) -> list[list[str]] | None:
98+
"""Patch a sequence of CLI commands.
99+
100+
For each command in this command sequence:
101+
102+
- If the command is not a build command or the build tool is not supported by us, it will be leave intact.
103+
104+
- If the command is a build command supported by us, it will be patch if a patch value is provided to ``patches``.
105+
If no patch value is provided for a build command, it will be leave intact.
106+
107+
`patches` is a mapping with:
108+
109+
- **Key**: an instance of the ``BuildTool`` enum
110+
111+
- **Value**: the patch value provided to ``CLICommandParser.apply_patch``. For more information on the patch value
112+
see the concrete implementations of the ``CLICommandParser.apply_patch`` method.
113+
For example: :class:`macaron.cli_command_parser.maven_cli_parser.MavenCLICommandParser.apply_patch`,
114+
:class:`macaron.cli_command_parser.gradle_cli_parser.GradleCLICommandParser.apply_patch`.
115+
116+
This means that all commands that matches a BuildTool will be apply by the same patch value.
117+
118+
Returns
119+
-------
120+
list[list[str]] | None
121+
The patched command sequence or None if there is an error. The errors that can happen if any command
122+
which we support is invalid in ``cmds_sequence``, or the patch value is valid.
123+
"""
124+
result = []
125+
patch_cli_commands = _patch_commands(
126+
cmds_sequence=cmds_sequence,
127+
cli_parsers=[MVN_CLI_PARSER, GRADLE_CLI_PARSER],
128+
patches=patches,
129+
)
130+
131+
if patch_cli_commands is None:
132+
return None
133+
134+
for patch_cmd in patch_cli_commands:
135+
result.append(patch_cmd.to_cmds())
136+
137+
return result

0 commit comments

Comments
 (0)