summaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
authorKN4CK3R <admin@oldschoolhack.me>2021-06-14 19:20:43 +0200
committerGitHub <noreply@github.com>2021-06-14 19:20:43 +0200
commit440039c0cce18622b12da5677bf6585caed6070a (patch)
tree8f8532a2d40983b35b3fdb5460b47218b26bbd89 /routers
parent5d113bdd1905c73fb8071f420ae2d248202971f9 (diff)
downloadgitea-440039c0cce18622b12da5677bf6585caed6070a.tar.gz
gitea-440039c0cce18622b12da5677bf6585caed6070a.zip
Add push to remote mirror repository (#15157)
* Added push mirror model. * Integrated push mirror into queue. * Moved methods into own file. * Added basic implementation. * Mirror wiki too. * Removed duplicated method. * Get url for different remotes. * Added migration. * Unified remote url access. * Add/Remove push mirror remotes. * Prevent hangs with missing credentials. * Moved code between files. * Changed sanitizer interface. * Added push mirror backend methods. * Only update the mirror remote. * Limit refs on push. * Added UI part. * Added missing table. * Delete mirror if repository gets removed. * Changed signature. Handle object errors. * Added upload method. * Added "upload" unit tests. * Added transfer adapter unit tests. * Send correct headers. * Added pushing of LFS objects. * Added more logging. * Simpler body handling. * Process files in batches to reduce HTTP calls. * Added created timestamp. * Fixed invalid column name. * Changed name to prevent xorm auto setting. * Remove table header im empty. * Strip exit code from error message. * Added docs page about mirroring. * Fixed date. * Fixed merge errors. * Moved test to integrations. * Added push mirror test. * Added test.
Diffstat (limited to 'routers')
-rw-r--r--routers/api/v1/repo/migrate.go2
-rw-r--r--routers/web/repo/migrate.go2
-rw-r--r--routers/web/repo/setting.go116
3 files changed, 114 insertions, 6 deletions
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index edae358338..5307fdc7d9 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -231,7 +231,7 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteA
case base.IsErrNotSupported(err):
ctx.Error(http.StatusUnprocessableEntity, "", err)
default:
- err = util.URLSanitizedError(err, remoteAddr)
+ err = util.NewStringURLSanitizedError(err, remoteAddr, true)
if strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "Bad credentials") ||
strings.Contains(err.Error(), "could not read Username") {
diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go
index 24d4ef4099..521a856dae 100644
--- a/routers/web/repo/migrate.go
+++ b/routers/web/repo/migrate.go
@@ -101,7 +101,7 @@ func handleMigrateError(ctx *context.Context, owner *models.User, err error, nam
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
default:
remoteAddr, _ := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
- err = util.URLSanitizedError(err, remoteAddr)
+ err = util.NewStringURLSanitizedError(err, remoteAddr, true)
if strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "Bad credentials") ||
strings.Contains(err.Error(), "could not read Username") {
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 21a82491fe..c48b19b63c 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
+ "strconv"
"strings"
"time"
@@ -25,6 +26,7 @@ import (
"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"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
@@ -49,6 +51,8 @@ func Settings(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.settings")
ctx.Data["PageIsSettingsOptions"] = true
ctx.Data["ForcePrivate"] = setting.Repository.ForcePrivate
+ ctx.Data["DisabledMirrors"] = setting.Repository.DisableMirrors
+ ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval
signing, _ := models.SigningKey(ctx.Repo.Repository.RepoPath())
ctx.Data["SigningKeyAvailable"] = len(signing) > 0
@@ -167,10 +171,9 @@ func SettingsPost(ctx *context.Context) {
}
}
- oldUsername := mirror_service.Username(ctx.Repo.Mirror)
- oldPassword := mirror_service.Password(ctx.Repo.Mirror)
- if form.MirrorPassword == "" && form.MirrorUsername == oldUsername {
- form.MirrorPassword = oldPassword
+ u, _ := git.GetRemoteAddress(ctx.Repo.Repository.RepoPath(), ctx.Repo.Mirror.GetRemoteName())
+ if u.User != nil && form.MirrorPassword == "" && form.MirrorUsername == u.User.Username() {
+ form.MirrorPassword, _ = u.User.Password()
}
address, err := forms.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
@@ -226,6 +229,92 @@ func SettingsPost(ctx *context.Context) {
ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress"))
ctx.Redirect(repo.Link() + "/settings")
+ case "push-mirror-sync":
+ m, err := selectPushMirrorByForm(form, repo)
+ if err != nil {
+ ctx.NotFound("", nil)
+ return
+ }
+
+ mirror_service.AddPushMirrorToQueue(m.ID)
+
+ ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress"))
+ ctx.Redirect(repo.Link() + "/settings")
+
+ case "push-mirror-remove":
+ // 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
+
+ m, err := selectPushMirrorByForm(form, repo)
+ if err != nil {
+ ctx.NotFound("", nil)
+ return
+ }
+
+ if err = mirror_service.RemovePushMirrorRemote(m); err != nil {
+ ctx.ServerError("RemovePushMirrorRemote", err)
+ return
+ }
+
+ if err = models.DeletePushMirrorByID(m.ID); err != nil {
+ ctx.ServerError("DeletePushMirrorByID", err)
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
+ ctx.Redirect(repo.Link() + "/settings")
+
+ case "push-mirror-add":
+ // 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.Data["Err_PushMirrorInterval"] = true
+ ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form)
+ return
+ }
+
+ address, err := forms.ParseRemoteAddr(form.PushMirrorAddress, form.PushMirrorUsername, form.PushMirrorPassword)
+ if err == nil {
+ err = migrations.IsMigrateURLAllowed(address, ctx.User)
+ }
+ if err != nil {
+ ctx.Data["Err_PushMirrorAddress"] = true
+ handleSettingRemoteAddrError(ctx, err, form)
+ return
+ }
+
+ remoteSuffix, err := util.RandomString(10)
+ if err != nil {
+ ctx.ServerError("RandomString", err)
+ return
+ }
+
+ m := &models.PushMirror{
+ RepoID: repo.ID,
+ Repo: repo,
+ RemoteName: fmt.Sprintf("remote_mirror_%s", remoteSuffix),
+ Interval: interval,
+ }
+ if err := models.InsertPushMirror(m); err != nil {
+ ctx.ServerError("InsertPushMirror", err)
+ return
+ }
+
+ if err := mirror_service.AddPushMirrorRemote(m, address); err != nil {
+ if err := models.DeletePushMirrorByID(m.ID); err != nil {
+ log.Error("DeletePushMirrorByID %v", err)
+ }
+ ctx.ServerError("AddPushMirrorRemote", err)
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
+ ctx.Redirect(repo.Link() + "/settings")
+
case "advanced":
var repoChanged bool
var units []models.RepoUnit
@@ -1051,3 +1140,22 @@ func SettingsDeleteAvatar(ctx *context.Context) {
}
ctx.Redirect(ctx.Repo.RepoLink + "/settings")
}
+
+func selectPushMirrorByForm(form *forms.RepoSettingForm, repo *models.Repository) (*models.PushMirror, error) {
+ id, err := strconv.ParseInt(form.PushMirrorID, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ if err = repo.LoadPushMirrors(); err != nil {
+ return nil, err
+ }
+
+ for _, m := range repo.PushMirrors {
+ if m.ID == id {
+ return m, nil
+ }
+ }
+
+ return nil, fmt.Errorf("PushMirror[%v] not associated to repository %v", id, repo)
+}