From 08eecba32bec00b12d6a02988c42adc898a8ff65 Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 20 Apr 2022 15:04:26 +0100 Subject: [PATCH] When updating mirror repo intervals by API reschedule next update too (#19429) (#19433) Backport #19429 When a mirror repo interval is updated by the UI it is rescheduled with that interval however the API does not do this. The API also lacks the enable_prune option. This PR adds this functionality in to the API Edit Repo endpoint. Signed-off-by: Andrew Thornton --- modules/structs/repo.go | 2 + routers/api/v1/repo/repo.go | 76 ++++++++++++++++++++++++---------- routers/web/repo/setting.go | 7 +--- templates/swagger/v1_json.tmpl | 5 +++ 4 files changed, 61 insertions(+), 29 deletions(-) diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 680277ea6..178704ab4 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -183,6 +183,8 @@ type EditRepoOption struct { Archived *bool `json:"archived,omitempty"` // set to a string like `8h30m0s` to set the mirror interval time MirrorInterval *string `json:"mirror_interval,omitempty"` + // enable prune - remove obsolete remote-tracking references + EnablePrune *bool `json:"enable_prune,omitempty"` } // GenerateRepoOption options when creating repository using a template diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 340ba0f6d..af8b06ed2 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -624,7 +624,7 @@ func Edit(ctx *context.APIContext) { } if opts.MirrorInterval != nil { - if err := updateMirrorInterval(ctx, opts); err != nil { + if err := updateMirror(ctx, opts); err != nil { return } } @@ -949,37 +949,67 @@ func updateRepoArchivedState(ctx *context.APIContext, opts api.EditRepoOption) e return nil } -// updateMirrorInterval updates the repo's mirror Interval -func updateMirrorInterval(ctx *context.APIContext, opts api.EditRepoOption) error { +// updateMirror updates a repo's mirror Interval and EnablePrune +func updateMirror(ctx *context.APIContext, opts api.EditRepoOption) error { repo := ctx.Repo.Repository + // only update mirror if interval or enable prune are provided + if opts.MirrorInterval == nil && opts.EnablePrune == nil { + return nil + } + + // these values only make sense if the repo is a mirror + if !repo.IsMirror { + err := fmt.Errorf("repo is not a mirror, can not change mirror interval") + ctx.Error(http.StatusUnprocessableEntity, err.Error(), err) + return err + } + + // get the mirror from the repo + mirror, err := repo_model.GetMirrorByRepoID(repo.ID) + if err != nil { + log.Error("Failed to get mirror: %s", err) + ctx.Error(http.StatusInternalServerError, "MirrorInterval", err) + return err + } + + // update MirrorInterval if opts.MirrorInterval != nil { - if !repo.IsMirror { - err := fmt.Errorf("repo is not a mirror, can not change mirror interval") - ctx.Error(http.StatusUnprocessableEntity, err.Error(), err) - return err - } - mirror, err := repo_model.GetMirrorByRepoID(repo.ID) + + // MirrorInterval should be a duration + interval, err := time.ParseDuration(*opts.MirrorInterval) if err != nil { - log.Error("Failed to get mirror: %s", err) - ctx.Error(http.StatusInternalServerError, "MirrorInterval", err) - return err - } - if interval, err := time.ParseDuration(*opts.MirrorInterval); err == nil { - mirror.Interval = interval - mirror.Repo = repo - if err := repo_model.UpdateMirror(mirror); err != nil { - log.Error("Failed to Set Mirror Interval: %s", err) - ctx.Error(http.StatusUnprocessableEntity, "MirrorInterval", err) - return err - } - log.Trace("Repository %s/%s Mirror Interval was Updated to %s", ctx.Repo.Owner.Name, repo.Name, interval) - } else { log.Error("Wrong format for MirrorInternal Sent: %s", err) ctx.Error(http.StatusUnprocessableEntity, "MirrorInterval", err) return err } + + // Ensure the provided duration is not too short + if interval != 0 && interval < setting.Mirror.MinInterval { + err := fmt.Errorf("invalid mirror interval: %s is below minimum interval: %s", interval, setting.Mirror.MinInterval) + ctx.Error(http.StatusUnprocessableEntity, "MirrorInterval", err) + return err + } + + mirror.Interval = interval + mirror.Repo = repo + mirror.ScheduleNextUpdate() + log.Trace("Repository %s Mirror[%d] Set Interval: %s NextUpdateUnix: %s", repo.FullName(), mirror.ID, interval, mirror.NextUpdateUnix) } + + // update EnablePrune + if opts.EnablePrune != nil { + mirror.EnablePrune = *opts.EnablePrune + log.Trace("Repository %s Mirror[%d] Set EnablePrune: %t", repo.FullName(), mirror.ID, mirror.EnablePrune) + } + + // finally update the mirror in the DB + if err := repo_model.UpdateMirror(mirror); err != nil { + log.Error("Failed to Set Mirror Interval: %s", err) + ctx.Error(http.StatusUnprocessableEntity, "MirrorInterval", err) + return err + } + return nil } diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index b7269b671..f89bffb00 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -31,7 +31,6 @@ import ( "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/validation" @@ -194,11 +193,7 @@ func SettingsPost(ctx *context.Context) { } else { ctx.Repo.Mirror.EnablePrune = form.EnablePrune ctx.Repo.Mirror.Interval = interval - if interval != 0 { - ctx.Repo.Mirror.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(interval) - } else { - ctx.Repo.Mirror.NextUpdateUnix = 0 - } + ctx.Repo.Mirror.ScheduleNextUpdate() if err := repo_model.UpdateMirror(ctx.Repo.Mirror); err != nil { ctx.Data["Err_Interval"] = true ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index bba728363..1085dcba4 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -14757,6 +14757,11 @@ "type": "string", "x-go-name": "Description" }, + "enable_prune": { + "description": "enable prune - remove obsolete remote-tracking references", + "type": "boolean", + "x-go-name": "EnablePrune" + }, "external_tracker": { "$ref": "#/definitions/ExternalTracker" },