Skip to content

Commit 897e2c7

Browse files
DecompressCommand can return 3 types of wrapped errors
1 parent e2a06e3 commit 897e2c7

File tree

5 files changed

+45
-36
lines changed

5 files changed

+45
-36
lines changed

arm.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package selfupdate
22

33
import (
4+
// unsafe is used to get a private variable from the runtime package
45
_ "unsafe"
56
)
67

decompress.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ var (
3232
)
3333

3434
// DecompressCommand decompresses the given source. Archive and compression format is
35-
// automatically detected from 'url' parameter, which represents the URL of asset.
35+
// automatically detected from 'url' parameter, which represents the URL of asset,
36+
// or simply a filename (with an extension).
3637
// This returns a reader for the decompressed command given by 'cmd'. '.zip',
3738
// '.tar.gz', '.tar.xz', '.tgz', '.gz', '.bz2' and '.xz' are supported.
39+
//
40+
// These wrapped errors can be returned:
41+
// - ErrCannotDecompressFile
42+
// - ErrExecutableNotFoundInArchive
43+
// - ErrCannotReadStream
3844
func DecompressCommand(src io.Reader, url, cmd, os, arch string) (io.Reader, error) {
3945
for _, fileType := range fileTypes {
4046
if strings.HasSuffix(url, fileType.ext) {
@@ -52,13 +58,13 @@ func unzip(src io.Reader, cmd, os, arch string) (io.Reader, error) {
5258
// So we need to read the HTTP response into a buffer at first.
5359
buf, err := ioutil.ReadAll(src)
5460
if err != nil {
55-
return nil, fmt.Errorf("failed to create buffer for zip file: %s", err)
61+
return nil, fmt.Errorf("%w for zip file: %v", ErrCannotReadStream, err)
5662
}
5763

5864
r := bytes.NewReader(buf)
5965
z, err := zip.NewReader(r, r.Size())
6066
if err != nil {
61-
return nil, fmt.Errorf("failed to decompress zip file: %s", err)
67+
return nil, fmt.Errorf("%w zip file: %s", ErrCannotDecompressFile, err)
6268
}
6369

6470
for _, file := range z.File {
@@ -69,15 +75,15 @@ func unzip(src io.Reader, cmd, os, arch string) (io.Reader, error) {
6975
}
7076
}
7177

72-
return nil, fmt.Errorf("file %q is not found", cmd)
78+
return nil, fmt.Errorf("%w in zip file: %q", ErrExecutableNotFoundInArchive, cmd)
7379
}
7480

7581
func untar(src io.Reader, cmd, os, arch string) (io.Reader, error) {
7682
log.Print("Decompressing tar.gz file")
7783

7884
gz, err := gzip.NewReader(src)
7985
if err != nil {
80-
return nil, fmt.Errorf("failed to decompress .tar.gz file: %s", err)
86+
return nil, fmt.Errorf("%w tar.gz file: %s", ErrCannotDecompressFile, err)
8187
}
8288

8389
return unarchiveTar(gz, cmd, os, arch)
@@ -88,12 +94,12 @@ func gunzip(src io.Reader, cmd, os, arch string) (io.Reader, error) {
8894

8995
r, err := gzip.NewReader(src)
9096
if err != nil {
91-
return nil, fmt.Errorf("failed to decompress gzip file: %s", err)
97+
return nil, fmt.Errorf("%w gzip file: %s", ErrCannotDecompressFile, err)
9298
}
9399

94100
name := r.Header.Name
95101
if !matchExecutableName(cmd, os, arch, name) {
96-
return nil, fmt.Errorf("file name '%s' does not match to command '%s' found", name, cmd)
102+
return nil, fmt.Errorf("%w: expected %q but found %q", ErrExecutableNotFoundInArchive, cmd, name)
97103
}
98104

99105
log.Printf("Executable file %q was found in gzip file", name)
@@ -105,7 +111,7 @@ func untarxz(src io.Reader, cmd, os, arch string) (io.Reader, error) {
105111

106112
xzip, err := xz.NewReader(src)
107113
if err != nil {
108-
return nil, fmt.Errorf("failed to decompress .tar.xz file: %s", err)
114+
return nil, fmt.Errorf("%w .tar.xz file: %s", ErrCannotDecompressFile, err)
109115
}
110116

111117
return unarchiveTar(xzip, cmd, os, arch)
@@ -116,7 +122,7 @@ func unxz(src io.Reader, cmd, os, arch string) (io.Reader, error) {
116122

117123
xzip, err := xz.NewReader(src)
118124
if err != nil {
119-
return nil, fmt.Errorf("failed to decompress xzip file: %s", err)
125+
return nil, fmt.Errorf("%w xzip file: %s", ErrCannotDecompressFile, err)
120126
}
121127

122128
log.Printf("Decompressed file from xzip is assumed to be an executable: %s", cmd)
@@ -160,13 +166,13 @@ func unarchiveTar(src io.Reader, cmd, os, arch string) (io.Reader, error) {
160166
break
161167
}
162168
if err != nil {
163-
return nil, fmt.Errorf("failed to unarchive tar file: %s", err)
169+
return nil, fmt.Errorf("%w tar file: %s", ErrCannotDecompressFile, err)
164170
}
165171
_, name := filepath.Split(h.Name)
166172
if matchExecutableName(cmd, os, arch, name) {
167173
log.Printf("Executable file %q was found in tar archive", h.Name)
168174
return t, nil
169175
}
170176
}
171-
return nil, fmt.Errorf("file %q is not found in tar", cmd)
177+
return nil, fmt.Errorf("%w in tar: %q", ErrExecutableNotFoundInArchive, cmd)
172178
}

decompress_test.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package selfupdate
22

33
import (
44
"bytes"
5+
"errors"
56
"io/ioutil"
67
"os"
78
"path/filepath"
@@ -71,12 +72,12 @@ func TestDecompressInvalidArchive(t *testing.T) {
7172
name string
7273
msg string
7374
}{
74-
{"testdata/invalid.zip", "not a valid zip file"},
75+
{"testdata/invalid.zip", "failed to decompress zip file"},
7576
{"testdata/invalid.gz", "failed to decompress gzip file"},
76-
{"testdata/invalid-tar.tar.gz", "failed to unarchive tar file"},
77-
{"testdata/invalid-gzip.tar.gz", "failed to decompress .tar.gz file"},
77+
{"testdata/invalid-tar.tar.gz", "failed to decompress tar file"},
78+
{"testdata/invalid-gzip.tar.gz", "failed to decompress tar.gz file"},
7879
{"testdata/invalid.xz", "failed to decompress xzip file"},
79-
{"testdata/invalid-tar.tar.xz", "failed to unarchive tar file"},
80+
{"testdata/invalid-tar.tar.xz", "failed to decompress tar file"},
8081
{"testdata/invalid-xz.tar.xz", "failed to decompress .tar.xz file"},
8182
} {
8283
f, err := os.Open(a.name)
@@ -85,9 +86,8 @@ func TestDecompressInvalidArchive(t *testing.T) {
8586
ext := getArchiveFileExt(a.name)
8687
url := "https://github.com/foo/bar/releases/download/v1.2.3/bar" + ext
8788
_, err = DecompressCommand(f, url, "bar", runtime.GOOS, runtime.GOOS)
88-
if err == nil {
89-
t.Fatal("Error should be raised")
90-
}
89+
require.Error(t, err)
90+
assert.True(t, errors.Is(err, ErrCannotDecompressFile))
9191
if !strings.Contains(err.Error(), a.msg) {
9292
t.Fatal("Unexpected error:", err)
9393
}
@@ -99,11 +99,11 @@ func TestTargetNotFound(t *testing.T) {
9999
name string
100100
msg string
101101
}{
102-
{"testdata/empty.zip", "is not found"},
103-
{"testdata/bar-not-found.zip", "is not found"},
104-
{"testdata/bar-not-found.gzip", "does not match to command"},
105-
{"testdata/empty.tar.gz", "is not found"},
106-
{"testdata/bar-not-found.tar.gz", "is not found"},
102+
{"testdata/empty.zip", "not found"},
103+
{"testdata/bar-not-found.zip", "not found"},
104+
{"testdata/bar-not-found.gzip", "not found"},
105+
{"testdata/empty.tar.gz", "not found"},
106+
{"testdata/bar-not-found.tar.gz", "not found"},
107107
} {
108108
t.Run(tc.name, func(t *testing.T) {
109109
f, err := os.Open(tc.name)
@@ -112,9 +112,8 @@ func TestTargetNotFound(t *testing.T) {
112112
ext := getArchiveFileExt(tc.name)
113113
url := "https://github.com/foo/bar/releases/download/v1.2.3/bar" + ext
114114
_, err = DecompressCommand(f, url, "bar", runtime.GOOS, runtime.GOOS)
115-
if err == nil {
116-
t.Fatal("Error should be raised for")
117-
}
115+
require.Error(t, err)
116+
assert.True(t, errors.Is(err, ErrExecutableNotFoundInArchive))
118117
if !strings.Contains(err.Error(), tc.msg) {
119118
t.Fatal("Unexpected error:", err)
120119
}

errors.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import "errors"
44

55
// Possible errors returned
66
var (
7-
ErrInvalidSlug = errors.New("invalid slug format, expected 'owner/name'")
8-
ErrIncorrectParameterOwner = errors.New("incorrect parameter \"owner\"")
9-
ErrIncorrectParameterRepo = errors.New("incorrect parameter \"repo\"")
10-
ErrAssetNotFound = errors.New("asset not found")
11-
ErrIncorrectChecksumFile = errors.New("incorrect checksum file format")
12-
ErrChecksumValidationFailed = errors.New("sha256 validation failed")
13-
ErrHashNotFound = errors.New("hash not found in checksum file")
14-
ErrECDSAValidationFailed = errors.New("ECDSA signature verification failed")
15-
ErrInvalidECDSASignature = errors.New("invalid ECDSA signature")
7+
ErrInvalidSlug = errors.New("invalid slug format, expected 'owner/name'")
8+
ErrIncorrectParameterOwner = errors.New("incorrect parameter \"owner\"")
9+
ErrIncorrectParameterRepo = errors.New("incorrect parameter \"repo\"")
10+
ErrAssetNotFound = errors.New("asset not found")
11+
ErrIncorrectChecksumFile = errors.New("incorrect checksum file format")
12+
ErrChecksumValidationFailed = errors.New("sha256 validation failed")
13+
ErrHashNotFound = errors.New("hash not found in checksum file")
14+
ErrECDSAValidationFailed = errors.New("ECDSA signature verification failed")
15+
ErrInvalidECDSASignature = errors.New("invalid ECDSA signature")
16+
ErrCannotDecompressFile = errors.New("failed to decompress")
17+
ErrExecutableNotFoundInArchive = errors.New("executable not found")
18+
ErrCannotReadStream = errors.New("error reading from stream")
1619
)

update_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func TestBrokenBinaryUpdate(t *testing.T) {
229229
if err == nil {
230230
t.Fatal("Error should occur for broken package")
231231
}
232-
if !strings.Contains(err.Error(), "failed to decompress .tar.gz file") {
232+
if !strings.Contains(err.Error(), "failed to decompress tar.gz file") {
233233
t.Fatal("Unexpected error:", err)
234234
}
235235
}

0 commit comments

Comments
 (0)