github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/cmd/info/internal/build_csv/main.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/csv"
     5  	"encoding/json"
     6  	"flag"
     7  	"fmt"
     8  	"io"
     9  	"log"
    10  	"os"
    11  	"sort"
    12  	"strconv"
    13  
    14  	"github.com/rclone/rclone/cmd/info/internal"
    15  )
    16  
    17  func main() {
    18  	fOut := flag.String("o", "out.csv", "Output file")
    19  	flag.Parse()
    20  
    21  	args := flag.Args()
    22  	remotes := make([]internal.InfoReport, 0, len(args))
    23  	for _, fn := range args {
    24  		f, err := os.Open(fn)
    25  		if err != nil {
    26  			log.Fatalf("Unable to open %q: %s", fn, err)
    27  		}
    28  		var remote internal.InfoReport
    29  		dec := json.NewDecoder(f)
    30  		err = dec.Decode(&remote)
    31  		if err != nil {
    32  			log.Fatalf("Unable to decode %q: %s", fn, err)
    33  		}
    34  		if remote.ControlCharacters == nil {
    35  			log.Printf("Skipping remote %s: no ControlCharacters", remote.Remote)
    36  		} else {
    37  			remotes = append(remotes, remote)
    38  		}
    39  		if err := f.Close(); err != nil {
    40  			log.Fatalf("Closing %q failed: %s", fn, err)
    41  		}
    42  	}
    43  
    44  	charsMap := make(map[string]string)
    45  	var remoteNames []string
    46  	for _, r := range remotes {
    47  		remoteNames = append(remoteNames, r.Remote)
    48  		for k, v := range *r.ControlCharacters {
    49  			v.Text = k
    50  			quoted := strconv.Quote(k)
    51  			charsMap[k] = quoted[1 : len(quoted)-1]
    52  		}
    53  	}
    54  	sort.Strings(remoteNames)
    55  
    56  	chars := make([]string, 0, len(charsMap))
    57  	for k := range charsMap {
    58  		chars = append(chars, k)
    59  	}
    60  	sort.Strings(chars)
    61  
    62  	//                     char       remote output
    63  	recordsMap := make(map[string]map[string][]string)
    64  	//                     remote output
    65  	hRemoteMap := make(map[string][]string)
    66  	hOperation := []string{"Write", "Write", "Write", "Get", "Get", "Get", "List", "List", "List"}
    67  	hPosition := []string{"L", "M", "R", "L", "M", "R", "L", "M", "R"}
    68  
    69  	// remote
    70  	// write							get 								list
    71  	// left	middle	right	left	middle	right	left	middle	right
    72  
    73  	for _, r := range remotes {
    74  		hRemoteMap[r.Remote] = []string{r.Remote, "", "", "", "", "", "", "", ""}
    75  		for k, v := range *r.ControlCharacters {
    76  			cMap, ok := recordsMap[k]
    77  			if !ok {
    78  				cMap = make(map[string][]string, 1)
    79  				recordsMap[k] = cMap
    80  			}
    81  
    82  			cMap[r.Remote] = []string{
    83  				sok(v.WriteError[internal.PositionLeft]), sok(v.WriteError[internal.PositionMiddle]), sok(v.WriteError[internal.PositionRight]),
    84  				sok(v.GetError[internal.PositionLeft]), sok(v.GetError[internal.PositionMiddle]), sok(v.GetError[internal.PositionRight]),
    85  				pok(v.InList[internal.PositionLeft]), pok(v.InList[internal.PositionMiddle]), pok(v.InList[internal.PositionRight]),
    86  			}
    87  		}
    88  	}
    89  
    90  	records := [][]string{
    91  		[]string{"", ""},
    92  		[]string{"", ""},
    93  		[]string{"Bytes", "Char"},
    94  	}
    95  	for _, r := range remoteNames {
    96  		records[0] = append(records[0], hRemoteMap[r]...)
    97  		records[1] = append(records[1], hOperation...)
    98  		records[2] = append(records[2], hPosition...)
    99  	}
   100  	for _, c := range chars {
   101  		k := charsMap[c]
   102  		row := []string{fmt.Sprintf("%X", c), k}
   103  		for _, r := range remoteNames {
   104  			if m, ok := recordsMap[c][r]; ok {
   105  				row = append(row, m...)
   106  			} else {
   107  				row = append(row, "", "", "", "", "", "", "", "", "")
   108  			}
   109  		}
   110  		records = append(records, row)
   111  	}
   112  
   113  	var writer io.Writer
   114  	if *fOut == "-" {
   115  		writer = os.Stdout
   116  	} else {
   117  		f, err := os.Create(*fOut)
   118  		if err != nil {
   119  			log.Fatalf("Unable to create %q: %s", *fOut, err)
   120  		}
   121  		defer func() {
   122  			if err := f.Close(); err != nil {
   123  				log.Fatalln("Error writing csv:", err)
   124  			}
   125  		}()
   126  		writer = f
   127  	}
   128  
   129  	w := csv.NewWriter(writer)
   130  	err := w.WriteAll(records)
   131  	if err != nil {
   132  		log.Fatalln("Error writing csv:", err)
   133  	} else if err := w.Error(); err != nil {
   134  		log.Fatalln("Error writing csv:", err)
   135  	}
   136  }
   137  
   138  func sok(s string) string {
   139  	if s != "" {
   140  		return "ERR"
   141  	}
   142  	return "OK"
   143  }
   144  
   145  func pok(p internal.Presence) string {
   146  	switch p {
   147  	case internal.Absent:
   148  		return "MIS"
   149  	case internal.Present:
   150  		return "OK"
   151  	case internal.Renamed:
   152  		return "REN"
   153  	case internal.Multiple:
   154  		return "MUL"
   155  	default:
   156  		return "ERR"
   157  	}
   158  }