gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package nuget
  4. import (
  5. "sort"
  6. "time"
  7. packages_model "code.gitea.io/gitea/models/packages"
  8. nuget_module "code.gitea.io/gitea/modules/packages/nuget"
  9. "golang.org/x/text/collate"
  10. "golang.org/x/text/language"
  11. )
  12. // https://docs.microsoft.com/en-us/nuget/api/service-index#resources
  13. type ServiceIndexResponseV3 struct {
  14. Version string `json:"version"`
  15. Resources []ServiceResource `json:"resources"`
  16. }
  17. // https://docs.microsoft.com/en-us/nuget/api/service-index#resource
  18. type ServiceResource struct {
  19. ID string `json:"@id"`
  20. Type string `json:"@type"`
  21. }
  22. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#response
  23. type RegistrationIndexResponse struct {
  24. RegistrationIndexURL string `json:"@id"`
  25. Type []string `json:"@type"`
  26. Count int `json:"count"`
  27. Pages []*RegistrationIndexPage `json:"items"`
  28. }
  29. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-page-object
  30. type RegistrationIndexPage struct {
  31. RegistrationPageURL string `json:"@id"`
  32. Lower string `json:"lower"`
  33. Upper string `json:"upper"`
  34. Count int `json:"count"`
  35. Items []*RegistrationIndexPageItem `json:"items"`
  36. }
  37. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf-object-in-a-page
  38. type RegistrationIndexPageItem struct {
  39. RegistrationLeafURL string `json:"@id"`
  40. PackageContentURL string `json:"packageContent"`
  41. CatalogEntry *CatalogEntry `json:"catalogEntry"`
  42. }
  43. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#catalog-entry
  44. type CatalogEntry struct {
  45. CatalogLeafURL string `json:"@id"`
  46. Authors string `json:"authors"`
  47. Copyright string `json:"copyright"`
  48. DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"`
  49. Description string `json:"description"`
  50. IconURL string `json:"iconUrl"`
  51. ID string `json:"id"`
  52. IsPrerelease bool `json:"isPrerelease"`
  53. Language string `json:"language"`
  54. LicenseURL string `json:"licenseUrl"`
  55. PackageContentURL string `json:"packageContent"`
  56. ProjectURL string `json:"projectUrl"`
  57. RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
  58. Summary string `json:"summary"`
  59. Tags string `json:"tags"`
  60. Version string `json:"version"`
  61. ReleaseNotes string `json:"releaseNotes"`
  62. Published time.Time `json:"published"`
  63. }
  64. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency-group
  65. type PackageDependencyGroup struct {
  66. TargetFramework string `json:"targetFramework"`
  67. Dependencies []*PackageDependency `json:"dependencies"`
  68. }
  69. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency
  70. type PackageDependency struct {
  71. ID string `json:"id"`
  72. Range string `json:"range"`
  73. }
  74. func createRegistrationIndexResponse(l *linkBuilder, pds []*packages_model.PackageDescriptor) *RegistrationIndexResponse {
  75. sort.Slice(pds, func(i, j int) bool {
  76. return pds[i].SemVer.LessThan(pds[j].SemVer)
  77. })
  78. items := make([]*RegistrationIndexPageItem, 0, len(pds))
  79. for _, p := range pds {
  80. items = append(items, createRegistrationIndexPageItem(l, p))
  81. }
  82. return &RegistrationIndexResponse{
  83. RegistrationIndexURL: l.GetRegistrationIndexURL(pds[0].Package.Name),
  84. Type: []string{"catalog:CatalogRoot", "PackageRegistration", "catalog:Permalink"},
  85. Count: 1,
  86. Pages: []*RegistrationIndexPage{
  87. {
  88. RegistrationPageURL: l.GetRegistrationIndexURL(pds[0].Package.Name),
  89. Count: len(pds),
  90. Lower: pds[0].Version.Version,
  91. Upper: pds[len(pds)-1].Version.Version,
  92. Items: items,
  93. },
  94. },
  95. }
  96. }
  97. func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationIndexPageItem {
  98. metadata := pd.Metadata.(*nuget_module.Metadata)
  99. return &RegistrationIndexPageItem{
  100. RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
  101. PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
  102. CatalogEntry: &CatalogEntry{
  103. CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
  104. Authors: metadata.Authors,
  105. Copyright: metadata.Copyright,
  106. DependencyGroups: createDependencyGroups(pd),
  107. Description: metadata.Description,
  108. IconURL: metadata.IconURL,
  109. ID: pd.Package.Name,
  110. IsPrerelease: pd.Version.IsPrerelease(),
  111. Language: metadata.Language,
  112. LicenseURL: metadata.LicenseURL,
  113. PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
  114. ProjectURL: metadata.ProjectURL,
  115. RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
  116. Summary: metadata.Summary,
  117. Tags: metadata.Tags,
  118. Version: pd.Version.Version,
  119. ReleaseNotes: metadata.ReleaseNotes,
  120. Published: pd.Version.CreatedUnix.AsLocalTime(),
  121. },
  122. }
  123. }
  124. func createDependencyGroups(pd *packages_model.PackageDescriptor) []*PackageDependencyGroup {
  125. metadata := pd.Metadata.(*nuget_module.Metadata)
  126. dependencyGroups := make([]*PackageDependencyGroup, 0, len(metadata.Dependencies))
  127. for k, v := range metadata.Dependencies {
  128. dependencies := make([]*PackageDependency, 0, len(v))
  129. for _, dep := range v {
  130. dependencies = append(dependencies, &PackageDependency{
  131. ID: dep.ID,
  132. Range: dep.Version,
  133. })
  134. }
  135. dependencyGroups = append(dependencyGroups, &PackageDependencyGroup{
  136. TargetFramework: k,
  137. Dependencies: dependencies,
  138. })
  139. }
  140. return dependencyGroups
  141. }
  142. // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf
  143. type RegistrationLeafResponse struct {
  144. RegistrationLeafURL string `json:"@id"`
  145. Type []string `json:"@type"`
  146. PackageContentURL string `json:"packageContent"`
  147. RegistrationIndexURL string `json:"registration"`
  148. CatalogEntry CatalogEntry `json:"catalogEntry"`
  149. }
  150. func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse {
  151. registrationLeafURL := l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version)
  152. packageDownloadURL := l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version)
  153. metadata := pd.Metadata.(*nuget_module.Metadata)
  154. return &RegistrationLeafResponse{
  155. RegistrationLeafURL: registrationLeafURL,
  156. RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name),
  157. PackageContentURL: packageDownloadURL,
  158. Type: []string{"Package", "http://schema.nuget.org/catalog#Permalink"},
  159. CatalogEntry: CatalogEntry{
  160. CatalogLeafURL: registrationLeafURL,
  161. Authors: metadata.Authors,
  162. Copyright: metadata.Copyright,
  163. DependencyGroups: createDependencyGroups(pd),
  164. Description: metadata.Description,
  165. IconURL: metadata.IconURL,
  166. ID: pd.Package.Name,
  167. IsPrerelease: pd.Version.IsPrerelease(),
  168. Language: metadata.Language,
  169. LicenseURL: metadata.LicenseURL,
  170. PackageContentURL: packageDownloadURL,
  171. ProjectURL: metadata.ProjectURL,
  172. RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
  173. Summary: metadata.Summary,
  174. Tags: metadata.Tags,
  175. Version: pd.Version.Version,
  176. ReleaseNotes: metadata.ReleaseNotes,
  177. Published: pd.Version.CreatedUnix.AsLocalTime(),
  178. },
  179. }
  180. }
  181. // https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource#response
  182. type PackageVersionsResponse struct {
  183. Versions []string `json:"versions"`
  184. }
  185. func createPackageVersionsResponse(pvs []*packages_model.PackageVersion) *PackageVersionsResponse {
  186. versions := make([]string, 0, len(pvs))
  187. for _, pv := range pvs {
  188. versions = append(versions, pv.Version)
  189. }
  190. return &PackageVersionsResponse{
  191. Versions: versions,
  192. }
  193. }
  194. // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#response
  195. type SearchResultResponse struct {
  196. TotalHits int64 `json:"totalHits"`
  197. Data []*SearchResult `json:"data"`
  198. }
  199. // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result
  200. type SearchResult struct {
  201. Authors string `json:"authors"`
  202. Copyright string `json:"copyright"`
  203. DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"`
  204. Description string `json:"description"`
  205. IconURL string `json:"iconUrl"`
  206. ID string `json:"id"`
  207. IsPrerelease bool `json:"isPrerelease"`
  208. Language string `json:"language"`
  209. LicenseURL string `json:"licenseUrl"`
  210. ProjectURL string `json:"projectUrl"`
  211. RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
  212. Summary string `json:"summary"`
  213. Tags string `json:"tags"`
  214. Title string `json:"title"`
  215. TotalDownloads int64 `json:"totalDownloads"`
  216. Version string `json:"version"`
  217. Versions []*SearchResultVersion `json:"versions"`
  218. RegistrationIndexURL string `json:"registration"`
  219. }
  220. // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result
  221. type SearchResultVersion struct {
  222. RegistrationLeafURL string `json:"@id"`
  223. Version string `json:"version"`
  224. Downloads int64 `json:"downloads"`
  225. }
  226. func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages_model.PackageDescriptor) *SearchResultResponse {
  227. grouped := make(map[string][]*packages_model.PackageDescriptor)
  228. for _, pd := range pds {
  229. grouped[pd.Package.Name] = append(grouped[pd.Package.Name], pd)
  230. }
  231. keys := make([]string, 0, len(grouped))
  232. for key := range grouped {
  233. keys = append(keys, key)
  234. }
  235. collate.New(language.English, collate.IgnoreCase).SortStrings(keys)
  236. data := make([]*SearchResult, 0, len(pds))
  237. for _, key := range keys {
  238. data = append(data, createSearchResult(l, grouped[key]))
  239. }
  240. return &SearchResultResponse{
  241. TotalHits: totalHits,
  242. Data: data,
  243. }
  244. }
  245. func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor) *SearchResult {
  246. latest := pds[0]
  247. versions := make([]*SearchResultVersion, 0, len(pds))
  248. totalDownloads := int64(0)
  249. for _, pd := range pds {
  250. if latest.SemVer.LessThan(pd.SemVer) {
  251. latest = pd
  252. }
  253. totalDownloads += pd.Version.DownloadCount
  254. versions = append(versions, &SearchResultVersion{
  255. RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
  256. Version: pd.Version.Version,
  257. })
  258. }
  259. metadata := latest.Metadata.(*nuget_module.Metadata)
  260. return &SearchResult{
  261. Authors: metadata.Authors,
  262. Copyright: metadata.Copyright,
  263. Description: metadata.Description,
  264. DependencyGroups: createDependencyGroups(latest),
  265. IconURL: metadata.IconURL,
  266. ID: latest.Package.Name,
  267. IsPrerelease: latest.Version.IsPrerelease(),
  268. Language: metadata.Language,
  269. LicenseURL: metadata.LicenseURL,
  270. ProjectURL: metadata.ProjectURL,
  271. RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
  272. Summary: metadata.Summary,
  273. Tags: metadata.Tags,
  274. Title: metadata.Title,
  275. TotalDownloads: totalDownloads,
  276. Version: latest.Version.Version,
  277. Versions: versions,
  278. RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name),
  279. }
  280. }