From 455be398694b8a642af5cf41c9e2296ffe90e24d Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Tue, 7 Feb 2023 15:53:55 +0000 Subject: [PATCH 1/2] Perform actions after a package was removed. --- routers/api/v1/packages/package.go | 7 +++++++ routers/web/admin/packages.go | 12 ++++++++++++ routers/web/user/package.go | 5 +++++ services/packages/cargo/index.go | 12 ++++++++++-- services/packages/cleanup/cleanup.go | 12 ++++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/packages/package.go b/routers/api/v1/packages/package.go index ab077090d1c7..2cd756904c5c 100644 --- a/routers/api/v1/packages/package.go +++ b/routers/api/v1/packages/package.go @@ -8,11 +8,13 @@ import ( "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/services/convert" packages_service "code.gitea.io/gitea/services/packages" + cleanup_service "code.gitea.io/gitea/services/packages/cleanup" ) // ListPackages gets all packages of an owner @@ -167,6 +169,11 @@ func DeletePackage(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "RemovePackageVersion", err) return } + + if err := cleanup_service.PostPackageRemoval(ctx, ctx.Package.Descriptor); err != nil { + log.Error("PostPackageRemoval failed: %v", err) + } + ctx.Status(http.StatusNoContent) } diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go index 88fb47ca0179..c5921e9742fd 100644 --- a/routers/web/admin/packages.go +++ b/routers/web/admin/packages.go @@ -11,9 +11,11 @@ import ( packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" packages_service "code.gitea.io/gitea/services/packages" + cleanup_service "code.gitea.io/gitea/services/packages/cleanup" ) const ( @@ -92,11 +94,21 @@ func DeletePackageVersion(ctx *context.Context) { return } + pd, err := packages_model.GetPackageDescriptor(ctx, pv) + if err != nil { + ctx.ServerError("GetPackageDescriptor", err) + return + } + if err := packages_service.RemovePackageVersion(ctx.Doer, pv); err != nil { ctx.ServerError("RemovePackageVersion", err) return } + if err := cleanup_service.PostPackageRemoval(ctx, pd); err != nil { + log.Error("PostPackageRemoval failed: %v", err) + } + ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) ctx.JSON(http.StatusOK, map[string]interface{}{ "redirect": setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")), diff --git a/routers/web/user/package.go b/routers/web/user/package.go index ed4f0dd79727..95e68268b566 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -22,6 +22,7 @@ import ( shared_user "code.gitea.io/gitea/routers/web/shared/user" "code.gitea.io/gitea/services/forms" packages_service "code.gitea.io/gitea/services/packages" + cleanup_service "code.gitea.io/gitea/services/packages/cleanup" ) const ( @@ -376,6 +377,10 @@ func PackageSettingsPost(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) } + if err := cleanup_service.PostPackageRemoval(ctx, ctx.Package.Descriptor); err != nil { + log.Error("PostPackageRemoval failed: %v", err) + } + ctx.Redirect(ctx.Package.Owner.HTMLURL() + "/-/packages") return } diff --git a/services/packages/cargo/index.go b/services/packages/cargo/index.go index e58a47281628..d2f0228b42d4 100644 --- a/services/packages/cargo/index.go +++ b/services/packages/cargo/index.go @@ -113,6 +113,11 @@ func AddOrUpdatePackageIndex(ctx context.Context, doer, owner *user_model.User, p, err := packages_model.GetPackageByID(ctx, packageID) if err != nil { + if errors.Is(err, util.ErrNotExist) { + // Ignore the package if it does not exist. + // This may leave a dirty index which can be rebuild from user settings. + return nil + } return fmt.Errorf("GetPackageByID[%d]: %w", packageID, err) } @@ -145,8 +150,11 @@ func addOrUpdatePackageIndex(ctx context.Context, t *files_service.TemporaryUplo if err != nil { return fmt.Errorf("SearchVersions[%s]: %w", p.Name, err) } + + path := BuildPackagePath(p.LowerName) + if len(pvs) == 0 { - return nil + return t.RemoveFilesFromIndex(path) } pds, err := packages_model.GetPackageDescriptors(ctx, pvs) @@ -186,7 +194,7 @@ func addOrUpdatePackageIndex(ctx context.Context, t *files_service.TemporaryUplo b.WriteString("\n") } - return writeObjectToIndex(t, BuildPackagePath(pds[0].Package.LowerName), &b) + return writeObjectToIndex(t, path, &b) } func getOrCreateIndexRepository(ctx context.Context, doer, owner *user_model.User) (*repo_model.Repository, error) { diff --git a/services/packages/cleanup/cleanup.go b/services/packages/cleanup/cleanup.go index 2d62a028a4c6..326e39a1b459 100644 --- a/services/packages/cleanup/cleanup.go +++ b/services/packages/cleanup/cleanup.go @@ -152,3 +152,15 @@ func Cleanup(taskCtx context.Context, olderThan time.Duration) error { return nil } + +// PostPackageRemoval performs actions after a package was deleted +// These actions are only needed if a package gets deleted outside of the defined +// package registry flow, for example when deleting a package from the UI or API. +func PostPackageRemoval(ctx context.Context, pd *packages_model.PackageDescriptor) error { + if pd.Package.Type == packages_model.TypeCargo { + if err := cargo_service.AddOrUpdatePackageIndex(ctx, pd.Owner, pd.Owner, pd.Package.ID); err != nil { + return fmt.Errorf("cargo.AddOrUpdatePackageIndex failed: %w", err) + } + } + return nil +} From 995b6b1e99221d4a9b9d463af02bb89e9c956c25 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Sat, 3 Feb 2024 22:39:33 +0000 Subject: [PATCH 2/2] Move code into common method. --- routers/api/v1/packages/package.go | 12 +++--------- routers/web/admin/packages.go | 10 ++-------- routers/web/user/package.go | 8 ++------ services/packages/cleanup/cleanup.go | 28 +++++++++++++++++++++++----- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/routers/api/v1/packages/package.go b/routers/api/v1/packages/package.go index 62f7b7bd0059..43dd75238496 100644 --- a/routers/api/v1/packages/package.go +++ b/routers/api/v1/packages/package.go @@ -8,13 +8,11 @@ import ( "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/services/convert" - packages_service "code.gitea.io/gitea/services/packages" - cleanup_service "code.gitea.io/gitea/services/packages/cleanup" + packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup" ) // ListPackages gets all packages of an owner @@ -166,16 +164,12 @@ func DeletePackage(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - err := packages_service.RemovePackageVersion(ctx, ctx.Doer, ctx.Package.Descriptor.Version) + err := packages_cleanup_service.RemovePackageVersionOutOfContext(ctx, ctx.Doer, ctx.Package.Descriptor) if err != nil { - ctx.Error(http.StatusInternalServerError, "RemovePackageVersion", err) + ctx.Error(http.StatusInternalServerError, "RemovePackageVersionOutOfContext", err) return } - if err := cleanup_service.PostPackageRemoval(ctx, ctx.Package.Descriptor); err != nil { - log.Error("PostPackageRemoval failed: %v", err) - } - ctx.Status(http.StatusNoContent) } diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go index 617c2567c83e..5b5dc9163885 100644 --- a/routers/web/admin/packages.go +++ b/routers/web/admin/packages.go @@ -12,10 +12,8 @@ import ( packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" - packages_service "code.gitea.io/gitea/services/packages" packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup" ) @@ -100,15 +98,11 @@ func DeletePackageVersion(ctx *context.Context) { return } - if err := packages_service.RemovePackageVersion(ctx, ctx.Doer, pv); err != nil { - ctx.ServerError("RemovePackageVersion", err) + if err := packages_cleanup_service.RemovePackageVersionOutOfContext(ctx, ctx.Doer, pd); err != nil { + ctx.ServerError("RemovePackageVersionOutOfContext", err) return } - if err := packages_cleanup_service.PostPackageRemoval(ctx, pd); err != nil { - log.Error("PostPackageRemoval failed: %v", err) - } - ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) ctx.JSONRedirect(setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type"))) } diff --git a/routers/web/user/package.go b/routers/web/user/package.go index 3b15c8604d0d..123543f57cf3 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -27,7 +27,7 @@ import ( shared_user "code.gitea.io/gitea/routers/web/shared/user" "code.gitea.io/gitea/services/forms" packages_service "code.gitea.io/gitea/services/packages" - cleanup_service "code.gitea.io/gitea/services/packages/cleanup" + packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup" ) const ( @@ -458,7 +458,7 @@ func PackageSettingsPost(ctx *context.Context) { ctx.Redirect(ctx.Link) return case "delete": - err := packages_service.RemovePackageVersion(ctx, ctx.Doer, ctx.Package.Descriptor.Version) + err := packages_cleanup_service.RemovePackageVersionOutOfContext(ctx, ctx.Doer, ctx.Package.Descriptor) if err != nil { log.Error("Error deleting package: %v", err) ctx.Flash.Error(ctx.Tr("packages.settings.delete.error")) @@ -466,10 +466,6 @@ func PackageSettingsPost(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) } - if err := cleanup_service.PostPackageRemoval(ctx, ctx.Package.Descriptor); err != nil { - log.Error("PostPackageRemoval failed: %v", err) - } - redirectURL := ctx.Package.Owner.HomeLink() + "/-/packages" // redirect to the package if there are still versions available if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID, IsInternal: util.OptionalBoolFalse}); has { diff --git a/services/packages/cleanup/cleanup.go b/services/packages/cleanup/cleanup.go index b41e3a3d538d..658c304126b2 100644 --- a/services/packages/cleanup/cleanup.go +++ b/services/packages/cleanup/cleanup.go @@ -192,14 +192,32 @@ func CleanupExpiredData(outerCtx context.Context, olderThan time.Duration) error return nil } -// PostPackageRemoval performs actions after a package was deleted +// RemovePackageVersionOutOfContext performs actions according to the package type after a package was deleted // These actions are only needed if a package gets deleted outside of the defined // package registry flow, for example when deleting a package from the UI or API. -func PostPackageRemoval(ctx context.Context, pd *packages_model.PackageDescriptor) error { - if pd.Package.Type == packages_model.TypeCargo { - if err := cargo_service.AddOrUpdatePackageIndex(ctx, pd.Owner, pd.Owner, pd.Package.ID); err != nil { - return fmt.Errorf("cargo.AddOrUpdatePackageIndex failed: %w", err) +func RemovePackageVersionOutOfContext(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) error { + if err := packages_service.RemovePackageVersion(ctx, doer, pd.Version); err != nil { + return err + } + + switch pd.Package.Type { + case packages_model.TypeAlpine: + if err := alpine_service.BuildAllRepositoryFiles(ctx, pd.Owner.ID); err != nil { + return fmt.Errorf("alpine.BuildAllRepositoryFiles failed: %w", err) + } + case packages_model.TypeCargo: + if err := cargo_service.UpdatePackageIndexIfExists(ctx, doer, pd.Owner, pd.Package.ID); err != nil { + return fmt.Errorf("cargo.UpdatePackageIndexIfExists failed: %w", err) + } + case packages_model.TypeDebian: + if err := debian_service.BuildAllRepositoryFiles(ctx, pd.Owner.ID); err != nil { + return fmt.Errorf("debian.BuildAllRepositoryFiles failed: %w", err) + } + case packages_model.TypeRpm: + if err := rpm_service.BuildAllRepositoryFiles(ctx, pd.Owner.ID); err != nil { + return fmt.Errorf("rpm.BuildAllRepositoryFiles failed: %w", err) } } + return nil }