diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..1771819 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,22 @@ +name: Validate + +on: + pull_request: + push: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Run repository validation + run: python scripts/validate_repo.py diff --git a/scripts/validate_repo.py b/scripts/validate_repo.py new file mode 100644 index 0000000..b263a19 --- /dev/null +++ b/scripts/validate_repo.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from pathlib import Path +import compileall +import sys + +ROOT = Path(__file__).resolve().parents[1] +CONFLICT_TOKENS = ("<<<<<<<", "=======", ">>>>>>>") + + +def check_conflict_markers() -> list[str]: + problems: list[str] = [] + targets = [ROOT / "main.py", *(ROOT / "src").rglob("*.py")] + for path in targets: + text = path.read_text(encoding="utf-8", errors="ignore") + for idx, line in enumerate(text.splitlines(), start=1): + if any(token in line for token in CONFLICT_TOKENS): + problems.append(f"{path.relative_to(ROOT)}:{idx}: marcador de conflito encontrado") + if line.strip().startswith("codex/review-repository-code-"): + problems.append(f"{path.relative_to(ROOT)}:{idx}: artefacto de branch encontrado") + return problems + + +def main() -> int: + marker_errors = check_conflict_markers() + if marker_errors: + for error in marker_errors: + print(error) + return 1 + + ok = compileall.compile_dir(str(ROOT / "src"), quiet=1) + ok_main = compileall.compile_file(str(ROOT / "main.py"), quiet=1) + if not ok or not ok_main: + print("Falha de compilação Python.") + return 1 + + print("Validação concluída com sucesso.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/app.py b/src/app.py index c034dc6..9d2b868 100644 --- a/src/app.py +++ b/src/app.py @@ -33,6 +33,7 @@ def _migrate_legacy_config_if_needed(): if CONFIG_FILE.exists() or not LEGACY_CONFIG_FILE.exists(): return + codex/review-repository-code-argiid try: legacy_data = json.loads(LEGACY_CONFIG_FILE.read_text(encoding="utf-8")) APP_CONFIG_DIR.mkdir(parents=True, exist_ok=True) @@ -44,6 +45,19 @@ def _migrate_legacy_config_if_needed(): def _read_json_file(path: Path): """Le JSON de um ficheiro devolvendo dict vazio em caso de erro.""" try: + + try: + legacy_data = json.loads(LEGACY_CONFIG_FILE.read_text(encoding="utf-8")) + APP_CONFIG_DIR.mkdir(parents=True, exist_ok=True) + CONFIG_FILE.write_text(json.dumps(legacy_data, indent=2, ensure_ascii=False), encoding="utf-8") + except Exception: + pass + + +def _read_json_file(path: Path): + """Le JSON de um ficheiro devolvendo dict vazio em caso de erro.""" + try: + main if path.exists(): with open(path, "r", encoding="utf-8") as f: return json.load(f) @@ -122,6 +136,9 @@ def __init__(self): self.config = load_config() self.scan_paths = [] self._selection_loaded = False + codex/review-repository-code-argiid + self.filters_panel_visible = True + codex/review-repository-code-l1cd2s self.filters_panel_visible = True @@ -129,6 +146,7 @@ def __init__(self): self.filters_panel_visible = True main +> main self.setWindowTitle("Duplicate File Cleaner") self.setMinimumSize(900, 620) @@ -389,6 +407,16 @@ def _build_scan_tab(self): self.scan_mode.currentIndexChanged.connect(self._on_mode_change) mode_layout.addWidget(self.scan_mode) mode_layout.addStretch() +codex/review-repository-code-argiid + + self.toggle_filters_btn = QPushButton("Esconder Selecao") + self.toggle_filters_btn.clicked.connect(self._toggle_filters_panel) + mode_layout.addWidget(self.toggle_filters_btn) + filter_layout.addLayout(mode_layout) + + self.filters_panel_widget = self._build_filters_panel() + filter_layout.addWidget(self.filters_panel_widget, 1) + codex/review-repository-code-l1cd2s self.toggle_filters_btn = QPushButton("Esconder Selecao") @@ -450,6 +478,7 @@ def _build_scan_tab(self): filter_layout.addLayout(custom_layout) main + main main scan_splitter.addWidget(filter_group)