From 2e58565d600200f5e26413be09d8b97e7863af90 Mon Sep 17 00:00:00 2001
From: JinnyYi <jinnyyi@yunify.com>
Date: Thu, 4 Nov 2021 10:33:15 +0800
Subject: [PATCH 1/2] feat: Add summarize support in ls

---
 cmd/byctl/ls.go    | 22 ++++++++++++++++---
 cmd/byctl/utils.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/cmd/byctl/ls.go b/cmd/byctl/ls.go
index f32c85f..185bfbe 100644
--- a/cmd/byctl/ls.go
+++ b/cmd/byctl/ls.go
@@ -14,8 +14,9 @@ import (
 )
 
 const (
-	lsFlagLongName = "l"
-	lsFlagFormat   = "format"
+	lsFlagLongName  = "l"
+	lsFlagFormat    = "format"
+	lsFlagSummarize = "summarize"
 )
 
 var lsFlags = []cli.Flag{
@@ -27,6 +28,10 @@ var lsFlags = []cli.Flag{
 		Name:  lsFlagFormat,
 		Usage: "across long -l",
 	},
+	&cli.BoolFlag{
+		Name:  lsFlagSummarize,
+		Usage: "display summary information",
+	},
 }
 
 var lsCmd = &cli.Command{
@@ -70,6 +75,8 @@ var lsCmd = &cli.Command{
 		}
 
 		isFirst := true
+		var totalNum int
+		var totalSize int64
 
 		for v := range ch {
 			if v.Error != nil {
@@ -84,9 +91,18 @@ var lsCmd = &cli.Command{
 			if isFirst {
 				isFirst = false
 			}
+
+			totalNum += 1
+			totalSize += oa.size
 		}
 		// End of line
 		fmt.Print("\n")
+
+		// display summary information
+		if c.Bool(lsFlagSummarize) {
+			fmt.Printf("\n%14s %d\n", "Total Objects:", totalNum)
+			fmt.Printf("%14s %s\n", "Total Size:", ByteSize(uint64(totalSize)))
+		}
 		return
 	},
 }
@@ -118,7 +134,7 @@ func (oa objectAttr) shortFormat(isFirst bool) string {
 	if isFirst {
 		return oa.name
 	}
-	return oa.name + " "
+	return " " + oa.name
 }
 
 func (oa objectAttr) longFormat(isFirst bool) string {
diff --git a/cmd/byctl/utils.go b/cmd/byctl/utils.go
index e36ca9d..f83a000 100644
--- a/cmd/byctl/utils.go
+++ b/cmd/byctl/utils.go
@@ -2,6 +2,8 @@ package main
 
 import (
 	"fmt"
+	"strconv"
+	"strings"
 	"time"
 
 	"github.com/Xuanwo/go-bufferpool"
@@ -50,3 +52,56 @@ func parseLimit(text string) (types.Pair, error) {
 		}
 	}), nil
 }
+
+const (
+	BYTE = 1 << (10 * iota)
+	KILOBYTE
+	MEGABYTE
+	GIGABYTE
+	TERABYTE
+	PETABYTE
+	EXABYTE
+)
+
+// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available:
+//  EiB: Exabyte
+//  PiB: Petabyte
+//  TiB: Terabyte
+//  GiB: Gigabyte
+//  MiB: Megabyte
+//  KiB: Kilobyte
+//  B: Byte
+// The unit that results in the smallest number greater than or equal to 1 is always chosen.
+func ByteSize(bytes uint64) string {
+	unit := ""
+	value := float64(bytes)
+
+	switch {
+	case bytes >= EXABYTE:
+		unit = "EiB"
+		value = value / EXABYTE
+	case bytes >= PETABYTE:
+		unit = "PiB"
+		value = value / PETABYTE
+	case bytes >= TERABYTE:
+		unit = "TiB"
+		value = value / TERABYTE
+	case bytes >= GIGABYTE:
+		unit = "GiB"
+		value = value / GIGABYTE
+	case bytes >= MEGABYTE:
+		unit = "MiB"
+		value = value / MEGABYTE
+	case bytes >= KILOBYTE:
+		unit = "KiB"
+		value = value / KILOBYTE
+	case bytes >= BYTE:
+		unit = "B"
+	case bytes == 0:
+		return "0"
+	}
+
+	result := strconv.FormatFloat(value, 'f', 1, 64)
+	result = strings.TrimSuffix(result, ".0")
+	return result + " " + unit
+}

From 474e0b12d99180436a14709486effa791c7eabdb Mon Sep 17 00:00:00 2001
From: JinnyYi <jinnyyi@yunify.com>
Date: Thu, 4 Nov 2021 12:40:38 +0800
Subject: [PATCH 2/2] Use go-unit to format output

---
 cmd/byctl/ls.go    |  3 ++-
 cmd/byctl/utils.go | 55 ----------------------------------------------
 2 files changed, 2 insertions(+), 56 deletions(-)

diff --git a/cmd/byctl/ls.go b/cmd/byctl/ls.go
index 185bfbe..75727fd 100644
--- a/cmd/byctl/ls.go
+++ b/cmd/byctl/ls.go
@@ -5,6 +5,7 @@ import (
 	"path/filepath"
 	"time"
 
+	"github.com/docker/go-units"
 	"github.com/urfave/cli/v2"
 	"go.uber.org/zap"
 
@@ -101,7 +102,7 @@ var lsCmd = &cli.Command{
 		// display summary information
 		if c.Bool(lsFlagSummarize) {
 			fmt.Printf("\n%14s %d\n", "Total Objects:", totalNum)
-			fmt.Printf("%14s %s\n", "Total Size:", ByteSize(uint64(totalSize)))
+			fmt.Printf("%14s %s\n", "Total Size:", units.BytesSize(float64(totalSize)))
 		}
 		return
 	},
diff --git a/cmd/byctl/utils.go b/cmd/byctl/utils.go
index f83a000..e36ca9d 100644
--- a/cmd/byctl/utils.go
+++ b/cmd/byctl/utils.go
@@ -2,8 +2,6 @@ package main
 
 import (
 	"fmt"
-	"strconv"
-	"strings"
 	"time"
 
 	"github.com/Xuanwo/go-bufferpool"
@@ -52,56 +50,3 @@ func parseLimit(text string) (types.Pair, error) {
 		}
 	}), nil
 }
-
-const (
-	BYTE = 1 << (10 * iota)
-	KILOBYTE
-	MEGABYTE
-	GIGABYTE
-	TERABYTE
-	PETABYTE
-	EXABYTE
-)
-
-// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available:
-//  EiB: Exabyte
-//  PiB: Petabyte
-//  TiB: Terabyte
-//  GiB: Gigabyte
-//  MiB: Megabyte
-//  KiB: Kilobyte
-//  B: Byte
-// The unit that results in the smallest number greater than or equal to 1 is always chosen.
-func ByteSize(bytes uint64) string {
-	unit := ""
-	value := float64(bytes)
-
-	switch {
-	case bytes >= EXABYTE:
-		unit = "EiB"
-		value = value / EXABYTE
-	case bytes >= PETABYTE:
-		unit = "PiB"
-		value = value / PETABYTE
-	case bytes >= TERABYTE:
-		unit = "TiB"
-		value = value / TERABYTE
-	case bytes >= GIGABYTE:
-		unit = "GiB"
-		value = value / GIGABYTE
-	case bytes >= MEGABYTE:
-		unit = "MiB"
-		value = value / MEGABYTE
-	case bytes >= KILOBYTE:
-		unit = "KiB"
-		value = value / KILOBYTE
-	case bytes >= BYTE:
-		unit = "B"
-	case bytes == 0:
-		return "0"
-	}
-
-	result := strconv.FormatFloat(value, 'f', 1, 64)
-	result = strings.TrimSuffix(result, ".0")
-	return result + " " + unit
-}