-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
143 lines (118 loc) · 3.01 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"bufio"
"encoding/base64"
"errors"
"fmt"
"io"
"io/fs"
"log"
"os"
"strings"
"github.com/goreleaser/fileglob"
)
const extension = ".b64"
func main() {
base := os.DirFS(".")
isDecode := true
if len(os.Args) > 1 && os.Args[1] == "encode" {
isDecode = false
}
if err := b64f(base, isDecode); err != nil {
log.Fatal(err)
}
}
func b64f(base fs.FS, isDecode bool) (err error) {
files, err := listFiles(base, isDecode)
if err != nil {
return err
}
for _, f := range files {
var err error
if isDecode {
err = decodeFile(base, f)
}
if !isDecode && !strings.HasSuffix(f, extension) {
err = encodeFile(base, f)
}
if err != nil {
return err
}
}
return
}
func listFiles(base fs.FS, isDecode bool) (files []string, err error) {
patterns, err := listPatternsFromFile(base)
if err != nil {
log.Printf("[WARN] failed to list from .b64f file with err: %v.\nWill try to read from stdin instead.", err)
patterns, err = listPatternsFromStdin()
}
if err != nil {
return nil, fmt.Errorf("failed to load patterns: %w", err)
}
for _, pattern := range patterns {
if isDecode {
pattern = pattern + extension
}
f, err := fileglob.Glob(pattern, fileglob.WithFs(base))
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("failed to find files based on pattern '%s': %w", pattern, err)
}
files = append(files, f...)
}
return
}
func listPatternsFromFile(base fs.FS) (patterns []string, err error) {
b, err := base.Open(".b64f")
if err != nil {
return nil, err
}
return listPatternsFromReader(b)
}
func listPatternsFromStdin() (patterns []string, err error) {
return listPatternsFromReader(os.Stdin)
}
func listPatternsFromReader(r io.Reader) (patterns []string, err error) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
patterns = append(patterns, scanner.Text())
}
return patterns, scanner.Err()
}
func decodeFile(base fs.FS, f string) (err error) {
r, err := base.Open(f)
if err != nil {
return fmt.Errorf("failed to open file '%s': %w", f, err)
}
defer r.Close()
dec := strings.TrimSuffix(f, extension)
w, err := os.OpenFile(dec, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return fmt.Errorf("failed to open file '%s' for write: %w", f, err)
}
defer w.Close()
rB64 := base64.NewDecoder(base64.StdEncoding, r)
if _, err := io.Copy(w, rB64); err != nil {
return fmt.Errorf("failed to decode file '%s' to '%s': %w", f, dec, err)
}
return
}
func encodeFile(base fs.FS, f string) (err error) {
r, err := base.Open(f)
if err != nil {
return fmt.Errorf("failed to open file '%s': %w", f, err)
}
defer r.Close()
enc := f + extension
w, err := os.OpenFile(enc, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return fmt.Errorf("failed to open file '%s' for write: %w", f, err)
}
defer w.Close()
wB64 := base64.NewEncoder(base64.StdEncoding, w)
defer wB64.Close()
if _, err := io.Copy(wB64, r); err != nil {
return fmt.Errorf("failed to decode file '%s' to '%s': %w", f, enc, err)
}
return
}