Skip to content

Commit b01831b

Browse files
authored
(goctl)fix file copy permission missed (#5475)
1 parent d1a0149 commit b01831b

File tree

2 files changed

+128
-1
lines changed

2 files changed

+128
-1
lines changed

tools/goctl/util/zipx/zipx.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ func fileCopy(file *zip.File, destPath string) error {
6464
return err
6565
}
6666
defer w.Close()
67+
6768
_, err = io.Copy(w, rc)
68-
return err
69+
if err != nil {
70+
return err
71+
}
72+
73+
if file.Mode().IsRegular() && file.Mode()&0111 != 0 {
74+
return w.Chmod(file.Mode())
75+
}
76+
77+
return nil
6978
}

tools/goctl/util/zipx/zipx_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package zipx
2+
3+
import (
4+
"archive/zip"
5+
"os"
6+
"path/filepath"
7+
"runtime"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func createTestZip(t *testing.T, files map[string]struct {
15+
content string
16+
mode os.FileMode
17+
}) string {
18+
t.Helper()
19+
20+
zipPath := filepath.Join(t.TempDir(), "test.zip")
21+
f, err := os.Create(zipPath)
22+
require.NoError(t, err)
23+
defer f.Close()
24+
25+
w := zip.NewWriter(f)
26+
defer w.Close()
27+
28+
for name, file := range files {
29+
header := &zip.FileHeader{
30+
Name: name,
31+
Method: zip.Deflate,
32+
}
33+
header.SetMode(file.mode)
34+
writer, err := w.CreateHeader(header)
35+
require.NoError(t, err)
36+
_, err = writer.Write([]byte(file.content))
37+
require.NoError(t, err)
38+
}
39+
40+
return zipPath
41+
}
42+
43+
func TestUnpacking(t *testing.T) {
44+
dest := t.TempDir()
45+
zipPath := createTestZip(t, map[string]struct {
46+
content string
47+
mode os.FileMode
48+
}{
49+
"hello.txt": {content: "hello world", mode: 0644},
50+
"skip.txt": {content: "should be skipped", mode: 0644},
51+
})
52+
53+
err := Unpacking(zipPath, dest, func(f *zip.File) bool {
54+
return f.Name == "hello.txt"
55+
})
56+
require.NoError(t, err)
57+
58+
content, err := os.ReadFile(filepath.Join(dest, "hello.txt"))
59+
assert.NoError(t, err)
60+
assert.Equal(t, "hello world", string(content))
61+
62+
_, err = os.Stat(filepath.Join(dest, "skip.txt"))
63+
assert.True(t, os.IsNotExist(err))
64+
}
65+
66+
func TestUnpackingPreservesExecutablePermission(t *testing.T) {
67+
if runtime.GOOS == "windows" {
68+
t.Skip("file permissions not applicable on Windows")
69+
}
70+
71+
dest := t.TempDir()
72+
zipPath := createTestZip(t, map[string]struct {
73+
content string
74+
mode os.FileMode
75+
}{
76+
"bin/mybinary": {content: "binary content", mode: 0755},
77+
"readme.txt": {content: "readme", mode: 0644},
78+
})
79+
80+
err := Unpacking(zipPath, dest, func(f *zip.File) bool {
81+
return true
82+
})
83+
require.NoError(t, err)
84+
85+
info, err := os.Stat(filepath.Join(dest, "mybinary"))
86+
require.NoError(t, err)
87+
assert.NotZero(t, info.Mode()&0111, "executable bit should be set")
88+
89+
info, err = os.Stat(filepath.Join(dest, "readme.txt"))
90+
require.NoError(t, err)
91+
assert.Zero(t, info.Mode()&0111, "executable bit should not be set for regular files")
92+
}
93+
94+
func TestUnpackingInvalidZip(t *testing.T) {
95+
err := Unpacking("/nonexistent/path.zip", t.TempDir(), func(f *zip.File) bool {
96+
return true
97+
})
98+
assert.Error(t, err)
99+
}
100+
101+
func TestUnpackingAllFilesFiltered(t *testing.T) {
102+
dest := t.TempDir()
103+
zipPath := createTestZip(t, map[string]struct {
104+
content string
105+
mode os.FileMode
106+
}{
107+
"a.txt": {content: "a", mode: 0644},
108+
})
109+
110+
err := Unpacking(zipPath, dest, func(f *zip.File) bool {
111+
return false
112+
})
113+
require.NoError(t, err)
114+
115+
entries, err := os.ReadDir(dest)
116+
assert.NoError(t, err)
117+
assert.Empty(t, entries)
118+
}

0 commit comments

Comments
 (0)