Initial commit
This commit is contained in:
commit
57fc43ff9c
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
cmd/pbuild/pbuild
|
11
cmd/pbuild/config.go
Normal file
11
cmd/pbuild/config.go
Normal file
@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
// Config file for the daemon.
|
||||
type Config struct {
|
||||
WorkDir string // Working directory.
|
||||
ListenAddr string // Listen address for net.Dial.
|
||||
}
|
||||
|
||||
// Post message in Gitea format, only taking what we're interested in.
|
||||
type GiteaPost struct {
|
||||
}
|
27
cmd/pbuild/main.go
Normal file
27
cmd/pbuild/main.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"edgaru089.ink/go/pbuild/internal/runner"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
var profile runner.Profile
|
||||
|
||||
file, err := os.ReadFile("profile.json")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.Unmarshal(file, &profile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logs, _, _ := profile.Run(".")
|
||||
|
||||
fmt.Print(logs)
|
||||
}
|
8
cmd/pbuild/profile.json
Normal file
8
cmd/pbuild/profile.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Name": "pbuild",
|
||||
"ID": "pbuild",
|
||||
"Commands": [
|
||||
"go clean",
|
||||
"go build -v"
|
||||
]
|
||||
}
|
41
internal/runner/profile.go
Normal file
41
internal/runner/profile.go
Normal file
@ -0,0 +1,41 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A Profile defines what to run when invoked on the target directory.
|
||||
type Profile struct {
|
||||
Name string // Name of the profile.
|
||||
ID string // ID of the profile.
|
||||
Commands []string // Commands to run on the profile.
|
||||
Environ map[string]string // Environment variables
|
||||
|
||||
Output []string // List of globs to match output files.
|
||||
OutputDir string // The globs will be matched in this relative directory.
|
||||
}
|
||||
|
||||
type LogEntry struct {
|
||||
Time time.Time
|
||||
Text string
|
||||
OutFd int // 0(manual) 1(stdout) 2(stderr)
|
||||
}
|
||||
|
||||
type Logs []LogEntry
|
||||
|
||||
func (logs Logs) String() string {
|
||||
var buf strings.Builder
|
||||
|
||||
for _, log := range logs {
|
||||
switch log.OutFd {
|
||||
case 0:
|
||||
fmt.Fprintf(&buf, "%s %s\n", log.Time.Format("15:04:05"), log.Text)
|
||||
case 1, 2:
|
||||
fmt.Fprintf(&buf, "%s %s\n", log.Time.Format("15:04:05"), log.Text)
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
82
internal/runner/run.go
Normal file
82
internal/runner/run.go
Normal file
@ -0,0 +1,82 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type logsWriter struct {
|
||||
lock *sync.Mutex
|
||||
logs *Logs
|
||||
outfd int // 0(manual message) 1(stdout) or 2(stderr)
|
||||
}
|
||||
|
||||
func (l *logsWriter) Write(data []byte) (len int, err error) {
|
||||
l.lock.Lock()
|
||||
defer l.lock.Unlock()
|
||||
|
||||
*l.logs = append(*l.logs, LogEntry{
|
||||
Time: time.Now(),
|
||||
Text: string(data),
|
||||
OutFd: l.outfd,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Run runs the profile on the target directory, preserving output.
|
||||
func (p *Profile) Run(dir string) (logs Logs, exitcode int, err error) {
|
||||
|
||||
// Try if the directory exists
|
||||
_, err = os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Construct the env slice
|
||||
env := make([]string, len(p.Environ))
|
||||
{
|
||||
i := 0
|
||||
for key, val := range p.Environ {
|
||||
env[i] = key + "=" + val
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
loglock := &sync.Mutex{}
|
||||
logman := &logsWriter{logs: &logs, lock: loglock, outfd: 0}
|
||||
logout := &logsWriter{logs: &logs, lock: loglock, outfd: 1}
|
||||
logerr := &logsWriter{logs: &logs, lock: loglock, outfd: 2}
|
||||
|
||||
var systime, usrtime time.Duration
|
||||
|
||||
// Run commands
|
||||
runcmds:
|
||||
for i, str := range p.Commands {
|
||||
|
||||
fmt.Fprintf(logman, "[%d/%d] running \"%s\"", i, len(p.Commands), str)
|
||||
|
||||
cmd := exec.Command("sh", "-c", str)
|
||||
cmd.Env = append(cmd.Env, env...)
|
||||
cmd.Stdout = logout
|
||||
cmd.Stderr = logerr
|
||||
cmd.Dir = dir
|
||||
|
||||
err := cmd.Run()
|
||||
|
||||
systime += cmd.ProcessState.SystemTime()
|
||||
usrtime += cmd.ProcessState.UserTime()
|
||||
|
||||
switch err.(type) {
|
||||
case *exec.ExitError:
|
||||
fmt.Fprintf(logman, "!!!!! command exit with code %d !!!!!", err.(*exec.ExitError).ExitCode())
|
||||
break runcmds
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(logman, "system %.4f, user %.4f", systime.Seconds(), usrtime.Seconds())
|
||||
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user