diff --git a/conf/app.ini b/conf/app.ini index 47dcffc37e..b1eb953cdf 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -461,8 +461,10 @@ PULL = 300 GC = 60 [mirror] -; Default interval in hours between each check -DEFAULT_INTERVAL = 8 +; Default interval as a duration between each check +DEFAULT_INTERVAL = 8h +; Min interval as a duration must be > 1m +MIN_INTERVAL = 10m [api] ; Max number of items will response in a page diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 07a56e879b..fee0fef79c 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -102,6 +102,8 @@ var migrations = []Migration{ NewMigration("add show field in user openid table", addUserOpenIDShow), // v26 -> v27 NewMigration("generate and migrate repo and wiki Git hooks", generateAndMigrateGitHookChains), + // v27 -> v28 + NewMigration("change mirror interval from hours to time.Duration", convertIntervalToDuration), } // Migrate database to current version diff --git a/models/migrations/v27.go b/models/migrations/v27.go new file mode 100644 index 0000000000..0ac9553725 --- /dev/null +++ b/models/migrations/v27.go @@ -0,0 +1,56 @@ +// Copyright 2017 Gitea. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + "time" + + "github.com/go-xorm/xorm" +) + +func convertIntervalToDuration(x *xorm.Engine) (err error) { + type Repository struct { + ID int64 + OwnerID int64 + Name string + } + type Mirror struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX"` + Repo *Repository `xorm:"-"` + Interval time.Duration + EnablePrune bool `xorm:"NOT NULL DEFAULT true"` + + Updated time.Time `xorm:"-"` + UpdatedUnix int64 `xorm:"INDEX"` + NextUpdate time.Time `xorm:"-"` + NextUpdateUnix int64 `xorm:"INDEX"` + + address string `xorm:"-"` + } + + sess := x.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + return err + } + + var mirrors []Mirror + err = sess.Table("mirror").Select("*").Find(&mirrors) + if err != nil { + return fmt.Errorf("Query repositories: %v", err) + } + for _, mirror := range mirrors { + mirror.Interval = mirror.Interval * time.Hour + _, err := sess.Id(mirror.ID).Cols("interval").Update(mirror) + if err != nil { + return fmt.Errorf("update mirror interval failed: %v", err) + } + } + + return sess.Commit() +} diff --git a/models/repo.go b/models/repo.go index 8548accb5d..c654356916 100644 --- a/models/repo.go +++ b/models/repo.go @@ -815,7 +815,7 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) { RepoID: repo.ID, Interval: setting.Mirror.DefaultInterval, EnablePrune: true, - NextUpdate: time.Now().Add(time.Duration(setting.Mirror.DefaultInterval) * time.Hour), + NextUpdate: time.Now().Add(setting.Mirror.DefaultInterval), }); err != nil { return repo, fmt.Errorf("InsertOne: %v", err) } diff --git a/models/repo_mirror.go b/models/repo_mirror.go index d8d4bc0bec..67ae449bde 100644 --- a/models/repo_mirror.go +++ b/models/repo_mirror.go @@ -27,8 +27,8 @@ type Mirror struct { ID int64 `xorm:"pk autoincr"` RepoID int64 `xorm:"INDEX"` Repo *Repository `xorm:"-"` - Interval int // Hour. - EnablePrune bool `xorm:"NOT NULL DEFAULT true"` + Interval time.Duration + EnablePrune bool `xorm:"NOT NULL DEFAULT true"` Updated time.Time `xorm:"-"` UpdatedUnix int64 `xorm:"INDEX"` @@ -68,7 +68,7 @@ func (m *Mirror) AfterSet(colName string, _ xorm.Cell) { // ScheduleNextUpdate calculates and sets next update time. func (m *Mirror) ScheduleNextUpdate() { - m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour) + m.NextUpdate = time.Now().Add(m.Interval) } func (m *Mirror) readAddress() { diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index 7fdb5e67e2..dd3fbff7bf 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -88,7 +88,7 @@ type RepoSettingForm struct { RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` Description string `binding:"MaxSize(255)"` Website string `binding:"Url;MaxSize(255)"` - Interval int + Interval string MirrorAddress string Private bool EnablePrune bool diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 5a0666ade2..c2e08b0c14 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -417,10 +417,9 @@ var ( } // Mirror settings - Mirror = struct { - DefaultInterval int - }{ - DefaultInterval: 8, + Mirror struct { + DefaultInterval time.Duration + MinInterval time.Duration } // API settings @@ -886,14 +885,20 @@ please consider changing to GITEA_CUSTOM`) log.Fatal(4, "Failed to map Cron settings: %v", err) } else if err = Cfg.Section("git").MapTo(&Git); err != nil { log.Fatal(4, "Failed to map Git settings: %v", err) - } else if err = Cfg.Section("mirror").MapTo(&Mirror); err != nil { - log.Fatal(4, "Failed to map Mirror settings: %v", err) } else if err = Cfg.Section("api").MapTo(&API); err != nil { log.Fatal(4, "Failed to map API settings: %v", err) } - if Mirror.DefaultInterval <= 0 { - Mirror.DefaultInterval = 24 + sec = Cfg.Section("mirror") + Mirror.MinInterval = sec.Key("MIN_INTERVAL").MustDuration(10 * time.Minute) + Mirror.DefaultInterval = sec.Key("DEFAULT_INTERVAL").MustDuration(8 * time.Hour) + if Mirror.MinInterval.Minutes() < 1 { + log.Warn("Mirror.MinInterval is too low") + Mirror.MinInterval = 1 * time.Minute + } + if Mirror.DefaultInterval < Mirror.MinInterval { + log.Warn("Mirror.DefaultInterval is less than Mirror.MinInterval") + Mirror.DefaultInterval = time.Hour * 8 } Langs = Cfg.Section("i18n").Key("LANGS").Strings(",") diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index c843a4b398..cfb4da30ae 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -440,7 +440,8 @@ create_repo = Create Repository default_branch = Default Branch mirror_prune = Prune mirror_prune_desc = Remove any remote-tracking references that no longer exist on the remote -mirror_interval = Mirror Interval (hour) +mirror_interval = Mirror interval (valid time units are "h", "m", "s") +mirror_interval_invalid = Mirror interval is not valid mirror_address = Mirror Address mirror_address_desc = Please include necessary user credentials in the address. mirror_last_synced = Last Synced diff --git a/routers/repo/setting.go b/routers/repo/setting.go index fb6d68ad9b..ed7254fe1b 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -111,12 +111,15 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { return } - if form.Interval > 0 { + interval, err := time.ParseDuration(form.Interval) + if err != nil || interval < setting.Mirror.MinInterval { + ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form) + } else { ctx.Repo.Mirror.EnablePrune = form.EnablePrune - ctx.Repo.Mirror.Interval = form.Interval - ctx.Repo.Mirror.NextUpdate = time.Now().Add(time.Duration(form.Interval) * time.Hour) + ctx.Repo.Mirror.Interval = interval + ctx.Repo.Mirror.NextUpdate = time.Now().Add(interval) if err := models.UpdateMirror(ctx.Repo.Mirror); err != nil { - ctx.Handle(500, "UpdateMirror", err) + ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form) return } } diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index dbe7d81f84..8ad09d4306 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -56,7 +56,7 @@