144 lines
4.8 KiB
Python
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
|