133 lines
2.4 KiB
Go
133 lines
2.4 KiB
Go
package rauc
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"regexp"
|
|
"strconv"
|
|
"sync"
|
|
|
|
"code.thetadev.de/TSGRain/SEBRAUC/src/util"
|
|
)
|
|
|
|
var (
|
|
expPercentage = regexp.MustCompile(`^ *(\d+)% +(.+)`)
|
|
expLastError = regexp.MustCompile(`^LastError: +(.+)`)
|
|
)
|
|
|
|
type Rauc struct {
|
|
broadcast chan string
|
|
status RaucStatus
|
|
runningMtx sync.Mutex
|
|
}
|
|
|
|
type RaucStatus struct {
|
|
Installing bool `json:"installing"`
|
|
Percent int `json:"percent"`
|
|
Message string `json:"message"`
|
|
LastError string `json:"last_error"`
|
|
Log string `json:"log"`
|
|
}
|
|
|
|
func NewRauc(broadcast chan string) *Rauc {
|
|
r := &Rauc{
|
|
broadcast: broadcast,
|
|
}
|
|
|
|
r.broadcast <- r.GetStatusJson()
|
|
|
|
return r
|
|
}
|
|
|
|
func (r *Rauc) completed(updateFile string) {
|
|
r.status.Installing = false
|
|
r.broadcast <- r.GetStatusJson()
|
|
|
|
_ = os.Remove(updateFile)
|
|
}
|
|
|
|
func (r *Rauc) RunRauc(updateFile string) error {
|
|
// Check file input
|
|
if !util.DoesFileExist(updateFile) {
|
|
return util.ErrFileDoesNotExist
|
|
}
|
|
|
|
// Only run one instance at a time
|
|
r.runningMtx.Lock()
|
|
isRunning := r.status.Installing
|
|
r.status.Installing = true
|
|
r.runningMtx.Unlock()
|
|
|
|
if isRunning {
|
|
return util.ErrAlreadyRunning
|
|
}
|
|
|
|
// Reset installer
|
|
r.status = RaucStatus{
|
|
Installing: true,
|
|
}
|
|
r.broadcast <- r.GetStatusJson()
|
|
|
|
cmd := util.CommandFromString(fmt.Sprintf("%s install %s", util.RaucCmd, updateFile))
|
|
|
|
readPipe, _ := cmd.StdoutPipe()
|
|
cmd.Stderr = cmd.Stdout
|
|
|
|
scanner := bufio.NewScanner(readPipe)
|
|
|
|
go func() {
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
hasUpdate := false
|
|
|
|
if line != "idle" && line != "installing" {
|
|
r.status.Log += line + "\n"
|
|
}
|
|
|
|
match := expPercentage.FindStringSubmatch(line)
|
|
if match != nil {
|
|
r.status.Percent, _ = strconv.Atoi(match[1])
|
|
r.status.Message = match[2]
|
|
hasUpdate = true
|
|
} else {
|
|
match = expLastError.FindStringSubmatch(line)
|
|
if match != nil {
|
|
r.status.LastError = match[1]
|
|
hasUpdate = true
|
|
}
|
|
}
|
|
|
|
if hasUpdate {
|
|
r.broadcast <- r.GetStatusJson()
|
|
}
|
|
}
|
|
}()
|
|
|
|
err := cmd.Start()
|
|
if err != nil {
|
|
r.completed(updateFile)
|
|
return err
|
|
}
|
|
|
|
go func() {
|
|
err := cmd.Wait()
|
|
if err != nil {
|
|
fmt.Printf("RAUC failed with %s\n", err)
|
|
}
|
|
r.completed(updateFile)
|
|
}()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Rauc) GetStatus() RaucStatus {
|
|
return r.status
|
|
}
|
|
|
|
func (r *Rauc) GetStatusJson() string {
|
|
statusJson, _ := json.Marshal(r.status)
|
|
return string(statusJson)
|
|
}
|