mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 05:11:41 +01:00 
			
		
		
		
	By default, the code extracts 200 package versions. If too many packages are generated every day or if rule cleaning is enabled later, which means there are more than 200 versions corresponding to the library package, it may not be cleaned up completely, resulting in residue Fix #31961 --------- Co-authored-by: yeyuanjie <yecao100@126.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
		
			
				
	
	
		
			252 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2022 The Gitea Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package packages
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"time"
 | |
| 
 | |
| 	packages_model "code.gitea.io/gitea/models/packages"
 | |
| 	user_model "code.gitea.io/gitea/models/user"
 | |
| 	"code.gitea.io/gitea/modules/log"
 | |
| 	"code.gitea.io/gitea/modules/optional"
 | |
| 	"code.gitea.io/gitea/modules/templates"
 | |
| 	"code.gitea.io/gitea/modules/web"
 | |
| 	"code.gitea.io/gitea/services/context"
 | |
| 	"code.gitea.io/gitea/services/forms"
 | |
| 	cargo_service "code.gitea.io/gitea/services/packages/cargo"
 | |
| 	container_service "code.gitea.io/gitea/services/packages/container"
 | |
| )
 | |
| 
 | |
| func SetPackagesContext(ctx *context.Context, owner *user_model.User) {
 | |
| 	pcrs, err := packages_model.GetCleanupRulesByOwner(ctx, owner.ID)
 | |
| 	if err != nil {
 | |
| 		ctx.ServerError("GetCleanupRulesByOwner", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	ctx.Data["CleanupRules"] = pcrs
 | |
| }
 | |
| 
 | |
| func SetRuleAddContext(ctx *context.Context) {
 | |
| 	setRuleEditContext(ctx, nil)
 | |
| }
 | |
| 
 | |
| func SetRuleEditContext(ctx *context.Context, owner *user_model.User) {
 | |
| 	pcr := getCleanupRuleByContext(ctx, owner)
 | |
| 	if pcr == nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	setRuleEditContext(ctx, pcr)
 | |
| }
 | |
| 
 | |
| func setRuleEditContext(ctx *context.Context, pcr *packages_model.PackageCleanupRule) {
 | |
| 	ctx.Data["IsEditRule"] = pcr != nil
 | |
| 
 | |
| 	if pcr == nil {
 | |
| 		pcr = &packages_model.PackageCleanupRule{}
 | |
| 	}
 | |
| 	ctx.Data["CleanupRule"] = pcr
 | |
| 	ctx.Data["AvailableTypes"] = packages_model.TypeList
 | |
| }
 | |
| 
 | |
| func PerformRuleAddPost(ctx *context.Context, owner *user_model.User, redirectURL string, template templates.TplName) {
 | |
| 	performRuleEditPost(ctx, owner, nil, redirectURL, template)
 | |
| }
 | |
| 
 | |
| func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectURL string, template templates.TplName) {
 | |
| 	pcr := getCleanupRuleByContext(ctx, owner)
 | |
| 	if pcr == nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	form := web.GetForm(ctx).(*forms.PackageCleanupRuleForm)
 | |
| 
 | |
| 	if form.Action == "remove" {
 | |
| 		if err := packages_model.DeleteCleanupRuleByID(ctx, pcr.ID); err != nil {
 | |
| 			ctx.ServerError("DeleteCleanupRuleByID", err)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cleanuprules.success.delete"))
 | |
| 		ctx.Redirect(redirectURL)
 | |
| 	} else {
 | |
| 		performRuleEditPost(ctx, owner, pcr, redirectURL, template)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func performRuleEditPost(ctx *context.Context, owner *user_model.User, pcr *packages_model.PackageCleanupRule, redirectURL string, template templates.TplName) {
 | |
| 	isEditRule := pcr != nil
 | |
| 
 | |
| 	if pcr == nil {
 | |
| 		pcr = &packages_model.PackageCleanupRule{}
 | |
| 	}
 | |
| 
 | |
| 	form := web.GetForm(ctx).(*forms.PackageCleanupRuleForm)
 | |
| 
 | |
| 	pcr.Enabled = form.Enabled
 | |
| 	pcr.OwnerID = owner.ID
 | |
| 	pcr.KeepCount = form.KeepCount
 | |
| 	pcr.KeepPattern = form.KeepPattern
 | |
| 	pcr.RemoveDays = form.RemoveDays
 | |
| 	pcr.RemovePattern = form.RemovePattern
 | |
| 	pcr.MatchFullName = form.MatchFullName
 | |
| 
 | |
| 	ctx.Data["IsEditRule"] = isEditRule
 | |
| 	ctx.Data["CleanupRule"] = pcr
 | |
| 	ctx.Data["AvailableTypes"] = packages_model.TypeList
 | |
| 
 | |
| 	if ctx.HasError() {
 | |
| 		ctx.HTML(http.StatusOK, template)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if isEditRule {
 | |
| 		if err := packages_model.UpdateCleanupRule(ctx, pcr); err != nil {
 | |
| 			ctx.ServerError("UpdateCleanupRule", err)
 | |
| 			return
 | |
| 		}
 | |
| 	} else {
 | |
| 		pcr.Type = packages_model.Type(form.Type)
 | |
| 
 | |
| 		if has, err := packages_model.HasOwnerCleanupRuleForPackageType(ctx, owner.ID, pcr.Type); err != nil {
 | |
| 			ctx.ServerError("HasOwnerCleanupRuleForPackageType", err)
 | |
| 			return
 | |
| 		} else if has {
 | |
| 			ctx.Data["Err_Type"] = true
 | |
| 			ctx.HTML(http.StatusOK, template)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		var err error
 | |
| 		if pcr, err = packages_model.InsertCleanupRule(ctx, pcr); err != nil {
 | |
| 			ctx.ServerError("InsertCleanupRule", err)
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	ctx.Flash.Success(ctx.Tr("packages.owner.settings.cleanuprules.success.update"))
 | |
| 	ctx.Redirect(fmt.Sprintf("%s/rules/%d", redirectURL, pcr.ID))
 | |
| }
 | |
| 
 | |
| func SetRulePreviewContext(ctx *context.Context, owner *user_model.User) {
 | |
| 	pcr := getCleanupRuleByContext(ctx, owner)
 | |
| 	if pcr == nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if err := pcr.CompiledPattern(); err != nil {
 | |
| 		ctx.ServerError("CompiledPattern", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	olderThan := time.Now().AddDate(0, 0, -pcr.RemoveDays)
 | |
| 
 | |
| 	packages, err := packages_model.GetPackagesByType(ctx, pcr.OwnerID, pcr.Type)
 | |
| 	if err != nil {
 | |
| 		ctx.ServerError("GetPackagesByType", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	versionsToRemove := make([]*packages_model.PackageDescriptor, 0, 10)
 | |
| 
 | |
| 	for _, p := range packages {
 | |
| 		pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
 | |
| 			PackageID:  p.ID,
 | |
| 			IsInternal: optional.Some(false),
 | |
| 			Sort:       packages_model.SortCreatedDesc,
 | |
| 		})
 | |
| 		if err != nil {
 | |
| 			ctx.ServerError("SearchVersions", err)
 | |
| 			return
 | |
| 		}
 | |
| 		if pcr.KeepCount > 0 {
 | |
| 			if pcr.KeepCount < len(pvs) {
 | |
| 				pvs = pvs[pcr.KeepCount:]
 | |
| 			} else {
 | |
| 				pvs = nil
 | |
| 			}
 | |
| 		}
 | |
| 		for _, pv := range pvs {
 | |
| 			if skip, err := container_service.ShouldBeSkipped(ctx, pcr, p, pv); err != nil {
 | |
| 				ctx.ServerError("ShouldBeSkipped", err)
 | |
| 				return
 | |
| 			} else if skip {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			toMatch := pv.LowerVersion
 | |
| 			if pcr.MatchFullName {
 | |
| 				toMatch = p.LowerName + "/" + pv.LowerVersion
 | |
| 			}
 | |
| 			if pcr.KeepPatternMatcher != nil && pcr.KeepPatternMatcher.MatchString(toMatch) {
 | |
| 				continue
 | |
| 			}
 | |
| 			if pv.CreatedUnix.AsLocalTime().After(olderThan) {
 | |
| 				continue
 | |
| 			}
 | |
| 			if pcr.RemovePatternMatcher != nil && !pcr.RemovePatternMatcher.MatchString(toMatch) {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			pd, err := packages_model.GetPackageDescriptor(ctx, pv)
 | |
| 			if err != nil {
 | |
| 				ctx.ServerError("GetPackageDescriptor", err)
 | |
| 				return
 | |
| 			}
 | |
| 			versionsToRemove = append(versionsToRemove, pd)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	ctx.Data["CleanupRule"] = pcr
 | |
| 	ctx.Data["VersionsToRemove"] = versionsToRemove
 | |
| }
 | |
| 
 | |
| func getCleanupRuleByContext(ctx *context.Context, owner *user_model.User) *packages_model.PackageCleanupRule {
 | |
| 	id := ctx.FormInt64("id")
 | |
| 	if id == 0 {
 | |
| 		id = ctx.PathParamInt64("id")
 | |
| 	}
 | |
| 
 | |
| 	pcr, err := packages_model.GetCleanupRuleByID(ctx, id)
 | |
| 	if err != nil {
 | |
| 		if err == packages_model.ErrPackageCleanupRuleNotExist {
 | |
| 			ctx.NotFound(err)
 | |
| 		} else {
 | |
| 			ctx.ServerError("GetCleanupRuleByID", err)
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	if pcr != nil && pcr.OwnerID == owner.ID {
 | |
| 		return pcr
 | |
| 	}
 | |
| 
 | |
| 	ctx.NotFound(fmt.Errorf("PackageCleanupRule[%v] not associated to owner %v", id, owner))
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func InitializeCargoIndex(ctx *context.Context, owner *user_model.User) {
 | |
| 	err := cargo_service.InitializeIndexRepository(ctx, owner, owner)
 | |
| 	if err != nil {
 | |
| 		log.Error("InitializeIndexRepository failed: %v", err)
 | |
| 		ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.initialize.error", err))
 | |
| 	} else {
 | |
| 		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cargo.initialize.success"))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func RebuildCargoIndex(ctx *context.Context, owner *user_model.User) {
 | |
| 	err := cargo_service.RebuildIndex(ctx, owner, owner)
 | |
| 	if err != nil {
 | |
| 		log.Error("RebuildIndex failed: %v", err)
 | |
| 		ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.error", err))
 | |
| 	} else {
 | |
| 		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cargo.rebuild.success"))
 | |
| 	}
 | |
| }
 |