From c35aaed66b5fab65a5a56fe02d45cd7abb9f4246 Mon Sep 17 00:00:00 2001 From: neoricalex Date: Sun, 9 Nov 2025 11:09:23 +0100 Subject: [PATCH] first commit --- .gitignore | 57 ++++++++++++++++++++ Makefile.am | 96 ++++++++++++++++++++++++++++++++++ README | 40 ++++++++++++++ configure.ac | 16 ++++++ src/Makefile.am | 14 +++++ src/bootstrap.py | 39 ++++++++++++++ src/manager/Makefile.am | 11 ++++ src/manager/__init__.py | 0 src/manager/manager_main.py | 81 ++++++++++++++++++++++++++++ src/manager/manifest_parser.py | 0 src/manager/module_loader.py | 0 src/manager/tui_manager.py | 0 src/modules.json | 16 ++++++ src/neoricalex | 11 ++++ src/neoricalex.in | 11 ++++ src/requirements.txt | 1 + 16 files changed, 393 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100644 README create mode 100644 configure.ac create mode 100644 src/Makefile.am create mode 100644 src/bootstrap.py create mode 100644 src/manager/Makefile.am create mode 100644 src/manager/__init__.py create mode 100644 src/manager/manager_main.py create mode 100644 src/manager/manifest_parser.py create mode 100644 src/manager/module_loader.py create mode 100644 src/manager/tui_manager.py create mode 100644 src/modules.json create mode 100755 src/neoricalex create mode 100644 src/neoricalex.in create mode 100644 src/requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..105002c --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +# === sub-módulos clonados === +src/modules/ + +# === Autotools build artefacts === +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +config.log +config.status +configure +depcomp +install-sh +missing +py-compile +stamp-h1 + +# === Build & dist directories === +build/ +dist/ +*.tar.gz +*.tar.bz2 +*.zip + +# === Python cache & venv === +__pycache__/ +*.pyc +*.pyo +*.pyd +*.egg-info/ +.eggs/ +venv/ +.env/ +.venv/ + +# === Editor / OS junk === +*.swp +*.swo +*.bak +*.tmp +*~ +.DS_Store +Thumbs.db + +# === Logs === +*.log +nohup.out + +# === IDE / workspace === +.vscode/ +.idea/ +*.iml + +# === Backup copies === +*.old +*.orig +*.rej diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..c674a94 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,96 @@ +SUBDIRS = src + +# =========================== +# Configurações de Git +# =========================== +GIT_USER ?= "neo.webmaster.2@gmail.com" +GIT_EMAIL ?= "neo.webmaster.2@gmail.com" +GIT_REMOTE ?= "origin" +GIT_BRANCH ?= "main" +COMMIT_MSG ?= "Auto-commit via make git" + +# =========================== +# Caminhos e artefactos +# =========================== +DIST_DIR ?= $(top_builddir)/dist +BUILD_DIR ?= $(top_builddir)/build +SRC_TAR ?= $(DIST_DIR)/neoricalex-src.tar.gz + +# =========================== +# Alvos principais +# =========================== +.PHONY: all tarball git release run clean-local + +all: $(DIST_DIR) + +$(DIST_DIR): + mkdir -p $(DIST_DIR) + +# =========================== +# Empacotamento do código-fonte +# =========================== +tarball: $(SRC_TAR) + +$(SRC_TAR): + @echo "[TAR] Empacotando código-fonte..." + mkdir -p $(DIST_DIR) + cd $(top_srcdir) && tar \ + --exclude="$(notdir $(SRC_TAR))" \ + --exclude="$(DIST_DIR)" \ + --exclude="$(BUILD_DIR)" \ + --exclude='*/__pycache__' \ + --exclude='*/.venv' \ + --exclude='*/venv' \ + --exclude='*.pyc' \ + --exclude='*.pyo' \ + --exclude='*.o' \ + --exclude='*.a' \ + --exclude='*.so' \ + -czf $(SRC_TAR) . + @echo "[✔] Tarball gerado em $(SRC_TAR)" + +# =========================== +# Git (commit + push) +# =========================== +git: + @echo "📦 Commit automático → Gitea" + @git config user.name $(GIT_USER) + @git config user.email $(GIT_EMAIL) + @git rev-parse --abbrev-ref HEAD >/dev/null 2>&1 || true + @git add -A + @git commit -m "$(COMMIT_MSG)" || echo "Nenhuma modificação para commitar." + @git push $(GIT_REMOTE) $(GIT_BRANCH) + +# =========================== +# Release (Tarball) +# =========================== +release: tarball + @echo "🚀 Publicando build em dist/releases" + @mkdir -p $(DIST_DIR)/releases + @if ls $(DIST_DIR)/neoricalex-*.tar.gz >/dev/null 2>&1; then \ + cp $(DIST_DIR)/neoricalex-*.tar.gz $(DIST_DIR)/releases/; \ + else \ + echo "⚠️ Nenhum tarball encontrado. Execute 'make tarball' primeiro."; \ + fi + @git add $(DIST_DIR)/releases/ + @git commit -m "Build automático: release $(shell date +%F_%H-%M)" || echo "Nenhum ficheiro novo para commitar." + @git push origin main + @TAG="v$(shell date +%Y.%m.%d-%H%M)" && \ + echo "🏷 Criando tag $$TAG" && \ + git tag -a $$TAG -m "Release automática em $$TAG" && \ + git push origin $$TAG || echo "⚠️ Tag já existente ou erro ao criar." + +# =========================== +# Teste +# =========================== +run: + @python3 src/manager/manager_main.py + +# =========================== +# Limpeza +# =========================== +clean-local: + @echo "[CLEAN] Removendo diretórios temporários..." + rm -rf $(BUILD_DIR) + find $(DIST_DIR) -type f ! -path "$(DIST_DIR)/releases/*" -delete + @echo "[✔] Limpeza concluída (releases preservadas)" diff --git a/README b/README new file mode 100644 index 0000000..25ca880 --- /dev/null +++ b/README @@ -0,0 +1,40 @@ +# NEORICALEX – System Manager + +Este repositório é o núcleo do ecossistema **NEORICALEX**. +Ele atua como um **gerenciador modular** capaz de clonar, atualizar e executar +outros projetos (como `my_os` e `my_distro`), integrando-os sob uma mesma estrutura. + +🧩 **Build system:** GNU Autotools + Python +🧠 **Função:** Sistema de orquestração dos módulos NEORICALEX + +--- + +## ⚙️ Requerimentos + +Antes de começar, certifique-se de ter instaladas as dependências principais: + +### 🧱 Sistema e Build +```bash +sudo apt update +sudo apt install -y \ + autoconf automake libtool \ + build-essential pkg-config \ + git python3 python3-venv python3-pip \ + make +``` + +## Passos + +1. Execute `aclocal` para criar **aclocal.m4** e o diretório **autom4te.cache/**. +2. Execute `autoconf` para gerar o script **configure**. +3. Execute `automake --add-missing` para criar os ficheiros **Makefile.in**. +4. Execute `./configure` para gerar os ficheiros **Makefile**. +5. Execute `make` para compilar e criar o executável. +6. Execute `src/neoricalex` para correr o executável. + +## Alvos Extras +make git # commit + push automático +make tarball # gera dist/neoricalex-src.tar.gz +make release # publica release e cria tag automática + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..932266e --- /dev/null +++ b/configure.ac @@ -0,0 +1,16 @@ +AC_INIT([NEORICALEX], [0.1], [https://gitea.neoricalex.com/neo/neoricalex.git]) +AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip]) +AM_PATH_PYTHON([3.0]) + +# Diretórios base +AC_SUBST([BUILD_DIR], [${abs_top_builddir}/build]) +AC_SUBST([DIST_DIR], [${abs_top_builddir}/dist]) +AC_SUBST([SRC_TAR], [${abs_top_builddir}/dist/neoricalex-${PACKAGE_VERSION}-src.tar.gz]) + +AC_CONFIG_FILES([ + Makefile + src/Makefile + src/manager/Makefile +]) +AC_OUTPUT + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..bd5965a --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS = manager + +bin_SCRIPTS = neoricalex +CLEANFILES = $(bin_SCRIPTS) +EXTRA_DIST = neoricalex.in + +do_substitution = sed -e 's,[@]pythondir[@],$(pythondir),g' \ + -e 's,[@]PACKAGE[@],$(PACKAGE),g' \ + -e 's,[@]VERSION[@],$(VERSION),g' + +neoricalex: neoricalex.in Makefile + @which git >/dev/null || { echo "⚠️ Git não encontrado — instale-o manualmente."; exit 1; } + $(do_substitution) < $(srcdir)/neoricalex.in > neoricalex + chmod +x neoricalex diff --git a/src/bootstrap.py b/src/bootstrap.py new file mode 100644 index 0000000..992efa5 --- /dev/null +++ b/src/bootstrap.py @@ -0,0 +1,39 @@ +import os +import shutil +import subprocess +import sys +from pathlib import Path + +class Application(object): + def __init__(self, *args, **kwargs): + for key in kwargs: + setattr(self, key, kwargs[key]) + self._hello() + + def _hello(self): + print(f"NEORICALEX {getattr(self, 'version', '')} — inicializador de ambiente") + + def run(self): + self._ensure_venv() + self.launch_welcome() + + def _ensure_venv(self): + """Cria e ativa o ambiente virtual, caso ainda não exista.""" + base_path = Path(__file__).resolve().parents[1] + venv_path = base_path / "venv" + os.chdir(base_path) + + if not venv_path.exists(): + print("[+] Criando ambiente virtual...") + subprocess.run([sys.executable, "-m", "venv", str(venv_path)], check=True) + else: + print("[=] Ambiente virtual já existente.") + + + def launch_welcome(self): + """Lança o gestor de módulos.""" + base_path = Path(__file__).resolve().parent + manager = base_path / "manager" / "manager_main.py" + subprocess.run(["python3", str(manager)]) + + diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am new file mode 100644 index 0000000..6b47378 --- /dev/null +++ b/src/manager/Makefile.am @@ -0,0 +1,11 @@ +# Python sources +neoricalex_PYTHON = \ + manager_main.py \ + manifest_parser.py \ + module_loader.py \ + tui_manager.py \ + __init__.py \ + ../bootstrap.py + +neoricalexdir = $(pythondir) + diff --git a/src/manager/__init__.py b/src/manager/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/manager/manager_main.py b/src/manager/manager_main.py new file mode 100644 index 0000000..f924fe4 --- /dev/null +++ b/src/manager/manager_main.py @@ -0,0 +1,81 @@ +from rich.console import Console +from rich.table import Table +from pathlib import Path +import os, subprocess, json + +console = Console() +BASE_DIR = Path(__file__).resolve().parents[2] +MODULES_FILE = BASE_DIR / "src" / "modules.json" +MODULES_DIR = BASE_DIR / "src" / "modules" + +def load_modules(): + if MODULES_FILE.exists(): + with open(MODULES_FILE) as f: + data = json.load(f) + return data.get("modules", []) + return [] + +def clone_module(mod): + path = Path(mod["path"]) + if not path.exists(): + console.print(f"[cyan]📦 Clonando {mod['name']}...[/cyan]") + subprocess.run(["git", "clone", mod["repo"], str(path)], check=True) + else: + console.print(f"[yellow]✔ {mod['name']} já existe localmente.[/yellow]") + +def update_module(mod): + path = Path(mod["path"]) + if path.exists(): + console.print(f"[blue]🔄 Atualizando {mod['name']}...[/blue]") + subprocess.run(["git", "-C", str(path), "pull"], check=True) + else: + console.print(f"[red]⚠ Módulo {mod['name']} não encontrado![/red]") + +def run_module(mod): + path = Path(mod["path"]) + if not path.exists(): + console.print(f"[red]❌ Módulo {mod['name']} não encontrado.[/red]") + return + console.print(f"[green]🚀 Executando {mod['name']}...[/green]") + subprocess.run(mod["entrypoint"], cwd=path, shell=True) + +def menu(): + modules = load_modules() + while True: + console.clear() + table = Table(title="NEORICALEX – System Manager") + table.add_column("ID", justify="center") + table.add_column("Módulo") + table.add_column("Ação") + + for i, mod in enumerate(modules, start=1): + table.add_row(str(i), mod["name"], mod["repo"]) + table.add_row("0", "Sair", "") + + console.print(table) + choice = console.input("[cyan]\nSelecione um módulo> [/cyan]") + + if choice == "0": + break + if not choice.isdigit() or int(choice) > len(modules): + continue + + mod = modules[int(choice)-1] + console.print(f"[bold yellow]Selecionado:[/bold yellow] {mod['name']}") + console.print("[1] Executar [2] Atualizar [3] Reinstalar [0] Voltar") + sub = console.input("[cyan]> [/cyan]") + + if sub == "1": + run_module(mod) + elif sub == "2": + update_module(mod) + elif sub == "3": + if Path(mod["path"]).exists(): + subprocess.run(["rm", "-rf", mod["path"]]) + clone_module(mod) + else: + continue + +if __name__ == "__main__": + os.makedirs(MODULES_DIR, exist_ok=True) + menu() diff --git a/src/manager/manifest_parser.py b/src/manager/manifest_parser.py new file mode 100644 index 0000000..e69de29 diff --git a/src/manager/module_loader.py b/src/manager/module_loader.py new file mode 100644 index 0000000..e69de29 diff --git a/src/manager/tui_manager.py b/src/manager/tui_manager.py new file mode 100644 index 0000000..e69de29 diff --git a/src/modules.json b/src/modules.json new file mode 100644 index 0000000..1de0de2 --- /dev/null +++ b/src/modules.json @@ -0,0 +1,16 @@ +{ + "modules": [ + { + "name": "my_os", + "repo": "https://gitea.neoricalex.com/neo/my_os.git", + "path": "src/modules/my_os", + "entrypoint": "python3 tui/menu_main.py" + }, + { + "name": "my_distro", + "repo": "https://gitea.neoricalex.com/neo/my_distro.git", + "path": "src/modules/my_distro", + "entrypoint": "bash build.sh" + } + ] +} diff --git a/src/neoricalex b/src/neoricalex new file mode 100755 index 0000000..52aa91a --- /dev/null +++ b/src/neoricalex @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import sys +sys.path.insert(1, '/usr/local/local/lib/python3.12/dist-packages') + +from bootstrap import Application + +if __name__ == "__main__": + app = Application(package="neoricalex", version="0.1") + app.run() + diff --git a/src/neoricalex.in b/src/neoricalex.in new file mode 100644 index 0000000..127b044 --- /dev/null +++ b/src/neoricalex.in @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import sys +sys.path.insert(1, '@pythondir@') + +from bootstrap import Application + +if __name__ == "__main__": + app = Application(package="@PACKAGE@", version="@VERSION@") + app.run() + diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..c94be38 --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1 @@ +rich \ No newline at end of file