1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 | // Package mirror knows about a repository's mirrors, which the
// post-receive hook pushes to: where a mirror URL reaches over ssh, and
// how the last push went.
package mirror
import (
"net/url"
"os"
"path/filepath"
"regexp"
"strings"
)
// FailedFile is the file in a repository where the hook keeps the
// failures of its last mirror push, a line each, and removes it when a
// push to every mirror works.
const FailedFile = "repo-render-mirror.failed"
// Failures are the failures of the last mirror push of the repository at
// gitDir, if it had any.
func Failures(gitDir string) []string {
b, err := os.ReadFile(filepath.Join(gitDir, FailedFile))
if err != nil {
return nil
}
var lines []string
for l := range strings.Lines(string(b)) {
if l = strings.TrimSpace(l); l != "" {
lines = append(lines, l)
}
}
return lines
}
// Failed reports whether the last push to the mirror at url failed, by
// failures.
func Failed(failures []string, url string) bool {
for _, f := range failures {
if strings.Contains(f, " "+url+" ") {
return true
}
}
return false
}
var hostRE = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]*$`)
// Host is the host and port a mirror URL reaches over ssh, if it does:
// user@host:path, or ssh://user@host:port/path. A local path, or a URL
// another way, has none.
func Host(m string) (host, port string) {
if strings.Contains(m, "://") {
u, err := url.Parse(m)
if err != nil || (u.Scheme != "ssh" && u.Scheme != "git+ssh" && u.Scheme != "ssh+git") {
return "", ""
}
host, port = u.Hostname(), u.Port()
} else if i := strings.IndexByte(m, ':'); i > 0 && !strings.Contains(m[:i], "/") {
host = m[:i]
if j := strings.LastIndexByte(host, '@'); j >= 0 {
host = host[j+1:]
}
}
if !hostRE.MatchString(host) {
return "", ""
}
return host, port
}
// Entry is a host as known_hosts names it: host, or [host]:port for a
// port other than 22.
func Entry(host, port string) string {
if port == "" || port == "22" {
return host
}
return "[" + host + "]:" + port
}
|