forked from opensearch-project/opensearch-build
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dist.py
136 lines (105 loc) · 4.9 KB
/
dist.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# Copyright OpenSearch Contributors
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.
import errno
import logging
import os
import shutil
import tarfile
import zipfile
from abc import ABC, abstractmethod
from assemble_workflow.bundle_linux_deb import BundleLinuxDeb
from assemble_workflow.bundle_linux_rpm import BundleLinuxRpm
from manifests.build_manifest import BuildManifest
from system.zip_file import ZipFile
class Dist(ABC):
def __init__(self, name: str, path: str, min_path: str, build_cls: BuildManifest.Build) -> None:
self.build_cls = build_cls
self.name = name
self.filename = name.lower()
self.path = path
self.min_path = min_path
@abstractmethod
def __extract__(self, dest: str) -> None:
pass
@abstractmethod
def __build__(self, name: str, dest: str) -> None:
pass
def find_min_archive_path(self, dest: str) -> str:
'''
Return the single folder that contains the main files of {name}.
This folder is normally in the format of {filename}-{exact or bc version}.
Ex: opensearch-1.3.0 or opensearch-dashboards-1.3.0
Adding a check of whether {filename} is in folder name is to ensure
that only folders in above format are returned.
In tar there is only 1 top level folders after extraction.
But in rpm there are multiple folders such as var / usr / opensearch-1.3.0 ......
This is to ensure corrent folder is found, instead of simply choosing the 1st in the list.
'''
for file in os.scandir(dest):
if self.filename in file.name and file.is_dir():
self.archive_path = file.path
return self.archive_path
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), os.path.join(dest, "*"))
def rename_archive_path(self, path: str) -> str:
'''
Rename the single folder at the top level of the tar that contains the min distribution to match current version.
For example, when OpenSearch 1.1.1 is built using the 1.1.0 artifact, we rename opensearch-1.1.0 to opensearch-1.1.1.
'''
current_name = os.path.basename(path)
target_name = self.min_path
if current_name != target_name:
logging.info(f"Renaming {path} to {target_name}.")
target_path = os.path.join(os.path.dirname(path), target_name)
os.rename(path, target_path)
return target_path
else:
return path
def extract(self, dest: str) -> str:
self.__extract__(dest)
self.archive_path = self.rename_archive_path(
self.find_min_archive_path(dest)
)
return self.archive_path
def build(self, name: str, dest: str) -> None:
self.__build__(name, dest)
path = os.path.join(dest, name)
shutil.copyfile(name, path)
logging.info(f"Published {path}.")
class DistTar(Dist):
def __extract__(self, dest: str) -> None:
with tarfile.open(self.path, "r:gz") as tar:
tar.extractall(dest)
def __build__(self, name: str, dest: str) -> None:
with tarfile.open(name, "w:gz") as tar:
tar.add(self.archive_path, arcname=os.path.basename(self.archive_path))
class DistZip(Dist):
def __extract__(self, dest: str) -> None:
with ZipFile(self.path, "r") as zip:
zip.extractall(dest)
def __build__(self, name: str, dest: str) -> None:
with ZipFile(name, "w", zipfile.ZIP_DEFLATED) as zip:
# root : /tmp/tmp********/opensearch-<version+qualifier>
# leadingdir : opensearch-<version+qualifier>
# root no leading dir: /tmp/tmp********/
# This is to preserve the leading directory `opensearch-<version+qualifier>` in zip
rootlen = len(self.archive_path)
leadingdirlen = len(os.path.basename(self.archive_path))
noleadingdirlen = rootlen - leadingdirlen
for base, _, files in os.walk(self.archive_path):
for file in files:
fn = os.path.join(base, file)
zip.write(fn, fn[noleadingdirlen:])
class DistDeb(Dist):
def __extract__(self, dest: str) -> None:
BundleLinuxDeb(self.filename, self.path, self.min_path).extract(dest)
def __build__(self, name: str, dest: str) -> None:
BundleLinuxDeb(self.filename, self.path, self.min_path).build(name, dest, self.archive_path, self.build_cls)
class DistRpm(Dist):
def __extract__(self, dest: str) -> None:
BundleLinuxRpm(self.filename, self.path, self.min_path).extract(dest)
def __build__(self, name: str, dest: str) -> None:
BundleLinuxRpm(self.filename, self.path, self.min_path).build(name, dest, self.archive_path, self.build_cls)