Skip to content

Commit 5968df7

Browse files
committed
fix(add): replace dependencies moved to new package IDs
1 parent 0c609bc commit 5968df7

1 file changed

Lines changed: 214 additions & 3 deletions

File tree

src/commands/AddCommand.cpp

Lines changed: 214 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ namespace vix::commands
598598
const fs::path &path,
599599
const std::string &dependency,
600600
const std::string &linkTarget,
601+
const std::vector<std::string> &replacedPackageIds,
601602
std::string &error)
602603
{
603604
if (!fs::exists(path))
@@ -625,6 +626,23 @@ namespace vix::commands
625626
std::vector<std::string> links =
626627
parse_ini_array(original, "deps", "links");
627628

629+
registry.erase(
630+
std::remove_if(
631+
registry.begin(),
632+
registry.end(),
633+
[&](const std::string &existingDependency)
634+
{
635+
PkgSpec existingSpec;
636+
637+
if (!parse_pkg_spec(existingDependency, existingSpec))
638+
return false;
639+
640+
return contains_string(
641+
replacedPackageIds,
642+
existingSpec.id());
643+
}),
644+
registry.end());
645+
628646
if (!contains_string(registry, dependency))
629647
registry.push_back(dependency);
630648

@@ -763,6 +781,128 @@ namespace vix::commands
763781
return j;
764782
}
765783

784+
void write_json_file_or_throw(
785+
const fs::path &path,
786+
const json &value)
787+
{
788+
std::ofstream out(path);
789+
790+
if (!out)
791+
{
792+
throw std::runtime_error(
793+
"cannot write file: " + path.string());
794+
}
795+
796+
out << value.dump(2) << "\n";
797+
798+
if (!out.good())
799+
{
800+
throw std::runtime_error(
801+
"failed to write file: " + path.string());
802+
}
803+
}
804+
805+
std::vector<std::string> find_packages_moved_to(
806+
const std::string &targetPackageId)
807+
{
808+
std::vector<std::string> packageIds;
809+
const fs::path indexPath = registry_index_dir();
810+
811+
if (!fs::exists(indexPath))
812+
return packageIds;
813+
814+
for (const auto &item :
815+
fs::directory_iterator(indexPath))
816+
{
817+
if (!item.is_regular_file() ||
818+
item.path().extension() != ".json")
819+
{
820+
continue;
821+
}
822+
823+
try
824+
{
825+
const json entry =
826+
read_json_file_or_throw(item.path());
827+
828+
const std::string movedTo =
829+
entry.value("movedTo", std::string{});
830+
831+
if (movedTo != targetPackageId)
832+
continue;
833+
834+
const std::string ns =
835+
entry.value("namespace", std::string{});
836+
837+
const std::string name =
838+
entry.value("name", std::string{});
839+
840+
if (ns.empty() || name.empty())
841+
continue;
842+
843+
const std::string packageId =
844+
ns + "/" + name;
845+
846+
if (!contains_string(packageIds, packageId))
847+
packageIds.push_back(packageId);
848+
}
849+
catch (...)
850+
{
851+
}
852+
}
853+
854+
return packageIds;
855+
}
856+
857+
std::size_t remove_manifest_dependencies(
858+
const fs::path &path,
859+
const std::vector<std::string> &packageIds)
860+
{
861+
if (packageIds.empty())
862+
return 0;
863+
864+
json manifest = read_json_file_or_throw(path);
865+
866+
if (!manifest.contains("deps") ||
867+
!manifest["deps"].is_array())
868+
{
869+
return 0;
870+
}
871+
872+
json dependencies = json::array();
873+
std::size_t removed = 0;
874+
875+
for (const auto &dependency : manifest["deps"])
876+
{
877+
if (!dependency.is_object() ||
878+
!dependency.contains("id") ||
879+
!dependency["id"].is_string())
880+
{
881+
dependencies.push_back(dependency);
882+
continue;
883+
}
884+
885+
const std::string packageId =
886+
dependency["id"].get<std::string>();
887+
888+
if (contains_string(packageIds, packageId))
889+
{
890+
++removed;
891+
continue;
892+
}
893+
894+
dependencies.push_back(dependency);
895+
}
896+
897+
if (removed > 0)
898+
{
899+
manifest["deps"] = std::move(dependencies);
900+
write_json_file_or_throw(path, manifest);
901+
}
902+
903+
return removed;
904+
}
905+
766906
fs::path entry_path(const std::string &ns, const std::string &name)
767907
{
768908
return registry_index_dir() / (ns + "." + name + ".json");
@@ -1062,7 +1202,9 @@ namespace vix::commands
10621202
return 1;
10631203
}
10641204

1065-
const fs::path packageEntryPath = entry_path(spec.ns, spec.name);
1205+
fs::path packageEntryPath =
1206+
entry_path(spec.ns, spec.name);
1207+
10661208
if (!fs::exists(packageEntryPath))
10671209
{
10681210
vix::cli::util::err_line(std::cerr, "package not found: " + spec.id());
@@ -1084,9 +1226,57 @@ namespace vix::commands
10841226

10851227
try
10861228
{
1087-
const json entry = read_json_file_or_throw(packageEntryPath);
1229+
json entry =
1230+
read_json_file_or_throw(packageEntryPath);
1231+
1232+
const std::string originalPackageId = spec.id();
1233+
1234+
if (entry.contains("movedTo") &&
1235+
entry["movedTo"].is_string())
1236+
{
1237+
const std::string movedTo =
1238+
trim_copy(entry["movedTo"].get<std::string>());
1239+
1240+
if (!movedTo.empty())
1241+
{
1242+
PkgSpec movedSpec;
1243+
1244+
if (!parse_pkg_spec(movedTo, movedSpec))
1245+
{
1246+
throw std::runtime_error(
1247+
"invalid movedTo package id: " + movedTo);
1248+
}
1249+
1250+
movedSpec.requestedVersion =
1251+
spec.requestedVersion;
1252+
1253+
movedSpec.resolvedVersion.clear();
1254+
1255+
spec = std::move(movedSpec);
1256+
1257+
packageEntryPath =
1258+
entry_path(spec.ns, spec.name);
1259+
1260+
if (!fs::exists(packageEntryPath))
1261+
{
1262+
throw std::runtime_error(
1263+
"moved package not found: " + spec.id());
1264+
}
10881265

1089-
const int resolveRc = resolve_version_v1(entry, spec);
1266+
entry =
1267+
read_json_file_or_throw(packageEntryPath);
1268+
1269+
vix::cli::util::warn_line(
1270+
std::cout,
1271+
"Package moved: " +
1272+
originalPackageId +
1273+
" -> " +
1274+
spec.id());
1275+
}
1276+
}
1277+
1278+
const int resolveRc =
1279+
resolve_version_v1(entry, spec);
10901280
if (resolveRc != 0)
10911281
{
10921282
return resolveRc;
@@ -1146,6 +1336,9 @@ namespace vix::commands
11461336
const std::string dependencySpec =
11471337
packageId + "@" + requested;
11481338

1339+
const std::vector<std::string> replacedPackageIds =
1340+
find_packages_moved_to(packageId);
1341+
11491342
if (!options.moduleName.empty())
11501343
{
11511344
const std::string linkTarget =
@@ -1159,6 +1352,7 @@ namespace vix::commands
11591352
module_manifest_path(options.moduleName),
11601353
dependencySpec,
11611354
linkTarget,
1355+
replacedPackageIds,
11621356
moduleError))
11631357
{
11641358
vix::cli::util::err_line(std::cerr, moduleError);
@@ -1199,12 +1393,29 @@ namespace vix::commands
11991393
return 0;
12001394
}
12011395

1396+
const std::size_t replacedCount =
1397+
remove_manifest_dependencies(
1398+
manifest_path(),
1399+
replacedPackageIds);
1400+
12021401
vix::cli::util::manifest::upsert_manifest_dependency_or_throw(
12031402
manifest_path(),
12041403
vix::cli::util::manifest::Dependency{
12051404
packageId,
12061405
requested});
12071406

1407+
if (replacedCount > 0)
1408+
{
1409+
for (const std::string &oldPackageId :
1410+
replacedPackageIds)
1411+
{
1412+
vix::cli::util::kv(
1413+
std::cout,
1414+
"replaced",
1415+
oldPackageId + " -> " + packageId);
1416+
}
1417+
}
1418+
12081419
vix::cli::util::section(std::cout, "Add");
12091420
vix::cli::util::kv(std::cout, "id", packageId);
12101421
vix::cli::util::kv(std::cout, "version", spec.resolvedVersion);

0 commit comments

Comments
 (0)