262 lines
12 KiB
C#
262 lines
12 KiB
C#
using System.CommandLine;
|
|
using NatsNet.PortTracker.Data;
|
|
|
|
namespace NatsNet.PortTracker.Commands;
|
|
|
|
public static class ModuleCommands
|
|
{
|
|
public static Command Create(Option<string> dbOption, Option<string> schemaOption)
|
|
{
|
|
var moduleCommand = new Command("module", "Manage modules");
|
|
|
|
// list
|
|
var listStatus = new Option<string?>("--status") { Description = "Filter by status" };
|
|
var listCmd = new Command("list", "List modules");
|
|
listCmd.Add(listStatus);
|
|
listCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var status = parseResult.GetValue(listStatus);
|
|
using var db = new Database(dbPath);
|
|
var sql = "SELECT id, name, status, go_package, go_line_count, dotnet_project, dotnet_class FROM modules";
|
|
var parameters = new List<(string, object?)>();
|
|
if (status is not null)
|
|
{
|
|
sql += " WHERE status = @status";
|
|
parameters.Add(("@status", status));
|
|
}
|
|
sql += " ORDER BY name";
|
|
|
|
var rows = db.Query(sql, parameters.ToArray());
|
|
Console.WriteLine($"{"ID",-5} {"Name",-25} {"Status",-15} {"Go Pkg",-15} {"LOC",-8} {"DotNet Project",-25} {"DotNet Class",-20}");
|
|
Console.WriteLine(new string('-', 113));
|
|
foreach (var row in rows)
|
|
{
|
|
Console.WriteLine($"{row["id"],-5} {row["name"],-25} {row["status"],-15} {row["go_package"],-15} {row["go_line_count"],-8} {row["dotnet_project"] ?? "",-25} {row["dotnet_class"] ?? "",-20}");
|
|
}
|
|
Console.WriteLine($"\nTotal: {rows.Count} modules");
|
|
});
|
|
|
|
// show
|
|
var showId = new Argument<int>("id") { Description = "Module ID" };
|
|
var showCmd = new Command("show", "Show module details");
|
|
showCmd.Add(showId);
|
|
showCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var id = parseResult.GetValue(showId);
|
|
using var db = new Database(dbPath);
|
|
var modules = db.Query("SELECT * FROM modules WHERE id = @id", ("@id", id));
|
|
if (modules.Count == 0)
|
|
{
|
|
Console.WriteLine($"Module {id} not found.");
|
|
return;
|
|
}
|
|
var mod = modules[0];
|
|
Console.WriteLine($"Module #{mod["id"]}: {mod["name"]}");
|
|
Console.WriteLine($" Status: {mod["status"]}");
|
|
Console.WriteLine($" Go Package: {mod["go_package"]}");
|
|
Console.WriteLine($" Go File: {mod["go_file"]}");
|
|
Console.WriteLine($" Go LOC: {mod["go_line_count"]}");
|
|
Console.WriteLine($" .NET: {mod["dotnet_project"]} / {mod["dotnet_namespace"]} / {mod["dotnet_class"]}");
|
|
Console.WriteLine($" Notes: {mod["notes"]}");
|
|
|
|
var features = db.Query(
|
|
"SELECT id, name, status, go_method, dotnet_method FROM features WHERE module_id = @id ORDER BY name",
|
|
("@id", id));
|
|
Console.WriteLine($"\n Features ({features.Count}):");
|
|
foreach (var f in features)
|
|
Console.WriteLine($" #{f["id"],-5} {f["name"],-35} {f["status"],-15} {f["dotnet_method"] ?? ""}");
|
|
|
|
var tests = db.Query(
|
|
"SELECT id, name, status, dotnet_method FROM unit_tests WHERE module_id = @id ORDER BY name",
|
|
("@id", id));
|
|
Console.WriteLine($"\n Tests ({tests.Count}):");
|
|
foreach (var t in tests)
|
|
Console.WriteLine($" #{t["id"],-5} {t["name"],-35} {t["status"],-15} {t["dotnet_method"] ?? ""}");
|
|
|
|
var deps = db.Query(
|
|
"SELECT d.target_type, d.target_id, d.dependency_kind, m.name as target_name FROM dependencies d LEFT JOIN modules m ON d.target_type = 'module' AND d.target_id = m.id WHERE d.source_type = 'module' AND d.source_id = @id",
|
|
("@id", id));
|
|
Console.WriteLine($"\n Dependencies ({deps.Count}):");
|
|
foreach (var d in deps)
|
|
Console.WriteLine($" -> {d["target_type"]} #{d["target_id"]} ({d["target_name"]}) [{d["dependency_kind"]}]");
|
|
});
|
|
|
|
// update
|
|
var updateId = new Argument<int>("id") { Description = "Module ID" };
|
|
var updateStatus = new Option<string>("--status") { Description = "New status", Required = true };
|
|
var updateCmd = new Command("update", "Update module status");
|
|
updateCmd.Add(updateId);
|
|
updateCmd.Add(updateStatus);
|
|
updateCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var id = parseResult.GetValue(updateId);
|
|
var status = parseResult.GetValue(updateStatus)!;
|
|
using var db = new Database(dbPath);
|
|
var affected = db.Execute("UPDATE modules SET status = @status WHERE id = @id",
|
|
("@status", status), ("@id", id));
|
|
Console.WriteLine(affected > 0 ? $"Module {id} updated to '{status}'." : $"Module {id} not found.");
|
|
});
|
|
|
|
// map
|
|
var mapId = new Argument<int>("id") { Description = "Module ID" };
|
|
var mapProject = new Option<string>("--project") { Description = "Target .NET project", Required = true };
|
|
var mapNamespace = new Option<string?>("--namespace") { Description = "Target namespace" };
|
|
var mapClass = new Option<string?>("--class") { Description = "Target class" };
|
|
var mapCmd = new Command("map", "Map module to .NET project");
|
|
mapCmd.Add(mapId);
|
|
mapCmd.Add(mapProject);
|
|
mapCmd.Add(mapNamespace);
|
|
mapCmd.Add(mapClass);
|
|
mapCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var id = parseResult.GetValue(mapId);
|
|
var project = parseResult.GetValue(mapProject)!;
|
|
var ns = parseResult.GetValue(mapNamespace);
|
|
var cls = parseResult.GetValue(mapClass);
|
|
using var db = new Database(dbPath);
|
|
var affected = db.Execute(
|
|
"UPDATE modules SET dotnet_project = @project, dotnet_namespace = @ns, dotnet_class = @cls WHERE id = @id",
|
|
("@project", project), ("@ns", ns), ("@cls", cls), ("@id", id));
|
|
Console.WriteLine(affected > 0 ? $"Module {id} mapped to {project}." : $"Module {id} not found.");
|
|
});
|
|
|
|
// set-na
|
|
var naId = new Argument<int>("id") { Description = "Module ID" };
|
|
var naReason = new Option<string>("--reason") { Description = "Reason for N/A", Required = true };
|
|
var naCmd = new Command("set-na", "Mark module as N/A");
|
|
naCmd.Add(naId);
|
|
naCmd.Add(naReason);
|
|
naCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var id = parseResult.GetValue(naId);
|
|
var reason = parseResult.GetValue(naReason)!;
|
|
using var db = new Database(dbPath);
|
|
var affected = db.Execute(
|
|
"UPDATE modules SET status = 'n_a', notes = @reason WHERE id = @id",
|
|
("@reason", reason), ("@id", id));
|
|
Console.WriteLine(affected > 0 ? $"Module {id} set to N/A: {reason}" : $"Module {id} not found.");
|
|
});
|
|
|
|
moduleCommand.Add(listCmd);
|
|
moduleCommand.Add(showCmd);
|
|
moduleCommand.Add(updateCmd);
|
|
moduleCommand.Add(mapCmd);
|
|
moduleCommand.Add(naCmd);
|
|
moduleCommand.Add(CreateBatchUpdate(dbOption));
|
|
moduleCommand.Add(CreateBatchMap(dbOption));
|
|
|
|
return moduleCommand;
|
|
}
|
|
|
|
private static Command CreateBatchUpdate(Option<string> dbOption)
|
|
{
|
|
var cmd = new Command("batch-update", "Bulk update module status");
|
|
var idsOpt = BatchFilters.IdsOption();
|
|
var statusOpt = BatchFilters.StatusOption();
|
|
var executeOpt = BatchFilters.ExecuteOption();
|
|
var setStatus = new Option<string>("--set-status") { Description = "New status to set", Required = true };
|
|
var setNotes = new Option<string?>("--set-notes") { Description = "Notes to set" };
|
|
|
|
cmd.Add(idsOpt);
|
|
cmd.Add(statusOpt);
|
|
cmd.Add(executeOpt);
|
|
cmd.Add(setStatus);
|
|
cmd.Add(setNotes);
|
|
|
|
cmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var ids = parseResult.GetValue(idsOpt);
|
|
var status = parseResult.GetValue(statusOpt);
|
|
var execute = parseResult.GetValue(executeOpt);
|
|
var newStatus = parseResult.GetValue(setStatus)!;
|
|
var notes = parseResult.GetValue(setNotes);
|
|
|
|
if (string.IsNullOrWhiteSpace(ids) && string.IsNullOrWhiteSpace(status))
|
|
{
|
|
Console.WriteLine("Error: at least one filter (--ids, --status) is required.");
|
|
return;
|
|
}
|
|
|
|
using var db = new Database(dbPath);
|
|
var (whereClause, filterParams) = BatchFilters.BuildWhereClause(ids, null, status);
|
|
|
|
var setClauses = new List<string> { "status = @newStatus" };
|
|
var updateParams = new List<(string, object?)> { ("@newStatus", newStatus) };
|
|
if (notes is not null)
|
|
{
|
|
setClauses.Add("notes = @newNotes");
|
|
updateParams.Add(("@newNotes", notes));
|
|
}
|
|
|
|
BatchFilters.PreviewOrExecute(db, "modules",
|
|
"id, name, status, notes",
|
|
string.Join(", ", setClauses), updateParams,
|
|
whereClause, filterParams, execute);
|
|
});
|
|
|
|
return cmd;
|
|
}
|
|
|
|
private static Command CreateBatchMap(Option<string> dbOption)
|
|
{
|
|
var cmd = new Command("batch-map", "Bulk map modules to .NET projects");
|
|
var idsOpt = BatchFilters.IdsOption();
|
|
var statusOpt = BatchFilters.StatusOption();
|
|
var executeOpt = BatchFilters.ExecuteOption();
|
|
var setProject = new Option<string?>("--set-project") { Description = ".NET project" };
|
|
var setNamespace = new Option<string?>("--set-namespace") { Description = ".NET namespace" };
|
|
var setClass = new Option<string?>("--set-class") { Description = ".NET class" };
|
|
|
|
cmd.Add(idsOpt);
|
|
cmd.Add(statusOpt);
|
|
cmd.Add(executeOpt);
|
|
cmd.Add(setProject);
|
|
cmd.Add(setNamespace);
|
|
cmd.Add(setClass);
|
|
|
|
cmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var ids = parseResult.GetValue(idsOpt);
|
|
var status = parseResult.GetValue(statusOpt);
|
|
var execute = parseResult.GetValue(executeOpt);
|
|
var project = parseResult.GetValue(setProject);
|
|
var ns = parseResult.GetValue(setNamespace);
|
|
var cls = parseResult.GetValue(setClass);
|
|
|
|
if (string.IsNullOrWhiteSpace(ids) && string.IsNullOrWhiteSpace(status))
|
|
{
|
|
Console.WriteLine("Error: at least one filter (--ids, --status) is required.");
|
|
return;
|
|
}
|
|
if (project is null && ns is null && cls is null)
|
|
{
|
|
Console.WriteLine("Error: at least one of --set-project, --set-namespace, --set-class is required.");
|
|
return;
|
|
}
|
|
|
|
using var db = new Database(dbPath);
|
|
var (whereClause, filterParams) = BatchFilters.BuildWhereClause(ids, null, status);
|
|
|
|
var setClauses = new List<string>();
|
|
var updateParams = new List<(string, object?)>();
|
|
if (project is not null) { setClauses.Add("dotnet_project = @setProject"); updateParams.Add(("@setProject", project)); }
|
|
if (ns is not null) { setClauses.Add("dotnet_namespace = @setNamespace"); updateParams.Add(("@setNamespace", ns)); }
|
|
if (cls is not null) { setClauses.Add("dotnet_class = @setClass"); updateParams.Add(("@setClass", cls)); }
|
|
|
|
BatchFilters.PreviewOrExecute(db, "modules",
|
|
"id, name, status, dotnet_project, dotnet_namespace, dotnet_class",
|
|
string.Join(", ", setClauses), updateParams,
|
|
whereClause, filterParams, execute);
|
|
});
|
|
|
|
return cmd;
|
|
}
|
|
}
|