[mike@mwxm4]
This commit is contained in:
@@ -238,18 +238,64 @@ func parsePushRemoteArgs(args string) (names []string, description string) {
|
||||
return names, strings.Join(fields[i:], " ")
|
||||
}
|
||||
|
||||
// remoteHost reduces a configured url — or whatever a user typed in its place —
|
||||
// to its bare host: scheme, credentials, port and path removed.
|
||||
func remoteHost(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if i := strings.Index(s, "://"); i >= 0 {
|
||||
s = s[i+3:]
|
||||
}
|
||||
if i := strings.IndexByte(s, '@'); i >= 0 { // user[:pass]@host
|
||||
s = s[i+1:]
|
||||
}
|
||||
if i := strings.IndexAny(s, "/:"); i >= 0 {
|
||||
s = s[:i]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// remoteMatches reports whether sel picks target t. A target answers both to its
|
||||
// configured name and to the host of its url: the name is what the config calls
|
||||
// the server, the host is what the user sees in the browser, and `@gitea` should
|
||||
// not be the only way to say `git.example.com`.
|
||||
func remoteMatches(t RemoteTarget, sel string) bool {
|
||||
sel = strings.TrimPrefix(strings.TrimSpace(sel), "@")
|
||||
if sel == "" {
|
||||
return false
|
||||
}
|
||||
if strings.EqualFold(t.Name, sel) {
|
||||
return true
|
||||
}
|
||||
h := remoteHost(t.URL)
|
||||
return h != "" && strings.EqualFold(h, remoteHost(sel))
|
||||
}
|
||||
|
||||
// activeRemotes keeps the targets that take part when a command was given no
|
||||
// target of its own (see RemoteTarget.isActive).
|
||||
func activeRemotes(all []RemoteTarget) []RemoteTarget {
|
||||
out := make([]RemoteTarget, 0, len(all))
|
||||
for _, t := range all {
|
||||
if t.isActive() {
|
||||
out = append(out, t)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// pickRemotes narrows all to the explicitly requested names, complaining about
|
||||
// any that are not configured. With no names given, all targets are used.
|
||||
// any that are not configured. With no names given the active targets are used
|
||||
// — `active = false` takes a server off that automatic path, and naming it is
|
||||
// what puts it back on.
|
||||
func pickRemotes(all []RemoteTarget, names []string) []RemoteTarget {
|
||||
if len(names) == 0 {
|
||||
return all
|
||||
return activeRemotes(all)
|
||||
}
|
||||
var out []RemoteTarget
|
||||
seen := map[string]bool{}
|
||||
for _, n := range names {
|
||||
found := false
|
||||
for _, t := range all {
|
||||
if !strings.EqualFold(t.Name, n) {
|
||||
if !remoteMatches(t, n) {
|
||||
continue
|
||||
}
|
||||
if !seen[t.Name] { // `@hub @hub` must not push twice
|
||||
@@ -266,8 +312,24 @@ func pickRemotes(all []RemoteTarget, names []string) []RemoteTarget {
|
||||
return out
|
||||
}
|
||||
|
||||
// reportNoTargets explains an empty selection. There are three ways to end up
|
||||
// with nothing to push to, and they need different answers: nothing configured
|
||||
// at all, everything configured switched to `active = false`, or a name nobody
|
||||
// recognised — which pickRemotes has already complained about by itself.
|
||||
func reportNoTargets(cmd string, configured []RemoteTarget, names []string) {
|
||||
switch {
|
||||
case len(names) > 0:
|
||||
return
|
||||
case len(configured) > 0:
|
||||
errorln("every configured remote is inactive — name one, e.g. '" +
|
||||
cmd + " @" + configured[0].Name + "'")
|
||||
default:
|
||||
errorln(cmd + " needs a 'remote.<name>.url' and 'remote.<name>.key' in " + configFile())
|
||||
}
|
||||
}
|
||||
|
||||
// handlePushRemote implements `pushremote [@name ...] [description]`. Without
|
||||
// a @name it mirrors to every configured target; the description, if given, is
|
||||
// a @name it mirrors to every active target; the description, if given, is
|
||||
// set on the repository when it is created.
|
||||
func handlePushRemote(args string) {
|
||||
if !requireRepo() {
|
||||
@@ -275,15 +337,13 @@ func handlePushRemote(args string) {
|
||||
}
|
||||
names, description := parsePushRemoteArgs(args)
|
||||
|
||||
targets, incomplete := cfg.mirrorTargets()
|
||||
configured, incomplete := cfg.mirrorTargets()
|
||||
for _, n := range incomplete {
|
||||
errorln("remote " + n + ": url or key missing — skipped")
|
||||
}
|
||||
targets = pickRemotes(targets, names)
|
||||
targets := pickRemotes(configured, names)
|
||||
if len(targets) == 0 {
|
||||
if len(names) == 0 { // an unknown @name already reported itself
|
||||
errorln("pushremote needs a 'remote.<name>.url' and 'remote.<name>.key' in " + configFile())
|
||||
}
|
||||
reportNoTargets("pushremote", configured, names)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user