Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--archinstall/__init__.py2
-rw-r--r--archinstall/lib/disk.py61
-rw-r--r--archinstall/lib/general.py18
-rw-r--r--archinstall/lib/hardware.py7
-rw-r--r--archinstall/lib/installer.py30
-rw-r--r--archinstall/lib/profiles.py22
-rw-r--r--archinstall/lib/user_interaction.py4
-rw-r--r--docs/archinstall/general.rst7
-rw-r--r--docs/index.rst2
-rw-r--r--docs/installing/guided.rst2
-rw-r--r--examples/guided.py14
-rw-r--r--examples/minimal.py2
-rw-r--r--profiles/52-54-00-12-34-56.py2
-rw-r--r--profiles/applications/awesome.py6
-rw-r--r--profiles/applications/xfce4.py3
-rw-r--r--profiles/awesome.py10
-rw-r--r--profiles/desktop.py2
-rw-r--r--profiles/xfce4.py34
19 files changed, 173 insertions, 59 deletions
diff --git a/README.md b/README.md
index c1ec746e..5451b55f 100644
--- a/README.md
+++ b/README.md
@@ -57,10 +57,10 @@ with archinstall.Filesystem(harddrive, archinstall.GPT) as fs:
This installer will perform the following:
* Prompt the user to select a disk and disk-password
- * Proceed to wipe the selected disk with a `GPT` partition table.
+ * Proceed to wipe the selected disk with a `GPT` partition table on a UEFI system and MBR on a bios system.
* Sets up a default 100% used disk with encryption.
* Installs a basic instance of Arch Linux *(base base-devel linux linux-firmware btrfs-progs efibootmgr)*
- * Installs and configures a bootloader to partition 0.
+ * 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 [awesome](https://github.com/Torxed/archinstall/blob/master/profiles/awesome.py) *(more on network profiles in the documentation)*
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 10d4ef5a..4ea9f214 100644
--- a/archinstall/lib/disk.py
+++ b/archinstall/lib/disk.py
@@ -5,6 +5,7 @@ from .exceptions import DiskError
from .general import *
from .output import log, LOG_LEVELS
from .storage import storage
+from .hardware import hasUEFI
ROOT_DIR_PATTERN = re.compile('^.*?/devices')
GPT = 0b00000001
@@ -72,7 +73,7 @@ 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']
@@ -93,10 +94,10 @@ class BlockDevice():
@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}')
@@ -218,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}')
@@ -411,7 +412,7 @@ class Filesystem():
# TODO:
# When instance of a HDD is selected, check all usages and gracefully unmount them
# as well as close any crypto handles.
- def __init__(self, blockdevice, mode=GPT):
+ def __init__(self, blockdevice,mode):
self.blockdevice = blockdevice
self.mode = mode
@@ -424,6 +425,11 @@ class Filesystem():
return self
else:
raise DiskError(f'Problem setting the partition format to GPT:', f'/usr/bin/parted -s {self.blockdevice.device} mklabel gpt')
+ elif self.mode == MBR:
+ if sys_command(f'/usr/bin/parted -s {self.blockdevice.device} mklabel msdos').exit_code == 0:
+ return self
+ else:
+ raise DiskError(f'Problem setting the partition format to GPT:', f'/usr/bin/parted -s {self.blockdevice.device} mklabel msdos')
else:
raise DiskError(f'Unknown mode selected to format in: {self.mode}')
@@ -466,28 +472,39 @@ class Filesystem():
def use_entire_disk(self, root_filesystem_type='ext4'):
log(f"Using and formatting the entire {self.blockdevice}.", level=LOG_LEVELS.Debug)
- self.add_partition('primary', start='1MiB', end='513MiB', format='fat32')
- self.set_name(0, 'EFI')
- self.set(0, 'boot on')
- # TODO: Probably redundant because in GPT mode 'esp on' is an alias for "boot on"?
- # https://www.gnu.org/software/parted/manual/html_node/set.html
- self.set(0, 'esp on')
- self.add_partition('primary', start='513MiB', end='100%')
-
- self.blockdevice.partition[0].filesystem = 'vfat'
- self.blockdevice.partition[1].filesystem = root_filesystem_type
- log(f"Set the root partition {self.blockdevice.partition[1]} to use filesystem {root_filesystem_type}.", level=LOG_LEVELS.Debug)
-
- self.blockdevice.partition[0].target_mountpoint = '/boot'
- self.blockdevice.partition[1].target_mountpoint = '/'
-
- self.blockdevice.partition[0].allow_formatting = True
- self.blockdevice.partition[1].allow_formatting = True
+ if hasUEFI():
+ self.add_partition('primary', start='1MiB', end='513MiB', format='fat32')
+ self.set_name(0, 'EFI')
+ self.set(0, 'boot on')
+ # TODO: Probably redundant because in GPT mode 'esp on' is an alias for "boot on"?
+ # https://www.gnu.org/software/parted/manual/html_node/set.html
+ self.set(0, 'esp on')
+ self.add_partition('primary', start='513MiB', end='100%')
+
+ self.blockdevice.partition[0].filesystem = 'vfat'
+ self.blockdevice.partition[1].filesystem = root_filesystem_type
+ log(f"Set the root partition {self.blockdevice.partition[1]} to use filesystem {root_filesystem_type}.", level=LOG_LEVELS.Debug)
+
+ self.blockdevice.partition[0].target_mountpoint = '/boot'
+ self.blockdevice.partition[1].target_mountpoint = '/'
+
+ self.blockdevice.partition[0].allow_formatting = True
+ self.blockdevice.partition[1].allow_formatting = True
+ else:
+ #we don't need a seprate boot partition it would be a waste of space
+ self.add_partition('primary', start='1MB', end='100%')
+ self.blockdevice.partition[0].filesystem=root_filesystem_type
+ log(f"Set the root partition {self.blockdevice.partition[0]} to use filesystem {root_filesystem_type}.", level=LOG_LEVELS.Debug)
+ self.blockdevice.partition[0].target_mountpoint = '/'
+ self.blockdevice.partition[0].allow_formatting = True
def add_partition(self, type, start, end, format=None):
log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info)
previous_partitions = self.blockdevice.partitions
+ if self.mode == MBR:
+ if len(self.blockdevice.partitions)>3:
+ DiskError("Too many partitions on disk, MBR disks can only have 3 parimary partitions")
if format:
partitioning = self.parted(f'{self.blockdevice.device} mkpart {type} {format} {start} {end}') == 0
else:
diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py
index f2a714e7..ae2501c2 100644
--- a/archinstall/lib/general.py
+++ b/archinstall/lib/general.py
@@ -86,11 +86,19 @@ 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
diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py
index 5828fd09..10f3970f 100644
--- a/archinstall/lib/hardware.py
+++ b/archinstall/lib/hardware.py
@@ -1,10 +1,15 @@
-import os
+import os, subprocess
from .general import sys_command
from .networking import list_interfaces, enrichIfaceTypes
def hasWifi():
return 'WIRELESS' in enrichIfaceTypes(list_interfaces().values()).values()
+def hasAMDCPU():
+ if subprocess.check_output("lscpu | grep AMD", shell=True).strip().decode():
+ return True
+ return False
+
def hasUEFI():
return os.path.isdir('/sys/firmware/efi')
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index a4321893..c0323c61 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -1,4 +1,4 @@
-import os, stat, time, shutil, pathlib
+import os, stat, time, shutil, pathlib, subprocess
from .exceptions import *
from .disk import *
@@ -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
@@ -67,9 +71,11 @@ class Installer():
log(*args, level=level, **kwargs)
def __enter__(self, *args, **kwargs):
- self.partition.mount(self.mountpoint)
- os.makedirs(f'{self.mountpoint}/boot', exist_ok=True)
- self.boot_partition.mount(f'{self.mountpoint}/boot')
+ if hasUEFI():
+ # on bios we don't have a boot partition
+ self.partition.mount(self.mountpoint)
+ os.makedirs(f'{self.mountpoint}/boot', exist_ok=True)
+ self.boot_partition.mount(f'{self.mountpoint}/boot')
return self
def __exit__(self, *args, **kwargs):
@@ -329,6 +335,8 @@ class Installer():
self.log(f'Adding bootloader {bootloader} to {self.boot_partition}', level=LOG_LEVELS.Info)
if bootloader == 'systemd-bootctl':
+ if not hasUEFI():
+ raise HardwareIncompatibilityError
# TODO: Ideally we would want to check if another config
# points towards the same disk and/or partition.
# And in which case we should do some clean up.
@@ -390,6 +398,16 @@ class Installer():
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":
+ if hasUEFI():
+ o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB'))
+ sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg')
+ else:
+ root_device = subprocess.check_output(f'basename "$(readlink -f "/sys/class/block/{self.partition.path.strip("/dev/")}/..")',shell=True).decode().strip()
+ if root_device == "block":
+ root_device = f"{self.partition.path}"
+ o = b''.join(sys_command(f'/usr/bin/arch-chroot {self.mountpoint} grub-install --target=--target=i386-pc /dev/{root_device}'))
+ sys_command('/usr/bin/arch-chroot grub-mkconfig -o /boot/grub/grub.cfg')
else:
raise RequirementError(f"Unknown (or not yet implemented) bootloader added to add_bootloader(): {bootloader}")
diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py
index 08b1d618..8198ff11 100644
--- a/archinstall/lib/profiles.py
+++ b/archinstall/lib/profiles.py
@@ -178,6 +178,28 @@ class Profile(Script):
return True
return False
+ @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/user_interaction.py b/archinstall/lib/user_interaction.py
index 630862ee..58f88bd2 100644
--- a/archinstall/lib/user_interaction.py
+++ b/archinstall/lib/user_interaction.py
@@ -94,10 +94,12 @@ def ask_to_configure_network():
# Optionally configure one network interface.
#while 1:
# {MAC: Ifname}
- interfaces = {'ISO-CONFIG' : 'Copy ISO network configuration to installation', **list_interfaces()}
+ interfaces = {'ISO-CONFIG' : 'Copy ISO network configuration to installation','NetworkManager':'Use NetworkManager to control and manage your internet connection', **list_interfaces()}
nic = generic_select(interfaces.values(), "Select one network interface to configure (leave blank to skip): ")
if nic and nic != 'Copy ISO network configuration to installation':
+ if nic == 'Use NetworkManager to control and manage your internet connection':
+ return {'nic': nic,'NetworkManager':True}
mode = generic_select(['DHCP (auto detect)', 'IP (static)'], f"Select which mode to configure for {nic}: ")
if mode == 'IP (static)':
while 1:
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/index.rst b/docs/index.rst
index eef368c5..fea8f788 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -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 7ce081ca..40d86055 100644
--- a/docs/installing/guided.rst
+++ b/docs/installing/guided.rst
@@ -1,5 +1,3 @@
-.. _installing.guided:
-
Guided installation
===================
diff --git a/examples/guided.py b/examples/guided.py
index 723eed5b..eba6e142 100644
--- a/examples/guided.py
+++ b/examples/guided.py
@@ -1,5 +1,6 @@
import getpass, time, json, sys, signal, os
import archinstall
+from archinstall.lib.hardware import hasUEFI
"""
This signal-handler chain (and global variable)
@@ -247,7 +248,12 @@ def perform_installation_steps():
Setup the blockdevice, filesystem (and optionally encryption).
Once that's done, we'll hand over to perform_installation()
"""
- with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs:
+ # maybe we can ask the user what they would prefer on uefi systems?
+ if hasUEFI():
+ mode = archinstall.GPT
+ else:
+ mode = archinstall.MBR
+ with archinstall.Filesystem(archinstall.arguments['harddrive'],mode) as fs:
# Wipe the entire drive if the disk flag `keep_partitions`is False.
if archinstall.arguments['harddrive'].keep_partitions is False:
fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs'))
@@ -314,7 +320,9 @@ def perform_installation(device, boot_partition, language, mirrors):
# Perform a copy of the config
if archinstall.arguments.get('nic', None) == 'Copy ISO network configuration to installation':
installation.copy_ISO_network_config(enable_services=True) # Sources the ISO network configuration to the install medium.
-
+ elif archinstall.arguments.get('nic',{}).get('NetworkManager',False):
+ installation.add_additional_packages("networkmanager")
+ installation.enable_service('NetworkManager.service')
# Otherwise, if a interface was selected, configure that interface
elif archinstall.arguments.get('nic', None):
installation.configure_nic(**archinstall.arguments.get('nic', {}))
@@ -342,4 +350,4 @@ def perform_installation(device, boot_partition, language, mirrors):
ask_user_questions()
-perform_installation_steps() \ No newline at end of file
+perform_installation_steps()
diff --git a/examples/minimal.py b/examples/minimal.py
index 664bad0d..b5bb34e0 100644
--- a/examples/minimal.py
+++ b/examples/minimal.py
@@ -8,7 +8,7 @@ archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_error
harddrive = archinstall.select_disk(archinstall.all_disks())
disk_password = getpass.getpass(prompt='Disk password (won\'t echo): ')
-with archinstall.Filesystem(harddrive, archinstall.GPT) as fs:
+with archinstall.Filesystem(harddrive) as fs:
# Use the entire disk instead of setting up partitions on your own
fs.use_entire_disk('luks2')
diff --git a/profiles/52-54-00-12-34-56.py b/profiles/52-54-00-12-34-56.py
index 679c6721..ed2c9d78 100644
--- a/profiles/52-54-00-12-34-56.py
+++ b/profiles/52-54-00-12-34-56.py
@@ -11,7 +11,7 @@ archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_error
harddrive = archinstall.all_disks()['/dev/sda']
disk_password = '1234'
-with archinstall.Filesystem(harddrive, archinstall.GPT) as fs:
+with archinstall.Filesystem(harddrive) as fs:
# Use the entire disk instead of setting up partitions on your own
fs.use_entire_disk('luks2')
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/xfce4.py b/profiles/applications/xfce4.py
new file mode 100644
index 00000000..74bf5990
--- /dev/null
+++ b/profiles/applications/xfce4.py
@@ -0,0 +1,3 @@
+import archinstall
+
+installation.add_additional_packages("xfce4 xfce4-goodies lightdm") # 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/desktop.py b/profiles/desktop.py
index 869cf0a0..331adf59 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']
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