44Canonical name (cname)
55"""
66
7+ from configparser import ConfigParser , UNNAMED_SECTION
8+ from pathlib import Path
9+ from typing import List , Optional
10+ from os import PathLike
711import re
8- from typing import Optional
912
1013from ..constants import ARCHS
1114from .parser import Parser
@@ -37,9 +40,11 @@ def __init__(self, cname, arch=None, commit_id=None, version=None):
3740 """
3841
3942 self ._arch = None
40- self ._flavor = None
4143 self ._commit_id = None
44+ self ._feature_set_cached = None
45+ self ._flavor = None
4246 self ._version = None
47+ self ._platforms_cached = None
4348
4449 re_match = re .match (
4550 "([a-zA-Z0-9]+([\\ _\\ -][a-zA-Z0-9]+)*?)(-([a-z0-9]+)(-([a-z0-9.]+)-([a-z0-9]+))*)?$" ,
@@ -81,6 +86,7 @@ def arch(self) -> Optional[str]:
8186 Returns the architecture for the cname parsed.
8287
8388 :return: (str) CName architecture
89+ :since: 0.7.0
8490 """
8591
8692 return self ._arch
@@ -91,6 +97,7 @@ def cname(self) -> str:
9197 Returns the cname parsed.
9298
9399 :return: (str) CName
100+ :since: 0.7.0
94101 """
95102
96103 cname = self ._flavor
@@ -109,6 +116,7 @@ def commit_id(self) -> Optional[str]:
109116 Returns the commit ID if part of the cname parsed.
110117
111118 :return: (str) Commit ID
119+ :since: 0.7.0
112120 """
113121
114122 return self ._commit_id
@@ -119,6 +127,7 @@ def flavor(self) -> str:
119127 Returns the flavor for the cname parsed.
120128
121129 :return: (str) Flavor
130+ :since: 0.7.0
122131 """
123132
124133 return self ._flavor
@@ -129,8 +138,12 @@ def feature_set(self) -> str:
129138 Returns the feature set for the cname parsed.
130139
131140 :return: (str) Feature set of the cname
141+ :since: 0.7.0
132142 """
133143
144+ if self ._feature_set_cached is not None :
145+ return self ._feature_set_cached
146+
134147 return Parser ().filter_as_string (self .flavor )
135148
136149 @property
@@ -139,16 +152,35 @@ def platform(self) -> str:
139152 Returns the platform for the cname parsed.
140153
141154 :return: (str) Flavor
155+ :since: 0.7.0
156+ """
157+
158+ if self ._platforms_cached is not None :
159+ return "," .join (self ._platforms_cached )
160+
161+ return "," .join (Parser ().filter_as_dict (self .flavor )["platform" ])
162+
163+ @property
164+ def platforms (self ) -> List [str ]:
165+ """
166+ Returns the platforms for the cname parsed.
167+
168+ :return: (str) Flavor
169+ :since: 0.9.2
142170 """
143171
144- return re .split ("[_-]" , self ._flavor , maxsplit = 1 )[0 ]
172+ if self ._platforms_cached is not None :
173+ return self ._platforms_cached
174+
175+ return Parser ().filter_as_dict (self .flavor )["platform" ]
145176
146177 @property
147178 def version (self ) -> Optional [str ]:
148179 """
149180 Returns the version if part of the cname parsed.
150181
151182 :return: (str) Version
183+ :since: 0.7.0
152184 """
153185
154186 return self ._version
@@ -159,9 +191,117 @@ def version_and_commit_id(self) -> Optional[str]:
159191 Returns the version and commit ID if part of the cname parsed.
160192
161193 :return: (str) Version and commit ID
194+ :since: 0.7.0
162195 """
163196
164197 if self ._commit_id is None :
165198 return None
166199
167200 return f"{ self ._version } -{ self ._commit_id } "
201+
202+ def load_from_metadata_file (self , metadata_file : PathLike | str ) -> None :
203+ """
204+ Loads and parses a metadata file.
205+
206+ :param metadata_file: Metadata file containing information about the CName instance.
207+
208+ :since: 0.9.2
209+ """
210+
211+ if not isinstance (metadata_file , PathLike ):
212+ metadata_file = Path (metadata_file )
213+
214+ if not metadata_file .exists ():
215+ raise RuntimeError (f"Metadata file given is invalid: { metadata_file } " )
216+
217+ metadata_config = ConfigParser (allow_unnamed_section = True )
218+ metadata_config .read (metadata_file )
219+
220+ for metadata_field in (
221+ "GARDENLINUX_CNAME" ,
222+ "GARDENLINUX_FEATURES" ,
223+ "GARDENLINUX_FEATURES_PLATFORMS" ,
224+ "GARDENLINUX_VERSION" ,
225+ ):
226+ if not metadata_config .has_option (UNNAMED_SECTION , metadata_field ):
227+ raise RuntimeError (
228+ f"Metadata file given is invalid: { metadata_file } misses { metadata_field } "
229+ )
230+
231+ loaded_cname_instance = CName (
232+ metadata_config .get (UNNAMED_SECTION , "GARDENLINUX_CNAME" )
233+ )
234+
235+ commit_id = metadata_config .get (UNNAMED_SECTION , "GARDENLINUX_COMMIT_ID" )
236+ version = metadata_config .get (UNNAMED_SECTION , "GARDENLINUX_VERSION" )
237+
238+ if (
239+ loaded_cname_instance .flavor != self .flavor
240+ or loaded_cname_instance .commit_id != commit_id
241+ or (self ._commit_id is not None and self ._commit_id != commit_id )
242+ or loaded_cname_instance .version != version
243+ or (self ._version is not None and self ._version != version )
244+ ):
245+ raise RuntimeError (
246+ f"Metadata file given is invalid: { metadata_file } failed consistency check - { self .cname } != { loaded_cname_instance .cname } "
247+ )
248+
249+ self ._arch = loaded_cname_instance .arch
250+ self ._flavor = loaded_cname_instance .flavor
251+ self ._commit_id = commit_id
252+ self ._version = version
253+
254+ self ._feature_set_cached = metadata_config .get (
255+ UNNAMED_SECTION , "GARDENLINUX_FEATURES"
256+ )
257+
258+ self ._platforms_cached = metadata_config .get (
259+ UNNAMED_SECTION , "GARDENLINUX_FEATURES_PLATFORMS"
260+ ).split ("," )
261+
262+ def save_to_metadata_file (
263+ self , metadata_file : PathLike | str , overwrite : Optional [bool ] = False
264+ ) -> None :
265+ """
266+ Saves the metadata file.
267+
268+ :param metadata_file: Metadata file containing information about the CName instance.
269+
270+ :since: 0.9.2
271+ """
272+
273+ if not isinstance (metadata_file , PathLike ):
274+ metadata_file = Path (metadata_file )
275+
276+ if not overwrite and metadata_file .exists ():
277+ raise RuntimeError (
278+ f"Refused to overwrite existing metadata file: { metadata_file } "
279+ )
280+
281+ features = Parser ().filter_as_dict (self .flavor )
282+
283+ elements = "," .join (features ["element" ])
284+ flags = "," .join (features ["flag" ])
285+ platforms = "," .join (features ["platform" ])
286+
287+ metadata = f"""
288+ ID=gardenlinux
289+ NAME="Garden Linux"
290+ PRETTY_NAME="Garden Linux { self .version } "
291+ IMAGE_VERSION={ self .version }
292+ VARIANT_ID="{ self .flavor } -{ self .arch } "
293+ HOME_URL="https://gardenlinux.io"
294+ SUPPORT_URL="https://github.com/gardenlinux/gardenlinux"
295+ BUG_REPORT_URL="https://github.com/gardenlinux/gardenlinux/issues"
296+ GARDENLINUX_CNAME="{ self .cname } "
297+ GARDENLINUX_FEATURES="{ self .feature_set } "
298+ GARDENLINUX_FEATURES_PLATFORMS="{ platforms } "
299+ GARDENLINUX_FEATURES_ELEMENTS="{ elements } "
300+ GARDENLINUX_FEATURES_FLAGS="{ flags } "
301+ GARDENLINUX_VERSION="{ self .version } "
302+ GARDENLINUX_COMMIT_ID="{ self .commit_id } "
303+ GARDENLINUX_COMMIT_ID_LONG=$BUILDER_COMMIT
304+ """ .strip ()
305+
306+ with metadata_file .open ("w" ) as fp :
307+ fp .write (metadata )
0 commit comments