mmpSearch/scripts/handler/dependency_checker.py

144 lines
4.8 KiB
Python

import json
import os
import logging
from urllib.parse import unquote
def load_json(path):
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
logging.error(f"Erro ao carregar {path}: {e}")
return {}
def create_sample_index(manifest_path):
"""
Cria um índice onde a CHAVE é o nome do arquivo (ex: 'kick.wav')
e o VALOR é uma lista de caminhos possíveis no servidor.
"""
manifest = load_json(manifest_path)
sample_index = {}
def traverse(node, current_path=""):
for key, value in node.items():
if key == "_isFile":
continue
# Constrói o caminho relativo web-friendly (usando /)
new_path = f"{current_path}/{key}" if current_path else key
if isinstance(value, dict) and "_isFile" in value:
# Normaliza o nome para minúsculo para busca insensível a caixa
filename_key = key.lower()
if filename_key in sample_index:
sample_index[filename_key].append(new_path)
else:
sample_index[filename_key] = [new_path]
elif isinstance(value, dict):
traverse(value, new_path)
traverse(manifest)
return sample_index
def check_dependencies(projects_json_path, manifest_path, output_report_path):
logging.info("=== Iniciando Análise Profunda de Dependências ===")
projects = load_json(projects_json_path)
server_inventory = create_sample_index(manifest_path)
report = {
"summary": {
"total": 0,
"healthy": 0, # Tudo certo de primeira
"recovered": 0, # Caminhos errados, mas arquivo encontrado no servidor
"broken": 0, # Arquivo inexistente no servidor
},
"projects": [],
}
for project in projects:
# Ajuste a chave 'file_name' ou 'name' conforme seu parser
p_name = project.get("file_name", "unknown")
# Ajuste para onde seu parser guarda os samples (ex: 'instruments' ou 'samples')
# Supondo que seu parser extraia uma lista de dicionários com 'src'
p_samples = project.get("samples", [])
project_status = {
"name": p_name,
"status": "HEALTHY", # HEALTHY | RECOVERED | BROKEN
"dependencies": [],
}
has_missing = False
has_remapped = False
for sample in p_samples:
# O caminho cru que vem do XML (ex: C:/Users/Jota/Desktop/kick.wav)
raw_src = sample.get("src", "")
if not raw_src:
continue
# 1. Normalização: Pega só o nome do arquivo (kick.wav)
# unquote resolve caracteres de URL (%20 -> espaço)
filename = os.path.basename(unquote(raw_src))
filename_key = filename.lower()
dep_info = {
"original_path": raw_src,
"filename": filename,
"status": "UNKNOWN",
"server_path": None,
}
# 2. Verificação no Inventário do Servidor
if filename_key in server_inventory:
# Encontramos o arquivo no servidor!
possible_paths = server_inventory[filename_key]
# Pega o primeiro encontrado (Heurística simples)
# Futuramente, poderia tentar casar a pasta pai para ser mais preciso
dep_info["server_path"] = possible_paths[0]
# Se o caminho original já era relativo e igual, é HEALTHY.
# Se era absoluto (C:/...) ou diferente, é RECOVERED.
if raw_src == possible_paths[0]:
dep_info["status"] = "OK"
else:
dep_info["status"] = "REMAPPED"
has_remapped = True
else:
# 3. O arquivo realmente não existe no servidor
dep_info["status"] = "MISSING"
has_missing = True
project_status["dependencies"].append(dep_info)
# Define o status final do projeto
if has_missing:
project_status["status"] = "BROKEN"
report["summary"]["broken"] += 1
elif has_remapped:
project_status["status"] = "RECOVERED"
report["summary"]["recovered"] += 1
else:
report["summary"]["healthy"] += 1
report["projects"].append(project_status)
report["summary"]["total"] = len(projects)
# Salva relatório
os.makedirs(os.path.dirname(output_report_path), exist_ok=True)
with open(output_report_path, "w", encoding="utf-8") as f:
json.dump(report, f, indent=2, ensure_ascii=False)
logging.info(f"Relatório salvo: {output_report_path}")
logging.info(f"Resumo: {json.dumps(report['summary'], indent=2)}")
return report