Skip to content

Commit 38d64ee

Browse files
Implement the Compress interface for Xz (#157)
* Implement the Compress interface for XZ * Fix the logic of finding a target file from xz * Move a common funtion extraFile to types.go Co-authored-by: rick <[email protected]>
1 parent b2f3676 commit 38d64ee

File tree

7 files changed

+121
-29
lines changed

7 files changed

+121
-29
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ require (
1515
github.com/onsi/gomega v1.16.0
1616
github.com/spf13/cobra v1.2.1
1717
github.com/stretchr/testify v1.7.0
18+
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8
1819
gopkg.in/yaml.v2 v2.4.0
1920
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
416416
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
417417
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
418418
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
419+
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
420+
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
419421
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
420422
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
421423
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

pkg/compress/gzip.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ import (
77
"fmt"
88
"io"
99
"os"
10-
"path/filepath"
11-
"strings"
1210
)
1311

14-
// GZip implements a compress which based gzip
12+
// GZip implements a compress which based is based on gzip
1513
type GZip struct {
1614
additionBinaries []string
1715
}
@@ -75,23 +73,7 @@ func (c *GZip) ExtractFiles(sourceFile, targetName string) (err error) {
7573
}
7674

7775
if err == nil && !found {
78-
err = fmt.Errorf("cannot found item '%s' from '%s'", targetName, sourceFile)
76+
err = fmt.Errorf("cannot find item '%s' from '%s'", targetName, sourceFile)
7977
}
8078
return
8179
}
82-
83-
func extraFile(name, targetName, tarFile string, header *tar.Header, tarReader *tar.Reader) (err error) {
84-
if name != targetName && !strings.HasSuffix(name, "/"+targetName) {
85-
return
86-
}
87-
var targetFile *os.File
88-
if targetFile, err = os.OpenFile(fmt.Sprintf("%s/%s", filepath.Dir(tarFile), targetName),
89-
os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)); err != nil {
90-
return
91-
}
92-
if _, err = io.Copy(targetFile, tarReader); err != nil {
93-
return
94-
}
95-
_ = targetFile.Close()
96-
return
97-
}

pkg/compress/interface.go

Lines changed: 0 additions & 6 deletions
This file was deleted.

pkg/compress/types.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package compress
2+
3+
import (
4+
"archive/tar"
5+
"fmt"
6+
"io"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
)
11+
12+
// Compress is a common compress interface
13+
type Compress interface {
14+
ExtractFiles(sourceFile, targetName string) error
15+
}
16+
17+
func extraFile(name, targetName, tarFile string, header *tar.Header, tarReader *tar.Reader) (err error) {
18+
if name != targetName && !strings.HasSuffix(name, "/"+targetName) {
19+
return
20+
}
21+
var targetFile *os.File
22+
if targetFile, err = os.OpenFile(fmt.Sprintf("%s/%s", filepath.Dir(tarFile), targetName),
23+
os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)); err != nil {
24+
return
25+
}
26+
if _, err = io.Copy(targetFile, tarReader); err != nil {
27+
return
28+
}
29+
_ = targetFile.Close()
30+
return
31+
}

pkg/compress/xz.go

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,79 @@
11
package compress
22

3-
// TODO implement extract files, for instance, you can use https://github.com/ulikunitz/xz
3+
import (
4+
"archive/tar"
5+
"errors"
6+
"fmt"
7+
"github.com/xi2/xz"
8+
"io"
9+
"log"
10+
"os"
11+
)
12+
13+
// Xz implements a compress which based is based on xz
14+
type Xz struct {
15+
additionBinaries []string
16+
}
17+
18+
// NewXz creates an instance of Xz
19+
func NewXz(additionBinaries []string) *Xz {
20+
return &Xz{additionBinaries: additionBinaries}
21+
}
22+
23+
// ExtractFiles extracts files from a target compress file
24+
func (x *Xz) ExtractFiles(sourceFile, targetName string) (err error) {
25+
if targetName == "" {
26+
err = errors.New("target filename is empty")
27+
return
28+
}
29+
var f *os.File
30+
if f, err = os.Open(sourceFile); err != nil {
31+
return err
32+
}
33+
defer func() {
34+
_ = f.Close()
35+
}()
36+
37+
// Create a xz Reader
38+
r, err := xz.NewReader(f, 0)
39+
if err != nil {
40+
log.Fatal(err)
41+
return
42+
}
43+
44+
var header *tar.Header
45+
var found bool
46+
// Create a tar Reader
47+
tarReader := tar.NewReader(r)
48+
for {
49+
if header, err = tarReader.Next(); err == io.EOF {
50+
err = nil
51+
break
52+
}
53+
if err != nil {
54+
log.Fatal(err)
55+
return
56+
}
57+
name := header.Name
58+
59+
switch header.Typeflag {
60+
case tar.TypeReg:
61+
if err = extraFile(name, targetName, sourceFile, header, tarReader); err == nil {
62+
found = true
63+
} else {
64+
break
65+
}
66+
67+
for i := range x.additionBinaries {
68+
addition := x.additionBinaries[i]
69+
if err = extraFile(addition, addition, sourceFile, header, tarReader); err != nil {
70+
return
71+
}
72+
}
73+
}
74+
}
75+
if err == nil && !found {
76+
err = fmt.Errorf("cannot find item '%s' from '%s'", targetName, sourceFile)
77+
}
78+
return
79+
}

pkg/installer/process.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,14 @@ func (o *Installer) OverWriteBinary(sourceFile, targetPath string) (err error) {
113113
}
114114

115115
func (o *Installer) extractFiles(tarFile, targetName string) (err error) {
116-
// TODO choose a correct compress instance
117-
compressor := compress.NewGZip(o.AdditionBinaries)
116+
// Select the right decompressor based on file type
117+
extension := path.Ext(tarFile)
118+
var compressor compress.Compress
119+
if extension == ".xz" {
120+
compressor = compress.NewXz(o.AdditionBinaries)
121+
} else {
122+
compressor = compress.NewGZip(o.AdditionBinaries)
123+
}
118124
err = compressor.ExtractFiles(tarFile, targetName)
119125
return
120126
}

0 commit comments

Comments
 (0)