88from functools import cached_property
99from re import Pattern
1010from shlex import quote
11- from typing import TYPE_CHECKING , Any , Optional
11+ from typing import TYPE_CHECKING , Any , ClassVar , Optional
1212
1313import tmt .log
1414import tmt .utils
@@ -115,6 +115,10 @@ class ArtifactProvider(ABC):
115115 #: The PrepareArtifact phase that owns this provider.
116116 parent : "PrepareArtifact"
117117
118+ #: Whether this provider downloads individual artifact files.
119+ #: Providers that only register repositories should set this to ``False``.
120+ downloads_artifacts : ClassVar [bool ] = True
121+
118122 def __post_init__ (self ) -> None :
119123 self .id = self ._extract_provider_id (self .raw_id )
120124
@@ -219,6 +223,11 @@ def fetch_contents(
219223 f"Unexpected error downloading '{ artifact } '."
220224 ) from error
221225
226+ if not downloaded_paths :
227+ raise tmt .utils .PrepareError (
228+ f"No artifacts were downloaded for provider '{ self .raw_id } '. "
229+ f"Verify the provider identifier is correct."
230+ )
222231 self .logger .info (f"Successfully downloaded '{ len (downloaded_paths )} ' artifacts." )
223232 return downloaded_paths
224233
@@ -284,15 +293,11 @@ def enumerate_artifacts(self, guest: Guest) -> None:
284293 f"Enumerated { len (packages )} packages from repository '{ repository .name } '."
285294 )
286295
287- # B027: "... is an empty method in an abstract base class, but has
288- # no abstract decorator" - expected, it's a default implementation
289- # provided for subclasses. It is acceptable to do nothing.
290- def contribute_to_shared_repo ( # noqa: B027
296+ def contribute_to_shared_repo (
291297 self ,
292298 guest : Guest ,
293299 source_path : Path ,
294300 shared_repo_dir : Path ,
295- exclude_patterns : Optional [list [Pattern [str ]]] = None ,
296301 ) -> None :
297302 """
298303 Contribute artifacts to the shared repository.
@@ -305,10 +310,20 @@ def contribute_to_shared_repo( # noqa: B027
305310 :param source_path: path where the artifacts are located (source for contribution).
306311 :param shared_repo_dir: path to the shared repository directory where
307312 artifacts should be contributed.
308- :param exclude_patterns: if set, artifacts whose names match any
309- of the given regular expressions would not be contributed.
310313 """
311- pass
314+ try :
315+ guest .execute (
316+ ShellScript (f"cp { quote (str (source_path ))} /*.rpm { quote (str (shared_repo_dir ))} " )
317+ )
318+ except tmt .utils .RunError as error :
319+ if error .stderr and "No such file" in error .stderr :
320+ self .logger .warning (f"No artifacts to contribute from '{ source_path } '." )
321+ return
322+ raise tmt .utils .PrepareError (
323+ f"Failed to copy artifacts from '{ source_path } ' to '{ shared_repo_dir } '."
324+ ) from error
325+
326+ self .logger .info (f"Contributed artifacts from '{ source_path } ' to '{ shared_repo_dir } '." )
312327
313328 @property
314329 def artifact_metadata (self ) -> list [dict [str , Any ]]:
0 commit comments