mirror of
https://github.com/ItsDrike/dotfiles.git
synced 2024-12-27 05:34:35 +00:00
Remove autodeploy scripts
This commit is contained in:
parent
b67f74d539
commit
21ca7d9f09
|
@ -1,113 +0,0 @@
|
||||||
# Arch installation checklist
|
|
||||||
This file contains simplified instructions for Arch Linux installation
|
|
||||||
Following these should lead to a full installation of barebone Arch system,
|
|
||||||
with grub bootloader and a priviledged sudoer user.
|
|
||||||
|
|
||||||
Note: Running the script can automated many of these points, if you are comming
|
|
||||||
here after running the script, look for a line saying: **Proceed from this line, if you're reading after chrooting**
|
|
||||||
## Set keyboard layout
|
|
||||||
Default layout will be US
|
|
||||||
`ls /usr/share/kbd/keymaps/**/*.map.gz` <- list keymaps
|
|
||||||
`loadkeys de-latin1` <- modify layout
|
|
||||||
|
|
||||||
## Verify boot mode
|
|
||||||
`ls /sys/firmware/efi/efivars` <- if exist, system is UEFI, else legacy BIOS
|
|
||||||
|
|
||||||
## Internet connection
|
|
||||||
Ethernet connection is automatic, WiFi:
|
|
||||||
`ip link` <- check network interface works and is enabled
|
|
||||||
`iwctl` <- authenticate to your WiFi network
|
|
||||||
|
|
||||||
`ping archlinux.org` <- test connection
|
|
||||||
|
|
||||||
## System clock
|
|
||||||
`timedatectl set-ntp true` <- make sure the clock will be accurate
|
|
||||||
`timedatectl status` <- check the status
|
|
||||||
|
|
||||||
## Partition the disk
|
|
||||||
`fdisk /dev/sdX` <- make partitions
|
|
||||||
- EFI (if UEFI)
|
|
||||||
- Swap
|
|
||||||
- Root
|
|
||||||
- (Home)
|
|
||||||
|
|
||||||
## Format the partitions and make filesystems
|
|
||||||
`mkfs.ext4 /dev/root_partition`
|
|
||||||
`mkfs.fat -F32 /dev/efi_system_partition`
|
|
||||||
`mkswap /dev/swap_partition`
|
|
||||||
|
|
||||||
## Mount the file systems
|
|
||||||
`mount /dev/root_partition /mnt`
|
|
||||||
`mount /dev/efi_system_partition /mnt/boot`
|
|
||||||
`swapon /dev/swap_partition`
|
|
||||||
|
|
||||||
## Install essentials
|
|
||||||
First select mirrors (`/etc/pacman.d/mirrorlist`)
|
|
||||||
`pacstrap /mnt base linux linux-firmware base-devel NetworkManager vim`
|
|
||||||
|
|
||||||
## Fstab
|
|
||||||
`genfstab -U /mnt >> /mnt/etc/fstab`
|
|
||||||
|
|
||||||
## Chroot
|
|
||||||
`arch-chroot /mnt`
|
|
||||||
# Proceed from this line, if you're reading after chrooting
|
|
||||||
|
|
||||||
## Set time zone
|
|
||||||
`ln -sf /usr/share/zoneinfo/Region/Ciry /etc/localtime` <- specify timezone
|
|
||||||
`hwclock --systohc` <- synchronize clock, to generate `/etc/adjtime`
|
|
||||||
|
|
||||||
## Localization
|
|
||||||
Edit `/etc/locale.gen` and uncomment `en_US.UTF-8 UTF-8` and ISO locales
|
|
||||||
`locale-gen` <- Generate locales
|
|
||||||
|
|
||||||
Set LANG variable in `locale.conf`:
|
|
||||||
```
|
|
||||||
LANG=en_US.UTF-8
|
|
||||||
```
|
|
||||||
|
|
||||||
Set persistent keyboard layout in `/etc/vconsole.conf`
|
|
||||||
(This will default to english, if not set)
|
|
||||||
```
|
|
||||||
KEYMAP=de-latin1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Network Config
|
|
||||||
Define hostname in `/etc/hostname` (name of computer)
|
|
||||||
Add matching entries to `/etc/hosts`
|
|
||||||
```
|
|
||||||
127.0.0.1 localhost
|
|
||||||
::1 localhost
|
|
||||||
127.0.1.1 hostname.localdomain hostname
|
|
||||||
```
|
|
||||||
|
|
||||||
## Set root password or make other account
|
|
||||||
`passwd` <- Set root password
|
|
||||||
|
|
||||||
It's better to work with priviledged user rather than root account directly.
|
|
||||||
To do this, we first have to install `sudo` and `vim`. (We did this with `pacstrap`)
|
|
||||||
After that, we can edit the configuration by `sudo EDITOR=vim visudo`, in which we will uncomment the line `%wheel ALL=(ALL) ALL` and save
|
|
||||||
|
|
||||||
After sudo is set up and `wheel` group is allowed to use it, we can make the user:
|
|
||||||
`useradd -G wheel,admin -d /path/to/home -m username -`
|
|
||||||
`passwd username`
|
|
||||||
|
|
||||||
After this, we can login as this user and make sure everything works as it shoud:
|
|
||||||
`sudo su username`
|
|
||||||
|
|
||||||
## Install bootloader
|
|
||||||
This will only cover grub, for other bootloaders, visit `https://wiki.archlinux.org/index.php/Arch_boot_process#Boot_loader`
|
|
||||||
|
|
||||||
Install `grub` package with pacman
|
|
||||||
Note: To detect other operating systems too, you will also need `os-prober` package, also with NTFS systems, if windows isn't detected, try installing `ntfs-3g` and remounting
|
|
||||||
|
|
||||||
|
|
||||||
UEFI:
|
|
||||||
`efibootmgr` package is also needed for UEFI systems
|
|
||||||
`grub-install --target=x86_64-efi --efi-directory=boot --bootloader-id=GRUB`
|
|
||||||
BIOS (Legacy):
|
|
||||||
`grub-install --target=i386-pc /dev/sdX`, where sdX is the disk, **not a partition**
|
|
||||||
|
|
||||||
Note: `--removable` option can be used, which will allow booting if EFI variables are reset or you move to another PC
|
|
||||||
|
|
||||||
### Generating grub configuration
|
|
||||||
`grub-mkconfig -o /boot/grub/grub.cfg`
|
|
|
@ -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
|
|
|
@ -1,5 +0,0 @@
|
||||||
pyyaml
|
|
||||||
psutil
|
|
||||||
colorama
|
|
||||||
pyinquirer
|
|
||||||
inquirer
|
|
|
@ -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()
|
|
|
@ -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()
|
|
|
@ -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()
|
|
|
@ -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()
|
|
|
@ -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()
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
19
tox.ini
|
@ -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
|
|
Loading…
Reference in a new issue