|
#!/usr/bin/env python |
|
# pylint: disable=line-too-long,missing-module-docstring |
|
|
|
import os |
|
import sys |
|
import logging |
|
import platform |
|
import subprocess |
|
|
|
class SetupDevice(): |
|
"""Executes my new device setup flows""" |
|
logger: logging.Logger |
|
ssh_setup_script = 'https://gist.githubusercontent.com/koiralakiran1/fd33f2b6162f827a0a90a7c45011df53/raw/8dca96fcf5ea49b3c353fa6f437da28bb1c7baef/setup_github_ssh_keys.sh' |
|
default_browser_preference = 'brave-bin' # Pacman's "brave-browser" doesn't work for some reason |
|
|
|
# Dotfiles specific config |
|
clone_directory = os.path.expanduser('~/dotfiles') |
|
link_files_script_path_in_dotfiles = 'v2/home/.scripts/link_files.py' |
|
|
|
def __init__(self) -> None: |
|
self.logger = self._get_logger() |
|
|
|
def _get_logger(self): |
|
handler = logging.StreamHandler() |
|
handler.setLevel(logging.NOTSET) |
|
handler.setFormatter(self._CustomFormatter()) |
|
|
|
logger = logging.getLogger('SetupDevice') |
|
logger.setLevel(logging.DEBUG) |
|
logger.addHandler(handler) |
|
return logger |
|
|
|
def _ask_yes_no(self, question: str, defaultValue = 'no'): |
|
answer = input(f'{question} (y/n/yes/no, default = {defaultValue}): ') or defaultValue |
|
return answer.lower() == 'yes' or answer.lower() == 'y' |
|
|
|
def _exec_full(self, filepath): |
|
global_namespace = { |
|
"__file__": filepath, |
|
"__name__": "__main__", |
|
} |
|
with open(filepath, 'rb') as file: |
|
exec(compile(file.read(), filepath, 'exec'), global_namespace) |
|
|
|
def _sync_packages(self): |
|
if self._ask_yes_no('Sync packages?', 'y'): |
|
self.logger.info('Syncing pacman package list. (sudo pacman -Sy)') |
|
subprocess.run(['sudo', 'pacman', '-Sy'], check=True) |
|
|
|
def _instal_necessary_utilities(self): |
|
self.logger.info('Installing yay and necessary utilities using pacman..') |
|
subprocess.run(['sudo', 'pacman', '-S', '--needed', 'curl', 'wget', 'bash', 'git', 'base-devel', 'yay'], check=True) |
|
|
|
def _install_preferred_browser(self): |
|
preferred_browser = input(f'Enter preferred browser (default = {self.default_browser_preference}): ') or self.default_browser_preference |
|
self.logger.info('Installing %s...', preferred_browser) |
|
subprocess.run(['yay', '-S', '--needed', preferred_browser], check=True) |
|
self.logger.info('Now open %s and sync it; Setup password manager, accounts etc.', preferred_browser) |
|
input('Press any key to continue...') |
|
|
|
def _setup_github_ssh_access(self): |
|
""" |
|
Setup ssh access to github. Using existing shell file from gist |
|
TODO: Make python version of the shell file |
|
""" |
|
if not self._ask_yes_no('Do you have git ssh setup already?'): |
|
self.logger.info('Setting up new github ssh access') |
|
self.logger.info('Running "%s"', self.ssh_setup_script) |
|
os.system(f'bash <(curl -s {self.ssh_setup_script})') |
|
self.logger.info('Github ssh access setup complete!') |
|
else: |
|
self.logger.info('Skipping ssh setup...') |
|
|
|
def _clone_dotfiles(self): |
|
dotfiles_profile = input('Enter github profile to clone "dotfiles" repo from: ') |
|
dotfiles_link = f'git@github.com:{dotfiles_profile}/dotfiles.git' |
|
|
|
# Backup existing dotfiles if any |
|
self.logger.info('Backing up existing dotfiles if exists') |
|
subprocess.run(['mv', '-f', self.clone_directory, f'{self.clone_directory}.bkp'], check=False) |
|
|
|
# Clone dotfiles |
|
self.logger.info('Cloning dotfiles from %s to %s', dotfiles_link, self.clone_directory) |
|
subprocess.run(['git', 'clone', dotfiles_link, self.clone_directory], check=True) |
|
self.logger.info('Dotfiles cloned!') |
|
|
|
def _execute_link_files(self): |
|
if self._ask_yes_no('Link files?'): |
|
self.logger.info('Executing link-files') |
|
self._exec_full(os.path.expanduser(f'{self.clone_directory}/{self.link_files_script_path_in_dotfiles}')) |
|
self.logger.info('Linked files!') |
|
|
|
def _install_package_list(self): |
|
if self._ask_yes_no('Install ~/.packagelist?', 'yes'): |
|
subprocess.run(['install-packagelist'], check=True) |
|
self.logger.info('All packages from packagelist are installed!') |
|
|
|
class _CustomFormatter(logging.Formatter): |
|
"""Custom log formatter""" |
|
grey = "\x1b[38m" |
|
green = "\x1B[32m" |
|
yellow = "\x1b[33m" |
|
red = "\x1b[31m" |
|
bold_red = "\x1b[31;1m" |
|
reset = "\x1b[0m" |
|
message_format = "%(asctime)s - %(name)s - %(levelname)s -> %(message)s (%(filename)s:%(lineno)d)" |
|
|
|
FORMATS = { |
|
logging.DEBUG: grey + message_format + reset, |
|
logging.INFO: green + message_format + reset, |
|
logging.WARNING: yellow + message_format + reset, |
|
logging.ERROR: red + message_format + reset, |
|
logging.CRITICAL: bold_red + message_format + reset |
|
} |
|
|
|
def format(self, record): |
|
log_fmt = self.FORMATS.get(record.levelno) |
|
formatter = logging.Formatter(log_fmt) |
|
return formatter.format(record) |
|
|
|
def main(self): |
|
"""Main function to run setup device flow""" |
|
self.logger.info('Setting up new system: %s', platform.node()) |
|
self._sync_packages() |
|
self._instal_necessary_utilities() |
|
self._install_preferred_browser() |
|
self._setup_github_ssh_access() |
|
self._clone_dotfiles() |
|
self._execute_link_files() |
|
self.logger.info('Now install packagelist. Run `install-packagelist`') |
|
self._install_package_list() |
|
self.logger.info('Setup Complete!') |
|
|
|
if __name__ == "__main__": |
|
obj = SetupDevice() |
|
sys.exit(obj.main()) |