mirror of
https://github.com/kopia/kopia.git
synced 2026-01-24 14:28:06 -05:00
* cli: added a flag to create repository with v2 index features * content: plumb through compression.ID parameter to content.Manager.WriteContent() * content: expose content.Manager.SupportsContentCompression This allows object manager to decide whether to create compressed object or let the content manager do it. * object: if compression is requested and the repo supports it, pass compression ID to the content manager * cli: show compression status in 'repository status' * cli: output compression information in 'content list' and 'content stats' * content: compression and decompression support * content: unit tests for compression * object: compression tests * testing: added integration tests against v2 index * testing: run all e2e tests with and without content-level compression * htmlui: added UI for specifying index format on creation * cli: additional tests for 'content ls' and 'content stats' * applied pr suggestions
107 lines
2.0 KiB
Go
107 lines
2.0 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/kopia/kopia/internal/iocopy"
|
|
"github.com/kopia/kopia/internal/units"
|
|
)
|
|
|
|
const oneHundredPercent = 100.0
|
|
|
|
// TODO - remove this global.
|
|
var timeZone = "local"
|
|
|
|
func showContentWithFlags(w io.Writer, rd io.Reader, unzip, indentJSON bool) error {
|
|
if unzip {
|
|
gz, err := gzip.NewReader(rd)
|
|
if err != nil {
|
|
return errors.Wrap(err, "unable to open gzip stream")
|
|
}
|
|
|
|
rd = gz
|
|
}
|
|
|
|
var buf1, buf2 bytes.Buffer
|
|
|
|
if indentJSON {
|
|
if _, err := iocopy.Copy(&buf1, rd); err != nil {
|
|
return errors.Wrap(err, "error copying data")
|
|
}
|
|
|
|
if err := json.Indent(&buf2, buf1.Bytes(), "", " "); err != nil {
|
|
return errors.Wrap(err, "errors indenting JSON")
|
|
}
|
|
|
|
rd = ioutil.NopCloser(&buf2)
|
|
}
|
|
|
|
if _, err := iocopy.Copy(w, rd); err != nil {
|
|
return errors.Wrap(err, "error copying data")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func maybeHumanReadableBytes(enable bool, value int64) string {
|
|
if enable {
|
|
return units.BytesStringBase10(value)
|
|
}
|
|
|
|
return fmt.Sprintf("%v", value)
|
|
}
|
|
|
|
func maybeHumanReadableCount(enable bool, value int64) string {
|
|
if enable {
|
|
return units.Count(value)
|
|
}
|
|
|
|
return fmt.Sprintf("%v", value)
|
|
}
|
|
|
|
func formatTimestamp(ts time.Time) string {
|
|
return convertTimezone(ts).Format("2006-01-02 15:04:05 MST")
|
|
}
|
|
|
|
func formatTimestampPrecise(ts time.Time) string {
|
|
return convertTimezone(ts).Format("2006-01-02 15:04:05.000 MST")
|
|
}
|
|
|
|
func convertTimezone(ts time.Time) time.Time {
|
|
switch timeZone {
|
|
case "local":
|
|
return ts.Local()
|
|
case "utc":
|
|
return ts.UTC()
|
|
case "original":
|
|
return ts
|
|
default:
|
|
loc, err := time.LoadLocation(timeZone)
|
|
if err == nil {
|
|
return ts.In(loc)
|
|
}
|
|
|
|
return ts
|
|
}
|
|
}
|
|
|
|
func formatCompressionPercentage(original, compressed int64) string {
|
|
if compressed >= original {
|
|
return "0%"
|
|
}
|
|
|
|
if original == 0 {
|
|
return "0%"
|
|
}
|
|
|
|
return fmt.Sprintf("%.1f%%", oneHundredPercent*(1-float64(compressed)/float64(original)))
|
|
}
|