diff --git a/CHANGELOG.md b/CHANGELOG.md index e4535d8..1cd9002 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,83 +9,159 @@ cat -A configure.ac | grep '\^I' nl -ba Makefile | sed -n '770,790p' grep -n "^[ ]" Makefile | head -oie amor bom dia 😘😎 enquanto aguardo pela hora do trabalho estava aqui a corrigir os caminhos (creio que estao todos mas falta testar), e dei com uma coisa curiosa 😎 no nfdos/src/tui/menu_libs.py esquecemos de adicionar a funcao remove_lib 😀: + +"Só deixo duas sugestões cosméticas/futuras: +Substituir $(shell date +%F_%H-%M) por $(GIT_VER) (tal como no neoricalex), quando o campo de versão dinâmica estiver ativo. +Adicionar uma verificação simples no início de make release para abortar se git status tiver ficheiros não commitados (só para evitar builds “dirty”)." + +boa. como sugeres o ajuste?: ``` -import os -import json -import subprocess -from pathlib import Path -from rich.console import Console -from rich.table import Table +SUBDIRS = src -console = Console() +# =========================== +# 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" -def safe_run(cmd, shell=False): - subprocess.run(cmd, check=True, shell=shell) +# =========================== +# Caminhos e artefactos +# =========================== +DIST_DIR ?= $(top_builddir)/dist +BUILD_DIR ?= $(top_builddir)/build +ISO_DIR ?= $(DIST_DIR)/iso/boot/grub +ISO_FILE ?= $(DIST_DIR)/nfdos-0.1.iso +SRC_TAR ?= $(DIST_DIR)/nfdos-0.1-src.tar.gz -def install_lib(name, version=None): - base_dir = Path(__file__).resolve().parents[1] - nfdos_dir = base_dir / "_nfdos" - libs_dir = nfdos_dir / "libs" - libs_dir.mkdir(parents=True, exist_ok=True) +KERNEL = $(top_builddir)/src/_nfdos/kernel/linux/arch/x86/boot/bzImage +INITRAMFS = $(top_builddir)/src/_nfdos/initramfs.cpio.gz - console.print(f"[cyan]📦 Instalando biblioteca:[/] {name} {version or ''}") - cmd = f"pip download {name}{'==' + version if version else ''} -d {libs_dir}" - safe_run(cmd, shell=True) +.PHONY: iso qemu tarball git release clean-local check-remote - # Registo no manifest - manifest_path = libs_dir / "libs_manifest.json" - manifest = json.loads(manifest_path.read_text()) if manifest_path.exists() else {} - manifest[name] = {"version": version or "latest"} - manifest_path.write_text(json.dumps(manifest, indent=4)) - console.print(f"[green]✔ {name} adicionada ao manifesto.[/green]") +# =========================== +# Criação da ISO +# =========================== +iso: $(ISO_FILE) -def list_libs(): - base_dir = Path(__file__).resolve().parents[1] - libs_dir = base_dir / "_nfdos" / "libs" - manifest_path = libs_dir / "libs_manifest.json" +$(ISO_FILE): + @echo "[ISO] Criando estrutura de diretórios..." + mkdir -p $(DIST_DIR)/iso/boot + mkdir -p $(ISO_DIR) - if not manifest_path.exists(): - console.print("[red]Nenhuma biblioteca instalada ainda.[/red]") - return + @echo "[ISO] Copiando Kernel e Initramfs..." + cp $(KERNEL) $(DIST_DIR)/iso/boot/ + cp $(INITRAMFS) $(DIST_DIR)/iso/boot/ - manifest = json.loads(manifest_path.read_text()) - table = Table(title="Bibliotecas do Neurotron") - table.add_column("Nome", style="cyan") - table.add_column("Versão", style="green") + @echo "[ISO] Gerando grub.cfg..." + @printf "set timeout=3\nset default=0\n\nmenuentry 'NFDOS Linux' {\n\tlinux /boot/bzImage console=ttyS0 root=/dev/ram0 loglevel=8\n\tinitrd /boot/initramfs.cpio.gz\n}\n" > $(ISO_DIR)/grub.cfg - for name, data in manifest.items(): - table.add_row(name, data.get("version", "?")) + @echo "[ISO] Gerando imagem ISO..." + grub-mkrescue -o $(ISO_FILE) $(DIST_DIR)/iso --compress=xz -V NFDOS + @echo "[✔] ISO criada em $(ISO_FILE)" - console.print(table) +# =========================== +# Teste no QEMU +# =========================== +qemu: $(ISO_FILE) + @echo "[QEMU] Iniciando NFDOS ISO..." + qemu-system-x86_64 -cdrom $(ISO_FILE) -m 1024 -nographic -serial mon:stdio -no-reboot -def run(): - while True: - console.clear() - console.rule("[bold yellow]📚 Bibliotecas do Neurotron[/bold yellow]") - console.print("1. Instalar biblioteca") - console.print("2. Listar bibliotecas instaladas") - console.print("3. Atualizar biblioteca") - console.print("4. Remover biblioteca") - console.print("0. Voltar") +# =========================== +# Empacotamento do código-fonte +# =========================== +tarball: $(SRC_TAR) - choice = console.input("\n[cyan]nfdos> [/cyan]") +$(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' \ + --exclude='*.iso' \ + --exclude='*.img' \ + --exclude='*.cpio*' \ + --exclude='*/linux' \ + --exclude='*/busybox' \ + --exclude='*/cpython' \ + -czf $(SRC_TAR) . + @echo "[✔] Tarball gerado em $(SRC_TAR)" - if choice == "1": - name = console.input("Nome da biblioteca: ") - version = console.input("Versão (ou vazio p/ latest): ") - install_lib(name, version or None) - elif choice == "2": - list_libs() - console.input("\n[grey]Pressiona Enter para continuar...[/grey]") - elif choice == "3": - name = console.input("Nome da biblioteca: ") - install_lib(name, None) - elif choice == "4": - name = console.input("Nome da biblioteca a remover: ") - remove_lib(name) - elif choice == "0": - break - else: - console.print("[red]Opção inválida![/red]") -``` \ No newline at end of file +# =========================== +# Git (commit + push) +# =========================== +git: check-remote + @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 "$$(echo '$(COMMIT_MSG)')" || echo "Nenhuma modificação para commitar." + @git push $(GIT_REMOTE) $(GIT_BRANCH) + +# =========================== +# Git Remote (HTTPS → SSH Auto-Fix) +# =========================== +check-remote: + @REMOTE_URL=$$(git remote get-url $(GIT_REMOTE)); \ + if echo $$REMOTE_URL | grep -q '^https://gitea\.neoricalex\.com'; then \ + echo "⚠️ Repositório configurado com HTTPS:"; \ + echo " $$REMOTE_URL"; \ + echo "🔄 Convertendo para SSH (porta 2222)..."; \ + SSH_URL=$$(echo $$REMOTE_URL | sed -E 's|https://gitea\.neoricalex\.com[:/]+|ssh://git@gitea.neoricalex.com:2222/|'); \ + git remote set-url $(GIT_REMOTE) $$SSH_URL; \ + echo "✅ Remote atualizado para:"; \ + git remote -v; \ + else \ + echo "✅ Remote SSH já configurado:"; \ + git remote -v | grep $(GIT_REMOTE); \ + fi; \ + echo "🔍 Testando conectividade SSH com Gitea..."; \ + if ssh -T git@gitea.neoricalex.com -p 2222 2>&1 | grep -q "successfully authenticated"; then \ + echo "✅ Conexão SSH funcional com Gitea."; \ + else \ + echo "❌ Falha na autenticação SSH com Gitea."; \ + echo " Verifique a chave em ~/.ssh/id_ed25519.pub e nas SSH Keys do Gitea."; \ + exit 1; \ + fi + +# =========================== +# Release (ISO + Tarball) +# =========================== +release: iso tarball + @echo "🚀 Publicando build em dist/releases" + @mkdir -p $(DIST_DIR)/releases + @if ls $(DIST_DIR)/nfdos-*.iso >/dev/null 2>&1; then \ + cp $(DIST_DIR)/nfdos-*.iso $(DIST_DIR)/releases/; \ + else \ + echo "⚠️ Nenhuma ISO encontrada. Execute 'make iso' primeiro."; \ + fi + @if ls $(DIST_DIR)/nfdos-*.tar.gz >/dev/null 2>&1; then \ + cp $(DIST_DIR)/nfdos-*.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 + +# =========================== +# 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/Makefile.am b/Makefile.am index 8ef4ee9..8fdb104 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,7 @@ GIT_EMAIL ?= "neo.webmaster.2@gmail.com" GIT_REMOTE ?= "origin" GIT_BRANCH ?= "main" COMMIT_MSG ?= "Auto-commit via make git" +GIT_VER := $(shell git describe --tags --always --dirty 2>/dev/null || echo "0.1-dev") # =========================== # Caminhos e artefactos @@ -15,8 +16,8 @@ COMMIT_MSG ?= "Auto-commit via make git" DIST_DIR ?= $(top_builddir)/dist BUILD_DIR ?= $(top_builddir)/build ISO_DIR ?= $(DIST_DIR)/iso/boot/grub -ISO_FILE ?= $(DIST_DIR)/nfdos-0.1.iso -SRC_TAR ?= $(DIST_DIR)/nfdos-0.1-src.tar.gz +ISO_FILE ?= $(DIST_DIR)/nfdos-$(GIT_VER).iso +SRC_TAR ?= $(DIST_DIR)/nfdos-$(GIT_VER)-src.tar.gz KERNEL = $(top_builddir)/src/_nfdos/kernel/linux/arch/x86/boot/bzImage INITRAMFS = $(top_builddir)/src/_nfdos/initramfs.cpio.gz @@ -122,7 +123,13 @@ check-remote: # Release (ISO + Tarball) # =========================== release: iso tarball - @echo "🚀 Publicando build em dist/releases" + @# --- Proteção: evitar builds "dirty" --- + @if ! git diff --quiet || ! git diff --cached --quiet; then \ + echo "❌ Existem alterações não commitadas. Faça commit antes de gerar a release."; \ + git status -s; \ + exit 1; \ + fi + @echo "🚀 Publicando build em dist/releases (versão: $(GIT_VER))" @mkdir -p $(DIST_DIR)/releases @if ls $(DIST_DIR)/nfdos-*.iso >/dev/null 2>&1; then \ cp $(DIST_DIR)/nfdos-*.iso $(DIST_DIR)/releases/; \ @@ -135,7 +142,7 @@ release: iso tarball 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 commit -m "Build automático: release $(GIT_VER)" || echo "Nenhum ficheiro novo para commitar." @git push origin main # =========================== @@ -146,4 +153,3 @@ clean-local: rm -rf $(BUILD_DIR) find $(DIST_DIR) -type f ! -path "$(DIST_DIR)/releases/*" -delete @echo "[✔] Limpeza concluída (releases preservadas)" - diff --git a/configure.ac b/configure.ac index f015a5f..7dc1b7b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([NFDOS], [0.1], [https://gitea.neoricalex.com/neo/nfdos.git]) +AC_INIT([NFDOS], [NEO_VERSION], [https://gitea.neoricalex.com/neo/nfdos.git]) AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip]) AM_PATH_PYTHON([2.5]) @@ -9,6 +9,13 @@ AC_SUBST([ISO_DIR], [$PWD/dist/iso/boot/grub]) AC_SUBST([ISO_FILE], [$PWD/dist/nfdos-${PACKAGE_VERSION}.iso]) AC_SUBST([SRC_TAR], [$PWD/dist/nfdos-${PACKAGE_VERSION}-src.tar.gz]) +# =========================== +# Versão dinâmica (Git) +# =========================== +m4_define([NEO_VERSION], + m4_esyscmd_s([git describe --tags --always --dirty 2>/dev/null || echo "0.1-dev"])) +AC_SUBST([NEO_VERSION]) + AC_CONFIG_FILES([ Makefile src/Makefile diff --git a/src/tui/menu_libs.py b/src/tui/menu_libs.py index 5803374..00580b8 100644 --- a/src/tui/menu_libs.py +++ b/src/tui/menu_libs.py @@ -1,6 +1,7 @@ import os import json import subprocess +import urllib.request from pathlib import Path from rich.console import Console from rich.table import Table @@ -10,6 +11,16 @@ console = Console() def safe_run(cmd, shell=False): subprocess.run(cmd, check=True, shell=shell) +def get_latest_version(name): + """Obtém a versão mais recente de um pacote PyPI.""" + url = f"https://pypi.org/pypi/{name}/json" + try: + with urllib.request.urlopen(url, timeout=5) as response: + data = json.load(response) + return data["info"]["version"] + except Exception: + return None + def install_lib(name, version=None): base_dir = Path(__file__).resolve().parents[1] nfdos_dir = base_dir / "_nfdos" @@ -27,25 +38,6 @@ def install_lib(name, version=None): manifest_path.write_text(json.dumps(manifest, indent=4)) console.print(f"[green]✔ {name} adicionada ao manifesto.[/green]") -def list_libs(): - base_dir = Path(__file__).resolve().parents[1] - libs_dir = base_dir / "_nfdos" / "libs" - manifest_path = libs_dir / "libs_manifest.json" - - if not manifest_path.exists(): - console.print("[red]Nenhuma biblioteca instalada ainda.[/red]") - return - - manifest = json.loads(manifest_path.read_text()) - table = Table(title="Bibliotecas do Neurotron") - table.add_column("Nome", style="cyan") - table.add_column("Versão", style="green") - - for name, data in manifest.items(): - table.add_row(name, data.get("version", "?")) - - console.print(table) - def remove_lib(name): base_dir = Path(__file__).resolve().parents[1] libs_dir = base_dir / "_nfdos" / "libs" @@ -79,6 +71,56 @@ def remove_lib(name): else: console.print(f"[yellow]⚠ Nenhum ficheiro físico encontrado para '{name}'.[/yellow]") +def update_lib(name): + """Compara e atualiza biblioteca para a versão mais recente do PyPI.""" + base_dir = Path(__file__).resolve().parents[1] + libs_dir = base_dir / "_nfdos" / "libs" + manifest_path = libs_dir / "libs_manifest.json" + + if not manifest_path.exists(): + console.print("[red]Nenhuma biblioteca instalada ainda.[/red]") + return + + manifest = json.loads(manifest_path.read_text()) + + if name not in manifest: + console.print(f"[yellow]⚠ Biblioteca '{name}' não está instalada.[/yellow]") + return + + current_version = manifest[name].get("version") + latest_version = get_latest_version(name) + + if not latest_version: + console.print(f"[red]❌ Falha ao consultar PyPI para {name}.[/red]") + return + + if current_version == latest_version or current_version == "latest": + console.print(f"[green]✔ {name} já está na versão mais recente ({latest_version}).[/green]") + return + + console.print(f"[yellow]🔄 Atualizando {name} ({current_version} → {latest_version})...[/yellow]") + remove_lib(name) + install_lib(name, latest_version) + console.print(f"[green]✅ {name} atualizado para a versão {latest_version}.[/green]") + +def list_libs(): + base_dir = Path(__file__).resolve().parents[1] + libs_dir = base_dir / "_nfdos" / "libs" + manifest_path = libs_dir / "libs_manifest.json" + + if not manifest_path.exists(): + console.print("[red]Nenhuma biblioteca instalada ainda.[/red]") + return + + manifest = json.loads(manifest_path.read_text()) + table = Table(title="Bibliotecas do Neurotron") + table.add_column("Nome", style="cyan") + table.add_column("Versão", style="green") + + for name, data in manifest.items(): + table.add_row(name, data.get("version", "?")) + + console.print(table) def run(): while True: @@ -101,7 +143,7 @@ def run(): console.input("\n[grey]Pressiona Enter para continuar...[/grey]") elif choice == "3": name = console.input("Nome da biblioteca: ") - install_lib(name, None) + update_lib(name) elif choice == "4": name = console.input("Nome da biblioteca a remover: ") remove_lib(name) @@ -109,3 +151,4 @@ def run(): break else: console.print("[red]Opção inválida![/red]") +