diff --git a/cmd/package_managers.go b/cmd/package_managers.go index b267c3dc7432..81ceb95ef094 100644 --- a/cmd/package_managers.go +++ b/cmd/package_managers.go @@ -96,8 +96,34 @@ type nugetIndexResults struct { Resources []nugetIndexResult `json:"resources"` } -type nugetpackageIndexResults struct { - Versions []string `json:"versions"` +type nugetPackageRegistrationCatalogRoot struct { + Pages []nugetPackageRegistrationCatalogPage `json:"items"` +} + +type nugetPackageRegistrationCatalogPage struct { + ID string `json:"@id"` + Packages []nugetPackageRegistrationPackage `json:"items"` +} + +type nugetPackageRegistrationPackage struct { + Entry nugetPackageRegistrationCatalogEntry `json:"catalogEntry"` +} + +type nugetPackageRegistrationCatalogEntry struct { + Version string `json:"version"` + Listed bool `json:"listed"` +} + +func (entry *nugetPackageRegistrationCatalogEntry) UnmarshalJSON(text []byte) error { + type Alias nugetPackageRegistrationCatalogEntry + aux := Alias{ + Listed: true, // set the default value before parsing JSON + } + if err := json.Unmarshal(text, &aux); err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to unmarshal json: %v", err)) + } + *entry = nugetPackageRegistrationCatalogEntry(aux) + return nil } type nugetNuspec struct { @@ -189,33 +215,31 @@ func fetchGitRepositoryFromNuget(packageName string, manager packageManagerClien err = json.NewDecoder(respIndex.Body).Decode(nugetIndexResults) if err != nil { - return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to parse nuget index json: %v", err)) + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to parse nuget index json: %v", err)) } - packageBaseAddressIndex := slices.IndexFunc(nugetIndexResults.Resources, - func(n nugetIndexResult) bool { return n.Type == "PackageBaseAddress/3.0.0" }) - if packageBaseAddressIndex == -1 { - return "", sce.WithMessage(sce.ErrScorecardInternal, "failed to find package base URI at nuget index json") + nugetPackageBaseURL, err := getFieldFromIndexResults(nugetIndexResults.Resources, + "PackageBaseAddress/3.0.0") + if err != nil { + return "", err } - - nugetPackageBaseURL := nugetIndexResults.Resources[packageBaseAddressIndex].ID - - respPackageIndex, err := manager.Get(nugetPackageBaseURL+"%s/index.json", packageName) + nugetRegistrationBaseURL, err := getFieldFromIndexResults(nugetIndexResults.Resources, + "RegistrationsBaseUrl/3.4.0") if err != nil { - return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get nuget package index json: %v", err)) + return "", err } - defer respPackageIndex.Body.Close() - packageIndexResults := &nugetpackageIndexResults{} - err = json.NewDecoder(respPackageIndex.Body).Decode(packageIndexResults) + lastPackageVersion, err := getLatestListedVersion(nugetRegistrationBaseURL, + packageName, manager) if err != nil { - return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to parse nuget package index json: %v", err)) + return "", err } - lastVersion := packageIndexResults.Versions[len(packageIndexResults.Versions)-1] - - respPackageSpec, err := manager.Get(nugetPackageBaseURL+"%[1]v/"+lastVersion+"/%[1]v.nuspec", packageName) + respPackageSpec, err := manager.Get( + nugetPackageBaseURL+"%[1]v/"+lastPackageVersion+"/%[1]v.nuspec", packageName) if err != nil { - return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get nuget package spec json: %v", err)) + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to get nuget package spec json: %v", err)) } defer respPackageSpec.Body.Close() @@ -223,7 +247,8 @@ func fetchGitRepositoryFromNuget(packageName string, manager packageManagerClien err = xml.NewDecoder(respPackageSpec.Body).Decode(packageSpecResults) if err != nil { - return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to parse nuget nuspec xml: %v", err)) + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to parse nuget nuspec xml: %v", err)) } if packageSpecResults.Metadata == (nuspecMetadata{}) || packageSpecResults.Metadata.Repository == (nuspecRepository{}) || @@ -233,3 +258,59 @@ func fetchGitRepositoryFromNuget(packageName string, manager packageManagerClien } return packageSpecResults.Metadata.Repository.URL, nil } + +func getLatestListedVersion(baseURL, packageName string, manager packageManagerClient) (string, error) { + resPackageRegistrationIndex, err := manager.Get(baseURL+"%s/index.json", packageName) + if err != nil { + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to get nuget package registration index json: %v", err)) + } + defer resPackageRegistrationIndex.Body.Close() + packageRegistrationCatalogRoot := &nugetPackageRegistrationCatalogRoot{} + err = json.NewDecoder(resPackageRegistrationIndex.Body).Decode(packageRegistrationCatalogRoot) + if err != nil { + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to parse package registration index json: %v", err)) + } + return getLatestListedVersionFromPackageRegistrationPages(packageRegistrationCatalogRoot.Pages, manager) +} + +func getLatestListedVersionFromPackageRegistrationPages(pages []nugetPackageRegistrationCatalogPage, + manager packageManagerClient, +) (string, error) { + for pageIndex := len(pages) - 1; pageIndex >= 0; pageIndex-- { + page := pages[pageIndex] + if page.Packages == nil { + respPage, err := manager.GetURI(page.ID) + if err != nil { + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to get nuget package registration page: %v", err)) + } + defer respPage.Body.Close() + err = json.NewDecoder(respPage.Body).Decode(&page) + + if err != nil { + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to parse nuget package registration page: %v", err)) + } + } + for packageIndex := len(page.Packages) - 1; packageIndex >= 0; packageIndex-- { + if page.Packages[packageIndex].Entry.Listed { + return page.Packages[packageIndex].Entry.Version, nil + } + } + } + return "", sce.WithMessage(sce.ErrScorecardInternal, + "failed to get a listed version for package") +} + +func getFieldFromIndexResults(resources []nugetIndexResult, resultType string) (string, error) { + packageBaseAddressIndex := slices.IndexFunc(resources, + func(n nugetIndexResult) bool { return n.Type == resultType }) + if packageBaseAddressIndex == -1 { + return "", sce.WithMessage(sce.ErrScorecardInternal, + fmt.Sprintf("failed to find %v URI at nuget index json", resultType)) + } + + return resources[packageBaseAddressIndex].ID, nil +} diff --git a/cmd/package_managers_test.go b/cmd/package_managers_test.go index 6a07810f565d..593a08e2d0f3 100644 --- a/cmd/package_managers_test.go +++ b/cmd/package_managers_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/golang/mock/gomock" + "golang.org/x/exp/slices" ) func Test_fetchGitRepositoryFromNPM(t *testing.T) { @@ -708,318 +709,980 @@ func Test_fetchGitRepositoryFromRubyGems(t *testing.T) { } } +type resultPackagePage struct { + url string + response string +} +type nugetTestArgs struct { + packageName string + resultIndex string + resultPackageRegistrationIndex string + resultPackageSpec string + version string + resultPackageRegistrationPages []resultPackagePage +} +type nugetTest struct { + name string + want string + args nugetTestArgs + wantErr bool +} + func Test_fetchGitRepositoryFromNuget(t *testing.T) { t.Parallel() - type args struct { - packageName string - resultIndex string - resultPackageIndex string - resultPackageSpec string - } - tests := []struct { - name string - args args - want string - wantErr bool - }{ + + tests := []nugetTest{ { - name: "fetchGitRepositoryFromNuget", + name: "fetchGitRepositoryFromNuget_find_latest_version_in_single_page", - args: args{ + args: nugetTestArgs{ packageName: "nuget-package", resultIndex: ` { "version": "3.0.0", "resources": [ - { - "@id": "https://azuresearch-usnc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://azuresearch-ussc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (secondary)" - }, - { - "@id": "https://azuresearch-usnc.nuget.org/autocomplete", - "@type": "SearchAutocompleteService", - "comment": "Autocomplete endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://api.nuget.org/v3/registration5-semver1/", - "@type": "RegistrationsBaseUrl", - "comment": "Base URL of Azure storage where NuGet package registration info is stored" - }, { "@id": "https://api.nuget.org/v3-flatcontainer/", "@type": "PackageBaseAddress/3.0.0", "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery" - }, - { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery/2.0.0" - }, - { - "@id": "https://www.nuget.org/api/v2/package", - "@type": "PackagePublish/2.0.0" + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." } ] } `, - resultPackageIndex: ` + resultPackageRegistrationIndex: ` { - "versions": [ - "13.0.2", - "13.0.3-beta1", - "13.0.3" - ] + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 1, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + ] } `, + resultPackageRegistrationPages: []resultPackagePage{}, resultPackageSpec: ` - + Foo - 13.0.3 - Foo.NET - Foo Foo - Foo Foo - false - MIT - https://licenses.nuget.org/MIT - https://www.newtonsoft.com/json - https://www.foo.com/content/images/nugeticon.png - Foo.NET is a popular foo framework for .NET - Copyright ©Foo Foo 2008 - foo - - - - - - - - - - - - - - - - - - - - - - - - - + 4.0.1 + Foo.NET + + `, + version: "4.0.1", }, - want: "foo", + want: "https://github.com/foo/foo.net", wantErr: false, }, { - name: "fetchGitRepositoryFromNuget_error_index", + name: "fetchGitRepositoryFromNuget_find_latest_version_in_first_of_multiple_pages", - args: args{ - packageName: "nuget-package", - resultIndex: "", - resultPackageIndex: "", - resultPackageSpec: "", + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "version": "3.0.0", + "resources": [ + { + "@id": "https://api.nuget.org/v3-flatcontainer/", + "@type": "PackageBaseAddress/3.0.0", + "comment": "Base URL of where NuGet packages are stored, in the format ..." + }, + { + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.2.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.2" + } + } + ] + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: ` + + + Foo + 4.0.1 + Foo.NET + + + + `, + version: "4.0.1", }, - want: "", - wantErr: true, + want: "https://github.com/foo/foo.net", + wantErr: false, }, { - name: "fetchGitRepositoryFromNuget_bad_index", + name: "fetchGitRepositoryFromNuget_find_latest_version_in_first_of_multiple_remote_pages", - args: args{ - packageName: "nuget-package", - resultIndex: "foo", - resultPackageIndex: "", - resultPackageSpec: "", + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "version": "3.0.0", + "resources": [ + { + "@id": "https://api.nuget.org/v3-flatcontainer/", + "@type": "PackageBaseAddress/3.0.0", + "comment": "Base URL of where NuGet packages are stored, in the format ..." + }, + { + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page1/index.json", + "@type": "catalog:CatalogPage", + "count": 2 + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page2/index.json", + "@type": "catalog:CatalogPage", + "count": 2 + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{ + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page1/index.json", + response: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.2.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.2" + } + } + ] + } + `, + }, + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page2/index.json", + response: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + `, + }, + }, + resultPackageSpec: ` + + + Foo + 4.0.1 + Foo.NET + + + + `, + version: "4.0.1", }, - want: "", - wantErr: true, + want: "https://github.com/foo/foo.net", + wantErr: false, }, { - name: "fetchGitRepositoryFromNuget_error_package_index", + name: "fetchGitRepositoryFromNuget_find_latest_version_in_last_of_multiple_pages", - args: args{ + args: nugetTestArgs{ packageName: "nuget-package", resultIndex: ` { "version": "3.0.0", "resources": [ - { - "@id": "https://azuresearch-usnc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://azuresearch-ussc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (secondary)" - }, - { - "@id": "https://azuresearch-usnc.nuget.org/autocomplete", - "@type": "SearchAutocompleteService", - "comment": "Autocomplete endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://api.nuget.org/v3/registration5-semver1/", - "@type": "RegistrationsBaseUrl", - "comment": "Base URL of Azure storage where NuGet package registration info is stored" - }, { "@id": "https://api.nuget.org/v3-flatcontainer/", "@type": "PackageBaseAddress/3.0.0", "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery" - }, - { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery/2.0.0" - }, - { - "@id": "https://www.nuget.org/api/v2/package", - "@type": "PackagePublish/2.0.0" + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." } ] } `, - resultPackageIndex: "", - resultPackageSpec: "", + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: ` + + + Foo + 4.0.1 + Foo.NET + + + + `, + version: "4.0.1", }, - want: "", - wantErr: true, + want: "https://github.com/foo/foo.net", + wantErr: false, }, { - name: "fetchGitRepositoryFromNuget_bad_package_index", + name: "fetchGitRepositoryFromNuget_find_latest_version_in_last_of_remote_multiple_pages", - args: args{ + args: nugetTestArgs{ packageName: "nuget-package", resultIndex: ` { "version": "3.0.0", "resources": [ { - "@id": "https://azuresearch-usnc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://azuresearch-ussc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (secondary)" - }, - { - "@id": "https://azuresearch-usnc.nuget.org/autocomplete", - "@type": "SearchAutocompleteService", - "comment": "Autocomplete endpoint of NuGet Search service (primary)" + "@id": "https://api.nuget.org/v3-flatcontainer/", + "@type": "PackageBaseAddress/3.0.0", + "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://api.nuget.org/v3/registration5-semver1/", - "@type": "RegistrationsBaseUrl", - "comment": "Base URL of Azure storage where NuGet package registration info is stored" - }, + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page1/index.json", + "@type": "catalog:CatalogPage", + "count": 2 + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page2/index.json", + "@type": "catalog:CatalogPage", + "count": 2 + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{ + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page1/index.json", + response: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + `, + }, + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/page2/index.json", + response: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + }, + }, + resultPackageSpec: ` + + + Foo + 4.0.1 + Foo.NET + + + + `, + version: "4.0.1", + }, + want: "https://github.com/foo/foo.net", + wantErr: false, + }, + { + name: "fetchGitRepositoryFromNuget_find_latest_version_with_default_listed_value_true", + + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "version": "3.0.0", + "resources": [ { "@id": "https://api.nuget.org/v3-flatcontainer/", "@type": "PackageBaseAddress/3.0.0", "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery" - }, + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info is stored in GZIP format." + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 1, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "version": "4.0.1" + } + } + ] + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: ` + + + Foo + 4.0.1 + Foo.NET + + + + `, + version: "4.0.1", + }, + want: "https://github.com/foo/foo.net", + wantErr: false, + }, + { + name: "fetchGitRepositoryFromNuget_find_latest_version_with_skip_not_listed", + + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "version": "3.0.0", + "resources": [ { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery/2.0.0" + "@id": "https://api.nuget.org/v3-flatcontainer/", + "@type": "PackageBaseAddress/3.0.0", + "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2/package", - "@type": "PackagePublish/2.0.0" + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info is stored in GZIP format." } ] } `, - resultPackageIndex: "foo", - resultPackageSpec: "", + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 1, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.0.1" + } + } + ] + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: ` + + + Foo + 3.5.8 + Foo.NET + + + + `, + version: "3.5.8", + }, + want: "https://github.com/foo/foo.net", + wantErr: false, + }, + { + name: "fetchGitRepositoryFromNuget_error_index", + + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: "", + resultPackageRegistrationIndex: "", + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: "", }, want: "", wantErr: true, }, { - name: "fetchGitRepositoryFromNuget_error_package_spec", + name: "fetchGitRepositoryFromNuget_bad_index", - args: args{ + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: "foo", + resultPackageRegistrationIndex: "", + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_error_package_registration_index", + + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + resultPackageRegistrationIndex: "", + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_bad_package_index", + + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + resultPackageRegistrationIndex: "foo", + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_error_package_registration_page", + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2 + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2 + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{ + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + response: "", + }, + }, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_bad_package_registration_page", + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2 + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2 + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{ + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + response: "foo", + }, + }, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_error_package_spec", + args: nugetTestArgs{ packageName: "nuget-package", resultIndex: ` { "version": "3.0.0", "resources": [ - { - "@id": "https://azuresearch-usnc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://azuresearch-ussc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (secondary)" - }, - { - "@id": "https://azuresearch-usnc.nuget.org/autocomplete", - "@type": "SearchAutocompleteService", - "comment": "Autocomplete endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://api.nuget.org/v3/registration5-semver1/", - "@type": "RegistrationsBaseUrl", - "comment": "Base URL of Azure storage where NuGet package registration info is stored" - }, { "@id": "https://api.nuget.org/v3-flatcontainer/", "@type": "PackageBaseAddress/3.0.0", "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery" - }, - { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery/2.0.0" - }, - { - "@id": "https://www.nuget.org/api/v2/package", - "@type": "PackagePublish/2.0.0" + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." } ] } `, - resultPackageIndex: ` + resultPackageRegistrationIndex: ` { - "versions": [ - "13.0.2", - "13.0.3-beta1", - "13.0.3" - ] + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 1, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + ] } `, - resultPackageSpec: "", + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: "", + version: "4.0.1", }, want: "", wantErr: true, @@ -1027,62 +1690,125 @@ func Test_fetchGitRepositoryFromNuget(t *testing.T) { { name: "fetchGitRepositoryFromNuget_bad_package_spec", - args: args{ + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2 + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2 + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{ + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + response: "foo", + }, + }, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_error_package_spec", + args: nugetTestArgs{ packageName: "nuget-package", resultIndex: ` { "version": "3.0.0", "resources": [ - { - "@id": "https://azuresearch-usnc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://azuresearch-ussc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (secondary)" - }, - { - "@id": "https://azuresearch-usnc.nuget.org/autocomplete", - "@type": "SearchAutocompleteService", - "comment": "Autocomplete endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://api.nuget.org/v3/registration5-semver1/", - "@type": "RegistrationsBaseUrl", - "comment": "Base URL of Azure storage where NuGet package registration info is stored" - }, { "@id": "https://api.nuget.org/v3-flatcontainer/", "@type": "PackageBaseAddress/3.0.0", "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery" - }, - { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery/2.0.0" - }, - { - "@id": "https://www.nuget.org/api/v2/package", - "@type": "PackagePublish/2.0.0" + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." } ] } `, - resultPackageIndex: ` + resultPackageRegistrationIndex: ` { - "versions": [ - "13.0.2", - "13.0.3-beta1", - "13.0.3" - ] + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 1, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + ] } `, - resultPackageSpec: "foo", + resultPackageRegistrationPages: []resultPackagePage{}, + resultPackageSpec: "foo", + version: "4.0.1", }, want: "", wantErr: true, @@ -1090,108 +1816,139 @@ func Test_fetchGitRepositoryFromNuget(t *testing.T) { { name: "fetchGitRepositoryFromNuget_missing_repo", - args: args{ + args: nugetTestArgs{ + packageName: "nuget-package", + resultIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.1.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.1" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.2.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.2.json", + "@type": "PackageDetails", + "listed": false, + "version": "4.2" + } + } + ] + } + `, + resultPackageRegistrationIndex: ` + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2 + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/2", + "@type": "catalog:CatalogPage", + "count": 2 + } + ] + } + `, + resultPackageRegistrationPages: []resultPackagePage{ + { + url: "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + response: "foo", + }, + }, + resultPackageSpec: "", + }, + want: "", + wantErr: true, + }, + { + name: "fetchGitRepositoryFromNuget_error_package_spec", + args: nugetTestArgs{ packageName: "nuget-package", resultIndex: ` { "version": "3.0.0", "resources": [ - { - "@id": "https://azuresearch-usnc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://azuresearch-ussc.nuget.org/query", - "@type": "SearchQueryService", - "comment": "Query endpoint of NuGet Search service (secondary)" - }, - { - "@id": "https://azuresearch-usnc.nuget.org/autocomplete", - "@type": "SearchAutocompleteService", - "comment": "Autocomplete endpoint of NuGet Search service (primary)" - }, - { - "@id": "https://api.nuget.org/v3/registration5-semver1/", - "@type": "RegistrationsBaseUrl", - "comment": "Base URL of Azure storage where NuGet package registration info is stored" - }, { "@id": "https://api.nuget.org/v3-flatcontainer/", "@type": "PackageBaseAddress/3.0.0", "comment": "Base URL of where NuGet packages are stored, in the format ..." }, { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery" - }, - { - "@id": "https://www.nuget.org/api/v2", - "@type": "LegacyGallery/2.0.0" - }, - { - "@id": "https://www.nuget.org/api/v2/package", - "@type": "PackagePublish/2.0.0" + "@id": "https://api.nuget.org/v3/registration5-gz-semver1/", + "@type": "RegistrationsBaseUrl/3.4.0", + "comment": "Base URL of Azure storage where NuGet package registration info." } ] } `, - resultPackageIndex: ` + resultPackageRegistrationIndex: ` { - "versions": [ - "13.0.2", - "13.0.3-beta1", - "13.0.3" - ] + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json", + "count": 1, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/index.json#page/1", + "@type": "catalog:CatalogPage", + "count": 2, + "items": [ + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/3.5.8.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.3.5.8.json", + "@type": "PackageDetails", + "listed": true, + "version": "3.5.8" + } + }, + { + "@id": "https://api.nuget.org/v3/registration5-semver1/Foo.NET/4.0.1.json", + "@type": "Package", + "catalogEntry": { + "@id": "https://api.nuget.org/v3/catalog0/data/2022.12.08.16.43.03/Foo.NET.4.0.1.json", + "@type": "PackageDetails", + "listed": true, + "version": "4.0.1" + } + } + ] + } + ] } `, + resultPackageRegistrationPages: []resultPackagePage{}, resultPackageSpec: ` - + Foo - 13.0.3 - Foo.NET - Foo Foo - Foo Foo - false - MIT - https://licenses.nuget.org/MIT - https://www.newtonsoft.com/json - https://www.foo.com/content/images/nugeticon.png - Foo.NET is a popular foo framework for .NET - Copyright ©Foo Foo 2008 - foo - - - - - - - - - - - - - - - - - - - - - - - - + 4.0.1 + Foo.NET + `, + version: "4.0.1", }, want: "", wantErr: true, }, } + for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { @@ -1200,39 +1957,22 @@ func Test_fetchGitRepositoryFromNuget(t *testing.T) { p := NewMockpackageManagerClient(ctrl) p.EXPECT().GetURI(gomock.Any()). DoAndReturn(func(url string) (*http.Response, error) { - if tt.wantErr && tt.args.resultIndex == "" { - //nolint - return nil, errors.New("error") - } - - return &http.Response{ - StatusCode: 200, - Body: io.NopCloser(bytes.NewBufferString(tt.args.resultIndex)), - }, nil + return nugetIndexOrPageTestResults(url, &tt) }).AnyTimes() + + // p.EXPECT().GetURI("https://api.nuget.org/v3/index.json"). + // DoAndReturn(func(url string) (*http.Response, error) { + // return nugetIndexTestResponse(&tt) + // }).MaxTimes(1) + // for _, pagePair := range tt.args.resultPackageRegistrationPages { + // p.EXPECT().GetURI(pagePair.url). + // DoAndReturn(func(url string) (*http.Response, error) { + // return nugetPageResponse(&tt, pagePair) + // }).MaxTimes(1) + // } p.EXPECT().Get(gomock.Any(), tt.args.packageName). DoAndReturn(func(url, packageName string) (*http.Response, error) { - if tt.wantErr && tt.args.resultPackageIndex == "" { - //nolint - return nil, errors.New("error") - } - - if tt.wantErr && tt.args.resultPackageSpec == "" { - //nolint - return nil, errors.New("error") - } - if strings.HasSuffix(url, "index.json") { - return &http.Response{ - StatusCode: 200, - Body: io.NopCloser(bytes.NewBufferString(tt.args.resultPackageIndex)), - }, nil - } else if strings.HasSuffix(url, ".nuspec") { - return &http.Response{ - StatusCode: 200, - Body: io.NopCloser(bytes.NewBufferString(tt.args.resultPackageSpec)), - }, nil - } - return nil, nil + return nugetPackageIndexAndSpecResponse(t, url, &tt) }).AnyTimes() got, err := fetchGitRepositoryFromNuget(tt.args.packageName, p) if (err != nil) != tt.wantErr { @@ -1245,3 +1985,60 @@ func Test_fetchGitRepositoryFromNuget(t *testing.T) { }) } } + +func nugetIndexOrPageTestResults(url string, test *nugetTest) (*http.Response, error) { + if url == "https://api.nuget.org/v3/index.json" { + if test.wantErr && (test.args.resultIndex == "") { + //nolint + return nil, errors.New("error") + } + + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(test.args.resultIndex)), + }, nil + } else { + urlResponseIndex := slices.IndexFunc(test.args.resultPackageRegistrationPages, + func(page resultPackagePage) bool { return page.url == url }) + if urlResponseIndex == -1 { + //nolint + return nil, errors.New("error") + } + if test.wantErr && (test.args.resultPackageRegistrationPages[urlResponseIndex].response == "") { + //nolint + return nil, errors.New("error") + } + + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(test.args.resultPackageRegistrationPages[urlResponseIndex].response)), + }, nil + } +} + +func nugetPackageIndexAndSpecResponse(t *testing.T, url string, test *nugetTest) (*http.Response, error) { + t.Helper() + if strings.HasSuffix(url, "index.json") { + if test.wantErr && test.args.resultPackageRegistrationIndex == "" { + //nolint + return nil, errors.New("error") + } + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(test.args.resultPackageRegistrationIndex)), + }, nil + } else if strings.HasSuffix(url, ".nuspec") { + if test.wantErr && test.args.resultPackageSpec == "" { + //nolint + return nil, errors.New("error") + } + if strings.Contains(url, test.args.version) { + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(test.args.resultPackageSpec)), + }, nil + } + t.Errorf("fetchGitRepositoryFromNuget() version = %v, expected version = %v", url, test.args.version) + } + return nil, nil +}