Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .coverage
Binary file not shown.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ venv.bak/
.pytest_cache/
tests/repo/
tests/repo_windows/
~/.gitauditor_ai_cache.json
*.json
.gitauditor_ai_cache.json
.coverage
htmlcov/

# IDEs and Editors
.vscode/
Expand Down
104 changes: 0 additions & 104 deletions BLUEPRINT.md

This file was deleted.

113 changes: 0 additions & 113 deletions repomix-output.xml

This file was deleted.

7 changes: 0 additions & 7 deletions requirements.txt

This file was deleted.

24 changes: 17 additions & 7 deletions src/gitauditor/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
with open(config_path) as f:
cfg = json.load(f)
lang_to_use = cfg.get("lang", "pt_BR")
except Exception:
pass
except Exception as e:
import sys
print(f"Aviso: Erro ao carregar config i18n: {e}", file=sys.stderr)

localedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'locales')
try:
translate = gettext.translation('gitauditor', localedir, languages=[lang_to_use], fallback=True)
translate.install()
_ = translate.gettext
except Exception:
except Exception as e:
import sys
print(f"Aviso: Não foi possível carregar a tradução: {e}", file=sys.stderr)
import builtins
builtins.__dict__['_'] = lambda x: x
# ----------------------------------------------------
Expand Down Expand Up @@ -457,17 +460,24 @@ def _action_filter_table(self):
app.add_typer(worktree_app, name="wt", hidden=True)

app.command(name="config", help=_("Configurações do GitAuditor"))(config_command)
cli_state = GitAuditorCLI()

_cli_state = None

def get_cli_state() -> GitAuditorCLI:
global _cli_state
if _cli_state is None:
_cli_state = GitAuditorCLI()
return _cli_state

@app.callback(invoke_without_command=True)
def main_callback(ctx: typer.Context):
if ctx.invoked_subcommand is None:
cli_state.run()
get_cli_state().run()

@app.command()
def ui():
"""Modo Interativo (UI/Launcher Clássico)."""
cli_state.run()
get_cli_state().run()

@app.command(name="sync", hidden=True)
def sync_shortcut():
Expand Down Expand Up @@ -507,7 +517,7 @@ def review_shortcut(path: str = ".", staged: bool = False):

@app.command(name="ssh", help=_("Gerenciar Chaves e Identidades SSH."))
def ssh_cmd():
handle_manage_ssh(cli_state)
handle_manage_ssh(get_cli_state())


if __name__ == "__main__":
Expand Down
73 changes: 62 additions & 11 deletions tests/test_cli_commands.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,72 @@
from typer.testing import CliRunner
from unittest.mock import patch

from gitauditor.cli import app

runner = CliRunner()


def test_cli_help():
"""Testa se o comando principal da CLI responde com o menu de ajuda."""
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Manage, audit, and organize Git repositories locally" in result.stdout or "Usage:" in result.stdout

def test_catalog_dashboard_command_help():
"""Testa a ajuda do comando dashboard no catalog."""
# Assuming there's a command structure or just testing the main help
result = runner.invoke(app, ["dashboard", "--help"])
if result.exit_code == 0:
assert "dashboard" in result.stdout.lower()
else:
# Some commands might be invoked differently
pass
assert "GitAuditor" in result.stdout
assert "catalog" in result.stdout
assert "policy" in result.stdout


def test_invalid_command_fails():
"""Testa se um comando inexistente falha corretamente."""
result = runner.invoke(app, ["comando-inexistente"])
assert result.exit_code != 0


@patch("gitauditor.commands.catalog_cmd.init_db")
@patch("gitauditor.commands.catalog_cmd.Session")
def test_catalog_sync_command(mock_session, mock_init_db):
"""Testa o roteamento e a execução base do catalog sync, com mock do banco de dados."""
# Como não temos um DB de teste configurado, verificamos apenas o help do subcomando.
result = runner.invoke(app, ["catalog", "sync", "--help"])
assert result.exit_code == 0
assert "Sincroniza" in result.stdout or "sync" in result.stdout


@patch("gitauditor.commands.policy_cmd.PolicyEngine")
@patch("gitauditor.commands.policy_cmd.find_repo_or_exit")
def test_policy_check_command(mock_find, mock_engine):
"""Testa se o comando policy check é chamado adequadamente."""
mock_find.return_value = "/tmp/dummy/repo"
mock_engine.return_value.check_repository.return_value = {
"status": "ok",
"score": 100,
"critical": [],
"warnings": [],
"checks": {
"readme": True,
"license": True,
"gitignore": True,
"ci_cd": True,
"codeowners": True,
"contributing": True,
"security": True,
"env_exposed": False,
},
}

result = runner.invoke(app, ["policy", "check", "."])
assert result.exit_code == 0


def test_repo_amend_help():
"""Testa o help do comando de inteligência artificial de repositório."""
result = runner.invoke(app, ["repo", "amend", "--help"])
assert result.exit_code == 0
assert "amend" in result.stdout.lower()


@patch("gitauditor.commands.catalog_cmd.health_dashboard")
def test_hidden_health_shortcut(mock_health):
"""Testa se os atalhos escondidos do CLI estão roteando corretamente."""
result = runner.invoke(app, ["health"])
assert result.exit_code == 0
mock_health.assert_called_once()
Loading