summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Milde <daniel@milde.cz>2024-05-31 22:21:48 +0200
committerDaniel Milde <daniel@milde.cz>2024-05-31 22:50:42 +0200
commitc66dcde41e78c7784507736e65a062ac66c51530 (patch)
tree2d42da84ccfe1537654163881e17e583a7bed9c4
parentfcaea05f7092429dd1b9ce32c45896d81ffe2d5f (diff)
feat: support for reading gzip,bzip2 and xz files
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--tui/show_file.go56
-rw-r--r--tui/show_file_test.go83
4 files changed, 142 insertions, 3 deletions
diff --git a/go.mod b/go.mod
index 7a23290..22c1d55 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@ require (
github.com/dgraph-io/badger/v3 v3.2103.2
github.com/fatih/color v1.16.0
github.com/gdamore/tcell/v2 v2.7.1
+ github.com/h2non/filetype v1.1.3
github.com/maruel/natural v1.1.0
github.com/mattn/go-isatty v0.0.20
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
@@ -14,6 +15,7 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
+ github.com/ulikunitz/xz v0.5.12
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3
golang.org/x/sys v0.20.0
gopkg.in/yaml.v3 v3.0.1
diff --git a/go.sum b/go.sum
index ec8eaf9..dedf57d 100644
--- a/go.sum
+++ b/go.sum
@@ -48,6 +48,8 @@ github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
+github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -116,6 +118,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
+github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/tui/show_file.go b/tui/show_file.go
index e5f1594..ed2f97c 100644
--- a/tui/show_file.go
+++ b/tui/show_file.go
@@ -2,11 +2,18 @@ package tui
import (
"bufio"
+ "compress/bzip2"
+ "compress/gzip"
+ "io"
"os"
"strings"
"github.com/gdamore/tcell/v2"
+ "github.com/h2non/filetype"
+ "github.com/h2non/filetype/matchers"
+ "github.com/pkg/errors"
"github.com/rivo/tview"
+ "github.com/ulikunitz/xz"
"github.com/dundee/gdu/v5/build"
"github.com/dundee/gdu/v5/pkg/fs"
@@ -23,18 +30,23 @@ func (ui *UI) showFile() *tview.TextView {
return nil
}
- f, err := os.Open(selectedFile.GetPath())
+ path := selectedFile.GetPath()
+ f, err := os.Open(path)
if err != nil {
ui.showErr("Error opening file", err)
return nil
}
+ scanner, err := getScanner(f)
+ if err != nil {
+ ui.showErr("Error reading file", err)
+ return nil
+ }
totalLines := 0
- scanner := bufio.NewScanner(f)
file := tview.NewTextView()
ui.currentDirLabel.SetText("[::b] --- " +
- strings.TrimPrefix(selectedFile.GetPath(), build.RootPathPrefix) +
+ strings.TrimPrefix(path, build.RootPathPrefix) +
" ---").SetDynamicColors(true)
readNextPart := func(linesCount int) int {
@@ -94,3 +106,41 @@ func (ui *UI) showFile() *tview.TextView {
return file
}
+
+func getScanner(f io.ReadSeeker) (scanner *bufio.Scanner, err error) {
+ // We only have to pass the file header = first 261 bytes
+ head := make([]byte, 261)
+ if _, err = f.Read(head); err != nil {
+ return nil, errors.Wrap(err, "error reading file header")
+ }
+
+ if pos, err := f.Seek(0, 0); pos != 0 || err != nil {
+ return nil, errors.Wrap(err, "error seeking file")
+ }
+ scanner = bufio.NewScanner(f)
+
+ typ, err := filetype.Match(head)
+ if err != nil {
+ return nil, errors.Wrap(err, "error matching file type")
+ }
+
+ switch typ.MIME.Value {
+ case matchers.TypeGz.MIME.Value:
+ r, err := gzip.NewReader(f)
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating gzip reader")
+ }
+ scanner = bufio.NewScanner(r)
+ case matchers.TypeBz2.MIME.Value:
+ r := bzip2.NewReader(f)
+ scanner = bufio.NewScanner(r)
+ case matchers.TypeXz.MIME.Value:
+ r, err := xz.NewReader(f)
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating xz reader")
+ }
+ scanner = bufio.NewScanner(r)
+ }
+
+ return scanner, nil
+}
diff --git a/tui/show_file_test.go b/tui/show_file_test.go
new file mode 100644
index 0000000..2958202
--- /dev/null
+++ b/tui/show_file_test.go
@@ -0,0 +1,83 @@
+package tui
+
+import (
+ "bytes"
+ "compress/gzip"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/ulikunitz/xz"
+)
+
+func TestGetScannerForPlainString(t *testing.T) {
+ r := bytes.NewReader([]byte("hello"))
+ s, err := getScanner(r)
+ assert.Nil(t, err)
+
+ assert.Equal(t, true, s.Scan())
+ assert.Equal(t, "hello", s.Text())
+ assert.Equal(t, nil, s.Err())
+}
+
+func TestGetScannerForGzipped(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ w := gzip.NewWriter(b)
+
+ _, err := w.Write([]byte("hello world"))
+ assert.Nil(t, err)
+
+ err = w.Close()
+ assert.Nil(t, err)
+
+ r := bytes.NewReader(b.Bytes())
+ s, err := getScanner(r)
+ assert.Nil(t, err)
+
+ assert.Equal(t, true, s.Scan())
+ assert.Equal(t, "hello world", s.Text())
+ assert.Equal(t, nil, s.Err())
+}
+
+func TestGetScannerForBzipped(t *testing.T) {
+ r := bytes.NewReader([]byte{
+ // bzip2 header
+ 0x42, 0x5A, 0x68, 0x39,
+ // bzip2 compressed data: "hello"
+ 0x31, 0x41, 0x59, 0x26,
+ 0x53, 0x59, 0xC1, 0xC0,
+ 0x80, 0xE2, 0x00, 0x00,
+ 0x01, 0x41, 0x00, 0x00,
+ 0x10, 0x02, 0x44, 0xA0,
+ 0x00, 0x30, 0xCD, 0x00,
+ 0xC3, 0x46, 0x29, 0x97,
+ 0x17, 0x72, 0x45, 0x38,
+ 0x50, 0x90, 0xC1, 0xC0,
+ 0x80, 0xE2,
+ })
+ s, err := getScanner(r)
+ assert.Nil(t, err)
+
+ assert.Equal(t, true, s.Scan())
+ assert.Equal(t, "hello", s.Text())
+ assert.Equal(t, nil, s.Err())
+}
+
+func TestGetScannerForXzipped(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ w, err := xz.NewWriter(b)
+ assert.Nil(t, err)
+
+ _, err = w.Write([]byte("hello world"))
+ assert.Nil(t, err)
+
+ err = w.Close()
+ assert.Nil(t, err)
+
+ r := bytes.NewReader(b.Bytes())
+ s, err := getScanner(r)
+ assert.Nil(t, err)
+
+ assert.Equal(t, true, s.Scan())
+ assert.Equal(t, "hello world", s.Text())
+ assert.Equal(t, nil, s.Err())
+}