Compare commits
8 Commits
78eecfc81a
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 36d3c6f992 | |||
| 217ccadc74 | |||
| d391c53c6c | |||
| 24c52c1bba | |||
| 80d7b3d86e | |||
| 72b477381f | |||
| e8d8429bc9 | |||
| afe8d29340 |
@@ -3,3 +3,9 @@
|
|||||||
A nixos-like declarative config and package manager for Arch Linux (or any other distro, with some tweaks).
|
A nixos-like declarative config and package manager for Arch Linux (or any other distro, with some tweaks).
|
||||||
|
|
||||||
See the [Wiki](https://git.janishutz.com/janishutz/archmgr/wiki)
|
See the [Wiki](https://git.janishutz.com/janishutz/archmgr/wiki)
|
||||||
|
|
||||||
|
## WIP
|
||||||
|
This project is very much Work In Progress.
|
||||||
|
The configs will likely move to python-based configs from the current yaml-based ones to provide you with more flexibility.
|
||||||
|
|
||||||
|
`archmgr` will automatically create a basic setup if you run `archmgr init`, so you can get up and running quickly
|
||||||
|
|||||||
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 templates 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)
|
||||||
@@ -8,5 +8,6 @@ def add_parser(sp: ap._SubParsersAction[ap.ArgumentParser]):
|
|||||||
dest="show",
|
dest="show",
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
|
show_sp.add_parser("config", help="show details about your configuration. Alias of config show")
|
||||||
pkgs = show_sp.add_parser("pkgs", help="show details on package presets")
|
pkgs = show_sp.add_parser("pkgs", help="show details on package presets")
|
||||||
pkgs.add_argument("show_pkg")
|
pkgs.add_argument("show_pkg")
|
||||||
@@ -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,10 +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)
|
|
||||||
@@ -1,28 +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 + "/db")
|
|
||||||
os.mkdir(dir + "/system")
|
|
||||||
os.mkdir(dir + "/includes")
|
|
||||||
shutil.copy(script_dir + "/templates/config/config.yml", dir + "/config.yml")
|
|
||||||
shutil.copy(script_dir + "/templates/config/system/", dir + "/includes/system/")
|
|
||||||
shutil.copy(script_dir + "/templates/config/templates/", dir + "/includes/templates/")
|
|
||||||
shutil.copy(script_dir + "/templates/README.md", dir + "/README.md")
|
|
||||||
print("Initialized a new archmgr repository")
|
|
||||||
# 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?)
|
|
||||||
# TODO: Consider collecting function -> If no files present, will only collect the pkgs, else also the files
|
|
||||||
# TODO: Config folder instead of single config file
|
|
||||||
# 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,380 +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": {
|
|
||||||
"enabled_repos": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "The repos to set up",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The repositories to set up",
|
|
||||||
"pattern": "^(core|extra|core-testing|extra-testing|multilib|multilib-testing|[a-z0-9-]+(?=[a-z0-9]$))"
|
|
||||||
},
|
|
||||||
"setup_cmds": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "The commands to run to set it up (optional if any of the explicitly supported ones)",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Command to run"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mirrors": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Configure the mirrors to use",
|
|
||||||
"properties": {
|
|
||||||
"use_default": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Whether to use the default mirrors or not",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"extra_mirrors": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Any extra mirrors you want to add. At least one mirror needs to be put here if use_default is false. Order matters",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"name"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"managed"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"themes": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {}
|
|
||||||
},
|
|
||||||
"git": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Automatically set up credential manager and clone repos",
|
|
||||||
"properties": {
|
|
||||||
"creds": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Which git services to log into",
|
|
||||||
"properties": {
|
|
||||||
"manager": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The git credential manager to use. Set to none if you don't want one (default)",
|
|
||||||
"pattern": "^(git-credential-manager|none)",
|
|
||||||
"default": "none"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"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": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name that appears in the template"
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The data that is to be inserted"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"name",
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
-62
@@ -1,62 +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
|
|
||||||
|
|
||||||
users:
|
|
||||||
- username: username
|
|
||||||
groups:
|
|
||||||
- group_1
|
|
||||||
home_dir: True
|
|
||||||
|
|
||||||
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:
|
|
||||||
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,91 +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):
|
|
||||||
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"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
# 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"))
|
|
||||||
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,32 +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
|
|
||||||
|
|
||||||
|
|
||||||
# Ideas
|
## Init
|
||||||
- [ ] function to collect new configs
|
- Copy
|
||||||
- [ ] config options for users and groups
|
|
||||||
- [ ] presets for things like desktops (like Hyprland)
|
|
||||||
- [ ] config options for the template rendering
|
|
||||||
- [ ] config options for themes
|
|
||||||
- [ ] grub config
|
|
||||||
- [ ] Dynamic selection of more configs (i.e. require syntax)
|
|
||||||
- [ ] Own config syntax?
|
|
||||||
- [ ] 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]$))`
|
|
||||||
|
|||||||
@@ -1,8 +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 file
|
|
||||||
TODO: Restructure this folder
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
from config.dtype.others import ArchMgrTemplateData
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMgrTemplates:
|
|
||||||
pkg_bundles: dict[str, list[str]]
|
|
||||||
bootloader_config: BootLoaderSettings
|
|
||||||
theme_templates: ArchMgrTemplateData
|
|
||||||
repo_config: None # TODO: Define a good dtype here
|
|
||||||
|
|
||||||
|
|
||||||
class BootLoaderSettings:
|
|
||||||
templates: ArchMgrTemplateData
|
|
||||||
theme_folder: str
|
|
||||||
conf_build_cmd: str
|
|
||||||
name: str
|
|
||||||
|
|
||||||
|
|
||||||
def load_templates():
|
|
||||||
pass
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
hyprland:
|
|
||||||
- hyprland
|
|
||||||
- hyprlock
|
|
||||||
- hypridle
|
|
||||||
- grimblast
|
|
||||||
- grim
|
|
||||||
- xdg-desktop-portal-hyprland
|
|
||||||
- polkit-kde-agent
|
|
||||||
|
|
||||||
hyrpland-extra:
|
|
||||||
- hyprpaper
|
|
||||||
- wl-clipboard
|
|
||||||
- cliphist
|
|
||||||
- rofi
|
|
||||||
|
|
||||||
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,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user