@@ -550,35 +550,74 @@ namespace mamba::solver::libsolv
550
550
LOG_INFO << " Reading repodata.json file " << filename << " for repo " << repo.name ()
551
551
<< " using mamba" ;
552
552
553
+ // WARNING:
554
+ // We use below SimdJson's "on demand" parser, which does not tolerate
555
+ // reading the same value more than once. This means we need to make
556
+ // sure that the objects and their fields are read once and kept around
557
+ // until being used if necessary. This is why the code belows tries hard
558
+ // to pre-read the general data in a way that prevents jumping up and down
559
+ // the hierarchy of json objects. When this rule is not followed, the parsing
560
+ // might end earlier than expected or might skip data that are read when they
561
+ // shouldnt be, leading to *runtime issues* that might not be visible at first.
562
+ // Because of these reasons, be careful when modifingy the following parsing
563
+ // code.
564
+
553
565
auto parser = simdjson::ondemand::parser ();
554
566
const auto lock = LockFile (filename);
555
567
const auto json_content = simdjson::padded_string::load (filename.string ()); // must be kept alive while reading json
556
568
auto repodata_doc = parser.iterate(json_content);
557
569
570
+ const auto repodata_version = [&] {
571
+ if (auto version = repodata_doc[" repodata_version" ].get_int64 (); !version.error ())
572
+ {
573
+ return version.value ();
574
+ }
575
+ else
576
+ {
577
+ return std::int64_t { 1 };
578
+ }
579
+ }();
580
+
581
+
582
+ auto info = [&]{
583
+ if (auto value = repodata_doc[" info" ]; !value.error ())
584
+ {
585
+ if (auto object = value.get_object (); !object.error ())
586
+ {
587
+ return std::make_optional (object);
588
+ }
589
+ }
590
+ return decltype (std::make_optional (repodata_doc[" info" ].get_object ())){};
591
+
592
+ }();
558
593
559
594
// An override for missing package subdir is found at the top level
560
- auto default_subdir = std::string ();
561
- if (auto subdir = repodata_doc[" /info/subdir" ]; !subdir.error ())
562
- {
563
- default_subdir = std::string (subdir.get_string ().value_unsafe ());
564
- }
595
+ const auto default_subdir = [&]{
596
+ if (info)
597
+ {
598
+ if (auto subdir = info.value ()[" subdir" ]; !subdir.error ())
599
+ {
600
+ return std::string (subdir.get_string ().value_unsafe ());
601
+ }
602
+ }
603
+
604
+ return std::string{};
605
+ }();
565
606
566
607
567
608
// Get `base_url` in case 'repodata_version': 2
568
609
// cf. https://github.com/conda-incubator/ceps/blob/main/cep-15.md
569
- auto base_url = repo_url;
570
- if (auto repodata_version = repodata_doc[" repodata_version" ].get_int64 ();
571
- !repodata_version.error ())
572
- {
573
- if (repodata_version.value_unsafe () == 2 )
610
+ const auto base_url = [&] {
611
+ if (repodata_version == 2 && info)
574
612
{
575
- if (auto url = repodata_doc[ " /info/ base_url" ]; !url.error ())
613
+ if (auto url = info. value ()[ " base_url" ]; !url.error ())
576
614
{
577
- base_url = std::string (url.get_string ().value_unsafe ());
615
+ return std::string (url.get_string ().value_unsafe ());
578
616
}
579
617
}
580
- }
581
618
619
+ return repo_url;
620
+ }();
582
621
583
622
const auto parsed_url = specs::CondaURL::parse (base_url)
584
623
.or_else ([](specs::ParseError&& err) { throw std::move (err); })
0 commit comments