index : archinstall32 | |
Archlinux32 installer | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | .editorconfig | 13 | ||||
-rw-r--r-- | .github/CODEOWNERS | 7 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | archinstall/__init__.py | 2 | ||||
-rw-r--r-- | archinstall/lib/disk.py | 36 | ||||
-rw-r--r-- | archinstall/lib/general.py | 54 | ||||
-rw-r--r-- | archinstall/lib/hardware.py | 18 | ||||
-rw-r--r-- | archinstall/lib/installer.py | 24 | ||||
-rw-r--r-- | archinstall/lib/luks.py | 25 | ||||
-rw-r--r-- | archinstall/lib/profiles.py | 22 | ||||
-rw-r--r-- | archinstall/lib/systemd.py | 16 | ||||
-rw-r--r-- | archinstall/lib/user_interaction.py | 13 | ||||
-rw-r--r-- | docs/archinstall/general.rst | 7 | ||||
-rw-r--r-- | docs/examples/python.rst | 4 | ||||
-rw-r--r-- | docs/index.rst | 4 | ||||
-rw-r--r-- | docs/installing/guided.rst | 6 | ||||
-rw-r--r-- | docs/installing/python.rst | 4 | ||||
-rw-r--r-- | examples/guided.py | 3 | ||||
-rw-r--r-- | profiles/applications/awesome.py | 6 | ||||
-rw-r--r-- | profiles/applications/cinnamon.py | 4 | ||||
-rw-r--r-- | profiles/applications/xfce4.py | 4 | ||||
-rw-r--r-- | profiles/awesome.py | 10 | ||||
-rw-r--r-- | profiles/cinnamon.py | 33 | ||||
-rw-r--r-- | profiles/desktop.py | 2 | ||||
-rw-r--r-- | profiles/xfce4.py | 34 |
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..59406405 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# http://editorconfig.org +# See coding conventions in CONTRIBUTING.md +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true + +[*.py] +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..4c93403a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,7 @@ +# As per https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#example-of-a-codeowners-file + +* @Torxed + +# Any PKGBUILD changes should tag grazzolini +/PKGBUILDs/ @grazzolini +/PKGBUILD @grazzolini @@ -48,7 +48,7 @@ with archinstall.Filesystem(harddrive, archinstall.GPT) as fs: installation.add_bootloader(harddrive.partition[0]) installation.add_additional_packages(['nano', 'wget', 'git']) - installation.install_profile('workstation') + installation.install_profile('awesome') installation.user_create('anton', 'test') installation.user_set_pw('root', 'toor') @@ -62,7 +62,7 @@ This installer will perform the following: * Installs a basic instance of Arch Linux *(base base-devel linux linux-firmware btrfs-progs efibootmgr)* * Installs and configures a bootloader to partition 0 on uefi. on bios it sets the root to partition 0. * Install additional packages *(nano, wget, git)* - * Installs a network-profile called [workstation](https://github.com/Torxed/archinstall/blob/master/profiles/workstation.json) *(more on network profiles in the docs)* + * Installs a network-profile called [awesome](https://github.com/Torxed/archinstall/blob/master/profiles/awesome.py) *(more on network profiles in the documentation)* > **Creating your own ISO with this script on it:** Follow [ArchISO](https://wiki.archlinux.org/index.php/archiso)'s guide on how to create your own ISO or use a pre-built [guided ISO](https://hvornum.se/archiso/) to skip the python installation step, or to create auto-installing ISO templates. Further down are examples and cheat sheets on how to create different live ISO's. diff --git a/archinstall/__init__.py b/archinstall/__init__.py index d4452d38..91cf17be 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -2,7 +2,7 @@ from .lib.general import * from .lib.disk import * from .lib.user_interaction import * from .lib.exceptions import * -from .lib.installer import * +from .lib.installer import __packages__, __base_packages__, Installer from .lib.profiles import * from .lib.luks import * from .lib.mirrors import * diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index fdc2fbc5..4ea9f214 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -73,26 +73,31 @@ class BlockDevice(): raise DiskError(f'Could not locate backplane info for "{self.path}"') if self.info['type'] == 'loop': - for drive in json.loads(b''.join(sys_command(f'losetup --json', hide_from_log=True)).decode('UTF_8'))['loopdevices']: + for drive in json.loads(b''.join(sys_command(['losetup', '--json'], hide_from_log=True)).decode('UTF_8'))['loopdevices']: if not drive['name'] == self.path: continue return drive['back-file'] elif self.info['type'] == 'disk': return self.path + elif self.info['type'][:4] == 'raid': + # This should catch /dev/md## raid devices + return self.path elif self.info['type'] == 'crypt': if 'pkname' not in self.info: raise DiskError(f'A crypt device ({self.path}) without a parent kernel device name.') return f"/dev/{self.info['pkname']}" + else: + log(f"Unknown blockdevice type for {self.path}: {self.info['type']}", level=LOG_LEVELS.Debug) # if not stat.S_ISBLK(os.stat(full_path).st_mode): # raise DiskError(f'Selected disk "{full_path}" is not a block device.') @property def partitions(self): - o = b''.join(sys_command(f'partprobe {self.path}')) + o = b''.join(sys_command(['partprobe', self.path])) #o = b''.join(sys_command('/usr/bin/lsblk -o name -J -b {dev}'.format(dev=dev))) - o = b''.join(sys_command(f'/usr/bin/lsblk -J {self.path}')) + o = b''.join(sys_command(['/usr/bin/lsblk', '-J', self.path])) if b'not a block device' in o: raise DiskError(f'Can not read partitions off something that isn\'t a block device: {self.path}') @@ -187,6 +192,17 @@ class Partition(): return f'Partition(path={self.path}, fs={self.filesystem}{mount_repr})' @property + def uuid(self) -> str: + """ + Returns the PARTUUID as returned by lsblk. + This is more reliable than relying on /dev/disk/by-partuuid as + it doesn't seam to be able to detect md raid partitions. + """ + lsblk = b''.join(sys_command(f'lsblk -J -o+PARTUUID {self.path}')) + for partition in json.loads(lsblk.decode('UTF-8'))['blockdevices']: + return partition.get('partuuid', None) + + @property def encrypted(self): return self._encrypted @@ -203,7 +219,7 @@ class Partition(): if not self._encrypted: return self.path else: - for blockdevice in json.loads(b''.join(sys_command('lsblk -J')).decode('UTF-8'))['blockdevices']: + for blockdevice in json.loads(b''.join(sys_command(['lsblk', '-J'])).decode('UTF-8'))['blockdevices']: if (parent := self.find_parent_of(blockdevice, os.path.basename(self.path))): return f"/dev/{parent}" # raise DiskError(f'Could not find appropriate parent for encrypted partition {self}') @@ -241,9 +257,15 @@ class Partition(): if self.allow_formatting is False: log(f"Partition {self} is not marked for formatting.", level=LOG_LEVELS.Debug) return False - elif self.target_mountpoint == '/boot' and self.has_content(): - log(f"Partition {self} is a boot partition and has content inside.", level=LOG_LEVELS.Debug) - return False + elif self.target_mountpoint == '/boot': + try: + if self.has_content(): + log(f"Partition {self} is a boot partition and has content inside.", level=LOG_LEVELS.Debug) + return False + except SysCallError as err: + log(err.message, LOG_LEVELS.Debug) + log(f"Partition {self} was identified as /boot but we could not mount to check for content, continuing!", level=LOG_LEVELS.Debug) + pass return True diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index f2a714e7..5b1b3c2a 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -76,7 +76,7 @@ class sys_command():#Thread): """ Stolen from archinstall_gui """ - def __init__(self, cmd, callback=None, start_callback=None, *args, **kwargs): + def __init__(self, cmd, callback=None, start_callback=None, peak_output=False, *args, **kwargs): kwargs.setdefault("worker_id", gen_uid()) kwargs.setdefault("emulate", False) kwargs.setdefault("suppress_errors", False) @@ -86,13 +86,22 @@ class sys_command():#Thread): if kwargs['emulate']: self.log(f"Starting command '{cmd}' in emulation mode.", level=LOG_LEVELS.Debug) - self.raw_cmd = cmd - try: - self.cmd = shlex.split(cmd) - except Exception as e: - raise ValueError(f'Incorrect string to split: {cmd}\n{e}') + if type(cmd) is list: + # if we get a list of arguments + self.raw_cmd = shlex.join(cmd) + self.cmd = cmd + else: + # else consider it a single shell string + # this should only be used if really necessary + self.raw_cmd = cmd + try: + self.cmd = shlex.split(cmd) + except Exception as e: + raise ValueError(f'Incorrect string to split: {cmd}\n{e}') + self.args = args self.kwargs = kwargs + self.peak_output = peak_output self.kwargs.setdefault("worker", None) self.callback = callback @@ -150,6 +159,38 @@ class sys_command():#Thread): 'exit_code': self.exit_code } + def peak(self, output :str): + if type(output) == bytes: + try: + output = output.decode('UTF-8') + except UnicodeDecodeError: + return None + + output = output.strip('\r\n ') + if len(output) <= 0: + return None + + if self.peak_output: + from .user_interaction import get_terminal_width + + # Move back to the beginning of the terminal + sys.stdout.flush() + sys.stdout.write("\033[%dG" % 0) + sys.stdout.flush() + + # Clear the line + sys.stdout.write(" " * get_terminal_width()) + sys.stdout.flush() + + # Move back to the beginning again + sys.stdout.flush() + sys.stdout.write("\033[%dG" % 0) + sys.stdout.flush() + + # And print the new output we're peaking on: + sys.stdout.write(output) + sys.stdout.flush() + def run(self): self.status = 'running' old_dir = os.getcwd() @@ -181,6 +222,7 @@ class sys_command():#Thread): for fileno, event in poller.poll(0.1): try: output = os.read(child_fd, 8192) + self.peak(output) self.trace_log += output except OSError: alive = False diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 3586ad09..10f3970f 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -3,9 +3,7 @@ from .general import sys_command from .networking import list_interfaces, enrichIfaceTypes def hasWifi(): - if 'WIRELESS' in enrichIfaceTypes(list_interfaces().values()).values(): - return True - return False + return 'WIRELESS' in enrichIfaceTypes(list_interfaces().values()).values() def hasAMDCPU(): if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode(): @@ -24,18 +22,12 @@ def graphicsDevices(): return cards def hasNvidiaGraphics(): - if [x for x in graphicsDevices() if 'nvidia' in x]: - return True - return False + return any('nvidia' in x for x in graphicsDevices()) def hasAmdGraphics(): - if [x for x in graphicsDevices() if 'amd' in x]: - return True - return False + return any('amd' in x for x in graphicsDevices()) def hasIntelGraphics(): - if [x for x in graphicsDevices() if 'intel' in x]: - return True - return False + return any('intel' in x for x in graphicsDevices()) -# TODO: Add more identifiers
\ No newline at end of file +# TODO: Add more identifiers diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index e38860d3..a99bc944 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -10,6 +10,10 @@ from .systemd import Networkd from .output import log, LOG_LEVELS from .storage import storage +# Any package that the Installer() is responsible for (optional and the default ones) +__packages__ = ["base", "base-devel", "linux", "linux-firmware", "efibootmgr", "nano", "ntp", "iwd"] +__base_packages__ = __packages__[:6] + class Installer(): """ `Installer()` is the wrapper for most basic installation steps. @@ -34,7 +38,7 @@ class Installer(): :type hostname: str, optional """ - def __init__(self, partition, boot_partition, *, base_packages='base base-devel linux linux-firmware efibootmgr nano', profile=None, mountpoint='/mnt', hostname='ArchInstalled', logdir=None, logfile=None): + def __init__(self, partition, boot_partition, *, base_packages=__base_packages__, profile=None, mountpoint='/mnt', hostname='ArchInstalled', logdir=None, logfile=None): self.profile = profile self.hostname = hostname self.mountpoint = mountpoint @@ -52,7 +56,7 @@ class Installer(): 'user' : False # Root counts as a user, if additional users are skipped. } - self.base_packages = base_packages.split(' ') + self.base_packages = base_packages.split(' ') if type(base_packages) is str else base_packages self.post_base_install = [] storage['session'] = self @@ -133,7 +137,7 @@ class Installer(): self.log(f'Installing packages: {packages}', level=LOG_LEVELS.Info) if (sync_mirrors := sys_command('/usr/bin/pacman -Syy')).exit_code == 0: - if (pacstrap := sys_command(f'/usr/bin/pacstrap {self.mountpoint} {" ".join(packages)}', **kwargs)).exit_code == 0: + if (pacstrap := sys_command(f'/usr/bin/pacstrap {self.mountpoint} {" ".join(packages)}', peak_output=True, **kwargs)).exit_code == 0: return True else: self.log(f'Could not strap in packages: {pacstrap.exit_code}', level=LOG_LEVELS.Info) @@ -388,18 +392,10 @@ class Installer(): break else: log(f"Identifying root partition by PART-UUID on {self.partition}, looking for '{os.path.basename(self.partition.path)}'.", level=LOG_LEVELS.Debug) - for root, folders, uids in os.walk('/dev/disk/by-partuuid'): - for uid in uids: - real_path = os.path.realpath(os.path.join(root, uid)) - - log(f"Checking root partition match {os.path.basename(real_path)} against {os.path.basename(self.partition.path)}: {os.path.basename(real_path) == os.path.basename(self.partition.path)}", level=LOG_LEVELS.Debug) - if not os.path.basename(real_path) == os.path.basename(self.partition.path): continue + entry.write(f'options root=PARTUUID={self.partition.uuid} rw intel_pstate=no_hwp\n') - entry.write(f'options root=PARTUUID={uid} rw intel_pstate=no_hwp\n') - - self.helper_flags['bootloader'] = bootloader - return True - break + self.helper_flags['bootloader'] = bootloader + return True raise RequirementError(f"Could not identify the UUID of {self.partition}, there for {self.mountpoint}/boot/loader/entries/arch.conf will be broken until fixed.") elif bootloader == "grub-install": diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 19c21795..62067ec1 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -1,4 +1,5 @@ import os +import shlex from .exceptions import * from .general import * from .disk import Partition @@ -64,9 +65,23 @@ class luks2(): with open(key_file, 'wb') as fh: fh.write(password) + cryptsetup_args = shlex.join([ + '/usr/bin/cryptsetup', + '--batch-mode', + '--verbose', + '--type', 'luks2', + '--pbkdf', 'argon2i', + '--hash', hash_type, + '--key-size', str(key_size), + '--iter-time', str(iter_time), + '--key-file', os.path.abspath(key_file), + '--use-urandom', + 'luksFormat', partition.path, + ]) + try: # Try to setup the crypt-device - cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + cmd_handle = sys_command(cryptsetup_args) except SysCallError as err: if err.exit_code == 256: log(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug) @@ -90,12 +105,12 @@ class luks2(): sys_command(f"cryptsetup close {child['name']}") # Then try again to set up the crypt-device - cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + cmd_handle = sys_command(cryptsetup_args) else: raise err - if b'Command successful.' not in b''.join(cmd_handle): - raise DiskError(f'Could not encrypt volume "{partition.path}": {o}') + if cmd_handle.exit_code != 0: + raise DiskError(f'Could not encrypt volume "{partition.path}": {cmd_output}') return key_file @@ -126,4 +141,4 @@ class luks2(): def format(self, path): if (handle := sys_command(f"/usr/bin/cryptsetup -q -v luksErase {path}")).exit_code != 0: - raise DiskError(f'Could not format {path} with {self.filesystem} because: {b"".join(handle)}')
\ No newline at end of file + raise DiskError(f'Could not format {path} with {self.filesystem} because: {b"".join(handle)}') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 77c9c6b2..70c21a67 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -193,6 +193,28 @@ class Profile(Script): if hasattr(imported, '_post_install'): return True + @property + def packages(self) -> list: + """ + Returns a list of packages baked into the profile definition. + If no package definition has been done, .packages() will return None. + """ + with open(self.path, 'r') as source: + source_data = source.read() + + # Some crude safety checks, make sure the imported profile has + # a __name__ check before importing. + # + # If the requirements are met, import with .py in the namespace to not + # trigger a traditional: + # if __name__ == 'moduleName' + if '__name__' in source_data and '__packages__' in source_data: + with self.load_instructions(namespace=f"{self.namespace}.py") as imported: + if hasattr(imported, '__packages__'): + return imported.__packages__ + return None + + class Application(Profile): def __repr__(self, *args, **kwargs): return f'Application({os.path.basename(self.profile)})' diff --git a/archinstall/lib/systemd.py b/archinstall/lib/systemd.py index edd75098..f2b7c9b3 100644 --- a/archinstall/lib/systemd.py +++ b/archinstall/lib/systemd.py @@ -26,15 +26,11 @@ class Ini(): return result class Systemd(Ini): - def __init__(self, *args, **kwargs): - """ - Placeholder class to do systemd specific setups. - """ - super(Systemd, self).__init__(*args, **kwargs) + """ + Placeholder class to do systemd specific setups. + """ class Networkd(Systemd): - def __init__(self, *args, **kwargs): - """ - Placeholder class to do systemd-network specific setups. - """ - super(Networkd, self).__init__(*args, **kwargs)
\ No newline at end of file + """ + Placeholder class to do systemd-network specific setups. + """ diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index f8b4d9c5..58f88bd2 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -274,9 +274,16 @@ def select_language(options, show_only_country_codes=True): print(' -- You can enter ? or help to search for more languages --') selected_language = input('Select one of the above keyboard languages (by number or full name): ') if selected_language.lower() in ('?', 'help'): - filter_string = input('Search for layout containing (example: "sv-"): ') - new_options = search_keyboard_layout(filter_string) - return select_language(new_options, show_only_country_codes=False) + while True: + filter_string = input('Search for layout containing (example: "sv-"): ') + new_options = list(search_keyboard_layout(filter_string)) + + if len(new_options) <= 0: + log(f"Search string '{filter_string}' yielded no results, please try another search or Ctrl+D to abort.", fg='yellow') + continue + + return select_language(new_options, show_only_country_codes=False) + elif selected_language.isdigit() and (pos := int(selected_language)) <= len(languages)-1: selected_language = languages[pos] # I'm leaving "options" on purpose here. diff --git a/docs/archinstall/general.rst b/docs/archinstall/general.rst index 349393de..e5459749 100644 --- a/docs/archinstall/general.rst +++ b/docs/archinstall/general.rst @@ -22,7 +22,10 @@ Locale related .. autofunction:: archinstall.search_keyboard_layout -.. autofunction:: archinstall.set_keyboard_layout +.. autofunction:: archinstall.set_keyboard_language + +.. + autofunction:: archinstall.Installer.set_keyboard_layout Services ======== @@ -34,7 +37,7 @@ Mirrors .. autofunction:: archinstall.filter_mirrors_by_region -.. autofunction:: archinstall.add_custom_mirror +.. autofunction:: archinstall.add_custom_mirrors .. autofunction:: archinstall.insert_mirrors diff --git a/docs/examples/python.rst b/docs/examples/python.rst index 04f2f43a..f6388738 100644 --- a/docs/examples/python.rst +++ b/docs/examples/python.rst @@ -9,9 +9,9 @@ The way the library is invoked in module mode is limited to executing scripts un It's there for important to place any script or profile you wish to invoke in the examples folder prior to building and installing. Pre-requisites -------------- +-------------- -We'll assume you've followed the `installing.python.manual`_ method. +We'll assume you've followed the :ref:`installing.python.manual` method. Before actually installing the library, you will need to place your custom installer-scripts under `./archinstall/examples/` as a python file. More on how you create these in the next section. diff --git a/docs/index.rst b/docs/index.rst index c03cc451..fea8f788 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,7 +2,7 @@ python-archinstall Documentation ================================ | **python-archinstall** *(or, archinstall for short)* is a helper library to install Arch Linux and manage services, packages and other things. -| It comes packaged with different pre-configured installers, such as the `installing.guided`_ installer. +| It comes packaged with different pre-configured installers, such as the :ref:`guided <installing.guided>` installer. | | A demo can be viewed here: `https://www.youtube.com/watch?v=9Xt7X_Iqg6E <https://www.youtube.com/watch?v=9Xt7X_Iqg6E>`_ which uses the default guided installer. @@ -43,12 +43,14 @@ Some of the features of Archinstall are: examples/python examples/binary +.. examples/scripting .. toctree:: :maxdepth: 3 :caption: Programming Guide +.. programming_guide/requirements programming_guide/basic_concept diff --git a/docs/installing/guided.rst b/docs/installing/guided.rst index 92324589..40d86055 100644 --- a/docs/installing/guided.rst +++ b/docs/installing/guided.rst @@ -1,5 +1,3 @@ -.. _installing.guided: - Guided installation =================== @@ -100,6 +98,8 @@ Default is :code:`Archinstall` The hostname in which the machine will identify itself on the local network. This step is optional, but a default hostname of `Archinstall` will be set if none is selected. +.. _root_password: + Root password ------------- @@ -115,7 +115,7 @@ Super User (sudo) ----------------- .. warning:: - This step only applies if you correctly skipped the previous step :ref:`root_password`_ which also makes this step mandatory. + This step only applies if you correctly skipped :ref:`the previous step <root_password>` which also makes this step mandatory. If the previous step was skipped, and only if it is skipped. This step enables you to create a :code:`sudo` enabled user with a password. diff --git a/docs/installing/python.rst b/docs/installing/python.rst index 44606166..94cfb243 100644 --- a/docs/installing/python.rst +++ b/docs/installing/python.rst @@ -10,7 +10,7 @@ But the library can be installed manually as well. This is not required if you're running archinstall on a pre-built ISO. The installation is only required if you're creating your own scripted installations. Using pacman ----------- +------------ Archinstall is on the `official repositories <https://wiki.archlinux.org/index.php/Official_repositories>`_. @@ -44,7 +44,7 @@ Or as a user module: Which will allow you to start using the library. -.. _installing.python.manual +.. _installing.python.manual: Manual installation ------------------- diff --git a/examples/guided.py b/examples/guided.py index 85492a81..81cc2991 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -20,6 +20,9 @@ def sig_handler(sig, frame): original_sigint_handler = signal.getsignal(signal.SIGINT) signal.signal(signal.SIGINT, sig_handler) +if archinstall.arguments.get('help'): + print("See `man archinstall` for help.") + exit(0) def ask_user_questions(): """ diff --git a/profiles/applications/awesome.py b/profiles/applications/awesome.py index 578f246e..b8d779c0 100644 --- a/profiles/applications/awesome.py +++ b/profiles/applications/awesome.py @@ -1,10 +1,10 @@ import archinstall +__packages__ = ["awesome", "xorg-xrandr", "xterm", "feh", "slock", "terminus-font", "gnu-free-fonts", "ttf-liberation", "xsel"] + installation.install_profile('xorg') -installation.add_additional_packages( - "awesome xorg-xrandr xterm feh slock terminus-font gnu-free-fonts ttf-liberation xsel" -) +installation.add_additional_packages(__packages__) with open(f'{installation.mountpoint}/etc/X11/xinit/xinitrc', 'r') as xinitrc: xinitrc_data = xinitrc.read() diff --git a/profiles/applications/cinnamon.py b/profiles/applications/cinnamon.py new file mode 100644 index 00000000..af1cbee2 --- /dev/null +++ b/profiles/applications/cinnamon.py @@ -0,0 +1,4 @@ +import archinstall + +installation.add_additional_packages("cinnamon system-config-printer gnome-keyring gnome-terminal blueberry metacity lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings") +# We'll create a cinnamon-minimal later, but for now, we'll avoid issues by giving more than we need. diff --git a/profiles/applications/xfce4.py b/profiles/applications/xfce4.py new file mode 100644 index 00000000..6d6f8f7c --- /dev/null +++ b/profiles/applications/xfce4.py @@ -0,0 +1,4 @@ +import archinstall + +installation.add_additional_packages("xfce4 xfce4-goodies lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings") +# We'll create a xfce4-minimal later, but for now, we'll avoid issues by giving more than we need. diff --git a/profiles/awesome.py b/profiles/awesome.py index b914b175..8004fc62 100644 --- a/profiles/awesome.py +++ b/profiles/awesome.py @@ -2,6 +2,7 @@ import archinstall +__packages__ = ['nano', 'nemo', 'gpicview-gtk3', 'chromium', 'openssh', 'sshfs', 'htop', 'scrot', 'wget'] def _prep_function(*args, **kwargs): """ @@ -28,14 +29,7 @@ if __name__ == 'awesome': awesome = archinstall.Application(installation, 'awesome') awesome.install() - # Then setup and configure the desktop environment: awesome - editor = "nano" - filebrowser = "nemo gpicview-gtk3" - webbrowser = "chromium" # TODO: Ask the user to select one instead - utils = "openssh sshfs htop scrot wget" - - - installation.add_additional_packages(f"{webbrowser} {utils} {filebrowser} {editor}") + installation.add_additional_packages(__packages__) alacritty = archinstall.Application(installation, 'alacritty') alacritty.install() diff --git a/profiles/cinnamon.py b/profiles/cinnamon.py new file mode 100644 index 00000000..e9c5d085 --- /dev/null +++ b/profiles/cinnamon.py @@ -0,0 +1,33 @@ +# A desktop environment using "Cinnamon" + +import archinstall + +def _prep_function(*args, **kwargs): + """ + Magic function called by the importing installer + before continuing any further. It also avoids executing any + other code in this stage. So it's a safe way to ask the user + for more input before any other installer steps start. + """ + + # Cinnamon optionally supports xorg, we'll install it since it also + # includes graphic driver setups (this might change in the future) + profile = archinstall.Profile(None, 'xorg') + with profile.load_instructions(namespace='xorg.py') as imported: + if hasattr(imported, '_prep_function'): + return imported._prep_function() + else: + print('Deprecated (??): xorg profile has no _prep_function() anymore') + +# Ensures that this code only gets executed if executed +# through importlib.util.spec_from_file_location("cinnamon", "/somewhere/cinnamon.py") +# or through conventional import cinnamon +if __name__ == 'cinnamon': + # Install dependency profiles + installation.install_profile('xorg') + + # Install the application cinnamon from the template under /applications/ + cinnamon = archinstall.Application(installation, 'cinnamon') + cinnamon.install() + + installation.enable_service('lightdm') # Light Display Manager diff --git a/profiles/desktop.py b/profiles/desktop.py index 869cf0a0..0c89e543 100644 --- a/profiles/desktop.py +++ b/profiles/desktop.py @@ -10,7 +10,7 @@ def _prep_function(*args, **kwargs): for more input before any other installer steps start. """ - supported_desktops = ['gnome', 'kde', 'awesome'] + supported_desktops = ['gnome', 'kde', 'awesome', 'xfce4', 'cinnamon'] desktop = archinstall.generic_select(supported_desktops, 'Select your desired desktop environment: ') # Temporarly store the selected desktop profile diff --git a/profiles/xfce4.py b/profiles/xfce4.py new file mode 100644 index 00000000..1cc4a62d --- /dev/null +++ b/profiles/xfce4.py @@ -0,0 +1,34 @@ + +# A desktop environment using "Xfce4" + +import archinstall + +def _prep_function(*args, **kwargs): + """ + Magic function called by the importing installer + before continuing any further. It also avoids executing any + other code in this stage. So it's a safe way to ask the user + for more input before any other installer steps start. + """ + + # Gnome optionally supports xorg, we'll install it since it also + # includes graphic driver setups (this might change in the future) + profile = archinstall.Profile(None, 'xorg') + with profile.load_instructions(namespace='xorg.py') as imported: + if hasattr(imported, '_prep_function'): + return imported._prep_function() + else: + print('Deprecated (??): xorg profile has no _prep_function() anymore') + +# Ensures that this code only gets executed if executed +# through importlib.util.spec_from_file_location("xfce4", "/somewhere/xfce4.py") +# or through conventional import xfce4 +if __name__ == 'xfce4': + # Install dependency profiles + installation.install_profile('xorg') + + # Install the application xfce4 from the template under /applications/ + xfce = archinstall.Application(installation, 'xfce4') + xfce.install() + + installation.enable_service('lightdm') # Light Display Manager |