remove deploy source

This commit is contained in:
ItsDrike 2021-07-14 14:24:08 +02:00
parent 33cccffc7d
commit 20c1734cbc
No known key found for this signature in database
GPG key ID: B5F6B41F708C3ADD
11 changed files with 0 additions and 612 deletions

View file

@ -1,9 +0,0 @@
if ! type "python3" &> /dev/null; then
sudo pacman -S python
fi
if ! type "pip3" &> /dev/null; then
sudo pacman -S python-pip
fi
pip install -r requirements.txt
python3 -m src

View file

@ -1,5 +0,0 @@
pyyaml
psutil
colorama
pyinquirer
inquirer

View file

@ -1,26 +0,0 @@
import sys
import colorama
import inquirer.shortcuts
from src.arch_install import install_arch
from src.dotfiles_install import install_dotfiles
from src.package_install import install_packages
from src.util.command import run_cmd
colorama.init(autoreset=True)
if inquirer.shortcuts.confirm("Do you wish to perform Arch install? (Directly from live ISO)"):
run_cmd("clear")
print(f"{colorama.Fore.BLUE}Running Arch Installation")
root_mountpoint = install_arch()
print(f"{colorama.Fore.GREEN}Arch installation complete")
print(f"{colorama.Fore.CYAN}To install packages and dotfiles, move this whole directory to the new installation and run it from there.")
sys.exit()
if inquirer.shortcuts.confirm("Do you wish to perform package installation (from packages.yaml)"):
install_packages()
if inquirer.shortcuts.confirm("Do you wish to install dotfiles? (from home and root folders)"):
install_dotfiles()

View file

@ -1,130 +0,0 @@
from pathlib import Path
from typing import Optional
import colorama
import inquirer.shortcuts
from src.util.command import run_cmd, run_root_cmd
from src.util.internet import connect_internet
colorama.init(autoreset=True)
def mount_partition(partition_path: Path, mount_path: Optional[Path] = None, default_path: str = "/mnt") -> Path:
"""
Mount given `partition_path` to `mount_path`.;
If `mount_path` wasn't provided, ask user for it.
After mounting, mount_path will be returned
"""
if not mount_path:
mount_path = Path(inquirer.shortcuts.path(f"Specify mountpoint for {partition_path}", default=default_path))
if not mount_path.exists():
run_root_cmd(f"mkdir -p {mount_path}")
run_root_cmd(f"mount {partition_path} {mount_path}")
return mount_path
def partition_disk() -> Path:
"""Create all necessary partitions and return root mountpoint"""
uefi = Path("/sys/firmware/efi/efivars").is_dir()
# Let user make partitions in shell environment
partitions_made = inquirer.shortcuts.confirm("Do you already have partitions pre-made?")
if not partitions_made:
print(
f"{colorama.Fore.CYAN}Dropping to shell environment, create your partitions here."
" When you are done, use `exit` to return\n"
f"{colorama.Style.DIM}This is {'UEFI' if uefi else 'LEGACY (BIOS)'} system\n"
)
run_cmd("exec $SHELL")
# Obtain partitions from user and mount them
root_part = Path(inquirer.shortcuts.path("Specify the root partition (/dev/sdXY)", exists=True))
if inquirer.shortcuts.confirm(f"Do you wish to make EXT4 filesystem on {root_part}?", default=True):
run_root_cmd(f"mkfs.ext4 {root_part}")
root_mountpoint = mount_partition(root_part)
if inquirer.shortcuts.confirm("Do you have an EFI partition?", default=uefi):
if not uefi:
print(
f"{colorama.Fore.RED}Warning: Adding EFI partition from non-uefi system isn't adviced.\n"
"While this process won't directly fail, you won't be able to install a bootloader from "
"this computer. You can proceed, but you will have to use another computer to install the bootloader."
)
efi_part = Path(inquirer.shortcuts.path("Specify EFI partition (/dev/sdXY)", exists=True))
if inquirer.shortcuts.confirm(f"Do you wish to make FAT32 filesystem on {efi_part}?", default=True):
run_root_cmd(f"mkfs.fat -F32 {efi_part}")
mount_partition(efi_part, default_path=str(Path(root_mountpoint, "boot")))
elif uefi:
print(
f"{colorama.Fore.RED}Proceeding without EFI partition on UEFI system is not adviced, "
"unless you want to run this OS with other UEFI capable system"
)
if inquirer.shortcuts.confirm("Do you have a swap partition?"):
swap_part = Path(inquirer.shortcuts.path("Specify the swap partition (/dev/sdXY)", exists=True))
if inquirer.shortcuts.confirm(f"Do you wish to make swap system on {root_part}?", default=True):
run_root_cmd(f"mkswap {swap_part}")
if inquirer.shortcuts.confirm("Do you wish to turn on swap?", default=True):
run_root_cmd(f"swapon {swap_part}")
while inquirer.shortcuts.confirm("Do you have any other partition?"):
part_path = Path(inquirer.shortcuts.path("Specify partition path (/dev/sdXY)", exists=True))
if inquirer.shortcuts.confirm("Do you wish to format this partition?"):
print(f"{colorama.Fore.CYAN}Dropping to shell, format the partition here and type `exit` to return")
run_cmd("exec $SHELL")
mount_partition(part_path)
print(f"{colorama.Fore.LIGHTCYAN_EX}Printing disk report (with lsblk)")
run_root_cmd("lsblk")
if inquirer.shortcuts.confirm("Do you want to drop to shell and make some further adjustments?"):
print(f"{colorama.Fore.CYAN}After you are done, return by typing `exit`")
run_cmd("exec $SHELL")
print(f"{colorama.Fore.GREEN}Partitioning complete")
return root_mountpoint
def run_pacstrap(root_mountpoint: Path):
mirror_setup = inquirer.shortcuts.confirm("Do you wish to setup your mirrors (This is necessary for fast downloads)?", default=True)
if mirror_setup:
print(
f"{colorama.Fore.CYAN}Dropping to shell environment, setup your mirrors from here."
" When you are done, use `exit` to return\n"
f"{colorama.Style.DIM}Mirrors are located in `/etc/pacman.d/mirrorlist`\n"
)
run_cmd("exec $SHELL")
extra_pkgs = inquirer.shortcuts.checkbox(
"You can choose to install additional packages with pacstrap here (select with space)",
choices=["networkmanager", "base-devel", "vim", "nano"]
)
run_root_cmd(f"pacstrap {root_mountpoint} base linux linux-firmware {' '.join(extra_pkgs)}")
if inquirer.shortcuts.confirm("Do you wish to make some further adjustments and drop to shell?"):
print(f"{colorama.Fore.CYAN}When you are done, use `exit` to return")
run_cmd("exec $SHELL")
def install_arch():
"""Perform full Arch installation and return mountpoint and default user"""
connect_internet()
run_root_cmd("timedatectl set-ntp true")
root_mountpoint = partition_disk()
run_pacstrap(root_mountpoint)
print(f"{colorama.Fore.CYAN}Generating fstab")
run_root_cmd(f"genfstab -U {root_mountpoint} >> {root_mountpoint}/etc/fstab")
print(
f"\n{colorama.Fore.GREEN}Core installation complete.\n"
f"{colorama.Fore.YELLOW}Instalation within chroot environment is not possible from this script, "
"run chroot_install.py within chroot environment.\n"
f"{colorama.Fore.LIGHTBLUE_EX}Execute: {colorama.Style.BRIGHT}`arch-chroot /mnt`"
)
if __name__ == "__main__":
install_arch()

View file

@ -1,12 +0,0 @@
import colorama
colorama.init(autoreset=True)
def install_chroot():
print(f"{colorama.Fore.RED}Sorry, chroot installation file is still WIP, for now, proceed manually.")
print(f"{colorama.Fore.LIGHTCYAN_EX}You can use `arch-install-checklist.md` file which containes detailed installation steps.")
if __name__ == "__main__":
install_chroot()

View file

@ -1,111 +0,0 @@
from datetime import datetime
from pathlib import Path
import colorama
import inquirer.shortcuts
from src.util.command import run_root_cmd
colorama.init(autoreset=True)
def _find_all_files(path: Path):
for subpath in path.iterdir():
if subpath.is_dir():
yield from _find_all_files(subpath)
else:
yield subpath
def _walk_dotfiles():
"""
Walk through every stored file in repositorie's dotfiles,
start by going through `home` specific files, and continue
with `root` dotfiles.
"""
yield from _find_all_files(Path.cwd().joinpath("home"))
yield from _find_all_files(Path.cwd().joinpath("root"))
def _dotfile_to_system(dotfile_path: Path) -> Path:
"""Convert dotfile path to corresponding path on real system"""
base_dir = str(Path.cwd())
if base_dir + "/home/" in str(dotfile_path):
rel_path = str(dotfile_path).replace(base_dir + "/home/", "")
return Path.home().joinpath(rel_path)
elif base_dir + "/root/" in str(dotfile_path):
rel_path = str(dotfile_path).replace(base_dir + "/root/", "")
return Path("/", rel_path)
else:
raise ValueError(f"Given path is not a valid dotfile path ({dotfile_path})")
def make_backup() -> None:
"""
Find all files which will be replaced and back them up.
Files which doesn't exist in the real system destination
will be ignored.
"""
print(f"{colorama.Fore.LIGHTYELLOW_EX}Creating current dotfiles backup")
time = str(datetime.now()).replace(" ", "--")
backup_dir = Path.joinpath(Path.cwd(), "backup", time)
backup_dir.mkdir(parents=True, exist_ok=True)
for dotfile_path in _walk_dotfiles():
real_path = _dotfile_to_system(dotfile_path)
if not real_path.exists():
continue
rel_path = str(dotfile_path).replace(str(Path.cwd()) + "/", "")
backup_path = backup_dir.joinpath(rel_path)
# Ensure backup directory existence
if real_path.is_dir():
backup_path.mkdir(parents=True, exist_ok=True)
else:
backup_path.parent.mkdir(parents=True, exist_ok=True)
print(f"{colorama.Style.DIM}Backing up{real_path}")
run_root_cmd(f"cp '{real_path}' '{backup_path}'", enable_debug=False)
print(f"{colorama.Fore.LIGHTYELLOW_EX}Backup complete")
def overwrite_dotfiles() -> None:
for dotfile_path in _walk_dotfiles():
real_path = _dotfile_to_system(dotfile_path)
# Ensure existence of system directory
if dotfile_path.is_dir():
real_path.mkdir(parents=True, exist_ok=True)
else:
dotfile_path.parent.mkdir(parents=True, exist_ok=True)
# If we encounter placeholder file, making folder is suffictient
# don't proceed with copying it to avoid clutterring the original system
# with empty placeholder files, these files are here only for git to
# recognize that directory
if str(dotfile_path).endswith("placeholder"):
continue
print(f"{colorama.Style.DIM}Overwriting {real_path}")
run_root_cmd(f"cp '{dotfile_path}' '{real_path}'")
def install_dotfiles() -> None:
if inquirer.shortcuts.confirm("Do you want to backup current dotfiles? (Recommended)", default=True):
make_backup()
print(f"{colorama.Fore.CYAN}Proceeding with dotfiles installation (this will overwrite your original files)")
if inquirer.shortcuts.confirm(
"Have you adjusted all dotfiles to your liking? "
f"{colorama.Fore.RED}(proceeding without checking the dotfiles first isn't adviced){colorama.Fore.RESET}"
):
overwrite_dotfiles()
print(f"{colorama.Fore.LIGHTYELLOW_EX}Dotfile installation complete, make sure to adjust the dotfiles to your liking.")
else:
print(f"{colorama.Fore.RED}Aborted...")
if __name__ == "__main__":
install_dotfiles()

View file

@ -1,45 +0,0 @@
import typing as t
import colorama
import inquirer.shortcuts
import yaml
from src.util.command import run_root_cmd
from src.util.package import InvalidPackage, Package, PackageAlreadyInstalled
colorama.init(autoreset=True)
def obtain_packages() -> t.List[Package]:
with open("packages.yaml") as f:
yaml_file = yaml.safe_load(f)
pacman_packages = yaml_file["pacman"]
aur_packages = yaml_file["aur"]
git_packages = yaml_file["git"]
packages = []
packages += Package.safe_load(pacman_packages)
packages += Package.safe_load(git_packages, git=True)
packages += Package.safe_load(aur_packages, aur=True)
return packages
def install_packages() -> None:
packages = obtain_packages()
if inquirer.shortcuts.confirm("Do you wish to perform system upgrade first? (Recommended)", default=True):
run_root_cmd("pacman -Syu")
for package in packages:
try:
print(f"{colorama.Fore.CYAN}Installing {package}")
package.install()
except PackageAlreadyInstalled:
print(f"{colorama.Style.DIM}Package {package} is already installed, skipping")
except InvalidPackage as e:
print(f"{colorama.Fore.RED}{str(e)}")
if __name__ == "__main__":
install_packages()

View file

@ -1,47 +0,0 @@
import os
import subprocess
import colorama
import inquirer.shortcuts
DEBUG = True
def debug_confirm_run(cmd):
if DEBUG:
cnfrm = inquirer.shortcuts.confirm(
f"{colorama.Fore.BLUE}[DEBUG] Running command: "
f"{colorama.Fore.YELLOW}{cmd}{colorama.Fore.RESET}"
)
return cnfrm
else:
return True
def run_root_cmd(cmd: str, enable_debug: bool = True) -> subprocess.CompletedProcess:
"""Run command as root"""
if os.geteuid() != 0:
return run_cmd(f"sudo {cmd}", enable_debug=enable_debug)
else:
return run_cmd(cmd, enable_debug=enable_debug)
def run_cmd(cmd: str, capture_out: bool = False, enable_debug: bool = True) -> subprocess.CompletedProcess:
"""Run given command"""
args = {}
if capture_out:
args.update({"stdout": subprocess.PIPE, "stderr": subprocess.STDOUT})
if not enable_debug or debug_confirm_run(cmd):
return subprocess.run(cmd, shell=True, **args)
else:
# If debug confirm wasn't confirmed, return code 1 (error)
return subprocess.CompletedProcess(cmd, returncode=1)
def command_exists(cmd) -> bool:
"""Check if given command can be executed"""
parts = cmd.split()
executable = parts[0] if parts[0] != "sudo" else parts[1]
proc = run_cmd(f"which {executable}", capture_out=True)
return proc.returncode != 1

View file

@ -1,95 +0,0 @@
import sys
import time
import urllib.request
from urllib.error import URLError
import colorama
import inquirer.shortcuts
from src.util.command import command_exists, run_cmd, run_root_cmd
def _connect_wifi() -> bool:
"""
Attempt to connect to internet using WiFI.
This uses `nmtui` with fallback to `iwctl`, if none
of these tools are aviable, either quit or return False,
if the tool was executed properly, return True
Note: True doesn't mean we connected, just that the tool was ran,
it is up to user to use that tool properly and make the connection.
"""
if command_exists("nmtui"):
run_root_cmd("nmtui")
elif command_exists("iwctl"):
run_root_cmd("iwctl")
else:
print(
f"{colorama.Fore.RED}{colorama.Style.BRIGHT}ERROR: "
"WiFi connection tool not found: `nmtui`/`iwctl`, please use Ethernet instead.\n"
"Alternatively, connect manually outside of this script and re-run it."
)
opt = inquirer.shortcuts.list_input(
"How do you wish to proceed?",
choices=["Quit and connect manually", "Proceed with Ethernet"]
)
if opt == "Quit and connect manually":
sys.exit()
else:
return False
return True
def _connect_ethernet(max_wait_time: int = 20, iteration_time: int = 1) -> bool:
"""
Attempt to connect to internet using Ethernet.
This will simply wait for the user to plug in the ethernet cable,
once that happens loop is interrupted and True is returned. In case
it takes over the `max_wait_time`, loop ends and False is returned.
`iteration_time` is the time of each loop iteration, after whcih we
check if connection is valid, if not, we continue iterating.
"""
print(f"{colorama.Style.DIM}Please plug in the Ethernet cable, waiting 20s")
time_elapsed = 0
while not check_connection() and time_elapsed < max_wait_time:
time.sleep(iteration_time)
time_elapsed += iteration_time
if time_elapsed >= max_wait_time:
# We stopped because max wait time was crossed
return False
else:
# We stopped because connection to internet was successful
return True
def connect_internet():
wifi_possible = True
while not check_connection():
run_cmd("clear")
print(f"{colorama.Fore.RED}Internet connection unaviable")
if wifi_possible:
connect_opt = inquirer.shortcuts.list_input("How do you wish to connect to internet?", choices=["Wi-Fi", "Ethernet"])
else:
connect_opt = "Ethernet"
if connect_opt == "Wi-Fi":
wifi_possible = _connect_wifi()
else:
if _connect_ethernet():
break
print(f"{colorama.Fore.GREEN}Internet connection successful")
def check_connection(host="https://google.com") -> bool:
"""Check if system is connected to the internet"""
try:
urllib.request.urlopen(host)
return True
except URLError:
return False

View file

@ -1,113 +0,0 @@
import os
import typing as t
from pathlib import Path
import colorama
import inquirer.shortcuts
from src.util.command import run_cmd, run_root_cmd
colorama.init(autoreset=True)
class InvalidPackage(Exception):
pass
class PackageAlreadyInstalled(Exception):
pass
def is_installed(pkg: str) -> bool:
"""Check if the package is already installed in the system"""
return run_cmd(f"pacman -Qi {pkg}", capture_out=True).returncode != 1
def pacman_install(package: str) -> None:
"""Install given `package`"""
run_root_cmd(f"pacman -S {package}")
def yay_install(package: str) -> None:
"""Install give package via `yay` (from AUR)"""
run_cmd(f"yay -S {package}")
def git_install(url: str) -> None:
"""Clone a git repository with given `url`"""
dir_name = Path(url.split("/")[-1].replace(".git", ""))
if dir_name.exists():
print(f"{colorama.Style.DIM}Git repository {dir_name} already exists")
ret_code = run_cmd(f"git clone {url}").returncode
if ret_code == 128:
print(f"{colorama.Fore.RED}Unable to install git repository {url}")
return
if not Path(dir_name, "PKGBUILD").exists:
print(f"{colorama.Fore.YELLOW}Git repository {dir_name} doesn't contain PKGBUILD, only downloaded.")
return
if inquirer.shortcuts.confirm("Do you wish to run makepkg on the downloaded git repository?"):
cwd = os.getcwd()
os.chdir(dir_name)
run_cmd("makepkg -si")
os.chdir(cwd)
run_cmd(f"rm -rf {dir_name}")
else:
os.makedirs("download")
run_cmd(f"mv {dir_name} download/")
print(f"{colorama.Style.DIM}Your git repository was cloned into `download/{dir_name}`")
class Package:
def __init__(self, name: str, aur: bool = False, git: bool = False):
self.name = name
self.aur = aur
self.git = git
if self.git:
self._resolve_git_package()
def _resolve_git_package(self) -> None:
"""Figure out `git_url` variable from `name`."""
if "/" not in self.name:
raise InvalidPackage("You need to specify both author and repository name for git packages (f.e. `ItsDrike/dotfiles`)")
if "http://" in self.name or "https://" in self.name:
self.git_url = self.name
else:
self.git_url = f"https://github.com/{self.name}"
def install(self) -> None:
if not self.git and is_installed(self.name):
raise PackageAlreadyInstalled(f"Package {self} is already installed")
if self.aur:
if not is_installed("yay"):
raise InvalidPackage(f"Package {self} can't be installed (missing `yay` - AUR installation software), alternatively, you can use git")
yay_install(self.name)
elif self.git:
git_install(self.git_url)
else:
pacman_install(self.name)
def __repr__(self) -> str:
if self.git:
if self.name == self.git_url:
return f"<Git package: {self.name}>"
return f"<Git package: {self.name} ({self.git_url})>"
elif self.aur:
return f"<Aur package: {self.name}>"
return f"<Package: {self.name}>"
@classmethod
def safe_load(cls, packages: t.List[str], aur: bool = False, git: bool = False) -> t.List["Package"]:
loaded_packages = []
for package in packages:
try:
loaded_packages.append(cls(package, aur=aur, git=git))
except InvalidPackage as e:
print(f"{colorama.Fore.RED}{str(e)}")
return loaded_packages

19
tox.ini
View file

@ -1,19 +0,0 @@
[flake8]
max_line_length=150
import-order-style=pycharm
application_import_names=src
exclude=
.venv/**,
.git/**
ignore=
# Ignore missing return type annotations for special methods
ANN204
# Ignore missing type annotations
ANN101 # Init
ANN102 # cls
ANN002, # *Args
ANN003, # **Kwargs
# Allow lambdas
E731
# Allow markdown inline HTML
MD033