Skip to content

Commit 7b46129

Browse files
authored
Add an interface for file compress (#155)
* Add an interface for file compress * make sure GZip implements the interface Compress
1 parent 5dd962f commit 7b46129

File tree

4 files changed

+110
-70
lines changed

4 files changed

+110
-70
lines changed

pkg/compress/gzip.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package compress
2+
3+
import (
4+
"archive/tar"
5+
"compress/gzip"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"os"
10+
"path/filepath"
11+
"strings"
12+
)
13+
14+
// GZip implements a compress which based gzip
15+
type GZip struct {
16+
additionBinaries []string
17+
}
18+
19+
// NewGZip creates an instance of GZip
20+
// additionBinaries could be empty or nil
21+
func NewGZip(additionBinaries []string) *GZip {
22+
return &GZip{additionBinaries: additionBinaries}
23+
}
24+
25+
// make sure GZip implements the interface Compress
26+
var _ Compress = &GZip{}
27+
28+
// ExtractFiles extracts files from a target compress file
29+
func (c *GZip) ExtractFiles(sourceFile, targetName string) (err error) {
30+
if targetName == "" {
31+
err = errors.New("target filename is empty")
32+
return
33+
}
34+
35+
var f *os.File
36+
var gzf *gzip.Reader
37+
if f, err = os.Open(sourceFile); err != nil {
38+
return
39+
}
40+
defer func() {
41+
_ = f.Close()
42+
}()
43+
44+
if gzf, err = gzip.NewReader(f); err != nil {
45+
return
46+
}
47+
48+
tarReader := tar.NewReader(gzf)
49+
var header *tar.Header
50+
var found bool
51+
for {
52+
if header, err = tarReader.Next(); err == io.EOF {
53+
err = nil
54+
break
55+
} else if err != nil {
56+
break
57+
}
58+
name := header.Name
59+
60+
switch header.Typeflag {
61+
case tar.TypeReg:
62+
if err = extraFile(name, targetName, sourceFile, header, tarReader); err == nil {
63+
found = true
64+
} else {
65+
break
66+
}
67+
68+
for i := range c.additionBinaries {
69+
addition := c.additionBinaries[i]
70+
if err = extraFile(addition, addition, sourceFile, header, tarReader); err != nil {
71+
return
72+
}
73+
}
74+
}
75+
}
76+
77+
if err == nil && !found {
78+
err = fmt.Errorf("cannot found item '%s' from '%s'", targetName, sourceFile)
79+
}
80+
return
81+
}
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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package compress
2+
3+
// Compress is a common compress interface
4+
type Compress interface {
5+
ExtractFiles(sourceFile, targetName string) error
6+
}

pkg/compress/xz.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package compress
2+
3+
// TODO implement extract files, for instance, you can use https://github.com/ulikunitz/xz

pkg/installer/process.go

Lines changed: 4 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
package installer
22

33
import (
4-
"archive/tar"
5-
"compress/gzip"
6-
"errors"
74
"fmt"
85
"github.com/linuxsuren/http-downloader/pkg/common"
6+
"github.com/linuxsuren/http-downloader/pkg/compress"
97
"github.com/linuxsuren/http-downloader/pkg/exec"
108
"io"
119
"os"
1210
"path"
1311
"path/filepath"
1412
"runtime"
15-
"strings"
1613
)
1714

1815
// Install installs a package
@@ -116,71 +113,8 @@ func (o *Installer) OverWriteBinary(sourceFile, targetPath string) (err error) {
116113
}
117114

118115
func (o *Installer) extractFiles(tarFile, targetName string) (err error) {
119-
if targetName == "" {
120-
err = errors.New("target filename is empty")
121-
return
122-
}
123-
124-
var f *os.File
125-
var gzf *gzip.Reader
126-
if f, err = os.Open(tarFile); err != nil {
127-
return
128-
}
129-
defer func() {
130-
_ = f.Close()
131-
}()
132-
133-
if gzf, err = gzip.NewReader(f); err != nil {
134-
return
135-
}
136-
137-
tarReader := tar.NewReader(gzf)
138-
var header *tar.Header
139-
var found bool
140-
for {
141-
if header, err = tarReader.Next(); err == io.EOF {
142-
err = nil
143-
break
144-
} else if err != nil {
145-
break
146-
}
147-
name := header.Name
148-
149-
switch header.Typeflag {
150-
case tar.TypeReg:
151-
if err = extraFile(name, targetName, tarFile, header, tarReader); err == nil {
152-
found = true
153-
} else {
154-
break
155-
}
156-
157-
for i := range o.AdditionBinaries {
158-
addition := o.AdditionBinaries[i]
159-
if err = extraFile(addition, addition, tarFile, header, tarReader); err != nil {
160-
return
161-
}
162-
}
163-
}
164-
}
165-
166-
if err == nil && !found {
167-
err = fmt.Errorf("cannot found item '%s' from '%s'", targetName, tarFile)
168-
}
169-
return
170-
}
171-
172-
func extraFile(name, targetName, tarFile string, header *tar.Header, tarReader *tar.Reader) (err error) {
173-
if name != targetName && !strings.HasSuffix(name, "/"+targetName) {
174-
return
175-
}
176-
var targetFile *os.File
177-
if targetFile, err = os.OpenFile(fmt.Sprintf("%s/%s", filepath.Dir(tarFile), targetName),
178-
os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)); err != nil {
179-
return
180-
}
181-
if _, err = io.Copy(targetFile, tarReader); err != nil {
182-
return
183-
}
184-
_ = targetFile.Close()
116+
// TODO choose a correct compress instance
117+
compressor := compress.NewGZip(o.AdditionBinaries)
118+
err = compressor.ExtractFiles(tarFile, targetName)
185119
return
186120
}

0 commit comments

Comments
 (0)