Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36d3c6f992 | |||
| 217ccadc74 |
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# PYTHON_ARGCOMPLETE_OK
|
||||||
|
|
||||||
|
# TODO: Re-export the config stuff
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from app import run as _run
|
||||||
|
|
||||||
|
_run()
|
||||||
Executable → Regular
+5
-8
@@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
# The main app
|
||||||
# PYTHON_ARGCOMPLETE_OK
|
|
||||||
|
|
||||||
from typing import cast
|
from typing import cast
|
||||||
import cli.args as cliargs
|
import cli as cliargs
|
||||||
|
|
||||||
import commands.commit as commit
|
import commands.commit as commit
|
||||||
import commands.config as config
|
import commands.config as config
|
||||||
@@ -11,10 +9,9 @@ import commands.pull as pull
|
|||||||
import commands.push as push
|
import commands.push as push
|
||||||
import commands.prepare as setup
|
import commands.prepare as setup
|
||||||
import commands.show as show
|
import commands.show as show
|
||||||
from config import load_config
|
|
||||||
from presets import ArchMgrTemplates
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
def run():
|
||||||
args, ap = cliargs.add_cli_args()
|
args, ap = cliargs.add_cli_args()
|
||||||
|
|
||||||
if args.cmd == None:
|
if args.cmd == None:
|
||||||
@@ -33,7 +30,7 @@ if __name__ == "__main__":
|
|||||||
\\___/
|
\\___/
|
||||||
""")
|
""")
|
||||||
|
|
||||||
conf = load_config("config.yml")
|
conf = {}
|
||||||
try:
|
try:
|
||||||
if args.cmd == "commit":
|
if args.cmd == "commit":
|
||||||
commit.commit(conf, args.force, args.no_render)
|
commit.commit(conf, args.force, args.no_render)
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
|
# CLI argument parsing and setup for it
|
||||||
import argparse
|
import argparse
|
||||||
import argcomplete
|
import argcomplete
|
||||||
|
|
||||||
from cli.commands import commit, config, init, pull, push, show
|
from args import commit, init, pull, push, show
|
||||||
|
|
||||||
|
|
||||||
def add_cli_args():
|
def add_cli_args():
|
||||||
@@ -22,7 +23,7 @@ def add_cli_args():
|
|||||||
# └ ┘
|
# └ ┘
|
||||||
sp.add_parser("setup", help="Do initial setup, like installing required tools")
|
sp.add_parser("setup", help="Do initial setup, like installing required tools")
|
||||||
commit.add_parser(sp)
|
commit.add_parser(sp)
|
||||||
config.add_parser(sp)
|
sp.add_parser("config", help="prints information about your config")
|
||||||
init.add_parser(sp)
|
init.add_parser(sp)
|
||||||
pull.add_parser(sp)
|
pull.add_parser(sp)
|
||||||
push.add_parser(sp)
|
push.add_parser(sp)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# Declare a file explicitly if it has different permissions
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def clone_git_repo(repo_url: str, clone_path: str, branch: str = "DEFAULT"):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
def add_packages(pkgs: list[str]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def add_package_bundles(pkgs: list[str]):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def enable_reflector():
|
||||||
|
pass
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def enable_repo(name: str):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
def add_template_data(name: str, data: str):
|
||||||
|
"""Replace all occurrences of variable specified by `name` by
|
||||||
|
the specified data
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The variable to replace
|
||||||
|
data: The data to replace it with
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def add_template_array(name: str, template: str, data: list[str]):
|
||||||
|
"""Replace all occurrences of variable specified by `name` in the files with
|
||||||
|
the specified template, where {{ data }} is replaced with the each element
|
||||||
|
of the data argument
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The name of the variable to replace
|
||||||
|
template:
|
||||||
|
Template syntax, with {{ data }} as variable, see example below or docs.
|
||||||
|
Recursive replacement is supported up to one layer deep
|
||||||
|
data: A list of data that is substituted into the {{ data }} variable in the template
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```python
|
||||||
|
add_template_array("test", "- Hello World {{ data }}\\n", [0, 1])
|
||||||
|
```
|
||||||
|
for example replaces {{ test }} in a file with
|
||||||
|
```
|
||||||
|
- Hello World 0
|
||||||
|
|
||||||
|
- Hello World 1
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
# TODO: Recursive replacement
|
||||||
|
pass
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
|
def add_custom_theme():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def custom_theme_color_source(src: Literal["wallpaper"] | Literal["default"]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: For desktop environments, what command??
|
||||||
|
def set_wallpaper(path: str):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def set_gtk_theme():
|
||||||
|
pass
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from commands.util.password_manager import PasswordManager
|
from password_mgr import PasswordManager
|
||||||
|
|
||||||
|
|
||||||
def choice(default: str, options: str, msg: str) -> str:
|
def choice(default: str, options: str, msg: str) -> str:
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import subprocess as sp
|
import subprocess as sp
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from commands.util.input_mgr import password
|
from util.input import password
|
||||||
|
|
||||||
pkg_manager = ["yay", "--noconfirm"]
|
pkg_manager = ["yay", "--noconfirm"]
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import list
|
||||||
|
import diff
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
import colorama as cl
|
import colorama as cl
|
||||||
|
|
||||||
from commands.util.printing.list import print_list
|
from list import print_list
|
||||||
|
|
||||||
|
|
||||||
def print_diff(add: List[str], remove: List[str]):
|
def print_diff(add: List[str], remove: List[str]):
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import argparse as ap
|
|
||||||
|
|
||||||
|
|
||||||
def add_parser(sp: ap._SubParsersAction[ap.ArgumentParser]):
|
|
||||||
config = sp.add_parser(
|
|
||||||
"config", help="prints information about your config and change some of them"
|
|
||||||
)
|
|
||||||
conf_sp = config.add_subparsers(title="config options", dest="conf", required=True)
|
|
||||||
conf_sp.add_parser("show", help="show config options")
|
|
||||||
config_update = conf_sp.add_parser(
|
|
||||||
"update", help="update the configuration from various"
|
|
||||||
)
|
|
||||||
conf_update_sp = config_update.add_subparsers(
|
|
||||||
title="Options for automatic configuration updates",
|
|
||||||
dest="conf_update",
|
|
||||||
required=True,
|
|
||||||
)
|
|
||||||
conf_update_sp.add_parser(
|
|
||||||
"pkgs",
|
|
||||||
help="Update the config to reflect the package state of the current system",
|
|
||||||
)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
from commands.util import pacman
|
|
||||||
from commands.util.diff import pkg_diff
|
|
||||||
from commands.util.input_mgr import confirm, password
|
|
||||||
|
|
||||||
from commands.util.printing.diff import print_diff
|
|
||||||
from config.dtype import ArchMgrConfig
|
|
||||||
|
|
||||||
|
|
||||||
def commit(config: ArchMgrConfig, force: bool = False, no_render: bool = False):
|
|
||||||
"""Commit the changes to the system
|
|
||||||
|
|
||||||
Args:
|
|
||||||
force: Apply, overriding any changes since the last commit without confirming
|
|
||||||
no_render: Don't rerender the templates (use cached version).
|
|
||||||
Will be ignored if cache is unavailable (and prompt the user)
|
|
||||||
"""
|
|
||||||
# TODO: Make sure we don't uninstall critical system packages by accident (i.e. prompt user)
|
|
||||||
# Probably do that check in the pacman util lib tho
|
|
||||||
add, remove = pkg_diff(config["pkgs"]["individual"] or [], pacman.list_explicitly_installed())
|
|
||||||
print_diff(add, remove)
|
|
||||||
if confirm(False, "Do you really want to proceed?"):
|
|
||||||
pacman.install_package_list(add)
|
|
||||||
pacman.uninstall_package_list(remove)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import argparse
|
|
||||||
from config.dtype import ArchMgrConfig
|
|
||||||
|
|
||||||
|
|
||||||
def config(args: argparse.Namespace, config: ArchMgrConfig):
|
|
||||||
if args.conf == "show":
|
|
||||||
print("""
|
|
||||||
Your config can be found at
|
|
||||||
""")
|
|
||||||
print(config)
|
|
||||||
elif args.conf_update == "pkgs":
|
|
||||||
print("Updating config's package list")
|
|
||||||
# TODO: Config saver
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
import commands.util.git as git
|
|
||||||
from commands.util.input_mgr import confirm
|
|
||||||
|
|
||||||
|
|
||||||
def init(force: bool = False):
|
|
||||||
dir = os.getcwd()
|
|
||||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
if force:
|
|
||||||
if confirm(
|
|
||||||
False,
|
|
||||||
"Do you really want to IRREVERSIBLY DELETE the contents of this folder and redo setup?",
|
|
||||||
):
|
|
||||||
[os.remove(file) for file in os.listdir(dir)]
|
|
||||||
git.init(dir)
|
|
||||||
os.mkdir(dir + "/config")
|
|
||||||
os.mkdir(dir + "/system")
|
|
||||||
os.mkdir(dir + "/includes")
|
|
||||||
shutil.copy(script_dir + "/templates/config.yml", dir + "/config.yml")
|
|
||||||
shutil.copy(script_dir + "/templates/system/", dir + "/includes/system/")
|
|
||||||
shutil.copy(script_dir + "/templates/templates/", dir + "/includes/templates/")
|
|
||||||
shutil.copy(script_dir + "/templates/README.md", dir + "/README.md")
|
|
||||||
print("Initialized a new archmgr repository")
|
|
||||||
# TODO: Instead of copying things over, clone the template repo, then copy its contents to the new repo?
|
|
||||||
# TODO: For the files, store the permissions in a db
|
|
||||||
# TODO: Warn user to not delete .config/archmgr repo
|
|
||||||
# TODO: Set up that repo (where to put it? /usr/share? or .config?)
|
|
||||||
# TODO: Consider collecting function -> If no files present, will only collect the pkgs, else also the files
|
|
||||||
# TODO: Also store the folder name of the config folder in that repo (needs to be easily changeable for user!)
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
|
|
||||||
from commands.util import pacman
|
|
||||||
from commands.util.input_mgr import confirm
|
|
||||||
|
|
||||||
|
|
||||||
def setup():
|
|
||||||
print("==> Installing required packages")
|
|
||||||
if not pacman.install_package_list(["git"]):
|
|
||||||
print("Git installation failed")
|
|
||||||
return
|
|
||||||
|
|
||||||
subprocess.run(
|
|
||||||
["git", "clone", "https://aur.archlinux.org/yay.git"],
|
|
||||||
cwd="/tmp",
|
|
||||||
capture_output=True,
|
|
||||||
)
|
|
||||||
yay_install = subprocess.run(
|
|
||||||
["makepkg", "-si"], cwd="/tmp/yay", capture_output=True
|
|
||||||
)
|
|
||||||
|
|
||||||
if yay_install.returncode != 0:
|
|
||||||
print("==> Installation of yay failed")
|
|
||||||
if confirm(True, "Do you wish to view the logs?"):
|
|
||||||
print(yay_install.stdout, "\n", yay_install.stderr)
|
|
||||||
return
|
|
||||||
|
|
||||||
print("==> Installation completed")
|
|
||||||
|
|
||||||
# TODO: Check if yay is available before installing
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
from config.dtype import ArchMgrConfig
|
|
||||||
|
|
||||||
|
|
||||||
def pull(config: ArchMgrConfig, rebase: bool = False, apply: bool = False):
|
|
||||||
print("pull")
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
def push(force: bool = False):
|
|
||||||
print("push")
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import argparse
|
|
||||||
|
|
||||||
from config.dtype import ArchMgrConfig
|
|
||||||
from templates import ArchMgrTemplates
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: Templates data
|
|
||||||
def show(
|
|
||||||
config: ArchMgrConfig,
|
|
||||||
spec: ArchMgrTemplates,
|
|
||||||
args: argparse.Namespace,
|
|
||||||
):
|
|
||||||
"""Show details / information about things like contents pkg bundles
|
|
||||||
|
|
||||||
Args:
|
|
||||||
config: The configuration
|
|
||||||
spec: The archmgr templates that were loaded
|
|
||||||
kind: The type of information to get
|
|
||||||
arg: The arg for the command (e.g. bundle name)
|
|
||||||
"""
|
|
||||||
print(args)
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
# yaml-language-server: $schema=config.schema.json
|
|
||||||
# TODO: Change the above to an import URL instead
|
|
||||||
requires:
|
|
||||||
- path/to/other/configs/relative/to/this # Reads the other configs after finishing this one
|
|
||||||
|
|
||||||
pkgs:
|
|
||||||
individual:
|
|
||||||
- pkg_name
|
|
||||||
bundles:
|
|
||||||
- name: hyprland
|
|
||||||
repos:
|
|
||||||
reflector:
|
|
||||||
enabled: false
|
|
||||||
countries:
|
|
||||||
- Switzerland
|
|
||||||
|
|
||||||
users:
|
|
||||||
- username: username
|
|
||||||
groups:
|
|
||||||
- group_1
|
|
||||||
home_dir: True
|
|
||||||
|
|
||||||
boot:
|
|
||||||
managed: True
|
|
||||||
bootloader: grub
|
|
||||||
esp_dir: /boot/
|
|
||||||
theme_folder: ~/.path/to/theme/
|
|
||||||
os_prober: False
|
|
||||||
# Also copies over the /etc/default/grub config or equivalent for other supported bootloaders
|
|
||||||
|
|
||||||
# TODO: Desktops, login managers, full disk encryption etc configuration?
|
|
||||||
|
|
||||||
themes:
|
|
||||||
gtk: theme_name
|
|
||||||
qt: theme_name # or use_gtk to use the gtk theme instaed
|
|
||||||
font: Comfortaa 11 # the font name to be used (also needs to be installed)
|
|
||||||
icon_theme: candy-icons # The icon theme to use (also needs to be installed)
|
|
||||||
cursor_theme: oreo_spark_blue_cursors # TODO: Consider if GTK settings file should just be copied
|
|
||||||
|
|
||||||
git:
|
|
||||||
creds:
|
|
||||||
manager: git-credential-manager # or none
|
|
||||||
repos:
|
|
||||||
- url: https://github.com/janishutz/janishutz
|
|
||||||
clone_path: ~/projects/ # Project location will be clone_path/<repo name>
|
|
||||||
- url: git@git.janishutz.com:janishutz/nvim
|
|
||||||
clone_path: ~/projects/ # Project location will be clone_path/<repo name>
|
|
||||||
|
|
||||||
template_data:
|
|
||||||
- name: template_data_name
|
|
||||||
data: the_data
|
|
||||||
|
|
||||||
cmds:
|
|
||||||
always:
|
|
||||||
- cmd: "cmd to run every time archmgr is run"
|
|
||||||
once:
|
|
||||||
- name: "cmd1"
|
|
||||||
cmd: "cmd to run on first execution of archmgr (or if not executed previously)"
|
|
||||||
@@ -1,460 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"requires": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^([a-zA-Z0-9.-_]+\\/)+",
|
|
||||||
"description": "Path to other configs, relative to this file (e.g. config/pkgs.yaml will expand to dirname(this_file)/config/pkgs.yaml)"
|
|
||||||
},
|
|
||||||
"description": "Imports for other config files that will be merged into this one. Precedence order is bottom up (i.e. lowest has highest precedence)"
|
|
||||||
},
|
|
||||||
"pkgs": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "The packages to be installed",
|
|
||||||
"properties": {
|
|
||||||
"individual": {
|
|
||||||
"type:": "array",
|
|
||||||
"description": "the packages to be installed, by their package name",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[a-z0-9-._]+(?=[a-z0-9]$)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"repos": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"reflector": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Use reflector to update the mirrors",
|
|
||||||
"properties": {
|
|
||||||
"enabled": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"interval": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "The number of days to elapse between reflector reruns"
|
|
||||||
},
|
|
||||||
"countries": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "The countries in which the should be located (only applies for the main arch repos)",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[A-Z][a-z]*[a-z]$"
|
|
||||||
},
|
|
||||||
"maxItems": 5,
|
|
||||||
"minItems": 1
|
|
||||||
},
|
|
||||||
"count": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "The number of mirrors to add to the list",
|
|
||||||
"maximum": 20,
|
|
||||||
"minimum": 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"enabled"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bundles": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Bundled packages, installing all the recommended extra software for them (such as hyprland and nvim)",
|
|
||||||
"maxItems": 1,
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The bundle name",
|
|
||||||
"pattern": "^[a-z0-9-._]+(?=[a-z0-9]$)"
|
|
||||||
},
|
|
||||||
"ignored_pkgs": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of packages from the bundle that should not be installed",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[a-z0-9-._]+(?=[a-z0-9]$)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"name"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"boot": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Settings for the bootloader, such as theme, using os-prober, etc",
|
|
||||||
"properties": {
|
|
||||||
"managed": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether or not to manage the bootloader using archmgr"
|
|
||||||
},
|
|
||||||
"bootloader": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The bootloader to use (more coming eventually)",
|
|
||||||
"pattern": "^(grub)"
|
|
||||||
},
|
|
||||||
"esp_dir": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The directory for the bootloader files. Has to end in slash",
|
|
||||||
"pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$"
|
|
||||||
},
|
|
||||||
"theme_folder": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Where the folder for the theme is found. Can be relative to the config repo or file system and has to end in slash",
|
|
||||||
"pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$"
|
|
||||||
},
|
|
||||||
"os_prober": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether to enable OS prober to search for other operating systems"
|
|
||||||
},
|
|
||||||
"kernel_params": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The kernel arguments to pass in"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"managed"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"themes": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"gtk": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The GTK theme to use. To use the custom generated theme, set this to Adaptive-Theme and set the Qt theme to gtk3"
|
|
||||||
},
|
|
||||||
"qt": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Qt theme to use. Write gtk3 to use the GTK theme instead",
|
|
||||||
"default": "gtk3"
|
|
||||||
},
|
|
||||||
"font": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The font (and size) to use for the interface. Needs to be installed to work",
|
|
||||||
"default": "Comfortaa 11"
|
|
||||||
},
|
|
||||||
"icon_theme": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Which icon theme to use. Needs to be installed to work"
|
|
||||||
},
|
|
||||||
"cursor_theme": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The cursor to use. Needs to be installed to work"
|
|
||||||
},
|
|
||||||
"selected_custom_theme_color": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The custom theme color to use. archmgr comes with 5 defaults than can be used without custom_theme_colors defined",
|
|
||||||
"pattern": "^(nordic|deep-dark|material|light|bright|.*)"
|
|
||||||
},
|
|
||||||
"color_source": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Where to get the colours from",
|
|
||||||
"pattern": "^(wallpaper|default)",
|
|
||||||
"default": "wallpaper"
|
|
||||||
},
|
|
||||||
"wallpaper": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to the wallpaper to use. If supported by manager for wallpaper, can also be folder. Please note that in that case the theme colours will fall back to the default values and will not use the wallpaper"
|
|
||||||
},
|
|
||||||
"custom_theme_colors": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Templates for a custom theme.",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the color theme. This can be used as the"
|
|
||||||
},
|
|
||||||
"base": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the custom_theme to base it off of. Defaults to deep-dark, which is a default theme provided by archmgr",
|
|
||||||
"default": "deep-dark"
|
|
||||||
},
|
|
||||||
"variables": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "The definition of the colors and other variables that override any set in template_data if present there",
|
|
||||||
"properties": {
|
|
||||||
"color-fore-primary": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-fore-accent-1": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-fore-accent-2": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-fore-accent-3": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-back-primary": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-back-accent-1": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-back-accent-2": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-shadow": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-fore-inactive": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"color-back-inactive": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"font-primary": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"font-accent": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"font-mono": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"git": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Automatically set up credential manager and clone repos",
|
|
||||||
"properties": {
|
|
||||||
"repos": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Which repos to clone (removing one from here doesn't delete it from the system and only pulls if folder does not exist)",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "git clone URL (ssh or HTTP(S))",
|
|
||||||
"pattern": "^((https?):\\/\\/(([a-z0-9-]+)((?=\\.))\\.)+[a-z]+(?=\\/)\\/([\\w\\-?.=]+(?=\\/[\\w\\-?.=])\\/)*([\\w\\-?&.=\\/]+(?=[\\w\\-.=\\/]$)))|([a-zA-Z0-9\\-._]+(?=[a-zA-Z0-9])[a-zA-Z0-9])@(([a-z0-9\\-]+(?=\\.))\\.)+[a-z]+(?=:):([a-zA-Z0-9\\-._]+(?=\\/)\\/)+([a-zA-Z0-9\\-._]+(?=[a-zA-Z0-9]$))"
|
|
||||||
},
|
|
||||||
"clone_path": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The location on the local system where to put it. Must be absolute path. Parent folders will be created if they don't exist",
|
|
||||||
"pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"url",
|
|
||||||
"clone_path"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"template_data": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "The data to be inserted into the templates",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"string",
|
|
||||||
"array"
|
|
||||||
],
|
|
||||||
"description": "The type of data included. Can be omitted, which then defaults to string",
|
|
||||||
"default": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"if": {
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"const": "array"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"then": {
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"string",
|
|
||||||
"array"
|
|
||||||
],
|
|
||||||
"description": "The type of data included. Can be omitted, which then defaults to string",
|
|
||||||
"default": "string"
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name that appears in the template"
|
|
||||||
},
|
|
||||||
"items": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"template": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"items",
|
|
||||||
"template",
|
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"else": {
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name that appears in the template"
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"string",
|
|
||||||
"array"
|
|
||||||
],
|
|
||||||
"description": "The type of data included. Can be omitted, which then defaults to string",
|
|
||||||
"default": "string"
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The data that is to be inserted"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"name"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"symlinks": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Symlinks to create",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"destination": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The directory the link should point to",
|
|
||||||
"pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))"
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "What to call the link",
|
|
||||||
"pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cmds": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"once": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Commands to run on only once (uses the name property to determine if it needs to run)",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "This name is used to track if a command was run before."
|
|
||||||
},
|
|
||||||
"cmd": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"hook": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Where in the execution of archmgr to run",
|
|
||||||
"default": "end",
|
|
||||||
"pattern": "^(pre-pkg|post-pkg|pre-git|post-git|end)"
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "root",
|
|
||||||
"pattern": "^[a-zA-Z0-9\\-._]{2,19}(?=[a-zA-Z0-9]$)",
|
|
||||||
"description": "The user to run as. Be aware that only the current user's password is available, unless capture_output is set to false"
|
|
||||||
},
|
|
||||||
"capture_output": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"description": "Whether or not to hide the output from the user"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"name",
|
|
||||||
"cmd"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"always": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Commands to run on each apply",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Used to indicate to user what command is executing. If omitted, will be truncated cmd"
|
|
||||||
},
|
|
||||||
"cmd": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"hook": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Where in the execution of archmgr to run",
|
|
||||||
"default": "end",
|
|
||||||
"pattern": "^(pre-pkg|post-pkg|pre-git|post-git|end)"
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "root",
|
|
||||||
"pattern": "^[a-zA-Z0-9\\-._]{2,19}(?=[a-zA-Z0-9]$)",
|
|
||||||
"description": "The user to run as. Be aware that only the current user's password is available, unless capture_output is set to false"
|
|
||||||
},
|
|
||||||
"capture_output": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"description": "Whether or not to hide the output from the user"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"pkgs",
|
|
||||||
"boot"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
-58
@@ -1,58 +0,0 @@
|
|||||||
# yaml-language-server: $schema=config.schema.json
|
|
||||||
# TODO: Change the above to an import URL instead
|
|
||||||
requires:
|
|
||||||
- ./config-include-test.yml # Reads the other configs after finishing this one
|
|
||||||
# - path/to/other/configs/relative/to/this # Reads the other configs after finishing this one
|
|
||||||
|
|
||||||
pkgs:
|
|
||||||
individual:
|
|
||||||
- acpi
|
|
||||||
- tk
|
|
||||||
- tldr
|
|
||||||
bundles:
|
|
||||||
- name: hyprland
|
|
||||||
repos:
|
|
||||||
reflector:
|
|
||||||
enabled: false
|
|
||||||
countries:
|
|
||||||
- Switzerland
|
|
||||||
|
|
||||||
boot:
|
|
||||||
managed: True
|
|
||||||
bootloader: grub
|
|
||||||
esp_dir: /boot/
|
|
||||||
theme_folder: ~/.path/to/theme/ # This could then be used with git to clone it in
|
|
||||||
os_prober: False
|
|
||||||
# Also copies over the /etc/default/grub config or equivalent for other supported bootloaders
|
|
||||||
|
|
||||||
# TODO: Desktops, login managers, full disk encryption etc configuration?
|
|
||||||
|
|
||||||
themes:
|
|
||||||
gtk: theme_name
|
|
||||||
qt: theme_name # or use_gtk to use the gtk theme instaed
|
|
||||||
font: Comfortaa 11 # the font name to be used (also needs to be installed)
|
|
||||||
icon_theme: candy-icons # The icon theme to use (also needs to be installed)
|
|
||||||
cursor_theme: oreo_spark_blue_cursors # TODO: Consider if GTK settings file should just be copied
|
|
||||||
# TODO: Cursor theme needs more flexibility
|
|
||||||
|
|
||||||
git:
|
|
||||||
repos:
|
|
||||||
- url: https://github.com/janishutz/janishutz
|
|
||||||
clone_path: ~/projects/ # Project location will be clone_path/<repo name>
|
|
||||||
- url: git@git.janishutz.com:janishutz/nvim
|
|
||||||
clone_path: ~/projects/ # Project location will be clone_path/<repo name>
|
|
||||||
|
|
||||||
template_data:
|
|
||||||
- name: template_data_name
|
|
||||||
type: array
|
|
||||||
template: |
|
|
||||||
test {{ data }}
|
|
||||||
items:
|
|
||||||
- test
|
|
||||||
|
|
||||||
cmds:
|
|
||||||
always:
|
|
||||||
- cmd: "cmd to run every time archmgr is run"
|
|
||||||
once:
|
|
||||||
- name: "cmd1"
|
|
||||||
cmd: "cmd to run on first execution of archmgr (or if not executed previously)"
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
from typing import Any, cast
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
from config import validator
|
|
||||||
from config.dtype import ArchMgrConfig
|
|
||||||
from config.merger import merge_configs
|
|
||||||
|
|
||||||
|
|
||||||
def load_config_file(file: str):
|
|
||||||
"""Load and parse the config file.
|
|
||||||
No verification is done and is not cast
|
|
||||||
|
|
||||||
Args:
|
|
||||||
file: The path to the file to be loaded
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The loaded and parsed file.
|
|
||||||
"""
|
|
||||||
with open(file, "r") as f:
|
|
||||||
parsed = yaml.load(f, Loader=yaml.FullLoader)
|
|
||||||
return parsed
|
|
||||||
|
|
||||||
|
|
||||||
def default_config() -> ArchMgrConfig:
|
|
||||||
"""Get the default configuration
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The default config
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
"pkgs": {
|
|
||||||
"individual": [],
|
|
||||||
"bundles": [],
|
|
||||||
"repos": {
|
|
||||||
"enabled_repos": [
|
|
||||||
{
|
|
||||||
"name": "core",
|
|
||||||
"setup_cmds": [],
|
|
||||||
"mirrors": {"use_default": True, "extra_mirrors": []},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"reflector": {
|
|
||||||
"enabled": False,
|
|
||||||
"count": 0,
|
|
||||||
"countries": [],
|
|
||||||
"interval": 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"boot": {
|
|
||||||
"managed": False,
|
|
||||||
"bootloader": "grub",
|
|
||||||
"esp_dir": "/boot",
|
|
||||||
"os_prober": False,
|
|
||||||
"theme_folder": "/usr/share/themes/grub",
|
|
||||||
},
|
|
||||||
"cmds": {"always": [], "once": []},
|
|
||||||
"git": {
|
|
||||||
"repos": [],
|
|
||||||
"creds": {"manager": "git-credential-manager"},
|
|
||||||
},
|
|
||||||
"users": [],
|
|
||||||
"symlinks": [],
|
|
||||||
"template_data": [],
|
|
||||||
"themes": {
|
|
||||||
"cursor_theme": "oreo_spark_blue_cursor",
|
|
||||||
"font": "Comfortaa 11",
|
|
||||||
"gtk": "Adaptive-Theme",
|
|
||||||
"qt": "gtk3",
|
|
||||||
"icon_theme": "candy-icons",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
requires_list: list[str] = []
|
|
||||||
source_list = {} # for each setting, in which files it appears
|
|
||||||
|
|
||||||
|
|
||||||
def load_config(file: str) -> ArchMgrConfig:
|
|
||||||
"""Load the configuration from the specified file path
|
|
||||||
|
|
||||||
Args:
|
|
||||||
file: Path to the file to be loaded
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The loaded, validated and parsed config
|
|
||||||
"""
|
|
||||||
global requires_list, source_list
|
|
||||||
# Load and validate initial config
|
|
||||||
try:
|
|
||||||
loaded_conf = load_config_file(file)
|
|
||||||
except Exception:
|
|
||||||
return default_config()
|
|
||||||
if not validator.validate(loaded_conf):
|
|
||||||
return default_config()
|
|
||||||
|
|
||||||
configuration = cast(dict[str, Any], loaded_conf)
|
|
||||||
requires = cast(list[str], configuration.pop("requires"))
|
|
||||||
|
|
||||||
# Keep track of all files
|
|
||||||
requires_list += requires
|
|
||||||
conf = cast(ArchMgrConfig, configuration)
|
|
||||||
|
|
||||||
# Recursively load files
|
|
||||||
for conf_file in requires:
|
|
||||||
conf = merge_configs(conf, load_config(conf_file))
|
|
||||||
|
|
||||||
return conf
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
from typing import Optional, TypedDict
|
|
||||||
|
|
||||||
from config.dtype.cmds import ArchMgrCmdsConfig
|
|
||||||
from config.dtype.git import ArchMgrGitConfig
|
|
||||||
from config.dtype.others import (
|
|
||||||
ArchMgrBootConfig,
|
|
||||||
ArchMgrSymlinkConfig,
|
|
||||||
ArchMgrTemplateData,
|
|
||||||
ArchMgrThemeConfig,
|
|
||||||
ArchMgrUserConfig,
|
|
||||||
)
|
|
||||||
from config.dtype.pkgs import ArchMgrPkgConfig
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrConfig(TypedDict):
|
|
||||||
pkgs: ArchMgrPkgConfig
|
|
||||||
users: Optional[list[ArchMgrUserConfig]]
|
|
||||||
boot: ArchMgrBootConfig
|
|
||||||
themes: Optional[ArchMgrThemeConfig]
|
|
||||||
git: Optional[ArchMgrGitConfig]
|
|
||||||
template_data: Optional[list[ArchMgrTemplateData]]
|
|
||||||
symlinks: Optional[list[ArchMgrSymlinkConfig]]
|
|
||||||
cmds: Optional[ArchMgrCmdsConfig]
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
from typing import Optional, TypedDict
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrCmdsConfig(TypedDict):
|
|
||||||
always: Optional[list[ArchMgrCommand]]
|
|
||||||
once: Optional[list[ArchMgrCommand]]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrCommand(TypedDict):
|
|
||||||
cmd: str
|
|
||||||
name: Optional[str]
|
|
||||||
capture_output: Optional[bool]
|
|
||||||
hook: Optional[str]
|
|
||||||
user: Optional[str]
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
from typing import Optional, TypedDict
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrGitConfig(TypedDict):
|
|
||||||
creds: Optional[ArchMgrGitCredsConfig]
|
|
||||||
repos: Optional[list[ArchMgrGitRepoConfig]]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrGitCredsConfig(TypedDict):
|
|
||||||
manager: Optional[str]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrGitRepoConfig(TypedDict):
|
|
||||||
clone_path: str
|
|
||||||
url: str
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
from typing import Optional, TypedDict
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrUserConfig(TypedDict):
|
|
||||||
username: str
|
|
||||||
groups: Optional[list[str]]
|
|
||||||
home_dir: Optional[bool]
|
|
||||||
sudo_user: Optional[bool]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrBootConfig(TypedDict):
|
|
||||||
managed: bool
|
|
||||||
bootloader: Optional[str]
|
|
||||||
esp_dir: Optional[str]
|
|
||||||
theme_folder: Optional[str]
|
|
||||||
os_prober: Optional[bool]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrThemeConfig(TypedDict):
|
|
||||||
gtk: Optional[str]
|
|
||||||
qt: Optional[str]
|
|
||||||
font: Optional[str]
|
|
||||||
icon_theme: Optional[str]
|
|
||||||
cursor_theme: Optional[str]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrTemplateData(TypedDict):
|
|
||||||
name: str
|
|
||||||
data: str
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrSymlinkConfig(TypedDict):
|
|
||||||
destination: str
|
|
||||||
location: str
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
from typing import Optional, TypedDict
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrPkgConfig(TypedDict):
|
|
||||||
individual: Optional[list[str]]
|
|
||||||
repos: Optional[ArchMgrReposConfig]
|
|
||||||
bundles: Optional[list[ArchMgrBundleConfig]]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrReposConfig(TypedDict):
|
|
||||||
enabled_repos: Optional[list[ArchMgrRepoSettings]]
|
|
||||||
reflector: Optional[ArchMgrReflectorConfig]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrReflectorConfig(TypedDict):
|
|
||||||
enabled: bool
|
|
||||||
interval: Optional[int]
|
|
||||||
countries: Optional[list[str]]
|
|
||||||
count: Optional[int]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrBundleConfig(TypedDict):
|
|
||||||
name: str
|
|
||||||
ignored_pkgs: Optional[list[str]]
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrRepoSettings(TypedDict):
|
|
||||||
name: str
|
|
||||||
setup_cmds: Optional[list[str]]
|
|
||||||
mirrors: ArchMgrRepoMirrors
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrRepoMirrors(TypedDict):
|
|
||||||
use_default: bool
|
|
||||||
extra_mirrors: Optional[list[str]]
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
from typing import cast
|
|
||||||
from config.dtype import ArchMgrConfig
|
|
||||||
|
|
||||||
|
|
||||||
def merge_configs(config: ArchMgrConfig, new_config: ArchMgrConfig) -> ArchMgrConfig:
|
|
||||||
"""Merge two configs, with the new_config taking precedence over the config
|
|
||||||
in the conflicting fields with arrays and dicts merged
|
|
||||||
|
|
||||||
Args:
|
|
||||||
config: Base config
|
|
||||||
new_config: Config to merge into the base config
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The merged config
|
|
||||||
"""
|
|
||||||
if len(new_config) == 0 or len(config) == 0:
|
|
||||||
return config
|
|
||||||
|
|
||||||
def combine(a: dict, b: dict):
|
|
||||||
combined = {}
|
|
||||||
for key in b:
|
|
||||||
val = b[key]
|
|
||||||
try:
|
|
||||||
a[key]
|
|
||||||
if isinstance(val, dict):
|
|
||||||
combined[key] = combine(val, a[key])
|
|
||||||
elif isinstance(val, list):
|
|
||||||
combined[key] = val
|
|
||||||
for v in a[key]:
|
|
||||||
combined[key].append(v)
|
|
||||||
else:
|
|
||||||
combined[key] = val
|
|
||||||
except KeyError:
|
|
||||||
combined[key] = val
|
|
||||||
|
|
||||||
for key in a:
|
|
||||||
try:
|
|
||||||
b[key]
|
|
||||||
except KeyError:
|
|
||||||
combined[key] = a[key]
|
|
||||||
|
|
||||||
return combined
|
|
||||||
|
|
||||||
# Merge configs (using nasty casts)
|
|
||||||
return cast(ArchMgrConfig, combine(cast(dict, config), cast(dict, new_config)))
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import json
|
|
||||||
import jsonschema
|
|
||||||
|
|
||||||
with open("config.schema.json") as file:
|
|
||||||
schema = json.load(file)
|
|
||||||
|
|
||||||
|
|
||||||
def validate(config: dict | list):
|
|
||||||
"""Validate the specified config
|
|
||||||
|
|
||||||
Args:
|
|
||||||
config: The raw configuration
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if the config is valid, False otherwise
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
jsonschema.validate(config, schema)
|
|
||||||
except jsonschema.SchemaError:
|
|
||||||
print("Schema invalid")
|
|
||||||
return False
|
|
||||||
except jsonschema.ValidationError:
|
|
||||||
print("Config invalid")
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Import the configuration preset templates
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# TODO: Material colors creator
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
def update_users_and_groups():
|
|
||||||
pass
|
|
||||||
@@ -1,84 +1,7 @@
|
|||||||
# Concept for tracking changes
|
# Concepts
|
||||||
- Create new commit (if possible)
|
## Config
|
||||||
- If force is unset: Diff system's files against current state by copying them into the current state branch
|
In python, using functions and args for them
|
||||||
- Then, diff the package state against the state branch by dumping it
|
|
||||||
- Else, or if no diff, continue
|
|
||||||
- Render and copy config files into correct directories
|
|
||||||
- Create config files from presets
|
|
||||||
- Retrieve explicitly installed packages and remove those that are not present in goal and install those that are not present in current state
|
|
||||||
|
|
||||||
|
|
||||||
# Concept for updating config automatically
|
## Init
|
||||||
1. Track which files contain the setting
|
- Copy
|
||||||
2. If there are multiple and is no array, then simply overwrite the last
|
|
||||||
3. If there are multiple and is array, then remove from the file where it is present and add to last file in requires list
|
|
||||||
-> To enable this, update the loader to keep more metadata (list of all requires, list of files for each setting)
|
|
||||||
|
|
||||||
|
|
||||||
# Ideas
|
|
||||||
- [X] function to collect new configs -> Not smart because templates
|
|
||||||
- [ ] Templates foreach (array of arrays or something like it)
|
|
||||||
- [ ] Improved base GTK theme
|
|
||||||
- [ ] config options for users and groups -> Omitted for now
|
|
||||||
- [ ] Wallpaper settings for other WM than hyprland
|
|
||||||
- [ ] presets for things like desktops (like Hyprland)
|
|
||||||
- [ ] config options for the template rendering
|
|
||||||
- [ ] config options for themes
|
|
||||||
- [ ] grub config
|
|
||||||
- [X] Dynamic selection of more configs (i.e. require syntax)
|
|
||||||
- [ ] Conditional require
|
|
||||||
- [X] Own config syntax? -> just use yaml
|
|
||||||
- [ ] Autocompletion
|
|
||||||
- [ ] Basic arch install how? -> Probably manual (or semi-automatic)
|
|
||||||
- [ ] Mounts?
|
|
||||||
|
|
||||||
|
|
||||||
# REGEX
|
|
||||||
TODO: Improve the below (especially file can be shortened with positive lookahead)
|
|
||||||
- File: `^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))`
|
|
||||||
- Folder: `^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$`
|
|
||||||
- URL (just domain): `^(https?):\\/\\/(([a-z0-9-]+)((?=\\.))\\.)+[a-z]+(?=[a-z]$)`
|
|
||||||
- Full URL: `^(https?):\\/\\/(([a-z0-9-]+)((?=\\.))\\.)+[a-z]+(?=\\/)\\/([\\w\\-?.=]+(?=\\/[\\w\\-?.=])\\/)*([\\w\\-?&.=\\/]+(?=[\\w\\-.=\\/]$))`
|
|
||||||
- UNIX username and groups: `^[a-zA-Z0-9\\-._]{2,19}(?=[a-zA-Z0-9]$)`
|
|
||||||
- Git SSH: `([a-zA-Z0-9\\-._]+(?=[a-zA-Z0-9])[a-zA-Z0-9])@(([a-z0-9\\-]+(?=\\.))\\.)+[a-z]+(?=:):([a-zA-Z0-9\\-._]+(?=\\/)\\/)+([a-zA-Z0-9\\-._]+(?=[a-zA-Z0-9]$))`
|
|
||||||
|
|
||||||
|
|
||||||
## User config schema
|
|
||||||
This may or may not ever be a thing
|
|
||||||
```json
|
|
||||||
"users": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Users to add, including groups. Users will be diffed and removed if they are removed from here. No files are deleted",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"username": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[a-zA-Z0-9\\-._]{2,19}(?=[a-zA-Z0-9]$)"
|
|
||||||
},
|
|
||||||
"groups": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "The groups to add the user to. Groups are created if they don't exist. User's own group doesn't have to be listed explicitly",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[a-zA-Z0-9\\-._]{2,19}(?=[a-zA-Z0-9]$)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sudo_user": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Whether a user can use sudo or not. Same as appending them to the `wheel` group"
|
|
||||||
},
|
|
||||||
"home_dir": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether to create a home directory for the user or not",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"username"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
from config.dtype.others import ArchMgrTemplateData
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrTemplates:
|
|
||||||
pkg_bundles: dict[str, list[str]]
|
|
||||||
bootloader_config: list[BootLoaderSettings]
|
|
||||||
theme_templates: dict[str, list[ArchMgrTemplateData]]
|
|
||||||
|
|
||||||
|
|
||||||
class BootLoaderSettings:
|
|
||||||
# Used to render the included template files
|
|
||||||
templates: list[ArchMgrTemplateData]
|
|
||||||
theme_folder: str
|
|
||||||
conf_build_cmd: str
|
|
||||||
name: str
|
|
||||||
|
|
||||||
|
|
||||||
def load_templates():
|
|
||||||
pass
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
grub:
|
|
||||||
name: grub
|
|
||||||
templates:
|
|
||||||
- name: "GFX_MODE"
|
|
||||||
data: "COMP:SCREENWIDTHxCOMP:SCREENHEIGHT"
|
|
||||||
theme_folder: "ESP_DIR/grub/themes/"
|
|
||||||
conf_build_cmd: "grub-mkconfig -o ESP_DIR/grub/grub.cfg"
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
hyprland:
|
|
||||||
- hyprland
|
|
||||||
- hyprlock
|
|
||||||
- hypridle
|
|
||||||
- hyprshutdown
|
|
||||||
- grimblast
|
|
||||||
- grim
|
|
||||||
- xdg-desktop-portal-hyprland
|
|
||||||
- hyprpolkitagent
|
|
||||||
|
|
||||||
hyrpland-extra:
|
|
||||||
- hyprpaper
|
|
||||||
- wl-clipboard
|
|
||||||
- cliphist
|
|
||||||
- hyprlauncher
|
|
||||||
- hyprpwcenter
|
|
||||||
- hyprtoolkit
|
|
||||||
|
|
||||||
pipewire:
|
|
||||||
- pipewire
|
|
||||||
- pipewire-alsa
|
|
||||||
- pipewire-pulse
|
|
||||||
- pipewire-jack
|
|
||||||
- wireplumber
|
|
||||||
|
|
||||||
neovim:
|
|
||||||
- neovim
|
|
||||||
- lua
|
|
||||||
- lua-language-server
|
|
||||||
- tree-sitter
|
|
||||||
- tree-sitter-cli
|
|
||||||
- stylua
|
|
||||||
|
|
||||||
archives:
|
|
||||||
- zip
|
|
||||||
- unzip
|
|
||||||
|
|
||||||
bluetooth:
|
|
||||||
- blueman
|
|
||||||
- bluez
|
|
||||||
- bluez-utils
|
|
||||||
|
|
||||||
utils:
|
|
||||||
- fastfetch
|
|
||||||
- tldr
|
|
||||||
- gdu
|
|
||||||
- dig
|
|
||||||
- glances
|
|
||||||
- bashtop
|
|
||||||
|
|
||||||
# TODO: For all, make it possible to be pkgs plus configs?
|
|
||||||
yazi:
|
|
||||||
- yazi
|
|
||||||
- xdg-desktop-portal-termfilechooser-hunkyburrito-git
|
|
||||||
- ouch
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
nordic:
|
|
||||||
deep-dark:
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# archmgr data folder
|
|
||||||
archmgr is a nixos-inspired package and config manager for Arch Linux.
|
|
||||||
|
|
||||||
To function, it needs both a configuration file (or multiple) and templates for its provided, preset configurations.
|
|
||||||
The latter reside in this folder and are a stripped-down version of the default config file.
|
|
||||||
|
|
||||||
## Template config folder
|
|
||||||
This folder contains the template configs for archmgr to copy into the user's newly created config repo
|
|
||||||
using the init function
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
# Templates folder
|
|
||||||
By convention, put here any yaml files that contain template information.
|
|
||||||
|
|
||||||
Ideally, each file in this folder contains config options for one of your programs.
|
|
||||||
|
|
||||||
Included you can find an example file for hyprland
|
|
||||||
Reference in New Issue
Block a user