mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 06:21:11 +00:00 
			
		
		
		
	- Currently in the Cargo section of the packages setting menu two buttons are always shown, "Initalize index" and "Rebuild index", however only of these should be shown depending on the state of the index, if there's no index the "Initalize index" button should be shown and if there's an index the "Rebuild index" button should be shown. This patch does exactly that. - Resolves #2628
		
			
				
	
	
		
			260 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2022 The Gitea Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package packages
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"time"
 | |
| 
 | |
| 	"code.gitea.io/gitea/models/db"
 | |
| 	packages_model "code.gitea.io/gitea/models/packages"
 | |
| 	repo_model "code.gitea.io/gitea/models/repo"
 | |
| 	user_model "code.gitea.io/gitea/models/user"
 | |
| 	"code.gitea.io/gitea/modules/base"
 | |
| 	"code.gitea.io/gitea/modules/log"
 | |
| 	"code.gitea.io/gitea/modules/optional"
 | |
| 	"code.gitea.io/gitea/modules/util"
 | |
| 	"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
 | |
| 
 | |
| 	ctx.Data["CargoIndexExists"], err = repo_model.IsRepositoryModelExist(ctx, owner, cargo_service.IndexRepositoryName)
 | |
| 	if err != nil {
 | |
| 		ctx.ServerError("IsRepositoryModelExist", err)
 | |
| 		return
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 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 base.TplName) {
 | |
| 	performRuleEditPost(ctx, owner, nil, redirectURL, template)
 | |
| }
 | |
| 
 | |
| func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.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 base.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,
 | |
| 			Paginator:  db.NewAbsoluteListOptions(pcr.KeepCount, 200),
 | |
| 		})
 | |
| 		if err != nil {
 | |
| 			ctx.ServerError("SearchVersions", err)
 | |
| 			return
 | |
| 		}
 | |
| 		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.ParamsInt64("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)
 | |
| 		if errors.Is(err, util.ErrNotExist) {
 | |
| 			ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.no_index"))
 | |
| 		} else {
 | |
| 			ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.error", err))
 | |
| 		}
 | |
| 	} else {
 | |
| 		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cargo.rebuild.success"))
 | |
| 	}
 | |
| }
 |