Merge pull request #2817 from filecoin-project/feat/improve-client-listdeals

client cli: Improve list-deals output
This commit is contained in:
Łukasz Magiera 2020-08-04 20:00:45 +02:00 committed by GitHub
commit b264cd6c4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 196 additions and 6 deletions

View File

@ -4,7 +4,6 @@ import (
"context"
"fmt"
"os"
"strings"
"testing"
@ -81,7 +80,7 @@ func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n,
s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM
require.NoError(t, err)
fmt.Printf("Sectors: %d\n", len(s))
if len(s) >= n + existing {
if len(s) >= n+existing {
break
}

View File

@ -30,6 +30,7 @@ import (
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/tablewriter"
)
var CidBaseFlag = cli.StringFlag{
@ -986,8 +987,8 @@ var clientListDeals = &cli.Command{
color := cctx.Bool("color")
w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
if cctx.Bool("verbose") {
w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
fmt.Fprintf(w, "DealCid\tDealId\tProvider\tState\tOn Chain?\tSlashed?\tPieceCID\tSize\tPrice\tDuration\tMessage\n")
for _, d := range deals {
onChain := "N"
@ -1003,8 +1004,19 @@ var clientListDeals = &cli.Command{
price := types.FIL(types.BigMul(d.LocalDeal.PricePerEpoch, types.NewInt(d.LocalDeal.Duration)))
fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%s\n", d.LocalDeal.ProposalCid, d.LocalDeal.DealID, d.LocalDeal.Provider, dealStateString(color, d.LocalDeal.State), onChain, slashed, d.LocalDeal.PieceCID, types.SizeStr(types.NewInt(d.LocalDeal.Size)), price, d.LocalDeal.Duration, d.LocalDeal.Message)
}
return w.Flush()
} else {
fmt.Fprintf(w, "DealCid\tDealId\tProvider\tState\tOn Chain?\tSlashed?\tPieceCID\tSize\tPrice\tDuration\n")
w := tablewriter.New(tablewriter.Col("DealCid"),
tablewriter.Col("DealId"),
tablewriter.Col("Provider"),
tablewriter.Col("State"),
tablewriter.Col("On Chain?"),
tablewriter.Col("Slashed?"),
tablewriter.Col("PieceCID"),
tablewriter.Col("Size"),
tablewriter.Col("Price"),
tablewriter.Col("Duration"),
tablewriter.NewLineCol("Message"))
for _, d := range deals {
propcid := d.LocalDeal.ProposalCid.String()
@ -1024,11 +1036,24 @@ var clientListDeals = &cli.Command{
piece = "..." + piece[len(piece)-8:]
price := types.FIL(types.BigMul(d.LocalDeal.PricePerEpoch, types.NewInt(d.LocalDeal.Duration)))
fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\n", propcid, d.LocalDeal.DealID, d.LocalDeal.Provider, dealStateString(color, d.LocalDeal.State), onChain, slashed, piece, types.SizeStr(types.NewInt(d.LocalDeal.Size)), price, d.LocalDeal.Duration)
w.Write(map[string]interface{}{
"DealCid": propcid,
"DealId": d.LocalDeal.DealID,
"Provider": d.LocalDeal.Provider,
"State": dealStateString(color, d.LocalDeal.State),
"On Chain?": onChain,
"Slashed?": slashed,
"PieceCID": piece,
"Size": types.SizeStr(types.NewInt(d.LocalDeal.Size)),
"Price": price,
"Duration": d.LocalDeal.Duration,
"Message": d.LocalDeal.Message,
})
}
return w.Flush(os.Stdout)
}
return w.Flush()
},
}

1
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/GeertJohan/go.rice v1.0.0
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/coreos/go-systemd/v22 v22.0.0
github.com/dgraph-io/badger/v2 v2.0.3
github.com/docker/go-units v0.4.0

2
go.sum
View File

@ -58,6 +58,8 @@ github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e/go.mod h1:3o
github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo=
github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=

View File

@ -0,0 +1,34 @@
package tablewriter
import (
"os"
"testing"
"github.com/fatih/color"
)
func TestTableWriter(t *testing.T) {
tw := New(Col("C1"), Col("X"), Col("C333"), NewLineCol("Thing"))
tw.Write(map[string]interface{}{
"C1": "234",
"C333": "ou",
})
tw.Write(map[string]interface{}{
"C1": "23uieui4",
"C333": "ou",
"X": color.GreenString("#"),
"Thing": "a very long thing, annoyingly so",
})
tw.Write(map[string]interface{}{
"C1": "ttttttttt",
"C333": "eui",
})
tw.Write(map[string]interface{}{
"C1": "1",
"C333": "2",
"SurpriseColumn": "42",
})
if err := tw.Flush(os.Stdout); err != nil {
t.Fatal(err)
}
}

View File

@ -0,0 +1,129 @@
package tablewriter
import (
"fmt"
"io"
"strings"
"unicode/utf8"
"github.com/acarl005/stripansi"
)
type Column struct {
Name string
SeparateLine bool
}
type TableWriter struct {
cols []Column
rows []map[int]string
}
func Col(name string) Column {
return Column{
Name: name,
SeparateLine: false,
}
}
func NewLineCol(name string) Column {
return Column{
Name: name,
SeparateLine: true,
}
}
// Unlike text/tabwriter, this works with CLI escape codes, and allows for info
// in separate lines
func New(cols ...Column) *TableWriter {
return &TableWriter{
cols: cols,
}
}
func (w *TableWriter) Write(r map[string]interface{}) {
// this can cause columns to be out of order, but will at least work
byColID := map[int]string{}
cloop:
for col, val := range r {
for i, column := range w.cols {
if column.Name == col {
byColID[i] = fmt.Sprint(val)
continue cloop
}
}
byColID[len(w.cols)] = fmt.Sprint(val)
w.cols = append(w.cols, Column{
Name: col,
SeparateLine: false,
})
}
w.rows = append(w.rows, byColID)
}
func (w *TableWriter) Flush(out io.Writer) error {
colLengths := make([]int, len(w.cols))
header := map[int]string{}
for i, col := range w.cols {
if col.SeparateLine {
continue
}
header[i] = col.Name
}
w.rows = append([]map[int]string{header}, w.rows...)
for col := range w.cols {
for _, row := range w.rows {
val, found := row[col]
if !found {
continue
}
if cliStringLength(val) > colLengths[col] {
colLengths[col] = cliStringLength(val)
}
}
}
for _, row := range w.rows {
cols := make([]string, len(w.cols))
for ci, col := range w.cols {
e, _ := row[ci]
pad := colLengths[ci] - cliStringLength(e) + 2
if !col.SeparateLine {
e = e + strings.Repeat(" ", pad)
if _, err := fmt.Fprint(out, e); err != nil {
return err
}
}
cols[ci] = e
}
if _, err := fmt.Fprintln(out); err != nil {
return err
}
for ci, col := range w.cols {
if !col.SeparateLine || len(cols[ci]) == 0 {
continue
}
if _, err := fmt.Fprintf(out, " %s: %s\n", col.Name, cols[ci]); err != nil {
return err
}
}
}
return nil
}
func cliStringLength(s string) (n int) {
return utf8.RuneCountInString(stripansi.Strip(s))
}