Skip to content

Instantly share code, notes, and snippets.

@mikoloism
Last active January 18, 2024 21:42
Show Gist options
  • Save mikoloism/b149e81beffc301cee3607b67cd2af0d to your computer and use it in GitHub Desktop.
Save mikoloism/b149e81beffc301cee3607b67cd2af0d to your computer and use it in GitHub Desktop.
DOTFILES Installer.py script

DOTFILES (Installer.py script)

Contents:

  • installer.sh
  • installer.py

Requirments:

Python3

$ pip3 install rich textual beaupy 

Makefile

$ make help
$ make init && make install

TODO

  • implement installing function
  • using native progress-bar (maybe tkinter)
  • more packages/dependencies
  • simulate user interact like mouse and keyboard (robot.js or python packages)
  • giving user data and login on there accounts
  • install browser extensions
  • install vscode extensions
  • adding dotfiles
  • setup network configurations (like dns or proxies)
#!/usr/bin/env python3
import json, subprocess
import click
from rich.console import Console
from rich.status import Status
from beaupy import select_multiple, prompt
# globals
console = Console()
status = Status("Running...", console=console)
# functions
class Installer():
def __init__(self, dependencies):
self.dependencies = dependencies
self.dependency = self.dependencies[0]
self.is_verbose = False
def set_verbose(self, verbose = False):
self.is_verbose = verbose
def install(self, commands):
if type(commands) is not list and type(commands) is not str:
raise Exception("<Installer.install(commands)>\n Accepted: List or Str \n Typeof: " + str(type(commands)))
if type(commands) is str:
status.start()
# TODO: options[1]
# output = subprocess.call([command], shell=True)
# TODO: options[2]
# output = subprocess.run([command], shell=True, capture_output=True, encoding='UTF-8')
# TODO: options[3]
process = subprocess.Popen(
[commands],
text=True, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, errors = process.communicate()
if len(errors) > 0:
for line in errors.splitlines():
console.print(f' | [ERROR] {line}')
if self.is_verbose == True:
for line in output.splitlines():
console.print(f' | {line}')
status.stop()
elif type(commands[0]) is dict:
for command in commands:
name = command['name']
status.update(f" | [yellow]{name}[/yellow]")
self.install(command['cmd'])
console.print(f' | [cyan]{name}[/cyan]')
elif type(commands) is list:
for command in commands:
self.install(command)
else:
raise Exception("Typeof <Installer.install(commands)> Not Accepted!")
def install(dependencies, is_verbose=False):
installer = Installer(dependencies)
installer.set_verbose(is_verbose)
selections_length = len(dependencies)
for step in range(selections_length):
dependency = dependencies[step]
name = dependency['name']
command = dependency['cmd']
status.update(f" >>> [yellow]Running[yellow]")
console.print(f" - [bold cyan]{name}[/bold cyan]")
installer.install(command)
class SelectionsFilter():
def __init__(self):
pass
def is_selected(self, dependency):
return dependency['name'] in self.selections
def filter(self, dependencies, selections):
self.selections = selections
return list(filter(self.is_selected, dependencies))
def filter_selections(dependencies, selections):
filter = SelectionsFilter()
return filter.filter(dependencies, selections)
def to_choices(deps):
choices = []
for dep in deps:
choices.append(dep['name'])
return choices
@click.command()
@click.option("--depsfile",
help="path of dependencies as json file")
# default="dependencies.json", show_default=True)
@click.option("--verbose",
help="print each line of <stdout>",
default=False)
def main(depsfile, verbose):
# load dependencies json file
if depsfile is None:
depsfile = prompt("Where is <dependencies.json> file path: ")
raw_dependencies = open(depsfile)
dependencies = json.load(raw_dependencies)
# prompt choices
choices = to_choices(dependencies)
console.print("Choice Each Essential Dependencies:")
default_selections = [t for t in range(len(dependencies))]
selections_choice = select_multiple(options=choices, ticked_indices=default_selections)
# filter selections
selections_dependency = filter_selections(dependencies, selections_choice)
# run installation
install(selections_dependency, verbose)
if __name__ == '__main__':
main()
interface Dep {
name: string;
cmd: DepCmd;
}
interface Cmd {
name: string;
cmd: DepCmd;
}
type DepCmd = Array<string> | Array<Cmd>;
init:
python3 -m venv .venv
. .venv/bin/activate
sudo chmod u+x "$(CURDIR)/main.py"
uninit:
rm -rf .venv
active:
@$(shell . "$(CURDIR)/.venv/bin/activate")
deactive:
deactivate
install:
pip3 install rich textual beaupy click
run:
python3 main.py
help:
@echo "Usage: make <target>"
@echo " | 'make run' - execute main.py file"
@echo " | 'make init' - initial virtualenv"
@echo " | 'make uninit' - remove venv directory"
@echo " | 'make active' - activate virtualenv"
@echo " | 'make deactive' - deactivate virtualenv"
@echo " | 'make install' - install dependencies"
@echo " | 'make help' - display help and usage message"
[
{
"name": "Net Tools",
"cmd": ["sudo apt-get install net-tools"]
},
{
"name": "Curl",
"cmd": ["sudo apt-get install curl"]
},
{
"name": "Python Stuff",
"cmd": [
{
"name": "Install PIP3",
"cmd": ["sudo apt-get install python-pip3"]
},
{
"name": "Install VENV",
"cmd": ["sudo apt-get install python3-venv"]
}
]
},
{
"name": "NeoVim",
"cmd": ["sudo apt-get install neovim"]
},
{
"name": "Ranger File Manager",
"cmd": ["sudo apt-get install ranger"]
},
{
"name": "Node.js Stuff",
"cmd": [
{
"name": "Install Volta",
"cmd": [
"curl https://get.volta.sh | bash",
"volta setup"
]
},
{
"name": "Install Node.js",
"cmd": ["volta install node"]
},
{
"name": "Install NPM",
"cmd": ["volta install npm"]
},
{
"name": "Install Yarn",
"cmd": ["volta install yarn"]
},
{
"name": "Install PNPM",
"cmd": [
"volta install pnpm",
"pnpm setup"
]
},
{
"name": "Install npm:typescript",
"cmd": ["npm install --global typescript"]
},
{
"name": "Install npm:zx",
"cmd": ["npm install --global zx"]
}
]
},
{
"name": "Deno",
"cmd": [
{
"name": "Download",
"cmd": ["curl -fsSL https://deno.land/install.sh | sh"]
},
{
"name": "Configure to $PATH",
"cmd": [
"echo '# deno' >> \"$HOME/.bashrc\"",
"echo 'export DENO_INSTALL=\"$HOME/.deno\"' >> \"$HOME/.bashrc\"",
"echo 'case \":$PATH:\" in' >> \"$HOME/.bashrc\"",
"echo ' *\":$DENO_INSTALL:\"*) ;;' >> \"$HOME/.bashrc\"",
"echo ' *) export PATH=\"$DENO_INSTALL/bin:$PATH\" ;;' >> \"$HOME/.bashrc\"",
"echo 'esac' >> \"$HOME/.bashrc\"",
"echo '# deno end' >> \"$HOME/.bashrc\""
]
}
]
},
{
"name": "Microsoft VSCode",
"cmd": ["sudo snap install --classic code"]
},
{
"name": "Brave Browser",
"cmd": [
{
"name": "Sign GPG",
"cmd": ["sudo curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg"]
},
{
"name": "Add to Repository",
"cmd": ["echo \"deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main\"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list"]
},
{
"name": "Update Repository",
"cmd": ["sudo apt-get update"]
},
{
"name": "Install",
"cmd": ["sudo apt-get install brave-browser"]
}
]
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment