task/1.9
1//go:build ignore
2
3// Command tools/vendor/unpack.go extracts `vendor.tar.gz` into the current
4// project `vendor` directory. Intended for use as a build support tool.
5package main
6
7import (
8 "archive/tar"
9 "compress/gzip"
10 "errors"
11 "io"
12 "log/slog"
13 "os"
14 "path/filepath"
15 "runtime"
16)
17
18// vendor.tar.gz unpack
19func main() {
20 const (
21 archiveName = "vendor.tar.gz"
22 vendorDir = "vendor"
23 vendorDirMode = 0o755
24 )
25
26 // discover this file's location
27 _, callerFilepath, _, callerFound := runtime.Caller(0)
28 if !callerFound {
29 slog.Error("failed to find caller location")
30 return
31 }
32 archivePath := filepath.Join(filepath.Dir(callerFilepath), archiveName)
33
34 archiveFile, err := os.Open(archivePath)
35 if err != nil {
36 slog.Error("failed to open vendor tarball",
37 slog.String("err", err.Error()),
38 slog.String("path", archivePath))
39 return
40 }
41 defer func() { _ = archiveFile.Close() }()
42
43 gzr, err := gzip.NewReader(archiveFile)
44 if err != nil {
45 slog.Error("failed to open gzip reader",
46 slog.String("err", err.Error()),
47 slog.String("path", archivePath))
48 return
49 }
50 defer func() { _ = gzr.Close() }()
51
52 tr := tar.NewReader(gzr)
53 for {
54 header, err := tr.Next()
55 if err != nil {
56 if errors.Is(err, io.EOF) {
57 break
58 }
59 slog.Error("failed to read next tar entry",
60 slog.String("err", err.Error()))
61 }
62 info := header.FileInfo()
63
64 if !info.IsDir() {
65 target := filepath.Join(vendorDir, header.Name)
66 dir := filepath.Dir(target)
67
68 err = os.MkdirAll(dir, vendorDirMode)
69 if err != nil {
70 slog.Error("failed to create vendor dir",
71 slog.String("err", err.Error()),
72 slog.String("dir", dir))
73 return
74 }
75
76 vendorFile, err := os.OpenFile(
77 target,
78 os.O_CREATE|os.O_WRONLY|os.O_TRUNC,
79 info.Mode())
80 if err != nil {
81 slog.Error("failed to open vendor file",
82 slog.String("err", err.Error()),
83 slog.String("path", target))
84 _ = vendorFile.Close()
85 return
86 }
87
88 _, err = io.Copy(vendorFile, tr)
89 if err != nil {
90 slog.Error("failed to copy vendor file from tar",
91 slog.String("err", err.Error()),
92 slog.String("path", target))
93 _ = vendorFile.Close()
94 return
95 }
96
97 err = vendorFile.Close()
98 if err != nil {
99 slog.Error("failed to close vendor file",
100 slog.String("err", err.Error()),
101 slog.String("path", target))
102 return
103 }
104 }
105 }
106}