rclone/cmd/info/internal/build_csv/main.go
2019-09-30 22:00:25 +01:00

158 lines
3.7 KiB
Go

package main
import (
"encoding/csv"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"sort"
"strconv"
"github.com/rclone/rclone/cmd/info/internal"
)
func main() {
fOut := flag.String("o", "out.csv", "Output file")
flag.Parse()
args := flag.Args()
remotes := make([]internal.InfoReport, 0, len(args))
for _, fn := range args {
f, err := os.Open(fn)
if err != nil {
log.Fatalf("Unable to open %q: %s", fn, err)
}
var remote internal.InfoReport
dec := json.NewDecoder(f)
err = dec.Decode(&remote)
if err != nil {
log.Fatalf("Unable to decode %q: %s", fn, err)
}
if remote.ControlCharacters == nil {
log.Printf("Skipping remote %s: no ControlCharacters", remote.Remote)
} else {
remotes = append(remotes, remote)
}
if err := f.Close(); err != nil {
log.Fatalf("Closing %q failed: %s", fn, err)
}
}
charsMap := make(map[string]string)
var remoteNames []string
for _, r := range remotes {
remoteNames = append(remoteNames, r.Remote)
for k, v := range *r.ControlCharacters {
v.Text = k
quoted := strconv.Quote(k)
charsMap[k] = quoted[1 : len(quoted)-1]
}
}
sort.Strings(remoteNames)
chars := make([]string, 0, len(charsMap))
for k := range charsMap {
chars = append(chars, k)
}
sort.Strings(chars)
// char remote output
recordsMap := make(map[string]map[string][]string)
// remote output
hRemoteMap := make(map[string][]string)
hOperation := []string{"Write", "Write", "Write", "Get", "Get", "Get", "List", "List", "List"}
hPosition := []string{"L", "M", "R", "L", "M", "R", "L", "M", "R"}
// remote
// write get list
// left middle right left middle right left middle right
for _, r := range remotes {
hRemoteMap[r.Remote] = []string{r.Remote, "", "", "", "", "", "", "", ""}
for k, v := range *r.ControlCharacters {
cMap, ok := recordsMap[k]
if !ok {
cMap = make(map[string][]string, 1)
recordsMap[k] = cMap
}
cMap[r.Remote] = []string{
sok(v.WriteError[internal.PositionLeft]), sok(v.WriteError[internal.PositionMiddle]), sok(v.WriteError[internal.PositionRight]),
sok(v.GetError[internal.PositionLeft]), sok(v.GetError[internal.PositionMiddle]), sok(v.GetError[internal.PositionRight]),
pok(v.InList[internal.PositionLeft]), pok(v.InList[internal.PositionMiddle]), pok(v.InList[internal.PositionRight]),
}
}
}
records := [][]string{
[]string{"", ""},
[]string{"", ""},
[]string{"Bytes", "Char"},
}
for _, r := range remoteNames {
records[0] = append(records[0], hRemoteMap[r]...)
records[1] = append(records[1], hOperation...)
records[2] = append(records[2], hPosition...)
}
for _, c := range chars {
k := charsMap[c]
row := []string{fmt.Sprintf("%X", c), k}
for _, r := range remoteNames {
if m, ok := recordsMap[c][r]; ok {
row = append(row, m...)
} else {
row = append(row, "", "", "", "", "", "", "", "", "")
}
}
records = append(records, row)
}
var writer io.Writer
if *fOut == "-" {
writer = os.Stdout
} else {
f, err := os.Create(*fOut)
if err != nil {
log.Fatalf("Unable to create %q: %s", *fOut, err)
}
defer func() {
if err := f.Close(); err != nil {
log.Fatalln("Error writing csv:", err)
}
}()
writer = f
}
w := csv.NewWriter(writer)
err := w.WriteAll(records)
if err != nil {
log.Fatalln("Error writing csv:", err)
} else if err := w.Error(); err != nil {
log.Fatalln("Error writing csv:", err)
}
}
func sok(s string) string {
if s != "" {
return "ERR"
}
return "OK"
}
func pok(p internal.Presence) string {
switch p {
case internal.Absent:
return "MIS"
case internal.Present:
return "OK"
case internal.Renamed:
return "REN"
case internal.Multiple:
return "MUL"
default:
return "ERR"
}
}