44Canonical name (cname)
55"""
66
7- from typing import Optional
7+ from configparser import ConfigParser , UNNAMED_SECTION
8+ from pathlib import Path
9+ from typing import List , Optional
10+ from os import PathLike
811import re
912
1013from ..constants import ARCHS
@@ -38,9 +41,11 @@ def __init__(self, cname, arch=None, commit_id=None, version=None):
3841 """
3942
4043 self ._arch = None
41- self ._flavor = None
4244 self ._commit_id = None
45+ self ._feature_set_cached = None
46+ self ._flavor = None
4347 self ._version = None
48+ self ._platforms_cached = None
4449
4550 re_match = re .match (
4651 "([a-zA-Z0-9]+([\\ _\\ -][a-zA-Z0-9]+)*?)(-([a-z0-9]+)(-([a-z0-9.]+)-([a-z0-9]+))*)?$" ,
@@ -82,6 +87,7 @@ def arch(self) -> Optional[str]:
8287 Returns the architecture for the cname parsed.
8388
8489 :return: (str) CName architecture
90+ :since: 0.7.0
8591 """
8692
8793 return self ._arch
@@ -92,6 +98,7 @@ def cname(self) -> str:
9298 Returns the cname parsed.
9399
94100 :return: (str) CName
101+ :since: 0.7.0
95102 """
96103
97104 cname = self ._flavor
@@ -110,6 +117,7 @@ def commit_id(self) -> Optional[str]:
110117 Returns the commit ID if part of the cname parsed.
111118
112119 :return: (str) Commit ID
120+ :since: 0.7.0
113121 """
114122
115123 return self ._commit_id
@@ -120,6 +128,7 @@ def flavor(self) -> str:
120128 Returns the flavor for the cname parsed.
121129
122130 :return: (str) Flavor
131+ :since: 0.7.0
123132 """
124133
125134 return self ._flavor
@@ -130,8 +139,12 @@ def feature_set(self) -> str:
130139 Returns the feature set for the cname parsed.
131140
132141 :return: (str) Feature set of the cname
142+ :since: 0.7.0
133143 """
134144
145+ if self ._feature_set_cached is not None :
146+ return self ._feature_set_cached
147+
135148 return Parser ().filter_as_string (self .flavor )
136149
137150 @property
@@ -140,16 +153,35 @@ def platform(self) -> str:
140153 Returns the platform for the cname parsed.
141154
142155 :return: (str) Flavor
156+ :since: 0.7.0
157+ """
158+
159+ if self ._platforms_cached is not None :
160+ return "," .join (self ._platforms_cached )
161+
162+ return "," .join (Parser ().filter_as_dict (self .flavor )["platform" ])
163+
164+ @property
165+ def platforms (self ) -> List [str ]:
166+ """
167+ Returns the platforms for the cname parsed.
168+
169+ :return: (str) Flavor
170+ :since: 0.9.1
143171 """
144172
145- return re .split ("[_-]" , self ._flavor , maxsplit = 1 )[0 ]
173+ if self ._platforms_cached is not None :
174+ return self ._platforms_cached
175+
176+ return Parser ().filter_as_dict (self .flavor )["platform" ]
146177
147178 @property
148179 def version (self ) -> Optional [str ]:
149180 """
150181 Returns the version if part of the cname parsed.
151182
152183 :return: (str) Version
184+ :since: 0.7.0
153185 """
154186
155187 return self ._version
@@ -160,9 +192,117 @@ def version_and_commit_id(self) -> Optional[str]:
160192 Returns the version and commit ID if part of the cname parsed.
161193
162194 :return: (str) Version and commit ID
195+ :since: 0.7.0
163196 """
164197
165198 if self ._commit_id is None :
166199 return None
167200
168201 return f"{ self ._version } -{ self ._commit_id } "
202+
203+ def load_from_metadata_file (self , metadata_file : PathLike | str ) -> None :
204+ """
205+ Loads and parses a metadata file.
206+
207+ :param metadata_file: Metadata file containing information about the CName instance.
208+
209+ :since: 0.9.1
210+ """
211+
212+ if not isinstance (metadata_file , PathLike ):
213+ metadata_file = Path (metadata_file )
214+
215+ if not metadata_file .exists ():
216+ raise RuntimeError (f"Metadata file given is invalid: { metadata_file } " )
217+
218+ metadata_config = ConfigParser (allow_unnamed_section = True )
219+ metadata_config .read (metadata_file )
220+
221+ for metadata_field in (
222+ "GARDENLINUX_CNAME" ,
223+ "GARDENLINUX_FEATURES" ,
224+ "GARDENLINUX_FEATURES_PLATFORMS" ,
225+ "GARDENLINUX_VERSION" ,
226+ ):
227+ if not metadata_config .has_option (UNNAMED_SECTION , metadata_field ):
228+ raise RuntimeError (
229+ f"Metadata file given is invalid: { metadata_file } misses { metadata_field } "
230+ )
231+
232+ loaded_cname_instance = CName (
233+ metadata_config .get (UNNAMED_SECTION , "GARDENLINUX_CNAME" )
234+ )
235+
236+ commit_id = metadata_config .get (UNNAMED_SECTION , "GARDENLINUX_COMMIT_ID" )
237+ version = metadata_config .get (UNNAMED_SECTION , "GARDENLINUX_VERSION" )
238+
239+ if (
240+ loaded_cname_instance .flavor != self .flavor
241+ or loaded_cname_instance .commit_id != commit_id
242+ or (self ._commit_id is not None and self ._commit_id != commit_id )
243+ or loaded_cname_instance .version != version
244+ or (self ._version is not None and self ._version != version )
245+ ):
246+ raise RuntimeError (
247+ f"Metadata file given is invalid: { metadata_file } failed consistency check - { self .cname } != { loaded_cname_instance .cname } "
248+ )
249+
250+ self ._arch = loaded_cname_instance .arch
251+ self ._flavor = loaded_cname_instance .flavor
252+ self ._commit_id = commit_id
253+ self ._version = version
254+
255+ self ._feature_set_cached = metadata_config .get (
256+ UNNAMED_SECTION , "GARDENLINUX_FEATURES"
257+ )
258+
259+ self ._platforms_cached = metadata_config .get (
260+ UNNAMED_SECTION , "GARDENLINUX_FEATURES_PLATFORMS"
261+ ).split ("," )
262+
263+ def save_to_metadata_file (
264+ self , metadata_file : PathLike | str , overwrite : Optional [bool ] = False
265+ ) -> None :
266+ """
267+ Saves the metadata file.
268+
269+ :param metadata_file: Metadata file containing information about the CName instance.
270+
271+ :since: 0.9.1
272+ """
273+
274+ if not isinstance (metadata_file , PathLike ):
275+ metadata_file = Path (metadata_file )
276+
277+ if not overwrite and metadata_file .exists ():
278+ raise RuntimeError (
279+ f"Refused to overwrite existing metadata file: { metadata_file } "
280+ )
281+
282+ features = Parser ().filter_as_dict (self .flavor )
283+
284+ elements = "," .join (features ["element" ])
285+ flags = "," .join (features ["flag" ])
286+ platforms = "," .join (features ["platform" ])
287+
288+ metadata = f"""
289+ ID=gardenlinux
290+ NAME="Garden Linux"
291+ PRETTY_NAME="Garden Linux { self .version } "
292+ IMAGE_VERSION={ self .version }
293+ VARIANT_ID="{ self .flavor } -{ self .arch } "
294+ HOME_URL="https://gardenlinux.io"
295+ SUPPORT_URL="https://github.com/gardenlinux/gardenlinux"
296+ BUG_REPORT_URL="https://github.com/gardenlinux/gardenlinux/issues"
297+ GARDENLINUX_CNAME="{ self .cname } "
298+ GARDENLINUX_FEATURES="{ self .feature_set } "
299+ GARDENLINUX_FEATURES_PLATFORMS="{ platforms } "
300+ GARDENLINUX_FEATURES_ELEMENTS="{ elements } "
301+ GARDENLINUX_FEATURES_FLAGS="{ flags } "
302+ GARDENLINUX_VERSION="{ self .version } "
303+ GARDENLINUX_COMMIT_ID="{ self .commit_id } "
304+ GARDENLINUX_COMMIT_ID_LONG=$BUILDER_COMMIT
305+ """ .strip ()
306+
307+ with metadata_file .open ("w" ) as fp :
308+ fp .write (metadata )
0 commit comments