Skip to content

Commit 0071b25

Browse files
committed
Use embedded zip to add Hugo submodule
Note: - golang/go#45197
1 parent bc17839 commit 0071b25

File tree

9 files changed

+104
-9
lines changed

9 files changed

+104
-9
lines changed

devenv/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
dist/
2+
publish.zip

devenv/.goreleaser.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ before:
1515
# You may remove this if you don't use go modules.
1616
- go mod tidy
1717
# you may remove this if you don't need go generate
18-
# - go generate ./...
18+
- go generate ./...
1919

2020
builds:
2121
- env:

devenv/Taskfile.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ tasks:
2222
- goreleaser build --clean --snapshot --single-target
2323

2424
run:
25+
- go generate ./...
2526
- go run main.go {{.CLI_ARGS}}
2627

2728
stdlib:

devenv/cmd/doctor.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ If everything is working fine: please don't worry or
2121
file an issue; just ignore this.`,
2222
RunE: func(cmd *cobra.Command, args []string) error {
2323
cacheDir := viper.GetString("cache-dir")
24-
args = append([]string{"--taskfile", path.Join(cacheDir, "stdlib", "Taskfile.yaml"), "global:doctor"}, args...)
24+
taskfile := path.Join(cacheDir, "embed", "stdlib", "Taskfile.yaml")
25+
args = append([]string{"--taskfile", taskfile, "global:doctor"}, args...)
2526
log.Debug("doctor called:", args)
2627
return task.Run(args...)
2728
},

devenv/cmd/init.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@ var initCmd = &cobra.Command{
1919
dir := viper.GetString("cache-dir")
2020
log.Debug("cache-dir:", dir)
2121

22+
// Extract stdlib
2223
stdlib := internal.NewStdlib(StdlibFS)
2324
err := stdlib.Write(dir)
2425
cobra.CheckErr(err)
25-
log.Debug("stdlib written")
26+
log.Debug("stdlib extracted")
2627

27-
// Prompt to check tools installed
28+
// Uncompress submodules
29+
err = internal.Unzip(path.Join(dir, "embed", "stdlib", "global", "publish.zip"), path.Join(dir))
30+
cobra.CheckErr(err)
31+
log.Debug("publish expanded")
32+
33+
// Run additional init tasks
2834
cacheDir := viper.GetString("cache-dir")
29-
args = append([]string{"--taskfile", path.Join(cacheDir, "stdlib", "Taskfile.yaml"), "global:init"}, args...)
35+
taskfile := path.Join(cacheDir, "embed", "stdlib", "Taskfile.yaml")
36+
args = append([]string{"--taskfile", taskfile, "global:init"}, args...)
3037
log.Debug("init called:", args)
3138
return task.Run(args...)
3239
},

devenv/cmd/run.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ var runCmd = &cobra.Command{
2424
// Use global tasks from stdlib
2525
global := viper.GetBool("global")
2626
cacheDir := viper.GetString("cache-dir")
27+
taskfile := path.Join(cacheDir, "embed", "stdlib", "Taskfile.yaml")
2728
if global {
28-
args = append([]string{"--taskfile", path.Join(cacheDir, "stdlib", "Taskfile.yaml")}, args...)
29+
args = append([]string{"--taskfile", taskfile}, args...)
2930
}
3031

3132
log.Debug("run called:", args)

devenv/internal/stdlib.go

-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"os"
99
"path"
1010
"path/filepath"
11-
"strings"
1211

1312
"github.com/metafeather/tools/devenv/internal/log"
1413
)
@@ -58,8 +57,6 @@ func (sl *Stdlib) Write(p string) error {
5857
if err != nil {
5958
return err
6059
}
61-
// embed/ is the prefix for embedded files, so we need to remove it
62-
file = strings.TrimPrefix(file, "embed/")
6360
fullpath := path.Join(p, file)
6461
err = os.MkdirAll(filepath.Dir(fullpath), 0700)
6562
if err != nil {

devenv/internal/unzip.go

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package internal
2+
3+
import (
4+
"archive/zip"
5+
"fmt"
6+
"io"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
)
11+
12+
func Unzip(src, dest string) error {
13+
dest = filepath.Clean(dest) + string(os.PathSeparator)
14+
15+
r, err := zip.OpenReader(src)
16+
if err != nil {
17+
return err
18+
}
19+
defer func() {
20+
if err := r.Close(); err != nil {
21+
panic(err)
22+
}
23+
}()
24+
25+
err = os.MkdirAll(dest, 0755)
26+
if err != nil {
27+
return err
28+
}
29+
30+
// Closure to address file descriptors issue with all the deferred .Close() methods
31+
extractAndWriteFile := func(f *zip.File) error {
32+
path := filepath.Join(dest, f.Name)
33+
// Check for ZipSlip: https://snyk.io/research/zip-slip-vulnerability
34+
if !strings.HasPrefix(path, dest) {
35+
return fmt.Errorf("%s: illegal file path", path)
36+
}
37+
38+
rc, err := f.Open()
39+
if err != nil {
40+
return err
41+
}
42+
defer func() {
43+
if err := rc.Close(); err != nil {
44+
panic(err)
45+
}
46+
}()
47+
48+
if f.FileInfo().IsDir() {
49+
err := os.MkdirAll(path, f.Mode())
50+
if err != nil {
51+
return err
52+
}
53+
} else {
54+
err := os.MkdirAll(filepath.Dir(path), f.Mode())
55+
if err != nil {
56+
return err
57+
}
58+
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
59+
if err != nil {
60+
return err
61+
}
62+
defer func() {
63+
if err := f.Close(); err != nil {
64+
panic(err)
65+
}
66+
}()
67+
68+
_, err = io.Copy(f, rc)
69+
if err != nil {
70+
return err
71+
}
72+
}
73+
return nil
74+
}
75+
76+
for _, f := range r.File {
77+
err := extractAndWriteFile(f)
78+
if err != nil {
79+
return err
80+
}
81+
}
82+
83+
return nil
84+
}

devenv/main.go

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import (
2323
"github.com/metafeather/tools/devenv/cmd"
2424
)
2525

26+
// Submodules cannot be embedded directly so zip them up
27+
//
28+
//go:generate zip -r embed/stdlib/global/publish.zip embed/stdlib/global/publish
2629
//go:embed all:embed/stdlib
2730
var stdlib embed.FS
2831

0 commit comments

Comments
 (0)