mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00:00 
			
		
		
		
	Fix some RPM registry flaws (#28782)
Related #26984 (https://github.com/go-gitea/gitea/pull/26984#issuecomment-1889588912) Fix admin cleanup message. Fix models `Get` not respecting default values. Rebuild RPM repository files after cleanup. Do not add RPM group to package version name. Force stable sorting of Alpine/Debian/RPM repository data. Fix missing deferred `Close`. Add tests for multiple RPM groups. Removed non-cached `ReplaceAllStringRegex`. If there are multiple groups available, it's stated in the package installation screen: 
This commit is contained in:
		| @@ -512,7 +512,77 @@ func CommonRoutes() *web.Route { | ||||
| 			r.Get("/files/{id}/{version}/{filename}", pypi.DownloadPackageFile) | ||||
| 			r.Get("/simple/{id}", pypi.PackageMetadata) | ||||
| 		}, reqPackageAccess(perm.AccessModeRead)) | ||||
| 		r.Group("/rpm", RpmRoutes(r), reqPackageAccess(perm.AccessModeRead)) | ||||
| 		r.Group("/rpm", func() { | ||||
| 			r.Group("/repository.key", func() { | ||||
| 				r.Head("", rpm.GetRepositoryKey) | ||||
| 				r.Get("", rpm.GetRepositoryKey) | ||||
| 			}) | ||||
|  | ||||
| 			var ( | ||||
| 				repoPattern     = regexp.MustCompile(`\A(.*?)\.repo\z`) | ||||
| 				uploadPattern   = regexp.MustCompile(`\A(.*?)/upload\z`) | ||||
| 				filePattern     = regexp.MustCompile(`\A(.*?)/package/([^/]+)/([^/]+)/([^/]+)(?:/([^/]+\.rpm)|)\z`) | ||||
| 				repoFilePattern = regexp.MustCompile(`\A(.*?)/repodata/([^/]+)\z`) | ||||
| 			) | ||||
|  | ||||
| 			r.Methods("HEAD,GET,PUT,DELETE", "*", func(ctx *context.Context) { | ||||
| 				path := ctx.Params("*") | ||||
| 				isHead := ctx.Req.Method == "HEAD" | ||||
| 				isGetHead := ctx.Req.Method == "HEAD" || ctx.Req.Method == "GET" | ||||
| 				isPut := ctx.Req.Method == "PUT" | ||||
| 				isDelete := ctx.Req.Method == "DELETE" | ||||
|  | ||||
| 				m := repoPattern.FindStringSubmatch(path) | ||||
| 				if len(m) == 2 && isGetHead { | ||||
| 					ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 					rpm.GetRepositoryConfig(ctx) | ||||
| 					return | ||||
| 				} | ||||
|  | ||||
| 				m = repoFilePattern.FindStringSubmatch(path) | ||||
| 				if len(m) == 3 && isGetHead { | ||||
| 					ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 					ctx.SetParams("filename", m[2]) | ||||
| 					if isHead { | ||||
| 						rpm.CheckRepositoryFileExistence(ctx) | ||||
| 					} else { | ||||
| 						rpm.GetRepositoryFile(ctx) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
|  | ||||
| 				m = uploadPattern.FindStringSubmatch(path) | ||||
| 				if len(m) == 2 && isPut { | ||||
| 					reqPackageAccess(perm.AccessModeWrite)(ctx) | ||||
| 					if ctx.Written() { | ||||
| 						return | ||||
| 					} | ||||
| 					ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 					rpm.UploadPackageFile(ctx) | ||||
| 					return | ||||
| 				} | ||||
|  | ||||
| 				m = filePattern.FindStringSubmatch(path) | ||||
| 				if len(m) == 6 && (isGetHead || isDelete) { | ||||
| 					ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 					ctx.SetParams("name", m[2]) | ||||
| 					ctx.SetParams("version", m[3]) | ||||
| 					ctx.SetParams("architecture", m[4]) | ||||
| 					if isGetHead { | ||||
| 						rpm.DownloadPackageFile(ctx) | ||||
| 					} else { | ||||
| 						reqPackageAccess(perm.AccessModeWrite)(ctx) | ||||
| 						if ctx.Written() { | ||||
| 							return | ||||
| 						} | ||||
| 						rpm.DeletePackageFile(ctx) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
|  | ||||
| 				ctx.Status(http.StatusNotFound) | ||||
| 			}) | ||||
| 		}, reqPackageAccess(perm.AccessModeRead)) | ||||
| 		r.Group("/rubygems", func() { | ||||
| 			r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) | ||||
| 			r.Get("/latest_specs.4.8.gz", rubygems.EnumeratePackagesLatest) | ||||
| @@ -577,82 +647,6 @@ func CommonRoutes() *web.Route { | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Support for uploading rpm packages with arbitrary depth paths | ||||
| func RpmRoutes(r *web.Route) func() { | ||||
| 	var ( | ||||
| 		groupRepoInfo = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)\.repo\z`) | ||||
| 		groupUpload   = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)/upload\z`) | ||||
| 		groupRpm      = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)/package/([^/]+)/([^/]+)/([^/]+)(?:/([^/]+\.rpm)|)\z`) | ||||
| 		groupMetadata = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)/repodata/([^/]+)\z`) | ||||
| 	) | ||||
|  | ||||
| 	return func() { | ||||
| 		r.Methods("HEAD,GET,POST,PUT,PATCH,DELETE", "*", func(ctx *context.Context) { | ||||
| 			path := ctx.Params("*") | ||||
| 			isHead := ctx.Req.Method == "HEAD" | ||||
| 			isGetHead := ctx.Req.Method == "HEAD" || ctx.Req.Method == "GET" | ||||
| 			isPut := ctx.Req.Method == "PUT" | ||||
| 			isDelete := ctx.Req.Method == "DELETE" | ||||
|  | ||||
| 			if path == "/repository.key" && isGetHead { | ||||
| 				rpm.GetRepositoryKey(ctx) | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			// get repo | ||||
| 			m := groupRepoInfo.FindStringSubmatch(path) | ||||
| 			if len(m) == 2 && isGetHead { | ||||
| 				ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 				rpm.GetRepositoryConfig(ctx) | ||||
| 				return | ||||
| 			} | ||||
| 			// get meta | ||||
| 			m = groupMetadata.FindStringSubmatch(path) | ||||
| 			if len(m) == 3 && isGetHead { | ||||
| 				ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 				ctx.SetParams("filename", m[2]) | ||||
| 				if isHead { | ||||
| 					rpm.CheckRepositoryFileExistence(ctx) | ||||
| 				} else { | ||||
| 					rpm.GetRepositoryFile(ctx) | ||||
| 				} | ||||
| 				return | ||||
| 			} | ||||
| 			// upload | ||||
| 			m = groupUpload.FindStringSubmatch(path) | ||||
| 			if len(m) == 2 && isPut { | ||||
| 				reqPackageAccess(perm.AccessModeWrite)(ctx) | ||||
| 				if ctx.Written() { | ||||
| 					return | ||||
| 				} | ||||
| 				ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 				rpm.UploadPackageFile(ctx) | ||||
| 				return | ||||
| 			} | ||||
| 			// rpm down/delete | ||||
| 			m = groupRpm.FindStringSubmatch(path) | ||||
| 			if len(m) == 6 { | ||||
| 				ctx.SetParams("group", strings.Trim(m[1], "/")) | ||||
| 				ctx.SetParams("name", m[2]) | ||||
| 				ctx.SetParams("version", m[3]) | ||||
| 				ctx.SetParams("architecture", m[4]) | ||||
| 				if isGetHead { | ||||
| 					rpm.DownloadPackageFile(ctx) | ||||
| 					return | ||||
| 				} else if isDelete { | ||||
| 					reqPackageAccess(perm.AccessModeWrite)(ctx) | ||||
| 					if ctx.Written() { | ||||
| 						return | ||||
| 					} | ||||
| 					rpm.DeletePackageFile(ctx) | ||||
| 				} | ||||
| 			} | ||||
| 			// default | ||||
| 			ctx.Status(http.StatusNotFound) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ContainerRoutes provides endpoints that implement the OCI API to serve containers | ||||
| // These have to be mounted on `/v2/...` to comply with the OCI spec: | ||||
| // https://github.com/opencontainers/distribution-spec/blob/main/spec.md | ||||
|   | ||||
		Reference in New Issue
	
	Block a user