parent
a63b9fbc70
commit
40f41dc694
5 changed files with 70 additions and 15 deletions
|
@ -1077,9 +1077,11 @@ func CleanUpMigrateInfo(repo *Repository) (*Repository, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cleanUpMigrateGitConfig(repo.GitConfigPath()); err != nil {
|
_, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath)
|
||||||
return repo, fmt.Errorf("cleanUpMigrateGitConfig: %v", err)
|
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||||
|
return repo, fmt.Errorf("CleanUpMigrateInfo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.HasWiki() {
|
if repo.HasWiki() {
|
||||||
if err := cleanUpMigrateGitConfig(path.Join(repo.WikiPath(), "config")); err != nil {
|
if err := cleanUpMigrateGitConfig(path.Join(repo.WikiPath(), "config")); err != nil {
|
||||||
return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %v", err)
|
return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %v", err)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
|
|
||||||
"github.com/Unknwon/com"
|
"github.com/Unknwon/com"
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MirrorQueue holds an UniqueQueue object of the mirror
|
// MirrorQueue holds an UniqueQueue object of the mirror
|
||||||
|
@ -71,11 +70,18 @@ func (m *Mirror) ScheduleNextUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func remoteAddress(repoPath string) (string, error) {
|
func remoteAddress(repoPath string) (string, error) {
|
||||||
cfg, err := ini.Load(GitConfigPath(repoPath))
|
cmd := git.NewCommand("remote", "get-url", "origin")
|
||||||
|
result, err := cmd.RunInDir(repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return cfg.Section("remote \"origin\"").Key("url").Value(), nil
|
if len(result) > 0 {
|
||||||
|
return result[:len(result)-1], nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mirror) readAddress() {
|
func (m *Mirror) readAddress() {
|
||||||
|
@ -115,14 +121,15 @@ func (m *Mirror) FullAddress() string {
|
||||||
|
|
||||||
// SaveAddress writes new address to Git repository config.
|
// SaveAddress writes new address to Git repository config.
|
||||||
func (m *Mirror) SaveAddress(addr string) error {
|
func (m *Mirror) SaveAddress(addr string) error {
|
||||||
configPath := m.Repo.GitConfigPath()
|
repoPath := m.Repo.RepoPath()
|
||||||
cfg, err := ini.Load(configPath)
|
// Remove old origin
|
||||||
if err != nil {
|
_, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath)
|
||||||
return fmt.Errorf("Load: %v", err)
|
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Section("remote \"origin\"").Key("url").SetValue(addr)
|
_, err = git.NewCommand("remote", "add", "origin", addr).RunInDir(repoPath)
|
||||||
return cfg.SaveToIndent(configPath, "\t")
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// gitShortEmptySha Git short empty SHA
|
// gitShortEmptySha Git short empty SHA
|
||||||
|
|
|
@ -566,7 +566,9 @@ mirror_prune_desc = Remove obsolete remote-tracking references
|
||||||
mirror_interval = Mirror Interval (valid time units are 'h', 'm', 's'). 0 to disable automatic sync.
|
mirror_interval = Mirror Interval (valid time units are 'h', 'm', 's'). 0 to disable automatic sync.
|
||||||
mirror_interval_invalid = The mirror interval is not valid.
|
mirror_interval_invalid = The mirror interval is not valid.
|
||||||
mirror_address = Clone From URL
|
mirror_address = Clone From URL
|
||||||
mirror_address_desc = Include any required authorization credentials in the URL.
|
mirror_address_desc = Include any required authorization credentials in the URL. These must be url escaped as appropriate
|
||||||
|
mirror_address_url_invalid = The provided url is invalid. You must escape all components of the url correctly.
|
||||||
|
mirror_address_protocol_invalid = The provided url is invalid. Only http(s):// or git:// locations can be mirrored from.
|
||||||
mirror_last_synced = Last Synchronized
|
mirror_last_synced = Last Synchronized
|
||||||
watchers = Watchers
|
watchers = Watchers
|
||||||
stargazers = Stargazers
|
stargazers = Stargazers
|
||||||
|
|
|
@ -7,11 +7,12 @@ package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/git"
|
"code.gitea.io/git"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/auth"
|
"code.gitea.io/gitea/modules/auth"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
@ -21,6 +22,8 @@ import (
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
"code.gitea.io/gitea/routers/utils"
|
"code.gitea.io/gitea/routers/utils"
|
||||||
|
|
||||||
|
"github.com/mvdan/xurls"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -33,6 +36,8 @@ const (
|
||||||
tplProtectedBranch base.TplName = "repo/settings/protected_branch"
|
tplProtectedBranch base.TplName = "repo/settings/protected_branch"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var validFormAddress *regexp.Regexp
|
||||||
|
|
||||||
// Settings show a repository's settings page
|
// Settings show a repository's settings page
|
||||||
func Settings(ctx *context.Context) {
|
func Settings(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
||||||
|
@ -146,7 +151,38 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := ctx.Repo.Mirror.SaveAddress(form.MirrorAddress); err != nil {
|
|
||||||
|
// Validate the form.MirrorAddress
|
||||||
|
u, err := url.Parse(form.MirrorAddress)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Data["Err_MirrorAddress"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Opaque != "" || !(u.Scheme == "http" || u.Scheme == "https" || u.Scheme == "git") {
|
||||||
|
ctx.Data["Err_MirrorAddress"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now use xurls
|
||||||
|
address := validFormAddress.FindString(form.MirrorAddress)
|
||||||
|
if address != form.MirrorAddress && form.MirrorAddress != "" {
|
||||||
|
ctx.Data["Err_MirrorAddress"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.EscapedPath() == "" || u.Host == "" || !u.IsAbs() {
|
||||||
|
ctx.Data["Err_MirrorAddress"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
address = u.String()
|
||||||
|
|
||||||
|
if err := ctx.Repo.Mirror.SaveAddress(address); err != nil {
|
||||||
ctx.ServerError("SaveAddress", err)
|
ctx.ServerError("SaveAddress", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -683,3 +719,11 @@ func DeleteDeployKey(ctx *context.Context) {
|
||||||
"redirect": ctx.Repo.RepoLink + "/settings/keys",
|
"redirect": ctx.Repo.RepoLink + "/settings/keys",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var err error
|
||||||
|
validFormAddress, err = xurls.StrictMatchingScheme(`(https?)|(git)://`)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
<label for="interval">{{.i18n.Tr "repo.mirror_interval"}}</label>
|
<label for="interval">{{.i18n.Tr "repo.mirror_interval"}}</label>
|
||||||
<input id="interval" name="interval" value="{{.MirrorInterval}}">
|
<input id="interval" name="interval" value="{{.MirrorInterval}}">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field {{if .Err_MirrorAddress}}error{{end}}">
|
||||||
<label for="mirror_address">{{.i18n.Tr "repo.mirror_address"}}</label>
|
<label for="mirror_address">{{.i18n.Tr "repo.mirror_address"}}</label>
|
||||||
<input id="mirror_address" name="mirror_address" value="{{.Mirror.FullAddress}}" required>
|
<input id="mirror_address" name="mirror_address" value="{{.Mirror.FullAddress}}" required>
|
||||||
<p class="help">{{.i18n.Tr "repo.mirror_address_desc"}}</p>
|
<p class="help">{{.i18n.Tr "repo.mirror_address_desc"}}</p>
|
||||||
|
|
Reference in a new issue