| 612 | } |
| 613 | |
| 614 | static bool collect_files(const fs::path & old_cache, |
| 615 | const std::string & owner, |
| 616 | const std::string & repo, |
| 617 | const nl::json & node, |
| 618 | const hf_files & files, |
| 619 | migrate_files & to_migrate) { |
| 620 | |
| 621 | if (!node.contains("rfilename") || |
| 622 | !node.contains("lfs") || |
| 623 | !node["lfs"].contains("sha256")) { |
| 624 | return true; |
| 625 | } |
| 626 | |
| 627 | std::string path = node["rfilename"]; |
| 628 | std::string sha256 = node["lfs"]["sha256"]; |
| 629 | |
| 630 | auto split = get_gguf_split_info(path); |
| 631 | |
| 632 | if (split.count <= 1) { |
| 633 | return collect_file(old_cache, owner, repo, path, sha256, files, to_migrate); |
| 634 | } |
| 635 | |
| 636 | std::vector<std::pair<std::string, std::string>> splits; |
| 637 | |
| 638 | for (const auto & f : files) { |
| 639 | auto split_f = get_gguf_split_info(f.path); |
| 640 | if (split_f.count == split.count && split_f.prefix == split.prefix) { |
| 641 | // sadly the manifest only provides the sha256 of the first file (index == 1) |
| 642 | // the rest will be verified using the size... |
| 643 | std::string f_sha256 = (split_f.index == 1) ? sha256 : ""; |
| 644 | splits.emplace_back(f.path, f_sha256); |
| 645 | } |
| 646 | } |
| 647 | |
| 648 | if ((int)splits.size() != split.count) { |
| 649 | LOG_WRN("%s: expected %d split files but found %d in repo\n", __func__, split.count, (int)splits.size()); |
| 650 | return false; |
| 651 | } |
| 652 | |
| 653 | for (const auto & [f_path, f_sha256] : splits) { |
| 654 | if (!collect_file(old_cache, owner, repo, f_path, f_sha256, files, to_migrate)) { |
| 655 | return false; |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | return true; |
| 660 | } |
| 661 | |
| 662 | static bool migrate_file(const migrate_file & file) { |
| 663 | std::error_code ec; |
no test coverage detected