77from enum import Enum
88from functools import partial
99from pathlib import Path
10+ from threading import Lock
1011from typing import (
1112 TYPE_CHECKING ,
1213 Any ,
@@ -160,6 +161,8 @@ def __init__(self, node: "Node", is_posix: bool) -> None:
160161 self ._log = get_logger (name = "os" , parent = self ._node .log )
161162 self ._information : Optional [OsInformation ] = None
162163 self ._packages : Dict [str , LisaVersionInfo ] = dict ()
164+ self ._source_installation_initialized = False
165+ self ._lock = Lock ()
163166
164167 @classmethod
165168 def create (cls , node : "Node" ) -> Any :
@@ -452,7 +455,6 @@ def enable_package_build_deps(self) -> None:
452455 turning on deb-src or srpm repositories.
453456 """
454457 self ._enable_package_build_deps ()
455- self ._src_repo_initialized = True
456458
457459 def install_build_deps (
458460 self ,
@@ -462,8 +464,12 @@ def install_build_deps(
462464 Install apt-get/yum build-deps package build dependency installation by
463465 turning on deb-src or srpm repositories.
464466 """
465- if not getattr (self , "_src_repo_initialized" , False ):
466- self .enable_package_build_deps ()
467+ # lock this to prevent double initialization;
468+ # some methods involve directly writing to a file
469+ with self ._lock :
470+ if not self ._source_installation_initialized :
471+ self .enable_package_build_deps ()
472+ self ._source_installation_initialized = True
467473
468474 package_names = self ._get_package_list (packages )
469475 for package in package_names :
@@ -964,14 +970,19 @@ def _get_package_information(self, package_name: str) -> LisaVersionInfo:
964970 return self ._cache_and_return_version_info (package_name , version_info )
965971
966972 def _enable_package_build_deps (self ) -> None :
967- if not getattr (self , "_src_repo_initialized" , False ):
973+ # debian uses apt sources.list.
974+ # we only need to uncomment the standard source repos
975+ # in that file
976+ sources_list = self ._node .get_pure_path ("/etc/apt/sources.list" )
977+ if self ._node .shell .exists (sources_list ):
968978 self ._node .tools [Sed ].substitute (
969- "# deb-src" , "deb-src" , "/etc/apt/sources.list" , sudo = True
979+ "# deb-src" , "deb-src" , str ( sources_list ) , sudo = True
970980 )
971981 self .get_repositories ()
972- self ._src_repo_initialized = True
973982
974983 def _install_build_deps (self , packages : str ) -> None :
984+ # apt-get build-dep installs the listed build dependencies
985+ # from the src .deb for a given package.
975986 self ._node .execute (
976987 f"apt-get build-dep -y { packages } " ,
977988 sudo = True ,
@@ -1501,11 +1512,12 @@ def _enable_package_build_deps(self) -> None:
15011512 # file in place of the sources.list file. It uses a fancier format, so
15021513 # requires special handling.
15031514 node = self ._node
1504- if node .shell .exists (node .get_pure_path ("/etc/apt/ubuntu.sources" )):
1515+ ubuntu_sources = node .get_pure_path ("/etc/apt/ubuntu.sources" )
1516+ if node .shell .exists (ubuntu_sources ):
15051517 node .tools [Sed ].substitute (
15061518 regexp = r"Types\: deb" ,
15071519 replacement = r"Types\: deb deb-src" ,
1508- file = "/etc/apt/ubuntu.sources" ,
1520+ file = str ( ubuntu_sources ) ,
15091521 sudo = True ,
15101522 )
15111523 else :
@@ -1888,6 +1900,7 @@ def _get_information(self) -> OsInformation:
18881900 return information
18891901
18901902 def _enable_package_build_deps (self ) -> None :
1903+ # epel enbables source repos by default
18911904 self .install_epel ()
18921905
18931906
@@ -2091,13 +2104,16 @@ def _dnf_tool(self) -> str:
20912104 def _enable_package_build_deps (self ) -> None :
20922105 # enable epel first
20932106 super ()._enable_package_build_deps ()
2107+ # almalinux has a few different source repos, they are easy to enable
20942108 self ._node .execute ("dnf install -y almalinux-release-devel" )
20952109 # then enable crb (code ready builder) using alma tool
20962110 # this enables some needed package build dependency srpms
2111+ # this was formerly known as the 'powertools' repo.
20972112 if int (self .information .version .major ) == 8 :
20982113 pkg = "powertools"
20992114 elif int (self .information .version .major ) == 9 :
21002115 pkg = "crb"
2116+ # set the repo as enabled
21012117 self ._node .execute (
21022118 f"dnf config-manager --set-enabled { pkg } " ,
21032119 sudo = True ,
@@ -2417,28 +2433,42 @@ def add_azure_core_repo(
24172433 )
24182434
24192435 def _enable_package_build_deps (self ) -> None :
2436+ # zypper seems more suited to interactive use
2437+ # to enable source repos, list the defaults and select the source repos
24202438 repos = self .get_repositories ()
24212439 for repo in repos :
24222440 if isinstance (repo , SuseRepositoryInfo ) and "Source-Pool" in repo .name :
2441+ # if it's a source repo, enable it
24232442 self ._node .execute (
24242443 f"zypper mr -e { repo .alias } " ,
24252444 sudo = True ,
24262445 expected_exit_code = 0 ,
2427- expected_exit_code_failure_message = f"Could not enable source pool for repo: { repo .alias } " ,
2446+ expected_exit_code_failure_message = (
2447+ f"Could not enable source pool for repo: { repo .alias } "
2448+ ),
24282449 )
2450+ # then refresh the repo status to fetch the new metadata
24292451 self ._node .execute (
24302452 "zypper refresh -y" ,
24312453 sudo = True ,
24322454 expected_exit_code = 0 ,
2433- expected_exit_code_failure_message = "Failure to zypper refresh after enabling source repos." ,
2455+ expected_exit_code_failure_message = (
2456+ "Failure to zypper refresh after enabling source repos."
2457+ ),
24342458 )
24352459
24362460 def _install_build_deps (self , packages : str ) -> None :
2461+ # zypper sourceinstall the packages
2462+ # if there are missing dependencies, you can attempt to
2463+ # force zypper to work out the problem. It seems to assume
2464+ # interactive usage for these even with the -n flag so YMMV.
24372465 self ._node .execute (
24382466 f"zypper si --build-deps-only --force-resolution { packages } " ,
24392467 sudo = True ,
24402468 expected_exit_code = 0 ,
2441- expected_exit_code_failure_message = f"failed to source install package: { packages } " ,
2469+ expected_exit_code_failure_message = (
2470+ f"failed to source install package: { packages } "
2471+ ),
24422472 )
24432473
24442474 def _initialize_package_installation (self ) -> None :
0 commit comments