1313#include < vix/cli/commands/modules/ModulesUtils.hpp>
1414#include < vix/cli/app/AppManifest.hpp>
1515#include < vix/cli/modules/ModuleManifest.hpp>
16+ #include < vix/cli/modules/ModuleGraph.hpp>
1617#include < vix/cli/Style.hpp>
1718#include < vix/cli/util/Ui.hpp>
1819
@@ -1357,109 +1358,6 @@ namespace vix::commands::modules_cmd::commands
13571358 return set_module_enabled_in_vix_app (root, module , false );
13581359 }
13591360
1360- static bool check_dependency_cycle_visit (
1361- const std::string &module ,
1362- const std::unordered_map<std::string, std::vector<std::string>> &graph,
1363- std::unordered_set<std::string> &visiting,
1364- std::unordered_set<std::string> &visited,
1365- std::vector<std::string> &stack,
1366- std::vector<std::string> &cycle)
1367- {
1368- if (visited.find (module ) != visited.end ())
1369- return false ;
1370-
1371- if (visiting.find (module ) != visiting.end ())
1372- {
1373- cycle.clear ();
1374-
1375- bool capture = false ;
1376-
1377- for (const std::string &item : stack)
1378- {
1379- if (item == module )
1380- capture = true ;
1381-
1382- if (capture)
1383- cycle.push_back (item);
1384- }
1385-
1386- cycle.push_back (module );
1387- return true ;
1388- }
1389-
1390- visiting.insert (module );
1391- stack.push_back (module );
1392-
1393- const auto it = graph.find (module );
1394-
1395- if (it != graph.end ())
1396- {
1397- for (const std::string &dep : it->second )
1398- {
1399- if (check_dependency_cycle_visit (
1400- dep,
1401- graph,
1402- visiting,
1403- visited,
1404- stack,
1405- cycle))
1406- {
1407- return true ;
1408- }
1409- }
1410- }
1411-
1412- stack.pop_back ();
1413- visiting.erase (module );
1414- visited.insert (module );
1415-
1416- return false ;
1417- }
1418-
1419- static bool check_dependency_cycles (
1420- const std::unordered_map<std::string, std::vector<std::string>> &graph,
1421- std::vector<std::string> &cycle)
1422- {
1423- std::unordered_set<std::string> visiting;
1424- std::unordered_set<std::string> visited;
1425- std::vector<std::string> stack;
1426-
1427- for (const auto &entry : graph)
1428- {
1429- if (check_dependency_cycle_visit (
1430- entry.first ,
1431- graph,
1432- visiting,
1433- visited,
1434- stack,
1435- cycle))
1436- {
1437- return true ;
1438- }
1439- }
1440-
1441- return false ;
1442- }
1443-
1444- static std::string join_cycle (
1445- const std::vector<std::string> &cycle)
1446- {
1447- if (cycle.empty ())
1448- return " -" ;
1449-
1450- std::ostringstream out;
1451-
1452- for (std::size_t i = 0 ; i < cycle.size (); ++i)
1453- {
1454- if (i > 0 )
1455- out << " -> " ;
1456-
1457- out << cycle[i];
1458- }
1459-
1460- return out.str ();
1461- }
1462-
14631361 bool cmd_check (const fs::path &root, const std::string &project)
14641362 {
14651363 const fs::path modulesDir = root / " modules" ;
@@ -1481,7 +1379,7 @@ namespace vix::commands::modules_cmd::commands
14811379 std::unordered_map<std::string, bool > enabledInApp;
14821380 std::unordered_map<std::string, std::string> kindInApp;
14831381 std::unordered_map<std::string, std::string> pathInApp;
1484- std::unordered_map<std::string, std::vector<std::string>> appDeps ;
1382+ vix::cli::modules::ModuleGraph graph ;
14851383
14861384 if (hasVixApp)
14871385 {
@@ -1495,6 +1393,15 @@ namespace vix::commands::modules_cmd::commands
14951393 return false ;
14961394 }
14971395
1396+ std::string graphError;
1397+ graph = vix::cli::modules::ModuleGraph::from_app_modules (
1398+ loadResult.manifest .appModules , graphError);
1399+ if (!graph.valid () || !graph.validate_paths (root, false , graphError))
1400+ {
1401+ ui::err_line (std::cout, " Invalid module graph: " + graphError);
1402+ return false ;
1403+ }
1404+
14981405 for (const auto &module : loadResult.manifest .appModules )
14991406 {
15001407 const std::string name =
@@ -1504,11 +1411,6 @@ namespace vix::commands::modules_cmd::commands
15041411 enabledInApp[name] = module .enabled ;
15051412 kindInApp[name] = module .kind .empty () ? " module" : module .kind ;
15061413 pathInApp[name] = module .path .empty () ? (" modules/" + name) : module .path ;
1507-
1508- for (const std::string &depRaw : module .depends )
1509- {
1510- appDeps[name].push_back (cnt::normalize_module_id (depRaw));
1511- }
15121414 }
15131415 }
15141416
@@ -1587,43 +1489,6 @@ namespace vix::commands::modules_cmd::commands
15871489 }
15881490 }
15891491
1590- for (const auto &entry : appDeps)
1591- {
1592- const std::string &module = entry.first ;
1593-
1594- for (const std::string &dep : entry.second )
1595- {
1596- if (declaredInApp.find (dep) == declaredInApp.end ())
1597- {
1598- ok = false ;
1599- ++violations;
1600-
1601- ui::err_line (std::cout, " Module depends on an undeclared module" );
1602- ui::kv (std::cout, " module" , module , 12 );
1603- ui::kv (std::cout, " depends" , dep, 12 );
1604- }
1605- else if (enabledInApp[module ] && !enabledInApp[dep])
1606- {
1607- ok = false ;
1608- ++violations;
1609-
1610- ui::err_line (std::cout, " Enabled module depends on a disabled module" );
1611- ui::kv (std::cout, " module" , module , 12 );
1612- ui::kv (std::cout, " depends" , dep, 12 );
1613- }
1614- }
1615- }
1616-
1617- std::vector<std::string> cycle;
1618-
1619- if (check_dependency_cycles (appDeps, cycle))
1620- {
1621- ok = false ;
1622- ++violations;
1623-
1624- ui::err_line (std::cout, " Circular module dependency detected" );
1625- ui::kv (std::cout, " cycle" , join_cycle (cycle), 12 );
1626- }
16271492 }
16281493
16291494 std::unordered_map<std::string, std::string> routePrefixes;
0 commit comments