Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel <blackrabbit256@gmail.com>2022-02-18 21:33:28 +1100
committerGitHub <noreply@github.com>2022-02-18 11:33:28 +0100
commit4b3b21ed756463914d618abe11345c9839217473 (patch)
tree94fecd8d11262a5423d6af3805f24d63012519b5
parent62a6aec197b0e83ab91fdec1ab15427ecf749dac (diff)
Check if pacman is available (#958)
* Check if pacman is available * Update pacman call * Added a graceful wait to `run_pacman` * Fix flake8 Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com> Co-authored-by: Anton Hvornum <anton.feeds+github@gmail.com>
-rw-r--r--archinstall/lib/installer.py8
-rw-r--r--archinstall/lib/networking.py7
-rw-r--r--archinstall/lib/packages/packages.py4
-rw-r--r--archinstall/lib/pacman.py28
4 files changed, 39 insertions, 8 deletions
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index 2a7b158a..257dda22 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -30,6 +30,8 @@ __packages__ = ["base", "base-devel", "linux-firmware", "linux", "linux-lts", "l
# Additional packages that are installed if the user is running the Live ISO with accessibility tools enabled
__accessibility_packages__ = ["brltty", "espeakup", "alsa-utils"]
+from .pacman import run_pacman
+
class InstallationFile:
def __init__(self, installation :'Installer', filename :str, owner :str, mode :str = "w"):
@@ -292,7 +294,7 @@ class Installer:
def enable_multilib_repository(self):
# Set up a regular expression pattern of a commented line containing 'multilib' within []
pattern = re.compile("^#\\[.*multilib.*\\]$")
-
+
# This is used to track if the previous line is a match, so we end up uncommenting the line after the block.
matched = False
@@ -318,7 +320,7 @@ class Installer:
def enable_testing_repositories(self, enable_multilib_testing=False):
# Set up a regular expression pattern of a commented line containing 'testing' within []
pattern = re.compile("^#\\[.*testing.*\\]$")
-
+
# This is used to track if the previous line is a match, so we end up uncommenting the line after the block.
matched = False
@@ -352,7 +354,7 @@ class Installer:
self.log(f'Installing packages: {packages}', level=logging.INFO)
- if (sync_mirrors := SysCommand('/usr/bin/pacman -Syy')).exit_code == 0:
+ if (sync_mirrors := run_pacman('-Syy', default_cmd='/usr/bin/pacman')).exit_code == 0:
if (pacstrap := SysCommand(f'/usr/bin/pacstrap -C /etc/pacman.conf {self.target} {" ".join(packages)} --noconfirm', peak_output=True)).exit_code == 0:
return True
else:
diff --git a/archinstall/lib/networking.py b/archinstall/lib/networking.py
index 5331216c..3e883a7b 100644
--- a/archinstall/lib/networking.py
+++ b/archinstall/lib/networking.py
@@ -7,6 +7,7 @@ from typing import Union, Dict, Any, List
from .exceptions import HardwareIncompatibilityError
from .general import SysCommand
from .output import log
+from .pacman import run_pacman
from .storage import storage
@@ -32,7 +33,7 @@ def list_interfaces(skip_loopback :bool = True) -> Dict[str, str]:
def check_mirror_reachable() -> bool:
log("Testing connectivity to the Arch Linux mirrors ...", level=logging.INFO)
- if SysCommand("pacman -Sy").exit_code == 0:
+ if run_pacman("-Sy").exit_code == 0:
return True
elif os.geteuid() != 0:
@@ -42,9 +43,9 @@ def check_mirror_reachable() -> bool:
def update_keyring() -> bool:
log("Updating archlinux-keyring ...", level=logging.INFO)
- if SysCommand("pacman -Sy --noconfirm archlinux-keyring").exit_code == 0:
+ if run_pacman("-Sy --noconfirm archlinux-keyring").exit_code == 0:
return True
-
+
elif os.geteuid() != 0:
log("update_keyring() uses 'pacman -Sy archlinux-keyring' which requires root.", level=logging.ERROR, fg="red")
diff --git a/archinstall/lib/packages/packages.py b/archinstall/lib/packages/packages.py
index 26d8ff68..b2c8ab8e 100644
--- a/archinstall/lib/packages/packages.py
+++ b/archinstall/lib/packages/packages.py
@@ -4,8 +4,8 @@ import urllib.request
from typing import Dict, Any, Tuple, List
from ..exceptions import PackageError, SysCallError
-from ..general import SysCommand
from ..models.dataclasses import PackageSearch, PackageSearchResult, LocalPackage
+from ..pacman import run_pacman
BASE_URL_PKG_SEARCH = 'https://archlinux.org/packages/search/json/?name={package}'
# BASE_URL_PKG_CONTENT = 'https://archlinux.org/packages/search/json/'
@@ -98,7 +98,7 @@ def validate_package_list(packages :list) -> Tuple[list, list]:
def installed_package(package :str) -> LocalPackage:
package_info = {}
try:
- for line in SysCommand(f"pacman -Q --info {package}"):
+ for line in run_pacman(f"-Q --info {package}"):
if b':' in line:
key, value = line.decode().split(':', 1)
package_info[key.strip().lower().replace(' ', '_')] = value.strip()
diff --git a/archinstall/lib/pacman.py b/archinstall/lib/pacman.py
new file mode 100644
index 00000000..9c427aff
--- /dev/null
+++ b/archinstall/lib/pacman.py
@@ -0,0 +1,28 @@
+import logging
+import pathlib
+import time
+
+from .general import SysCommand
+from .output import log
+
+
+def run_pacman(args :str, default_cmd :str = 'pacman') -> SysCommand:
+ """
+ A centralized function to call `pacman` from.
+ It also protects us from colliding with other running pacman sessions (if used locally).
+ The grace period is set to 10 minutes before exiting hard if another pacman instance is running.
+ """
+ pacman_db_lock = pathlib.Path('/var/lib/pacman/db.lck')
+
+ if pacman_db_lock.exists():
+ log(_('Pacman is already running, waiting maximum 10 minutes for it to terminate.'), level=logging.WARNING, fg="red")
+
+ started = time.time()
+ while pacman_db_lock.exists():
+ time.sleep(0.25)
+
+ if time.time() - started > (60 * 10):
+ log(_('Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall.'), level=logging.WARNING, fg="red")
+ exit(1)
+
+ return SysCommand(f'{default_cmd} {args}')