Skip to content

Commit

Permalink
feat: support for reading gzip,bzip2 and xz files
Browse files Browse the repository at this point in the history
  • Loading branch information
dundee committed May 31, 2024
1 parent 3dda7c5 commit 82598a7
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down
53 changes: 50 additions & 3 deletions tui/show_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ 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/rivo/tview"
"github.com/ulikunitz/xz"

"github.com/dundee/gdu/v5/build"
"github.com/dundee/gdu/v5/pkg/fs"
Expand All @@ -23,18 +29,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

Check warning on line 41 in tui/show_file.go

View check run for this annotation

Codecov / codecov/patch

tui/show_file.go#L40-L41

Added lines #L40 - L41 were not covered by tests
}

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 {
Expand Down Expand Up @@ -94,3 +105,39 @@ 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)
f.Read(head)

Check failure on line 112 in tui/show_file.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `f.Read` is not checked (errcheck)

if pos, err := f.Seek(0, 0); pos != 0 || err != nil {
return nil, err

Check warning on line 115 in tui/show_file.go

View check run for this annotation

Codecov / codecov/patch

tui/show_file.go#L115

Added line #L115 was not covered by tests
}
scanner = bufio.NewScanner(f)

typ, err := filetype.Match(head)
if err != nil {
return nil, err

Check warning on line 121 in tui/show_file.go

View check run for this annotation

Codecov / codecov/patch

tui/show_file.go#L121

Added line #L121 was not covered by tests
}

switch typ.MIME.Value {
case matchers.TypeGz.MIME.Value:
r, err := gzip.NewReader(f)
if err != nil {
return nil, err

Check warning on line 128 in tui/show_file.go

View check run for this annotation

Codecov / codecov/patch

tui/show_file.go#L128

Added line #L128 was not covered by tests
}
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, err

Check warning on line 137 in tui/show_file.go

View check run for this annotation

Codecov / codecov/patch

tui/show_file.go#L137

Added line #L137 was not covered by tests
}
scanner = bufio.NewScanner(r)
}

return scanner, nil
}
83 changes: 83 additions & 0 deletions tui/show_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package tui

import (
"bytes"
"compress/gzip"
"testing"

"github.com/stretchr/testify/assert"
"github.com/ulikunitz/xz"
)

func TestGetScannerForEmptyString(t *testing.T) {
r := bytes.NewReader([]byte{})
s, err := getScanner(r)
assert.NoError(t, err)

assert.Equal(t, false, s.Scan())
assert.Equal(t, "", 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.NoError(t, err)

err = w.Close()
assert.NoError(t, err)

r := bytes.NewReader(b.Bytes())
s, err := getScanner(r)
assert.NoError(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.NoError(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.NoError(t, err)

_, err = w.Write([]byte("hello world"))
assert.NoError(t, err)

err = w.Close()
assert.NoError(t, err)

r := bytes.NewReader(b.Bytes())
s, err := getScanner(r)
assert.NoError(t, err)

assert.Equal(t, true, s.Scan())
assert.Equal(t, "hello world", s.Text())
assert.Equal(t, nil, s.Err())
}

0 comments on commit 82598a7

Please sign in to comment.