Compare commits

..

3 Commits

Author SHA1 Message Date
janishutz 2fd69cc595 feat(init): Templates handling 2026-04-25 16:43:53 +02:00
janishutz 541a876307 feat(config): Schema validator, initial config merger setup 2026-04-23 11:31:01 +02:00
janishutz 5126e0373f feat(PKGBUILD): First setup 2026-04-23 11:30:31 +02:00
17 changed files with 128 additions and 7 deletions
+28
View File
@@ -0,0 +1,28 @@
# Maintainer: Janis Hutz <development@janishutz.com>
pkgname=archmgr-git
pkgver=0.0.0
pkgrel=1
pkgdesc='A nixos-like declarative config and package manager for Arch Linux'
arch=('any')
url="https://github.com/janishutz/archmgr"
license=('GPL3')
depends=('python', 'python-pyaml')
makedepends=('git')
provides=('archmgr')
conflicts=('archmgr')
source=("$pkgname"::git+${url}.git)
sha256sums=('SKIP') # TODO: Add?
pkgver() {
cd "${pkgname}"
# TODO: For the non-git pkgbuild, need to use different output
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
package() {
cd "${pkgname}"
# TODO: Need to finish
}
+2
View File
@@ -9,6 +9,7 @@ import commands.init as init
import commands.pull as pull
import commands.push as push
import commands.prepare as setup
from config import load_config
if __name__ == "__main__":
args, ap = cliargs.add_cli_args()
@@ -29,6 +30,7 @@ if __name__ == "__main__":
\\___/
""")
print(load_config("config.yml"))
try:
if args.cmd == "commit":
commit.commit(args.force, args.no_render)
+14 -5
View File
@@ -1,19 +1,28 @@
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:
[os.remove(dir) for dir in os.listdir(dir)]
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 + "/etc")
with open(dir + "/config.yaml") as file:
file.write("")
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
# 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!)
+25
View File
@@ -88,6 +88,12 @@
},
"maxItems": 5,
"minItems": 1
},
"count": {
"type": "number",
"description": "The number of mirrors to add to the list",
"maximum": 20,
"minimum": 3
}
},
"required": [
@@ -273,6 +279,25 @@
"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": {
+31
View File
@@ -0,0 +1,31 @@
from typing import Any, cast
import yaml
from config import validator
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 load_config(file: str):
# Load and validate initial config
try:
loaded_conf = _load_config_file(file)
except Exception:
return {}
if not validator.validate(loaded_conf):
return {}
conf = cast(dict[str, Any], loaded_conf)
requires = cast(list[str], conf["requires"])
conf.pop("requires")
# Recursively load files
for conf_file in requires:
conf = merge_configs(conf, load_config(conf_file))
return conf
+6
View File
@@ -0,0 +1,6 @@
def merge_configs(config: dict, new_config: dict):
if len(new_config) == 0 or len(config) == 0:
return config
# Merge configs
return config
+18 -2
View File
@@ -1,2 +1,18 @@
def validate():
pass
import json
import jsonschema
with open("config.schema.json") as file:
schema = json.load(file)
def validate(config):
try:
jsonschema.validate(config, schema)
except jsonschema.SchemaError:
print("Schema invalid")
return False
except jsonschema.ValidationError:
print("Config invalid")
return False
return True
+1
View File
@@ -1,3 +1,4 @@
pyyaml
pylette
argcomplete
inquirer
+3
View File
@@ -0,0 +1,3 @@
# 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
View File
View File
View File
View File
View File
View File