Skip to content

Commit

Permalink
Implement the Compress interface for Xz (#157)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
amoghrajesh and LinuxSuRen authored Oct 11, 2021
1 parent b2f3676 commit 38d64ee
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 29 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ require (
github.com/onsi/gomega v1.16.0
github.com/spf13/cobra v1.2.1
github.com/stretchr/testify v1.7.0
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8
gopkg.in/yaml.v2 v2.4.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
22 changes: 2 additions & 20 deletions pkg/compress/gzip.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
)

// GZip implements a compress which based gzip
// GZip implements a compress which based is based on gzip
type GZip struct {
additionBinaries []string
}
Expand Down Expand Up @@ -75,23 +73,7 @@ func (c *GZip) ExtractFiles(sourceFile, targetName string) (err error) {
}

if err == nil && !found {
err = fmt.Errorf("cannot found item '%s' from '%s'", targetName, sourceFile)
err = fmt.Errorf("cannot find item '%s' from '%s'", targetName, sourceFile)
}
return
}

func extraFile(name, targetName, tarFile string, header *tar.Header, tarReader *tar.Reader) (err error) {
if name != targetName && !strings.HasSuffix(name, "/"+targetName) {
return
}
var targetFile *os.File
if targetFile, err = os.OpenFile(fmt.Sprintf("%s/%s", filepath.Dir(tarFile), targetName),
os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)); err != nil {
return
}
if _, err = io.Copy(targetFile, tarReader); err != nil {
return
}
_ = targetFile.Close()
return
}
6 changes: 0 additions & 6 deletions pkg/compress/interface.go

This file was deleted.

31 changes: 31 additions & 0 deletions pkg/compress/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package compress

import (
"archive/tar"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)

// Compress is a common compress interface
type Compress interface {
ExtractFiles(sourceFile, targetName string) error
}

func extraFile(name, targetName, tarFile string, header *tar.Header, tarReader *tar.Reader) (err error) {
if name != targetName && !strings.HasSuffix(name, "/"+targetName) {
return
}
var targetFile *os.File
if targetFile, err = os.OpenFile(fmt.Sprintf("%s/%s", filepath.Dir(tarFile), targetName),
os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)); err != nil {
return
}
if _, err = io.Copy(targetFile, tarReader); err != nil {
return
}
_ = targetFile.Close()
return
}
78 changes: 77 additions & 1 deletion pkg/compress/xz.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,79 @@
package compress

// TODO implement extract files, for instance, you can use https://github.com/ulikunitz/xz
import (
"archive/tar"
"errors"
"fmt"
"github.com/xi2/xz"
"io"
"log"
"os"
)

// Xz implements a compress which based is based on xz
type Xz struct {
additionBinaries []string
}

// NewXz creates an instance of Xz
func NewXz(additionBinaries []string) *Xz {
return &Xz{additionBinaries: additionBinaries}
}

// ExtractFiles extracts files from a target compress file
func (x *Xz) ExtractFiles(sourceFile, targetName string) (err error) {
if targetName == "" {
err = errors.New("target filename is empty")
return
}
var f *os.File
if f, err = os.Open(sourceFile); err != nil {
return err
}
defer func() {
_ = f.Close()
}()

// Create a xz Reader
r, err := xz.NewReader(f, 0)
if err != nil {
log.Fatal(err)
return
}

var header *tar.Header
var found bool
// Create a tar Reader
tarReader := tar.NewReader(r)
for {
if header, err = tarReader.Next(); err == io.EOF {
err = nil
break
}
if err != nil {
log.Fatal(err)
return
}
name := header.Name

switch header.Typeflag {
case tar.TypeReg:
if err = extraFile(name, targetName, sourceFile, header, tarReader); err == nil {
found = true
} else {
break
}

for i := range x.additionBinaries {
addition := x.additionBinaries[i]
if err = extraFile(addition, addition, sourceFile, header, tarReader); err != nil {
return
}
}
}
}
if err == nil && !found {
err = fmt.Errorf("cannot find item '%s' from '%s'", targetName, sourceFile)
}
return
}
10 changes: 8 additions & 2 deletions pkg/installer/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,14 @@ func (o *Installer) OverWriteBinary(sourceFile, targetPath string) (err error) {
}

func (o *Installer) extractFiles(tarFile, targetName string) (err error) {
// TODO choose a correct compress instance
compressor := compress.NewGZip(o.AdditionBinaries)
// Select the right decompressor based on file type
extension := path.Ext(tarFile)
var compressor compress.Compress
if extension == ".xz" {
compressor = compress.NewXz(o.AdditionBinaries)
} else {
compressor = compress.NewGZip(o.AdditionBinaries)
}
err = compressor.ExtractFiles(tarFile, targetName)
return
}

0 comments on commit 38d64ee

Please sign in to comment.