Skip to content

Commit dbf1785

Browse files
authored
Merge pull request #360 from yma955/main
Feat: Add merge cmd for multiple maven zips
2 parents e51048c + 0a32943 commit dbf1785

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

charon/cmd/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from charon.cmd.cmd_checksum import init_checksum, checksum
2121
from charon.cmd.cmd_cache import init_cf, cf
2222
from charon.cmd.cmd_sign import sign
23+
from charon.cmd.cmd_merge import merge
2324

2425

2526
@group()
@@ -47,3 +48,6 @@ def cli(ctx):
4748

4849
# radas sign cmd
4950
cli.add_command(sign)
51+
52+
# maven zips merge cmd
53+
cli.add_command(merge)

charon/cmd/cmd_merge.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
"""
2+
Copyright (C) 2022 Red Hat, Inc. (https://github.com/Commonjava/charon)
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://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,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
16+
from typing import List
17+
18+
from charon.utils.archive import detect_npm_archives, NpmArchiveType
19+
from charon.cmd.internal import _get_local_repos, _decide_mode
20+
from charon.pkgs.maven import _extract_tarballs
21+
from click import command, option, argument
22+
from zipfile import ZipFile, ZIP_DEFLATED
23+
from tempfile import mkdtemp
24+
25+
import logging
26+
import os
27+
import sys
28+
29+
logger = logging.getLogger(__name__)
30+
31+
32+
@argument(
33+
"repos",
34+
type=str,
35+
nargs=-1 # This allows multiple arguments for zip urls
36+
)
37+
@option(
38+
"--product",
39+
"-p",
40+
help="""
41+
The product key, will combine with version to decide
42+
the metadata of the files in tarball.
43+
""",
44+
nargs=1,
45+
required=True,
46+
multiple=False,
47+
)
48+
@option(
49+
"--version",
50+
"-v",
51+
help="""
52+
The product version, will combine with key to decide
53+
the metadata of the files in tarball.
54+
""",
55+
required=True,
56+
multiple=False,
57+
)
58+
@option(
59+
"--root_path",
60+
"-r",
61+
default="maven-repository",
62+
help="""
63+
The root path in the tarball before the real maven paths,
64+
will be trailing off before uploading.
65+
""",
66+
)
67+
@option(
68+
"--work_dir",
69+
"-w",
70+
help="""
71+
The temporary working directory into which archives should
72+
be extracted, when needed.
73+
""",
74+
)
75+
@option(
76+
"--merge_result",
77+
"-m",
78+
help="""
79+
The path of the final merged zip file will be compressed and saved.
80+
Default is the ZIP file which is created in a temporary directory based on work_dir.
81+
e.g. /tmp/work/jboss-eap-8.1.0_merged_a1b2c3/jboss-eap-8.1.0_merged.zip
82+
""",
83+
)
84+
@option(
85+
"--debug",
86+
"-D",
87+
help="Debug mode, will print all debug logs for problem tracking.",
88+
is_flag=True,
89+
default=False
90+
)
91+
@option(
92+
"--quiet",
93+
"-q",
94+
help="Quiet mode, will shrink most of the logs except warning and errors.",
95+
is_flag=True,
96+
default=False
97+
)
98+
@command()
99+
def merge(
100+
repos: List[str],
101+
product: str,
102+
version: str,
103+
root_path="maven-repository",
104+
work_dir=None,
105+
merge_result=None,
106+
debug=False,
107+
quiet=False
108+
):
109+
"""Merge multiple Maven ZIP archives and compress the result into a single ZIP file.
110+
The merged file is stored locally as specified by merge_result.
111+
112+
Note: This function does not support merging single archive, NPM archives,
113+
or archives of inconsistent types.
114+
"""
115+
_decide_mode(product, version, is_quiet=quiet, is_debug=debug)
116+
if len(repos) == 1:
117+
logger.info("Skip merge step, single archive detected, no merge needed")
118+
sys.exit(0)
119+
120+
product_key = f"{product}-{version}"
121+
archive_paths = _get_local_repos(repos)
122+
archive_types = detect_npm_archives(archive_paths)
123+
124+
maven_count = archive_types.count(NpmArchiveType.NOT_NPM)
125+
npm_count = len(archive_types) - maven_count
126+
if maven_count == len(archive_types):
127+
tmp_root = _extract_tarballs(archive_paths, root_path, product_key, dir__=work_dir)
128+
_create_merged_zip(tmp_root, merge_result, product_key, work_dir)
129+
elif npm_count == len(archive_types):
130+
logger.error("Skip merge step for the npm archives")
131+
sys.exit(1)
132+
else:
133+
logger.error("Skip merge step since the types are not consistent")
134+
sys.exit(1)
135+
136+
137+
def _create_merged_zip(
138+
root_path: str,
139+
merge_result: str,
140+
product_key: str,
141+
work_dir: str
142+
):
143+
zip_path = merge_result
144+
if not merge_result:
145+
merge_path = mkdtemp(prefix=f"{product_key}_merged_", dir=work_dir)
146+
zip_path = os.path.join(merge_path, f"{product_key}_merged.zip")
147+
148+
# pylint: disable=unused-variable
149+
with ZipFile(zip_path, 'w', ZIP_DEFLATED) as zipf:
150+
for root, dirs, files in os.walk(root_path):
151+
for file in files:
152+
file_path = os.path.join(root, file)
153+
# Calculate relative path to preserve directory structure
154+
arcname = os.path.relpath(file_path, root_path)
155+
zipf.write(file_path, arcname)
156+
logger.info("Done for the merged zip generation: %s", zip_path)

0 commit comments

Comments
 (0)