} | } | ||||
} | } | ||||
if err := cleanUpMigrateGitConfig(repo.GitConfigPath()); err != nil { | |||||
return repo, fmt.Errorf("cleanUpMigrateGitConfig: %v", err) | |||||
_, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath) | |||||
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) |
"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 | ||||
} | } | ||||
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() { | ||||
// 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() | |||||
cfg, err := ini.Load(configPath) | |||||
if err != nil { | |||||
return fmt.Errorf("Load: %v", err) | |||||
repoPath := m.Repo.RepoPath() | |||||
// Remove old origin | |||||
_, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath) | |||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") { | |||||
return err | |||||
} | } | ||||
cfg.Section("remote \"origin\"").Key("url").SetValue(addr) | |||||
return cfg.SaveToIndent(configPath, "\t") | |||||
_, err = git.NewCommand("remote", "add", "origin", addr).RunInDir(repoPath) | |||||
return err | |||||
} | } | ||||
// gitShortEmptySha Git short empty SHA | // gitShortEmptySha Git short empty SHA |
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 |
import ( | import ( | ||||
"errors" | "errors" | ||||
"net/url" | |||||
"regexp" | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
"mvdan.cc/xurls/v2" | |||||
"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" | ||||
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") | ||||
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 | ||||
} | } | ||||
"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) | |||||
} | |||||
} |
<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> |