Allow users to edit the sync interval for existing push mirrors. Currently, there is no way to modify the interval once the mirror is created. <details> <summary>Screenshots</summary> ## Before <img width="936" alt="Screenshot 2023-07-26 at 9 31 21 AM" src="https://github.com/go-gitea/gitea/assets/80308335/35b8a40c-4320-474c-a866-1dea0f1fa0de"> ## After <img width="945" alt="Screenshot 2023-07-26 at 9 44 40 AM" src="https://github.com/go-gitea/gitea/assets/80308335/ee12e12f-0f68-4feb-90eb-33366f5997d3"> ### On hover <img width="247" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/2f32de45-bd50-4150-9623-3be2ef3ea7f8"> <img width="237" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/49f4ab4d-ccff-4489-80ce-a9788a73c3bb"> <img width="245" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/165fc888-9d48-438a-b730-d4beb12122af"> ### Edit modal <img width="905" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/2a7ca24b-4f36-4e0e-9799-39f2ecc46413"> ### Only valid times are allowed <img width="728" alt="Screenshot 2023-07-26 at 9 50 01 AM" src="https://github.com/go-gitea/gitea/assets/80308335/ced6d330-c235-4e29-8f17-28daddcf1444"> <img width="853" alt="image" src="https://github.com/go-gitea/gitea/assets/80308335/8636f62a-70d1-4684-a3e8-b205adc03580"> </details> Fixes #21295 --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>tags/v1.21.0-rc0
return err | return err | ||||
} | } | ||||
// UpdatePushMirrorInterval updates the push-mirror | |||||
func UpdatePushMirrorInterval(ctx context.Context, m *PushMirror) error { | |||||
_, err := db.GetEngine(ctx).ID(m.ID).Cols("interval").Update(m) | |||||
return err | |||||
} | |||||
func DeletePushMirrors(ctx context.Context, opts PushMirrorOptions) error { | func DeletePushMirrors(ctx context.Context, opts PushMirrorOptions) error { | ||||
if opts.RepoID > 0 { | if opts.RepoID > 0 { | ||||
_, err := db.GetEngine(ctx).Where(opts.toConds()).Delete(&PushMirror{}) | _, err := db.GetEngine(ctx).Where(opts.toConds()).Delete(&PushMirror{}) |
settings.mirror_settings.push_mirror.none = No push mirrors configured | settings.mirror_settings.push_mirror.none = No push mirrors configured | ||||
settings.mirror_settings.push_mirror.remote_url = Git Remote Repository URL | settings.mirror_settings.push_mirror.remote_url = Git Remote Repository URL | ||||
settings.mirror_settings.push_mirror.add = Add Push Mirror | settings.mirror_settings.push_mirror.add = Add Push Mirror | ||||
settings.mirror_settings.push_mirror.edit_sync_time = Edit mirror sync interval | |||||
settings.sync_mirror = Synchronize Now | settings.sync_mirror = Synchronize Now | ||||
settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check back in a minute. | settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check back in a minute. | ||||
settings.site = Website | settings.site = Website |
ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress")) | ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress")) | ||||
ctx.Redirect(repo.Link() + "/settings") | ctx.Redirect(repo.Link() + "/settings") | ||||
case "push-mirror-update": | |||||
if !setting.Mirror.Enabled { | |||||
ctx.NotFound("", nil) | |||||
return | |||||
} | |||||
// This section doesn't require repo_name/RepoName to be set in the form, don't show it | |||||
// as an error on the UI for this action | |||||
ctx.Data["Err_RepoName"] = nil | |||||
interval, err := time.ParseDuration(form.PushMirrorInterval) | |||||
if err != nil || (interval != 0 && interval < setting.Mirror.MinInterval) { | |||||
ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &forms.RepoSettingForm{}) | |||||
return | |||||
} | |||||
id, err := strconv.ParseInt(form.PushMirrorID, 10, 64) | |||||
if err != nil { | |||||
ctx.ServerError("UpdatePushMirrorIntervalPushMirrorID", err) | |||||
return | |||||
} | |||||
m := &repo_model.PushMirror{ | |||||
ID: id, | |||||
Interval: interval, | |||||
} | |||||
if err := repo_model.UpdatePushMirrorInterval(ctx, m); err != nil { | |||||
ctx.ServerError("UpdatePushMirrorInterval", err) | |||||
return | |||||
} | |||||
// Background why we are adding it to Queue | |||||
// If we observed its implementation in the context of `push-mirror-sync` where it | |||||
// is evident that pushing to the queue is necessary for updates. | |||||
// So, there are updates within the given interval, it is necessary to update the queue accordingly. | |||||
mirror_module.AddPushMirrorToQueue(m.ID) | |||||
ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success")) | |||||
ctx.Redirect(repo.Link() + "/settings") | |||||
case "push-mirror-remove": | case "push-mirror-remove": | ||||
if !setting.Mirror.Enabled { | if !setting.Mirror.Enabled { | ||||
ctx.NotFound("", nil) | ctx.NotFound("", nil) |
<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td> | <td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td> | ||||
<td>{{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label" data-tooltip-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td> | <td>{{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label" data-tooltip-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td> | ||||
<td class="right aligned"> | <td class="right aligned"> | ||||
<button | |||||
class="ui tiny button show-modal" | |||||
data-modal="#push-mirror-edit-modal" | |||||
data-tooltip-content="{{$.locale.Tr "repo.settings.mirror_settings.push_mirror.edit_sync_time"}}" | |||||
data-modal-push-mirror-edit-id="{{.ID}}" | |||||
data-modal-push-mirror-edit-interval="{{.Interval}}" | |||||
data-modal-push-mirror-edit-address="{{$address.Address}}" | |||||
> | |||||
{{svg "octicon-pencil" 14}} | |||||
</button> | |||||
<form method="post" class="gt-dib"> | <form method="post" class="gt-dib"> | ||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
<input type="hidden" name="action" value="push-mirror-remove"> | |||||
<input type="hidden" name="action" value="push-mirror-sync"> | |||||
<input type="hidden" name="push_mirror_id" value="{{.ID}}"> | <input type="hidden" name="push_mirror_id" value="{{.ID}}"> | ||||
<button class="ui basic red tiny button inline text-thin">{{$.locale.Tr "remove"}}</button> | |||||
<button class="ui primary tiny button" data-tooltip-content="{{$.locale.Tr "repo.settings.sync_mirror"}}">{{svg "octicon-sync" 14}}</button> | |||||
</form> | </form> | ||||
<form method="post" class="gt-dib"> | <form method="post" class="gt-dib"> | ||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
<input type="hidden" name="action" value="push-mirror-sync"> | |||||
<input type="hidden" name="action" value="push-mirror-remove"> | |||||
<input type="hidden" name="push_mirror_id" value="{{.ID}}"> | <input type="hidden" name="push_mirror_id" value="{{.ID}}"> | ||||
<button class="ui primary tiny button inline text-thin">{{$.locale.Tr "repo.settings.sync_mirror"}}</button> | |||||
<button class="ui basic red tiny button" data-tooltip-content="{{$.locale.Tr "remove"}}">{{svg "octicon-trash" 14}}</button> | |||||
</form> | </form> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
{{end}} | {{end}} | ||||
{{template "repo/settings/push_mirror_sync_modal" .}} |
<div class="ui small modal" id="push-mirror-edit-modal"> | |||||
<div class="header"> | |||||
{{$.locale.Tr "repo.settings.mirror_settings.push_mirror.edit_sync_time"}} | |||||
</div> | |||||
<div class="content"> | |||||
<form class="ui form ignore-dirty" method="post"> | |||||
{{.CsrfTokenHtml}} | |||||
<input type="hidden" name="action" value="push-mirror-update"> | |||||
<input type="hidden" name="push_mirror_id" id="push-mirror-edit-id"> | |||||
<div class="field"> | |||||
<label for="name">{{$.locale.Tr "repo.settings.mirror_settings.mirrored_repository"}}</label> | |||||
<div class="ui small input"> | |||||
<input id="push-mirror-edit-address" readonly> | |||||
</div> | |||||
</div> | |||||
<div class="inline field"> | |||||
<label for="push-mirror-edit-interval">{{.locale.Tr "repo.mirror_interval" .MinimumMirrorInterval}}</label> | |||||
<input id="push-mirror-edit-interval" name="push_mirror_interval" autofocus> | |||||
</div> | |||||
<div class="actions"> | |||||
<button class="ui small basic cancel button"> | |||||
{{svg "octicon-x"}} | |||||
{{.locale.Tr "cancel"}} | |||||
</button> | |||||
<button class="ui primary small approve button"> | |||||
{{svg "fontawesome-save"}} | |||||
{{.locale.Tr "save"}} | |||||
</button> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> |