More formatting fixes
This commit is contained in:
parent
e966bef891
commit
6057203e5b
|
|
@ -1,57 +1,79 @@
|
||||||
# Contributing to archinstall
|
# Contributing to archinstall
|
||||||
|
|
||||||
Any contributions through pull requests are welcome as this project aims to be a community based project to ease some Arch Linux installation steps. Bear in mind that in the future this repo might be transferred to the official [GitLab repo under Arch Linux](http://gitlab.archlinux.org/archlinux/) *(if GitLab becomes open to the general public)*.
|
Any contributions through pull requests are welcome as this project aims to be a community based project to ease some
|
||||||
|
Arch Linux installation steps. Bear in mind that in the future this repo might be transferred to the
|
||||||
|
official [GitLab repo under Arch Linux](http://gitlab.archlinux.org/archlinux/) *(if GitLab becomes open to the general
|
||||||
|
public)*.
|
||||||
|
|
||||||
Therefore guidelines and style changes to the code might come into affect as well as guidelines surrounding bug reporting and discussions.
|
Therefore guidelines and style changes to the code might come into affect as well as guidelines surrounding bug
|
||||||
|
reporting and discussions.
|
||||||
|
|
||||||
## Branches
|
## Branches
|
||||||
|
|
||||||
`master` is currently the default branch, and that's where all future feature work is being done, this means that `master` is a living entity and will most likely never be in a fully stable state. For stable releases, please see the tagged commits.
|
`master` is currently the default branch, and that's where all future feature work is being done, this means
|
||||||
|
that `master` is a living entity and will most likely never be in a fully stable state. For stable releases, please see
|
||||||
|
the tagged commits.
|
||||||
|
|
||||||
Patch releases will be done against their own branches, branched from stable tagged releases and will be named according to the version it will become on release *(Patches to `v2.1.4` will be done on branch `v2.1.5` for instance)*.
|
Patch releases will be done against their own branches, branched from stable tagged releases and will be named according
|
||||||
|
to the version it will become on release *(Patches to `v2.1.4` will be done on branch `v2.1.5` for instance)*.
|
||||||
|
|
||||||
## Discussions
|
## Discussions
|
||||||
|
|
||||||
Currently, questions, bugs and suggestions should be reported through [GitHub issue tracker](https://github.com/archlinux/archinstall/issues).<br>
|
Currently, questions, bugs and suggestions should be reported
|
||||||
|
through [GitHub issue tracker](https://github.com/archlinux/archinstall/issues).<br>
|
||||||
For less formal discussions there are also a [archinstall Discord server](https://discord.gg/cqXU88y).
|
For less formal discussions there are also a [archinstall Discord server](https://discord.gg/cqXU88y).
|
||||||
|
|
||||||
## Coding convention
|
## Coding convention
|
||||||
|
|
||||||
Archinstall's goal is to follow [PEP8](https://www.python.org/dev/peps/pep-0008/) as best as it can with some minor exceptions.<br>
|
Archinstall's goal is to follow [PEP8](https://www.python.org/dev/peps/pep-0008/) as best as it can with some minor
|
||||||
|
exceptions.<br>
|
||||||
The exceptions to PEP8 are:
|
The exceptions to PEP8 are:
|
||||||
|
|
||||||
* Archinstall uses [tabs instead of spaces](https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces) simply to make it easier for non-IDE developers to navigate the code *(Tab display-width should be equal to 4 spaces)*. Exception to the rule are comments that need fine-tuned indentation for documentation purposes.
|
* Archinstall uses [tabs instead of spaces](https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces) simply to make it
|
||||||
* [Line length](https://www.python.org/dev/peps/pep-0008/#maximum-line-length) should aim for no more than 100 characters, but not strictly enforced.
|
easier for non-IDE developers to navigate the code *(Tab display-width should be equal to 4 spaces)*. Exception to the
|
||||||
* [Line breaks before/after binary operator](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator) is not enforced, as long as the style of line breaks are consistent within the same code block.
|
rule are comments that need fine-tuned indentation for documentation purposes.
|
||||||
* Archinstall should always be saved with **Unix-formatted line endings** and no other platform-specific formats.
|
* [Line length](https://www.python.org/dev/peps/pep-0008/#maximum-line-length) should aim for no more than 100
|
||||||
* [Blank lines](https://www.python.org/dev/peps/pep-0008/#blank-lines) before/after imports and functions are not followed and discouraged. One space is commonly used in archinstall.
|
characters, but not strictly enforced.
|
||||||
* Multiple [Imports](https://www.python.org/dev/peps/pep-0008/#imports) on the same line is allowed, but more than five imports should be avoided on any given line. This simply saves up some space at the top of the file *(for non-IDE developers)* and will not be enforced.
|
* [Line breaks before/after binary operator](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
|
||||||
* [String quotes](https://www.python.org/dev/peps/pep-0008/#string-quotes) follow PEP8, the exception being when creating formatted strings, double-quoted strings are *preferred* but not required on the outer edges *(Example: `f"Welcome {name}"` rather than `f'Welcome {name}'`)*.
|
is not enforced, as long as the style of line breaks are consistent within the same code block.
|
||||||
|
* Archinstall should always be saved with **Unix-formatted line endings** and no other platform-specific formats.
|
||||||
|
* [Blank lines](https://www.python.org/dev/peps/pep-0008/#blank-lines) before/after imports and functions are not
|
||||||
|
followed and discouraged. One space is commonly used in archinstall.
|
||||||
|
* Multiple [Imports](https://www.python.org/dev/peps/pep-0008/#imports) on the same line is allowed, but more than five
|
||||||
|
imports should be avoided on any given line. This simply saves up some space at the top of the file *(for non-IDE
|
||||||
|
developers)* and will not be enforced.
|
||||||
|
* [String quotes](https://www.python.org/dev/peps/pep-0008/#string-quotes) follow PEP8, the exception being when
|
||||||
|
creating formatted strings, double-quoted strings are *preferred* but not required on the outer edges *(
|
||||||
|
Example: `f"Welcome {name}"` rather than `f'Welcome {name}'`)*.
|
||||||
|
|
||||||
Most of these style guidelines have been put into place after the fact *(in an attempt to clean up the code)*.<br>
|
Most of these style guidelines have been put into place after the fact *(in an attempt to clean up the code)*.<br>
|
||||||
There might therefore be older code which does not follow the coding convention and the code is subject to change.
|
There might therefore be older code which does not follow the coding convention and the code is subject to change.
|
||||||
|
|
||||||
## Submitting Changes
|
## Submitting Changes
|
||||||
|
|
||||||
Archinstall uses Github's pull-request workflow and all contributions in terms of code should be done through pull requests.<br>
|
Archinstall uses Github's pull-request workflow and all contributions in terms of code should be done through pull
|
||||||
|
requests.<br>
|
||||||
|
|
||||||
Anyone interested in archinstall may review your code. One of the core developers will merge your pull request when they think it is ready.
|
Anyone interested in archinstall may review your code. One of the core developers will merge your pull request when they
|
||||||
For every pull request, we aim to promptly either merge it or say why it is not yet ready; if you go a few days without a reply, please feel free to ping the thread by adding a new comment.
|
think it is ready. For every pull request, we aim to promptly either merge it or say why it is not yet ready; if you go
|
||||||
|
a few days without a reply, please feel free to ping the thread by adding a new comment.
|
||||||
|
|
||||||
To get your pull request merged sooner, you should explain why you are making the change. For example, you can point to a code sample that is outdated in terms of Arch Linux command lines.
|
To get your pull request merged sooner, you should explain why you are making the change. For example, you can point to
|
||||||
It is also helpful to add links to online documentation or to the implementation of the code you are changing.
|
a code sample that is outdated in terms of Arch Linux command lines. It is also helpful to add links to online
|
||||||
|
documentation or to the implementation of the code you are changing.
|
||||||
|
|
||||||
Also, do not squash your commits after you have submitted a pull request, as this erases context during review. We will squash commits when the pull request is merged.
|
Also, do not squash your commits after you have submitted a pull request, as this erases context during review. We will
|
||||||
|
squash commits when the pull request is merged.
|
||||||
|
|
||||||
At present the current contributors are (alphabetically):
|
At present the current contributors are (alphabetically):
|
||||||
|
|
||||||
* Anton Hvornum ([@Torxed](https://github.com/Torxed))
|
* Anton Hvornum ([@Torxed](https://github.com/Torxed))
|
||||||
* Borislav Kosharov ([@nikibobi](https://github.com/nikibobi))
|
* Borislav Kosharov ([@nikibobi](https://github.com/nikibobi))
|
||||||
* demostanis ([@demostanis](https://github.com/demostanis))
|
* demostanis ([@demostanis](https://github.com/demostanis))
|
||||||
* Giancarlo Razzolini (@[grazzolini](https://github.com/grazzolini))
|
* Giancarlo Razzolini (@[grazzolini](https://github.com/grazzolini))
|
||||||
* j-james ([@j-james](https://github.com/j-james))
|
* j-james ([@j-james](https://github.com/j-james))
|
||||||
* Jerker Bengtsson ([@jaybent](https://github.com/jaybent))
|
* Jerker Bengtsson ([@jaybent](https://github.com/jaybent))
|
||||||
* Ninchester ([@ninchester](https://github.com/ninchester))
|
* Ninchester ([@ninchester](https://github.com/ninchester))
|
||||||
* Philipp Schaffrath ([@phisch](https://github.com/phisch))
|
* Philipp Schaffrath ([@phisch](https://github.com/phisch))
|
||||||
* Varun Madiath ([@vamega](https://github.com/vamega))
|
* Varun Madiath ([@vamega](https://github.com/vamega))
|
||||||
* nullrequest ([@advaithm](https://github.com/advaithm))
|
* nullrequest ([@advaithm](https://github.com/advaithm))
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ def insert_mirrors(mirrors, *args, **kwargs):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def use_mirrors(regions :dict, destination='/etc/pacman.d/mirrorlist'):
|
def use_mirrors(regions: dict, destination='/etc/pacman.d/mirrorlist'):
|
||||||
log(f'A new package mirror-list has been created: {destination}', level=logging.INFO)
|
log(f'A new package mirror-list has been created: {destination}', level=logging.INFO)
|
||||||
for region, mirrors in regions.items():
|
for region, mirrors in regions.items():
|
||||||
with open(destination, 'w') as mirrorlist:
|
with open(destination, 'w') as mirrorlist:
|
||||||
|
|
@ -86,7 +86,6 @@ def list_mirrors():
|
||||||
log(f'Could not fetch an active mirror-list: {err}', level=logging.WARNING, fg="yellow")
|
log(f'Could not fetch an active mirror-list: {err}', level=logging.WARNING, fg="yellow")
|
||||||
return regions
|
return regions
|
||||||
|
|
||||||
|
|
||||||
region = 'Unknown region'
|
region = 'Unknown region'
|
||||||
for line in response.readlines():
|
for line in response.readlines():
|
||||||
if len(line.strip()) == 0:
|
if len(line.strip()) == 0:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import os
|
|
||||||
import fcntl
|
import fcntl
|
||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from .exceptions import *
|
from .exceptions import *
|
||||||
from .general import sys_command
|
from .general import sys_command
|
||||||
from .storage import storage
|
from .storage import storage
|
||||||
|
|
@ -10,7 +11,7 @@ from .storage import storage
|
||||||
|
|
||||||
def get_hw_addr(ifname):
|
def get_hw_addr(ifname):
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15]))
|
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15]))
|
||||||
return ':'.join('%02x' % b for b in info[18:24])
|
return ':'.join('%02x' % b for b in info[18:24])
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,7 +26,7 @@ def list_interfaces(skip_loopback=True):
|
||||||
return interfaces
|
return interfaces
|
||||||
|
|
||||||
|
|
||||||
def enrich_iface_types(interfaces :dict):
|
def enrich_iface_types(interfaces: dict):
|
||||||
result = {}
|
result = {}
|
||||||
for iface in interfaces:
|
for iface in interfaces:
|
||||||
if os.path.isdir(f"/sys/class/net/{iface}/bridge/"):
|
if os.path.isdir(f"/sys/class/net/{iface}/bridge/"):
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import abc
|
import abc
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .storage import storage
|
from .storage import storage
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -21,7 +22,7 @@ class journald(dict):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def log(message, level=logging.DEBUG):
|
def log(message, level=logging.DEBUG):
|
||||||
try:
|
try:
|
||||||
import systemd.journal # type: ignore
|
import systemd.journal # type: ignore
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -77,8 +78,8 @@ def supports_color():
|
||||||
|
|
||||||
# Heavily influenced by: https://github.com/django/django/blob/ae8338daf34fd746771e0678081999b656177bae/django/utils/termcolors.py#L13
|
# Heavily influenced by: https://github.com/django/django/blob/ae8338daf34fd746771e0678081999b656177bae/django/utils/termcolors.py#L13
|
||||||
# Color options here: https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i
|
# Color options here: https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i
|
||||||
def stylize_output(text :str, *opts, **kwargs):
|
def stylize_output(text: str, *opts, **kwargs):
|
||||||
opt_dict = {'bold': '1', 'italic' : '3', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'}
|
opt_dict = {'bold': '1', 'italic': '3', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'}
|
||||||
color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
|
color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
|
||||||
foreground = {color_names[x]: '3%s' % x for x in range(8)}
|
foreground = {color_names[x]: '3%s' % x for x in range(8)}
|
||||||
background = {color_names[x]: '4%s' % x for x in range(8)}
|
background = {color_names[x]: '4%s' % x for x in range(8)}
|
||||||
|
|
@ -120,8 +121,8 @@ def log(*args, **kwargs):
|
||||||
log_file.write("")
|
log_file.write("")
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
# Fallback to creating the log file in the current folder
|
# Fallback to creating the log file in the current folder
|
||||||
err_string = f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute()/filename} instead."
|
err_string = f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute() / filename} instead."
|
||||||
absolute_logfile = Path('./').absolute()/filename
|
absolute_logfile = Path('./').absolute() / filename
|
||||||
absolute_logfile.parents[0].mkdir(exist_ok=True)
|
absolute_logfile.parents[0].mkdir(exist_ok=True)
|
||||||
absolute_logfile = str(absolute_logfile)
|
absolute_logfile = str(absolute_logfile)
|
||||||
storage['LOG_PATH'] = './'
|
storage['LOG_PATH'] = './'
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ def find_packages(*names):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def validate_package_list(packages :list):
|
def validate_package_list(packages: list):
|
||||||
"""
|
"""
|
||||||
Validates a list of given packages.
|
Validates a list of given packages.
|
||||||
Raises `RequirementError` if one or more packages are not found.
|
Raises `RequirementError` if one or more packages are not found.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import sys
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .general import multisplit
|
from .general import multisplit
|
||||||
from .networking import *
|
from .networking import *
|
||||||
from .storage import storage
|
from .storage import storage
|
||||||
|
|
@ -16,7 +17,7 @@ def grab_url_data(path):
|
||||||
safe_path = path[:path.find(':')+1]+''.join([item if item in ('/', '?', '=', '&') else urllib.parse.quote(item) for item in multisplit(path[path.find(':')+1:], ('/', '?', '=', '&'))])
|
safe_path = path[:path.find(':')+1]+''.join([item if item in ('/', '?', '=', '&') else urllib.parse.quote(item) for item in multisplit(path[path.find(':')+1:], ('/', '?', '=', '&'))])
|
||||||
ssl_context = ssl.create_default_context()
|
ssl_context = ssl.create_default_context()
|
||||||
ssl_context.check_hostname = False
|
ssl_context.check_hostname = False
|
||||||
ssl_context.verify_mode=ssl.CERT_NONE
|
ssl_context.verify_mode = ssl.CERT_NONE
|
||||||
response = urllib.request.urlopen(safe_path, context=ssl_context)
|
response = urllib.request.urlopen(safe_path, context=ssl_context)
|
||||||
return response.read()
|
return response.read()
|
||||||
|
|
||||||
|
|
@ -29,7 +30,7 @@ def list_profiles(filter_irrelevant_macs=True, subpath='', filter_top_level_prof
|
||||||
cache = {}
|
cache = {}
|
||||||
# Grab all local profiles found in PROFILE_PATH
|
# Grab all local profiles found in PROFILE_PATH
|
||||||
for PATH_ITEM in storage['PROFILE_PATH']:
|
for PATH_ITEM in storage['PROFILE_PATH']:
|
||||||
for root, folders, files in os.walk(os.path.abspath(os.path.expanduser(PATH_ITEM+subpath))):
|
for root, folders, files in os.walk(os.path.abspath(os.path.expanduser(PATH_ITEM + subpath))):
|
||||||
for file in files:
|
for file in files:
|
||||||
if file == '__init__.py':
|
if file == '__init__.py':
|
||||||
continue
|
continue
|
||||||
|
|
@ -51,7 +52,7 @@ def list_profiles(filter_irrelevant_macs=True, subpath='', filter_top_level_prof
|
||||||
|
|
||||||
# Grab profiles from upstream URL
|
# Grab profiles from upstream URL
|
||||||
if storage['PROFILE_DB']:
|
if storage['PROFILE_DB']:
|
||||||
profiles_url = os.path.join(storage["UPSTREAM_URL"]+subpath, storage['PROFILE_DB'])
|
profiles_url = os.path.join(storage["UPSTREAM_URL"] + subpath, storage['PROFILE_DB'])
|
||||||
try:
|
try:
|
||||||
profile_list = json.loads(grab_url_data(profiles_url))
|
profile_list = json.loads(grab_url_data(profiles_url))
|
||||||
except urllib.error.HTTPError as err:
|
except urllib.error.HTTPError as err:
|
||||||
|
|
@ -74,7 +75,7 @@ def list_profiles(filter_irrelevant_macs=True, subpath='', filter_top_level_prof
|
||||||
if filter_top_level_profiles:
|
if filter_top_level_profiles:
|
||||||
for profile in list(cache.keys()):
|
for profile in list(cache.keys()):
|
||||||
if Profile(None, profile).is_top_level_profile() is False:
|
if Profile(None, profile).is_top_level_profile() is False:
|
||||||
del(cache[profile])
|
del (cache[profile])
|
||||||
|
|
||||||
return cache
|
return cache
|
||||||
|
|
||||||
|
|
@ -166,7 +167,7 @@ class Profile(Script):
|
||||||
super(Profile, self).__init__(path, installer)
|
super(Profile, self).__init__(path, installer)
|
||||||
|
|
||||||
def __dump__(self, *args, **kwargs):
|
def __dump__(self, *args, **kwargs):
|
||||||
return {'path' : self.path}
|
return {'path': self.path}
|
||||||
|
|
||||||
def __repr__(self, *args, **kwargs):
|
def __repr__(self, *args, **kwargs):
|
||||||
return f'Profile({os.path.basename(self.profile)})'
|
return f'Profile({os.path.basename(self.profile)})'
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,15 @@ import os
|
||||||
#
|
#
|
||||||
# And Keeping this in dict ensures that variables are shared across imports.
|
# And Keeping this in dict ensures that variables are shared across imports.
|
||||||
storage = {
|
storage = {
|
||||||
'PROFILE_PATH' : [
|
'PROFILE_PATH': [
|
||||||
'./profiles',
|
'./profiles',
|
||||||
'~/.config/archinstall/profiles',
|
'~/.config/archinstall/profiles',
|
||||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'profiles'),
|
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'profiles'),
|
||||||
# os.path.abspath(f'{os.path.dirname(__file__)}/../examples')
|
# os.path.abspath(f'{os.path.dirname(__file__)}/../examples')
|
||||||
],
|
],
|
||||||
'UPSTREAM_URL' : 'https://raw.githubusercontent.com/archlinux/archinstall/master/profiles',
|
'UPSTREAM_URL': 'https://raw.githubusercontent.com/archlinux/archinstall/master/profiles',
|
||||||
'PROFILE_DB' : None, # Used in cases when listing profiles is desired, not mandatory for direct profile grabing.
|
'PROFILE_DB': None, # Used in cases when listing profiles is desired, not mandatory for direct profile grabing.
|
||||||
'LOG_PATH' : '/var/log/archinstall',
|
'LOG_PATH': '/var/log/archinstall',
|
||||||
'LOG_FILE' : 'install.log',
|
'LOG_FILE': 'install.log',
|
||||||
'MOUNT_POINT' : '/mnt'
|
'MOUNT_POINT': '/mnt'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ def check_for_correct_username(username):
|
||||||
|
|
||||||
def do_countdown():
|
def do_countdown():
|
||||||
SIG_TRIGGER = False
|
SIG_TRIGGER = False
|
||||||
|
|
||||||
def kill_handler(sig, frame):
|
def kill_handler(sig, frame):
|
||||||
print()
|
print()
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
@ -101,17 +102,17 @@ def print_large_list(options, padding=5, margin_bottom=0, separator=': '):
|
||||||
longest_line = highest_index_number_length + len(separator) + get_longest_option(options) + padding
|
longest_line = highest_index_number_length + len(separator) + get_longest_option(options) + padding
|
||||||
spaces_without_option = longest_line - (len(separator) + highest_index_number_length)
|
spaces_without_option = longest_line - (len(separator) + highest_index_number_length)
|
||||||
max_num_of_columns = get_terminal_width() // longest_line
|
max_num_of_columns = get_terminal_width() // longest_line
|
||||||
max_options_in_cells = max_num_of_columns * (get_terminal_height()-margin_bottom)
|
max_options_in_cells = max_num_of_columns * (get_terminal_height() - margin_bottom)
|
||||||
|
|
||||||
if (len(options) > max_options_in_cells):
|
if (len(options) > max_options_in_cells):
|
||||||
for index, option in enumerate(options):
|
for index, option in enumerate(options):
|
||||||
print(f"{index}: {option}")
|
print(f"{index}: {option}")
|
||||||
return 1, index
|
return 1, index
|
||||||
else:
|
else:
|
||||||
for row in range(0, (get_terminal_height()-margin_bottom)):
|
for row in range(0, (get_terminal_height() - margin_bottom)):
|
||||||
for column in range(row, len(options), (get_terminal_height()-margin_bottom)):
|
for column in range(row, len(options), (get_terminal_height() - margin_bottom)):
|
||||||
spaces = " "*(spaces_without_option - len(options[column]))
|
spaces = " " * (spaces_without_option - len(options[column]))
|
||||||
print(f"{str(column): >{highest_index_number_length}}{separator}{options[column]}", end = spaces)
|
print(f"{str(column): >{highest_index_number_length}}{separator}{options[column]}", end=spaces)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
return column, row
|
return column, row
|
||||||
|
|
@ -148,7 +149,7 @@ def generic_multi_select(options, text="Select one or more of the options above
|
||||||
else:
|
else:
|
||||||
printed_options.append(f'{option}')
|
printed_options.append(f'{option}')
|
||||||
|
|
||||||
section.clear(0, get_terminal_height()-section._cursor_y-1)
|
section.clear(0, get_terminal_height() - section._cursor_y - 1)
|
||||||
print_large_list(printed_options, margin_bottom=2)
|
print_large_list(printed_options, margin_bottom=2)
|
||||||
section._cursor_y = len(printed_options)
|
section._cursor_y = len(printed_options)
|
||||||
section._cursor_x = 0
|
section._cursor_x = 0
|
||||||
|
|
@ -204,7 +205,7 @@ class MiniCurses:
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stdout.write("\033[%dG" % 0)
|
sys.stdout.write("\033[%dG" % 0)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stdout.write(" " * (get_terminal_width()-1))
|
sys.stdout.write(" " * (get_terminal_width() - 1))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stdout.write("\033[%dG" % 0)
|
sys.stdout.write("\033[%dG" % 0)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
@ -223,17 +224,17 @@ class MiniCurses:
|
||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stdout.write('\033[%d;%df' % (y, x))
|
sys.stdout.write('\033[%d;%df' % (y, x))
|
||||||
for line in range(get_terminal_height()-y-1, y):
|
for line in range(get_terminal_height() - y - 1, y):
|
||||||
sys.stdout.write(" " * (get_terminal_width()-1))
|
sys.stdout.write(" " * (get_terminal_width() - 1))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stdout.write('\033[%d;%df' % (y, x))
|
sys.stdout.write('\033[%d;%df' % (y, x))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def deal_with_control_characters(self, char):
|
def deal_with_control_characters(self, char):
|
||||||
mapper = {
|
mapper = {
|
||||||
'\x7f' : 'BACKSPACE',
|
'\x7f': 'BACKSPACE',
|
||||||
'\r' : 'CR',
|
'\r': 'CR',
|
||||||
'\n' : 'NL'
|
'\n': 'NL'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapped_char := mapper.get(char, None)) == 'BACKSPACE':
|
if (mapped_char := mapper.get(char, None)) == 'BACKSPACE':
|
||||||
|
|
@ -319,7 +320,7 @@ def ask_for_superuser_account(prompt='Username for required superuser with sudo
|
||||||
continue
|
continue
|
||||||
|
|
||||||
password = get_password(prompt=f'Password for user {new_user}: ')
|
password = get_password(prompt=f'Password for user {new_user}: ')
|
||||||
return {new_user: {"!password" : password}}
|
return {new_user: {"!password": password}}
|
||||||
|
|
||||||
|
|
||||||
def ask_for_additional_users(prompt='Any additional users to install (leave blank for no users): '):
|
def ask_for_additional_users(prompt='Any additional users to install (leave blank for no users): '):
|
||||||
|
|
@ -335,9 +336,9 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan
|
||||||
password = get_password(prompt=f'Password for user {new_user}: ')
|
password = get_password(prompt=f'Password for user {new_user}: ')
|
||||||
|
|
||||||
if input("Should this user be a superuser (sudoer) [y/N]: ").strip(' ').lower() in ('y', 'yes'):
|
if input("Should this user be a superuser (sudoer) [y/N]: ").strip(' ').lower() in ('y', 'yes'):
|
||||||
superusers[new_user] = {"!password" : password}
|
superusers[new_user] = {"!password": password}
|
||||||
else:
|
else:
|
||||||
users[new_user] = {"!password" : password}
|
users[new_user] = {"!password": password}
|
||||||
|
|
||||||
return users, superusers
|
return users, superusers
|
||||||
|
|
||||||
|
|
@ -347,7 +348,7 @@ def ask_for_a_timezone():
|
||||||
timezone = input('Enter a valid timezone (examples: Europe/Stockholm, US/Eastern) or press enter to use UTC: ').strip().strip('*.')
|
timezone = input('Enter a valid timezone (examples: Europe/Stockholm, US/Eastern) or press enter to use UTC: ').strip().strip('*.')
|
||||||
if timezone == '':
|
if timezone == '':
|
||||||
timezone = 'UTC'
|
timezone = 'UTC'
|
||||||
if (pathlib.Path("/usr")/"share"/"zoneinfo"/timezone).exists():
|
if (pathlib.Path("/usr") / "share" / "zoneinfo" / timezone).exists():
|
||||||
return timezone
|
return timezone
|
||||||
else:
|
else:
|
||||||
log(
|
log(
|
||||||
|
|
@ -359,17 +360,17 @@ def ask_for_a_timezone():
|
||||||
|
|
||||||
def ask_for_bootloader() -> str:
|
def ask_for_bootloader() -> str:
|
||||||
bootloader = "systemd-bootctl"
|
bootloader = "systemd-bootctl"
|
||||||
if hasUEFI()==False:
|
if hasUEFI() == False:
|
||||||
bootloader="grub-install"
|
bootloader = "grub-install"
|
||||||
else:
|
else:
|
||||||
bootloader_choice = input("Would you like to use GRUB as a bootloader instead of systemd-boot? [y/N] ").lower()
|
bootloader_choice = input("Would you like to use GRUB as a bootloader instead of systemd-boot? [y/N] ").lower()
|
||||||
if bootloader_choice == "y":
|
if bootloader_choice == "y":
|
||||||
bootloader="grub-install"
|
bootloader = "grub-install"
|
||||||
return bootloader
|
return bootloader
|
||||||
|
|
||||||
|
|
||||||
def ask_for_audio_selection():
|
def ask_for_audio_selection():
|
||||||
audio = "pulseaudio" # Default for most desktop environments
|
audio = "pulseaudio" # Default for most desktop environments
|
||||||
pipewire_choice = input("Would you like to install pipewire instead of pulseaudio as the default audio server? [Y/n] ").lower()
|
pipewire_choice = input("Would you like to install pipewire instead of pulseaudio as the default audio server? [Y/n] ").lower()
|
||||||
if pipewire_choice in ("y", ""):
|
if pipewire_choice in ("y", ""):
|
||||||
audio = "pipewire"
|
audio = "pipewire"
|
||||||
|
|
@ -379,18 +380,18 @@ def ask_for_audio_selection():
|
||||||
|
|
||||||
def ask_to_configure_network():
|
def ask_to_configure_network():
|
||||||
# Optionally configure one network interface.
|
# Optionally configure one network interface.
|
||||||
#while 1:
|
# while 1:
|
||||||
# {MAC: Ifname}
|
# {MAC: Ifname}
|
||||||
interfaces = {
|
interfaces = {
|
||||||
'ISO-CONFIG' : 'Copy ISO network configuration to installation',
|
'ISO-CONFIG': 'Copy ISO network configuration to installation',
|
||||||
'NetworkManager':'Use NetworkManager to control and manage your internet connection',
|
'NetworkManager': 'Use NetworkManager to control and manage your internet connection',
|
||||||
**list_interfaces()
|
**list_interfaces()
|
||||||
}
|
}
|
||||||
|
|
||||||
nic = generic_select(interfaces, "Select one network interface to configure (leave blank to skip): ")
|
nic = generic_select(interfaces, "Select one network interface to configure (leave blank to skip): ")
|
||||||
if nic and nic != 'Copy ISO network configuration to installation':
|
if nic and nic != 'Copy ISO network configuration to installation':
|
||||||
if nic == 'Use NetworkManager to control and manage your internet connection':
|
if nic == 'Use NetworkManager to control and manage your internet connection':
|
||||||
return {'nic': nic,'NetworkManager':True}
|
return {'nic': nic, 'NetworkManager': True}
|
||||||
|
|
||||||
# Current workaround:
|
# Current workaround:
|
||||||
# For selecting modes without entering text within brackets,
|
# For selecting modes without entering text within brackets,
|
||||||
|
|
@ -401,7 +402,7 @@ def ask_to_configure_network():
|
||||||
print(f"{index}: {mode}")
|
print(f"{index}: {mode}")
|
||||||
|
|
||||||
mode = generic_select(['DHCP', 'IP'], f"Select which mode to configure for {nic} or leave blank for DHCP: ",
|
mode = generic_select(['DHCP', 'IP'], f"Select which mode to configure for {nic} or leave blank for DHCP: ",
|
||||||
options_output=False)
|
options_output=False)
|
||||||
if mode == 'IP':
|
if mode == 'IP':
|
||||||
while 1:
|
while 1:
|
||||||
ip = input(f"Enter the IP and subnet for {nic} (example: 192.168.0.5/24): ").strip()
|
ip = input(f"Enter the IP and subnet for {nic} (example: 192.168.0.5/24): ").strip()
|
||||||
|
|
@ -436,7 +437,7 @@ def ask_to_configure_network():
|
||||||
if len(dns_input := input('Enter your DNS servers (space separated, blank for none): ').strip()):
|
if len(dns_input := input('Enter your DNS servers (space separated, blank for none): ').strip()):
|
||||||
dns = dns_input.split(' ')
|
dns = dns_input.split(' ')
|
||||||
|
|
||||||
return {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway' : gateway, 'dns' : dns}
|
return {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway': gateway, 'dns': dns}
|
||||||
else:
|
else:
|
||||||
return {'nic': nic}
|
return {'nic': nic}
|
||||||
elif nic:
|
elif nic:
|
||||||
|
|
@ -447,26 +448,26 @@ def ask_to_configure_network():
|
||||||
|
|
||||||
def ask_for_disk_layout():
|
def ask_for_disk_layout():
|
||||||
options = {
|
options = {
|
||||||
'keep-existing' : 'Keep existing partition layout and select which ones to use where',
|
'keep-existing': 'Keep existing partition layout and select which ones to use where',
|
||||||
'format-all' : 'Format entire drive and setup a basic partition scheme',
|
'format-all': 'Format entire drive and setup a basic partition scheme',
|
||||||
'abort' : 'Abort the installation'
|
'abort': 'Abort the installation'
|
||||||
}
|
}
|
||||||
|
|
||||||
value = generic_select(options, "Found partitions on the selected drive, (select by number) what you want to do: ",
|
value = generic_select(options, "Found partitions on the selected drive, (select by number) what you want to do: ",
|
||||||
allow_empty_input=False, sort=True)
|
allow_empty_input=False, sort=True)
|
||||||
return next((key for key, val in options.items() if val == value), None)
|
return next((key for key, val in options.items() if val == value), None)
|
||||||
|
|
||||||
|
|
||||||
def ask_for_main_filesystem_format():
|
def ask_for_main_filesystem_format():
|
||||||
options = {
|
options = {
|
||||||
'btrfs' : 'btrfs',
|
'btrfs': 'btrfs',
|
||||||
'ext4' : 'ext4',
|
'ext4': 'ext4',
|
||||||
'xfs' : 'xfs',
|
'xfs': 'xfs',
|
||||||
'f2fs' : 'f2fs'
|
'f2fs': 'f2fs'
|
||||||
}
|
}
|
||||||
|
|
||||||
value = generic_select(options, "Select which filesystem your main partition should use (by number or name): ",
|
value = generic_select(options, "Select which filesystem your main partition should use (by number or name): ",
|
||||||
allow_empty_input=False)
|
allow_empty_input=False)
|
||||||
return next((key for key, val in options.items() if val == value), None)
|
return next((key for key, val in options.items() if val == value), None)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -526,7 +527,7 @@ def generic_select(options, input_text="Select one of the above by index or abso
|
||||||
selected_option = options[selected_option]
|
selected_option = options[selected_option]
|
||||||
break
|
break
|
||||||
elif selected_option in options:
|
elif selected_option in options:
|
||||||
break # We gave a correct absolute value
|
break # We gave a correct absolute value
|
||||||
else:
|
else:
|
||||||
raise RequirementError(f'Selected option "{selected_option}" does not exist in available options')
|
raise RequirementError(f'Selected option "{selected_option}" does not exist in available options')
|
||||||
except RequirementError as err:
|
except RequirementError as err:
|
||||||
|
|
@ -584,7 +585,7 @@ def select_profile(options):
|
||||||
print(' -- (Leave blank and hit enter to skip this step and continue) --')
|
print(' -- (Leave blank and hit enter to skip this step and continue) --')
|
||||||
|
|
||||||
selected_profile = generic_select(profiles, 'Enter a pre-programmed profile name if you want to install one: ',
|
selected_profile = generic_select(profiles, 'Enter a pre-programmed profile name if you want to install one: ',
|
||||||
options_output=False)
|
options_output=False)
|
||||||
if selected_profile:
|
if selected_profile:
|
||||||
return Profile(None, selected_profile)
|
return Profile(None, selected_profile)
|
||||||
else:
|
else:
|
||||||
|
|
@ -674,8 +675,9 @@ def select_mirror_regions(mirrors, show_top_mirrors=True):
|
||||||
print_large_list(regions, margin_bottom=4)
|
print_large_list(regions, margin_bottom=4)
|
||||||
|
|
||||||
print(' -- You can skip this step by leaving the option blank --')
|
print(' -- You can skip this step by leaving the option blank --')
|
||||||
selected_mirror = generic_select(regions, 'Select one of the above regions to download packages from (by number or full name): ',
|
selected_mirror = generic_select(regions,
|
||||||
options_output=False)
|
'Select one of the above regions to download packages from (by number or full name): ',
|
||||||
|
options_output=False)
|
||||||
if not selected_mirror:
|
if not selected_mirror:
|
||||||
# Returning back empty options which can be both used to
|
# Returning back empty options which can be both used to
|
||||||
# do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining
|
# do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ author = 'Anton Hvornum'
|
||||||
# The full version, including alpha/beta/rc tags
|
# The full version, including alpha/beta/rc tags
|
||||||
release = 'v2.1.0'
|
release = 'v2.1.0'
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
@ -64,7 +63,6 @@ templates_path = ['_templates']
|
||||||
# This pattern also affects html_static_path and html_extra_path.
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
|
|
||||||
|
|
@ -12,5 +12,5 @@ If the PR is larger than ~20 lines, please describe it here unless described in
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
|
||||||
Any new feature or stability improvement should be tested if possible.
|
Any new feature or stability improvement should be tested if possible. Please follow the test instructions at the bottom
|
||||||
Please follow the test instructions at the bottom of the README or use the ISO built on each PR.
|
of the README or use the ISO built on each PR.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import time
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
import archinstall
|
import archinstall
|
||||||
from archinstall.lib.hardware import hasUEFI
|
from archinstall.lib.hardware import hasUEFI
|
||||||
from archinstall.lib.profiles import Profile
|
|
||||||
|
|
||||||
if archinstall.arguments.get('help'):
|
if archinstall.arguments.get('help'):
|
||||||
print("See `man archinstall` for help.")
|
print("See `man archinstall` for help.")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue