115 lines
2.7 KiB
Go
115 lines
2.7 KiB
Go
package arthur
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/tabwriter"
|
|
"time"
|
|
|
|
"git.csclub.uwaterloo.ca/public/merlin/config"
|
|
"git.csclub.uwaterloo.ca/public/merlin/logger"
|
|
"git.csclub.uwaterloo.ca/public/merlin/sync"
|
|
)
|
|
|
|
// get repo by name function in config
|
|
|
|
func GetAndRunCommand(conn net.Conn) (newSync bool) {
|
|
newSync = false
|
|
defer conn.Close()
|
|
|
|
var buf bytes.Buffer
|
|
_, err := io.Copy(&buf, conn)
|
|
if err != nil {
|
|
logger.ErrLog(err.Error())
|
|
return
|
|
}
|
|
|
|
command := buf.String()
|
|
args := strings.Split(command, ":")
|
|
respondAndLogErr := func(msg string) {
|
|
logger.OutLog(msg)
|
|
conn.Write([]byte(msg))
|
|
}
|
|
|
|
if args[0] == "status" {
|
|
status := tabwriter.NewWriter(conn, 5, 5, 5, ' ', 0)
|
|
fmt.Fprintf(status, "Repository\tLast Synced\tNext Expected Sync\n")
|
|
|
|
// for time formating see https://pkg.go.dev/time#pkg-constants
|
|
for name, repo := range config.RepoMap {
|
|
fmt.Fprintf(status, "%s\t%s\t%s\n",
|
|
name,
|
|
time.Unix(repo.State.LastAttemptStartTime, 0).Format(time.RFC1123),
|
|
time.Unix(repo.State.LastAttemptRunTime+int64(repo.Frequency), 0).Format(time.RFC1123),
|
|
)
|
|
}
|
|
|
|
status.Flush()
|
|
} else if args[0] == "sync" {
|
|
if len(args) != 2 {
|
|
respondAndLogErr("Could not parse sync command, forced sync fails.")
|
|
return
|
|
}
|
|
|
|
if repo, inMap := config.RepoMap[args[1]]; inMap {
|
|
logger.OutLog("Attempting to force sync of " + repo.Name)
|
|
if sync.SyncIfPossible(repo) {
|
|
conn.Write([]byte("Forced sync for " + repo.Name))
|
|
newSync = true
|
|
} else {
|
|
respondAndLogErr("Cannot force sync: " + repo.Name + ", already syncing.")
|
|
}
|
|
} else {
|
|
respondAndLogErr(args[1] + " is not tracked so cannot sync")
|
|
}
|
|
} else {
|
|
respondAndLogErr("Received unrecognized command: " + command)
|
|
}
|
|
return
|
|
}
|
|
|
|
func UnixSockListener(connChan chan net.Conn, stopLisChan chan struct{}) {
|
|
sockpath := config.Conf.SockPath
|
|
// must remove cfg.SockPath otherwise get "bind: address already in use"
|
|
if filepath.Ext(sockpath) != ".sock" {
|
|
panic(fmt.Errorf("Socket file must end with .sock"))
|
|
} else if _, err := os.Stat(sockpath); err == nil {
|
|
if err := os.Remove(sockpath); err != nil {
|
|
panic(err)
|
|
}
|
|
} else if !errors.Is(err, os.ErrNotExist) {
|
|
panic(err)
|
|
}
|
|
|
|
ear, err := net.Listen("unix", sockpath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
logger.OutLog("Listening to unix socket at " + sockpath)
|
|
|
|
go func() {
|
|
for {
|
|
// will exit when ear is closed
|
|
conn, err := ear.Accept()
|
|
if err != nil {
|
|
if ne, ok := err.(net.Error); ok && ne.Temporary() {
|
|
logger.ErrLog("Accepted socket error: " + err.Error())
|
|
continue
|
|
}
|
|
logger.ErrLog("Unhandlable socket error: " + err.Error())
|
|
return
|
|
}
|
|
connChan <- conn
|
|
}
|
|
}()
|
|
|
|
<-stopLisChan
|
|
ear.Close()
|
|
}
|