Repository: archlinux/archinstall

Issue:
ArchInstall should expose a flag to install a system with testing repo enabled
For trying things out on non-production machines with the testing repository, it'd be neat to be able to do a full system install with the unstable packages available in testing in a VM by doing something like `archinstall --testing`. This would simply make sure that this repository is not commented out in /etc/pacman.conf:

```
[testing]
Include = /etc/pacman.d/mirrorlist
```

Probably a low-priority feature request, but a nice to have.


Discussion:
I think this would be a great feature, and hopefully could be a part of #814.

For example, a new function, something like `custom_repos()` could replace `add_custom_mirrors` in `mirrors.py` and take as parameters: A list/dict in the same format as used by `add_custom_mirrors`, an option to choose prepending or appending to the mirror definitions in `/etc/pacman.conf`, and a boolean specifying whether the custom mirror definitions should be copied to the installed system (defaults as true). In the case of [testing], this could be a special case where the definition is uncommented rather than prepended (since it's already defined by default).

Resolving patch:
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -1,6 +1,7 @@
 import time
 import logging
 import os
+import re
 import shutil
 import shlex
 import pathlib
@@ -288,6 +289,32 @@ def mount(self, partition :Partition, mountpoint :str, create_mountpoint :bool =
 	def post_install_check(self, *args :str, **kwargs :str) -> List[str]:
 		return [step for step, flag in self.helper_flags.items() if flag is False]
 
+	def enable_testing_repositories(self):
+		# 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
+
+		# Read in the lines from the original file
+		with open("/etc/pacman.conf", "r") as pacman_conf:
+			lines = pacman_conf.readlines()
+
+		# Open the file again in write mode, to replace the contents
+		with open("/etc/pacman.conf", "w") as pacman_conf:
+			for line in lines:
+				if pattern.match(line):
+					# If this is the [] block containing 'testing', uncomment it and set the matched tracking boolean.
+					pacman_conf.write(line.lstrip('#'))
+					matched = True
+				elif matched:
+					# The previous line was a match for [.*testing.*].
+					# This means we're on a line that looks like '#Include = /etc/pacman.d/mirrorlist'
+					pacman_conf.write(line.lstrip('#'))
+					matched = False # Reset the state of matched to False.
+				else:
+					pacman_conf.write(line)
+
 	def pacstrap(self, *packages :str, **kwargs :str) -> bool:
 		if type(packages[0]) in (list, tuple):
 			packages = packages[0]
@@ -533,7 +560,7 @@ def mkinitcpio(self, *flags :str) -> bool:
 
 		return SysCommand(f'/usr/bin/arch-chroot {self.target} mkinitcpio {" ".join(flags)}').exit_code == 0
 
-	def minimal_installation(self) -> bool:
+	def minimal_installation(self, testing=False) -> bool:
 		# Add necessary packages if encrypting the drive
 		# (encrypted partitions default to btrfs for now, so we need btrfs-progs)
 		# TODO: Perhaps this should be living in the function which dictates
@@ -582,6 +609,14 @@ def minimal_installation(self) -> bool:
 			else:
 				self.log(f"Unknown CPU vendor '{vendor}' detected. Archinstall won't install any ucode.", level=logging.DEBUG)
 
+		# Determine whether to enable testing repositories before running pacstrap if testing flag is set.
+		# This action takes place on the host system as pacstrap copies over package repository lists.
+		if testing:
+			self.log("The testing flag is set. This system will be installed with testing repositories enabled.")
+			self.enable_testing_repositories()
+		else:
+			self.log("The testing flag is not set. This system will be installed without testing repositories enabled.")
+
 		self.pacstrap(self.base_packages)
 		self.helper_flags['base-strapped'] = True
 
diff --git a/examples/guided.py b/examples/guided.py
--- a/examples/guided.py
+++ b/examples/guided.py
@@ -144,7 +144,7 @@ def perform_installation(mountpoint):
 		if archinstall.arguments.get('mirror-region', None):
 			archinstall.use_mirrors(archinstall.arguments['mirror-region'])  # Set the mirrors for the live medium
 
-		if installation.minimal_installation():
+		if installation.minimal_installation(archinstall.arguments.get('testing', False)):
 			installation.set_locale(archinstall.arguments['sys-language'], archinstall.arguments['sys-encoding'].upper())
 			installation.set_hostname(archinstall.arguments['hostname'])
 			if archinstall.arguments['mirror-region'].get("mirrors", None) is not None:


Test patch: