fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

Remove branchMap in prepareNormalBuild (#838)

This PR refactors the "build preparation" code to remove `branchMap`, in favor of storing everything in a single map. The main motivation is just to make the code clearer.

Specific changes:
* Store branches in the same map as blob locations, remove `branchMap`
* Introduce new struct `BlobIndexInfo` to hold the old location information, plus branches
* Rename `BlobLocation` -> `BlobRepo`

+149 -98
+6 -6
cmd/zoekt-repo-index/main.go
··· 180 180 } 181 181 } 182 182 183 - perBranch := map[string]map[fileKey]gitindex.BlobLocation{} 183 + perBranch := map[string]map[fileKey]gitindex.BlobRepo{} 184 184 opts.SubRepositories = map[string]*zoekt.Repository{} 185 185 186 186 // branch => repo => version ··· 193 193 } 194 194 195 195 perBranch[br.branch] = files 196 - for key, loc := range files { 196 + for key, repo := range files { 197 197 _, ok := opts.SubRepositories[key.SubRepoPath] 198 198 if ok { 199 199 // This can be incorrect: if the layout of manifests ··· 204 204 } 205 205 206 206 desc := &zoekt.Repository{} 207 - if err := gitindex.SetTemplatesFromOrigin(desc, loc.URL); err != nil { 208 - log.Fatalf("SetTemplatesFromOrigin(%s): %v", loc.URL, err) 207 + if err := gitindex.SetTemplatesFromOrigin(desc, repo.URL); err != nil { 208 + log.Fatalf("SetTemplatesFromOrigin(%s): %v", repo.URL, err) 209 209 } 210 210 211 211 opts.SubRepositories[key.SubRepoPath] = desc ··· 325 325 func iterateManifest(mf *manifest.Manifest, 326 326 baseURL url.URL, revPrefix string, 327 327 cache *gitindex.RepoCache, 328 - ) (map[fileKey]gitindex.BlobLocation, map[string]plumbing.Hash, error) { 329 - allFiles := map[fileKey]gitindex.BlobLocation{} 328 + ) (map[fileKey]gitindex.BlobRepo, map[string]plumbing.Hash, error) { 329 + allFiles := map[fileKey]gitindex.BlobRepo{} 330 330 allVersions := map[string]plumbing.Hash{} 331 331 for _, p := range mf.Project { 332 332 rev := mf.ProjectRevision(&p)
+81 -73
gitindex/index.go
··· 426 426 } 427 427 428 428 // branch => (path, sha1) => repo. 429 - var repos map[fileKey]BlobLocation 430 - 431 - // fileKey => branches 432 - var branchMap map[fileKey][]string 429 + var repos map[fileKey]BlobIndexInfo 433 430 434 431 // Branch => Repo => SHA1 435 432 var branchVersions map[string]map[string]plumbing.Hash ··· 441 438 var changedOrRemovedFiles []string 442 439 443 440 if opts.BuildOptions.IsDelta { 444 - repos, branchMap, branchVersions, changedOrRemovedFiles, err = prepareDeltaBuild(opts, repo) 441 + repos, branchVersions, changedOrRemovedFiles, err = prepareDeltaBuild(opts, repo) 445 442 if err != nil { 446 443 log.Printf("delta build: falling back to normal build since delta build failed, repository=%q, err=%s", opts.BuildOptions.RepositoryDescription.Name, err) 447 444 opts.BuildOptions.IsDelta = false ··· 449 446 } 450 447 451 448 if !opts.BuildOptions.IsDelta { 452 - repos, branchMap, branchVersions, err = prepareNormalBuild(opts, repo) 449 + repos, branchVersions, err = prepareNormalBuild(opts, repo) 453 450 if err != nil { 454 451 return false, fmt.Errorf("preparing normal build: %w", err) 455 452 } 456 453 } 457 454 458 - reposByPath := map[string]BlobLocation{} 459 - for key, location := range repos { 460 - reposByPath[key.SubRepoPath] = location 455 + reposByPath := map[string]BlobIndexInfo{} 456 + for key, info := range repos { 457 + reposByPath[key.SubRepoPath] = info 461 458 } 462 459 463 460 opts.BuildOptions.SubRepositories = map[string]*zoekt.Repository{} 464 - for path, location := range reposByPath { 461 + for path, info := range reposByPath { 465 462 tpl := opts.BuildOptions.RepositoryDescription 466 463 if path != "" { 467 - tpl = zoekt.Repository{URL: location.URL.String()} 468 - if err := SetTemplatesFromOrigin(&tpl, location.URL); err != nil { 469 - log.Printf("setTemplatesFromOrigin(%s, %s): %s", path, location.URL, err) 464 + tpl = zoekt.Repository{URL: info.Repo.URL.String()} 465 + if err := SetTemplatesFromOrigin(&tpl, info.Repo.URL); err != nil { 466 + log.Printf("setTemplatesFromOrigin(%s, %s): %s", path, info.Repo.URL, err) 470 467 } 471 468 } 472 469 opts.BuildOptions.SubRepositories[path] = &tpl ··· 542 539 keys := fileKeys[name] 543 540 544 541 for _, key := range keys { 545 - doc, err := createDocument(key, repos, branchMap, ranks, opts.BuildOptions) 542 + doc, err := createDocument(key, repos, ranks, opts.BuildOptions) 546 543 if err != nil { 547 544 return false, err 548 545 } ··· 595 592 596 593 // prepareDeltaBuildFunc is a function that calculates the necessary metadata for preparing 597 594 // a build.Builder instance for generating a delta build. 598 - type prepareDeltaBuildFunc func(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchMap map[fileKey][]string, branchVersions map[string]map[string]plumbing.Hash, changedOrDeletedPaths []string, err error) 595 + type prepareDeltaBuildFunc func(options Options, repository *git.Repository) (repos map[fileKey]BlobIndexInfo, branchVersions map[string]map[string]plumbing.Hash, changedOrDeletedPaths []string, err error) 599 596 600 597 // prepareNormalBuildFunc is a function that calculates the necessary metadata for preparing 601 598 // a build.Builder instance for generating a normal build. 602 - type prepareNormalBuildFunc func(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchMap map[fileKey][]string, branchVersions map[string]map[string]plumbing.Hash, err error) 599 + type prepareNormalBuildFunc func(options Options, repository *git.Repository) (repos map[fileKey]BlobIndexInfo, branchVersions map[string]map[string]plumbing.Hash, err error) 603 600 604 601 type gitIndexConfig struct { 605 602 // prepareDeltaBuild, if not nil, is the function that is used to calculate the metadata that will be used to ··· 615 612 prepareNormalBuild prepareNormalBuildFunc 616 613 } 617 614 618 - func prepareDeltaBuild(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchMap map[fileKey][]string, branchVersions map[string]map[string]plumbing.Hash, changedOrDeletedPaths []string, err error) { 615 + func prepareDeltaBuild(options Options, repository *git.Repository) (repos map[fileKey]BlobIndexInfo, branchVersions map[string]map[string]plumbing.Hash, changedOrDeletedPaths []string, err error) { 619 616 if options.Submodules { 620 - return nil, nil, nil, nil, fmt.Errorf("delta builds currently don't support submodule indexing") 617 + return nil, nil, nil, fmt.Errorf("delta builds currently don't support submodule indexing") 621 618 } 622 619 623 620 // discover what commits we indexed during our last build 624 621 existingRepository, _, ok, err := options.BuildOptions.FindRepositoryMetadata() 625 622 if err != nil { 626 - return nil, nil, nil, nil, fmt.Errorf("failed to get repository metadata: %w", err) 623 + return nil, nil, nil, fmt.Errorf("failed to get repository metadata: %w", err) 627 624 } 628 625 629 626 if !ok { 630 - return nil, nil, nil, nil, fmt.Errorf("no existing shards found for repository") 627 + return nil, nil, nil, fmt.Errorf("no existing shards found for repository") 631 628 } 632 629 633 630 if options.DeltaShardNumberFallbackThreshold > 0 { ··· 641 638 642 639 oldShards := options.BuildOptions.FindAllShards() 643 640 if uint64(len(oldShards)) > options.DeltaShardNumberFallbackThreshold { 644 - return nil, nil, nil, nil, fmt.Errorf("number of existing shards (%d) > requested shard threshold (%d)", len(oldShards), options.DeltaShardNumberFallbackThreshold) 641 + return nil, nil, nil, fmt.Errorf("number of existing shards (%d) > requested shard threshold (%d)", len(oldShards), options.DeltaShardNumberFallbackThreshold) 645 642 } 646 643 } 647 644 ··· 663 660 existingBranchList := strings.Join(existingBranchNames, ", ") 664 661 optionsBranchList := strings.Join(optionsBranchNames, ", ") 665 662 666 - return nil, nil, nil, nil, fmt.Errorf("requested branch set in build options (%q) != branch set found on disk (%q) - branch set must be the same for delta shards", optionsBranchList, existingBranchList) 663 + return nil, nil, nil, fmt.Errorf("requested branch set in build options (%q) != branch set found on disk (%q) - branch set must be the same for delta shards", optionsBranchList, existingBranchList) 667 664 } 668 665 669 666 // Check if the build options hash does not match the repository metadata's hash 670 667 // If it does not match then one or more index options has changed and will require a normal build instead of a delta build 671 668 if options.BuildOptions.GetHash() != existingRepository.IndexOptions { 672 - return nil, nil, nil, nil, fmt.Errorf("one or more index options previously stored for repository %s (ID: %d) does not match the index options for this requested build; These index option updates are incompatible with delta build. new index options: %+v", existingRepository.Name, existingRepository.ID, options.BuildOptions.HashOptions()) 669 + return nil, nil, nil, fmt.Errorf("one or more index options previously stored for repository %s (ID: %d) does not match the index options for this requested build; These index option updates are incompatible with delta build. new index options: %+v", existingRepository.Name, existingRepository.ID, options.BuildOptions.HashOptions()) 673 670 } 674 671 675 672 // branch => (path, sha1) => repo. 676 - repos = map[fileKey]BlobLocation{} 677 - 678 - // fileKey => branches 679 - branchMap = map[fileKey][]string{} 673 + repos = map[fileKey]BlobIndexInfo{} 680 674 681 675 // branch name -> git worktree at most current commit 682 676 branchToCurrentTree := make(map[string]*object.Tree, len(options.Branches)) ··· 684 678 for _, b := range options.Branches { 685 679 commit, err := getCommit(repository, options.BranchPrefix, b) 686 680 if err != nil { 687 - return nil, nil, nil, nil, fmt.Errorf("getting last current commit for branch %q: %w", b, err) 681 + return nil, nil, nil, fmt.Errorf("getting last current commit for branch %q: %w", b, err) 688 682 } 689 683 690 684 tree, err := commit.Tree() 691 685 if err != nil { 692 - return nil, nil, nil, nil, fmt.Errorf("getting current git tree for branch %q: %w", b, err) 686 + return nil, nil, nil, fmt.Errorf("getting current git tree for branch %q: %w", b, err) 693 687 } 694 688 695 689 branchToCurrentTree[b] = tree ··· 698 692 rawURL := options.BuildOptions.RepositoryDescription.URL 699 693 u, err := url.Parse(rawURL) 700 694 if err != nil { 701 - return nil, nil, nil, nil, fmt.Errorf("parsing repository URL %q: %w", rawURL, err) 695 + return nil, nil, nil, fmt.Errorf("parsing repository URL %q: %w", rawURL, err) 702 696 } 703 697 704 698 // TODO: Support repository submodules for delta builds 705 699 // For this prototype, we are ignoring repository submodules, which means that we can use the same 706 700 // blob location for all files 707 - hackSharedBlobLocation := BlobLocation{ 708 - Repo: repository, 709 - URL: u, 701 + hackSharedBlobLocation := BlobRepo{ 702 + GitRepo: repository, 703 + URL: u, 710 704 } 711 - 712 705 // loop over all branches, calculate the diff between our 713 706 // last indexed commit and the current commit, and add files mentioned in the diff 714 707 for _, branch := range existingRepository.Branches { 715 708 lastIndexedCommit, err := getCommit(repository, "", branch.Version) 716 709 if err != nil { 717 - return nil, nil, nil, nil, fmt.Errorf("getting last indexed commit for branch %q: %w", branch.Name, err) 710 + return nil, nil, nil, fmt.Errorf("getting last indexed commit for branch %q: %w", branch.Name, err) 718 711 } 719 712 720 713 lastIndexedTree, err := lastIndexedCommit.Tree() 721 714 if err != nil { 722 - return nil, nil, nil, nil, fmt.Errorf("getting lasted indexed git tree for branch %q: %w", branch.Name, err) 715 + return nil, nil, nil, fmt.Errorf("getting lasted indexed git tree for branch %q: %w", branch.Name, err) 723 716 } 724 717 725 718 changes, err := object.DiffTreeWithOptions(context.Background(), lastIndexedTree, branchToCurrentTree[branch.Name], &object.DiffTreeOptions{DetectRenames: false}) 726 719 if err != nil { 727 - return nil, nil, nil, nil, fmt.Errorf("generating changeset for branch %q: %w", branch.Name, err) 720 + return nil, nil, nil, fmt.Errorf("generating changeset for branch %q: %w", branch.Name, err) 728 721 } 729 722 730 723 for i, c := range changes { 731 724 oldFile, newFile, err := c.Files() 732 725 if err != nil { 733 - return nil, nil, nil, nil, fmt.Errorf("change #%d: getting files before and after change: %w", i, err) 726 + return nil, nil, nil, fmt.Errorf("change #%d: getting files before and after change: %w", i, err) 734 727 } 735 728 736 729 if newFile != nil { ··· 740 733 741 734 // TODO@ggilmore: HACK - remove once ignore files are supported in delta builds 742 735 if newFileRelativeRootPath == ignore.IgnoreFile { 743 - return nil, nil, nil, nil, fmt.Errorf("%q file is not yet supported in delta builds", ignore.IgnoreFile) 736 + return nil, nil, nil, fmt.Errorf("%q file is not yet supported in delta builds", ignore.IgnoreFile) 744 737 } 745 738 746 739 // either file is added or renamed, so we need to add the new version to the build 747 740 file := fileKey{Path: newFileRelativeRootPath, ID: newFile.Hash} 748 - repos[file] = hackSharedBlobLocation 749 - branchMap[file] = append(branchMap[file], branch.Name) 741 + if existing, ok := repos[file]; ok { 742 + existing.Branches = append(existing.Branches, branch.Name) 743 + repos[file] = existing 744 + } else { 745 + repos[file] = BlobIndexInfo{ 746 + Repo: hackSharedBlobLocation, 747 + Branches: []string{branch.Name}, 748 + } 749 + } 750 750 } 751 751 752 752 if oldFile == nil { ··· 759 759 oldFileRelativeRootPath := c.From.Name 760 760 761 761 if oldFileRelativeRootPath == ignore.IgnoreFile { 762 - return nil, nil, nil, nil, fmt.Errorf("%q file is not yet supported in delta builds", ignore.IgnoreFile) 762 + return nil, nil, nil, fmt.Errorf("%q file is not yet supported in delta builds", ignore.IgnoreFile) 763 763 } 764 764 765 765 // The file is either modified or deleted. So, we need to add ALL versions ··· 772 772 continue 773 773 } 774 774 775 - return nil, nil, nil, nil, fmt.Errorf("getting hash for file %q in branch %q: %w", oldFile.Name, b, err) 775 + return nil, nil, nil, fmt.Errorf("getting hash for file %q in branch %q: %w", oldFile.Name, b, err) 776 776 } 777 777 778 778 file := fileKey{Path: oldFileRelativeRootPath, ID: f.ID()} 779 - repos[file] = hackSharedBlobLocation 780 - branchMap[file] = append(branchMap[file], b) 779 + if existing, ok := repos[file]; ok { 780 + existing.Branches = append(existing.Branches, b) 781 + repos[file] = existing 782 + } else { 783 + repos[file] = BlobIndexInfo{ 784 + Repo: hackSharedBlobLocation, 785 + Branches: []string{b}, 786 + } 787 + } 781 788 } 782 789 783 790 changedOrDeletedPaths = append(changedOrDeletedPaths, oldFileRelativeRootPath) ··· 786 793 787 794 // we need to de-duplicate the branch map before returning it - it's possible for the same 788 795 // branch to have been added multiple times if a file has been modified across multiple commits 789 - 790 - for file, branches := range branchMap { 791 - sort.Strings(branches) 792 - branchMap[file] = uniq(branches) 796 + for _, info := range repos { 797 + sort.Strings(info.Branches) 798 + info.Branches = uniq(info.Branches) 793 799 } 794 800 795 801 // we also need to de-duplicate the list of changed or deleted file paths, it's also possible to have duplicates 796 802 // for the same reasoning as above 797 - 798 803 sort.Strings(changedOrDeletedPaths) 799 804 changedOrDeletedPaths = uniq(changedOrDeletedPaths) 800 805 801 - return repos, branchMap, nil, changedOrDeletedPaths, nil 806 + return repos, nil, changedOrDeletedPaths, nil 802 807 } 803 808 804 - func prepareNormalBuild(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchMap map[fileKey][]string, branchVersions map[string]map[string]plumbing.Hash, err error) { 809 + func prepareNormalBuild(options Options, repository *git.Repository) (repos map[fileKey]BlobIndexInfo, branchVersions map[string]map[string]plumbing.Hash, err error) { 805 810 var repoCache *RepoCache 806 811 if options.Submodules { 807 812 repoCache = NewRepoCache(options.RepoCacheDir) 808 813 } 809 814 810 - // branch => (path, sha1) => repo. 811 - repos = map[fileKey]BlobLocation{} 812 - 813 - // fileKey => branches 814 - branchMap = map[fileKey][]string{} 815 + // branch => (path, sha1) => metadata. 816 + repos = map[fileKey]BlobIndexInfo{} 815 817 816 818 // Branch => Repo => SHA1 817 819 branchVersions = map[string]map[string]plumbing.Hash{} 818 820 819 821 branches, err := expandBranches(repository, options.Branches, options.BranchPrefix) 820 822 if err != nil { 821 - return nil, nil, nil, fmt.Errorf("expandBranches: %w", err) 823 + return nil, nil, fmt.Errorf("expandBranches: %w", err) 822 824 } 823 825 824 826 for _, b := range branches { ··· 828 830 continue 829 831 } 830 832 831 - return nil, nil, nil, fmt.Errorf("getCommit: %w", err) 833 + return nil, nil, fmt.Errorf("getCommit: %w", err) 832 834 } 833 835 834 836 tree, err := commit.Tree() 835 837 if err != nil { 836 - return nil, nil, nil, fmt.Errorf("commit.Tree: %w", err) 838 + return nil, nil, fmt.Errorf("commit.Tree: %w", err) 837 839 } 838 840 839 841 ig, err := newIgnoreMatcher(tree) 840 842 if err != nil { 841 - return nil, nil, nil, fmt.Errorf("newIgnoreMatcher: %w", err) 843 + return nil, nil, fmt.Errorf("newIgnoreMatcher: %w", err) 842 844 } 843 845 844 846 files, subVersions, err := TreeToFiles(repository, tree, options.BuildOptions.RepositoryDescription.URL, repoCache) 845 847 if err != nil { 846 - return nil, nil, nil, fmt.Errorf("TreeToFiles: %w", err) 848 + return nil, nil, fmt.Errorf("TreeToFiles: %w", err) 847 849 } 848 850 for k, v := range files { 849 851 if ig.Match(k.Path) { 850 852 continue 851 853 } 852 - repos[k] = v 853 - branchMap[k] = append(branchMap[k], b) 854 + 855 + if existing, ok := repos[k]; ok { 856 + existing.Branches = append(existing.Branches, b) 857 + repos[k] = existing 858 + } else { 859 + repos[k] = BlobIndexInfo{Repo: v, Branches: []string{b}} 860 + } 854 861 } 855 862 856 863 branchVersions[b] = subVersions 857 864 } 858 865 859 - return repos, branchMap, branchVersions, nil 866 + return repos, branchVersions, nil 860 867 } 861 868 862 869 func createDocument(key fileKey, 863 - repos map[fileKey]BlobLocation, 864 - branchMap map[fileKey][]string, 870 + repos map[fileKey]BlobIndexInfo, 865 871 ranks repoPathRanks, 866 872 opts build.Options, 867 873 ) (zoekt.Document, error) { 868 - blob, err := repos[key].Repo.BlobObject(key.ID) 874 + repo := repos[key].Repo 875 + blob, err := repo.GitRepo.BlobObject(key.ID) 876 + branches := repos[key].Branches 869 877 870 878 // We filter out large documents when fetching the repo. So if an object is too large, it will not be found. 871 879 if errors.Is(err, plumbing.ErrObjectNotFound) { 872 - return skippedLargeDoc(key, branchMap, opts), nil 880 + return skippedLargeDoc(key, branches, opts), nil 873 881 } 874 882 875 883 if err != nil { ··· 878 886 879 887 keyFullPath := key.FullPath() 880 888 if blob.Size > int64(opts.SizeMax) && !opts.IgnoreSizeMax(keyFullPath) { 881 - return skippedLargeDoc(key, branchMap, opts), nil 889 + return skippedLargeDoc(key, branches, opts), nil 882 890 } 883 891 884 892 contents, err := blobContents(blob) ··· 897 905 SubRepositoryPath: key.SubRepoPath, 898 906 Name: keyFullPath, 899 907 Content: contents, 900 - Branches: branchMap[key], 908 + Branches: branches, 901 909 Ranks: pathRanks, 902 910 }, nil 903 911 } 904 912 905 - func skippedLargeDoc(key fileKey, branchMap map[fileKey][]string, opts build.Options) zoekt.Document { 913 + func skippedLargeDoc(key fileKey, branches []string, opts build.Options) zoekt.Document { 906 914 return zoekt.Document{ 907 915 SkipReason: fmt.Sprintf("file size exceeds maximum size %d", opts.SizeMax), 908 916 Name: key.FullPath(), 909 - Branches: branchMap[key], 917 + Branches: branches, 910 918 SubRepositoryPath: key.SubRepoPath, 911 919 } 912 920 }
+43 -2
gitindex/index_test.go
··· 21 21 "os" 22 22 "os/exec" 23 23 "path/filepath" 24 + "runtime" 24 25 "sort" 25 26 "testing" 26 27 ··· 607 608 // setup: prepare spy versions of prepare delta / normal build so that we can observe 608 609 // whether they were called appropriately 609 610 deltaBuildCalled := false 610 - prepareDeltaSpy := func(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchMap map[fileKey][]string, branchVersions map[string]map[string]plumbing.Hash, changedOrDeletedPaths []string, err error) { 611 + prepareDeltaSpy := func(options Options, repository *git.Repository) (repos map[fileKey]BlobIndexInfo, branchVersions map[string]map[string]plumbing.Hash, changedOrDeletedPaths []string, err error) { 611 612 deltaBuildCalled = true 612 613 return prepareDeltaBuild(options, repository) 613 614 } 614 615 615 616 normalBuildCalled := false 616 - prepareNormalSpy := func(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchMap map[fileKey][]string, branchVersions map[string]map[string]plumbing.Hash, err error) { 617 + prepareNormalSpy := func(options Options, repository *git.Repository) (repos map[fileKey]BlobIndexInfo, branchVersions map[string]map[string]plumbing.Hash, err error) { 617 618 normalBuildCalled = true 618 619 return prepareNormalBuild(options, repository) 619 620 } ··· 784 785 t.Errorf("got %q, want %q", got, want) 785 786 } 786 787 } 788 + 789 + func BenchmarkPrepareNormalBuild(b *testing.B) { 790 + // NOTE: To run the benchmark, download a large repo (like github.com/chromium/chromium/) and change this to its path. 791 + repoDir := "/path/to/your/repo" 792 + repo, err := git.PlainOpen(repoDir) 793 + if err != nil { 794 + b.Fatalf("Failed to open test repository: %v", err) 795 + } 796 + 797 + opts := Options{ 798 + RepoDir: repoDir, 799 + Submodules: false, 800 + BranchPrefix: "refs/heads/", 801 + Branches: []string{"main"}, 802 + BuildOptions: build.Options{ 803 + RepositoryDescription: zoekt.Repository{ 804 + Name: "test-repo", 805 + URL: "https://github.com/example/test-repo", 806 + }, 807 + }, 808 + } 809 + 810 + b.ReportAllocs() 811 + 812 + repos, branchVersions, err := prepareNormalBuild(opts, repo) 813 + if err != nil { 814 + b.Fatalf("prepareNormalBuild failed: %v", err) 815 + } 816 + 817 + runtime.GC() 818 + 819 + var m runtime.MemStats 820 + runtime.ReadMemStats(&m) 821 + b.ReportMetric(float64(m.HeapInuse), "heap-used-bytes") 822 + b.ReportMetric(float64(m.HeapInuse), "heap-allocated-bytes") 823 + 824 + if len(repos) == 0 || len(branchVersions) == 0 { 825 + b.Fatalf("Unexpected empty results") 826 + } 827 + }
+19 -17
gitindex/tree.go
··· 35 35 repo *git.Repository 36 36 37 37 repoURL *url.URL 38 - tree map[fileKey]BlobLocation 38 + tree map[fileKey]BlobRepo 39 39 40 40 // Path => SubmoduleEntry 41 41 submodules map[string]*SubmoduleEntry ··· 65 65 return &repoWalker{ 66 66 repo: r, 67 67 repoURL: u, 68 - tree: map[fileKey]BlobLocation{}, 68 + tree: map[fileKey]BlobRepo{}, 69 69 repoCache: repoCache, 70 70 subRepoVersions: map[string]plumbing.Hash{}, 71 71 } ··· 97 97 // TreeToFiles fetches the blob SHA1s for a tree. If repoCache is 98 98 // non-nil, recurse into submodules. In addition, it returns a mapping 99 99 // that indicates in which repo each SHA1 can be found. 100 - func TreeToFiles(r *git.Repository, t *object.Tree, 101 - repoURL string, repoCache *RepoCache, 102 - ) (map[fileKey]BlobLocation, map[string]plumbing.Hash, error) { 100 + func TreeToFiles(r *git.Repository, t *object.Tree, repoURL string, repoCache *RepoCache) (map[fileKey]BlobRepo, map[string]plumbing.Hash, error) { 103 101 rw := newRepoWalker(r, repoURL, repoCache) 104 102 105 103 if err := rw.parseModuleMap(t); err != nil { ··· 184 182 return nil 185 183 } 186 184 187 - r.tree[fileKey{ 188 - Path: p, 189 - ID: e.Hash, 190 - }] = BlobLocation{ 191 - Repo: r.repo, 192 - URL: r.repoURL, 185 + r.tree[fileKey{Path: p, ID: e.Hash}] = BlobRepo{ 186 + GitRepo: r.repo, 187 + URL: r.repoURL, 193 188 } 194 189 return nil 195 190 } ··· 206 201 return filepath.Join(k.SubRepoPath, k.Path) 207 202 } 208 203 209 - // BlobLocation holds data where a blob can be found. 210 - type BlobLocation struct { 211 - Repo *git.Repository 212 - URL *url.URL 204 + // BlobIndexInfo contains information about the blob that's needed for indexing. 205 + type BlobIndexInfo struct { 206 + Repo BlobRepo 207 + // Branches is the list of branches that contain the blob. 208 + Branches []string 213 209 } 214 210 215 - func (l *BlobLocation) Blob(id *plumbing.Hash) ([]byte, error) { 216 - blob, err := l.Repo.BlobObject(*id) 211 + // BlobRepo holds the repo where the blob can be found. 212 + type BlobRepo struct { 213 + GitRepo *git.Repository 214 + URL *url.URL 215 + } 216 + 217 + func (l *BlobRepo) Blob(id *plumbing.Hash) ([]byte, error) { 218 + blob, err := l.GitRepo.BlobObject(*id) 217 219 if err != nil { 218 220 return nil, err 219 221 }