-
Notifications
You must be signed in to change notification settings - Fork 0
/
replace.go
112 lines (103 loc) · 2.54 KB
/
replace.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
// Gendo replicates common code across Git repos.
// Copyright (C) 2022 Ken Shibata <[email protected]>
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"html/template"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
)
type Config struct {
Mappings []Mapping
}
type Mapping struct {
Slug string
Comment string
Data map[string]string
Source string
SourcePath string
TargetGlob string
}
const startKeyF = "<!-- GENDO START %s -->"
const endKeyF = "<!-- GENDO END %s -->"
type TmplData struct {
Mapping Mapping
Path string
}
func main() {
var root, configRaw string
var config Config
flag.StringVar(&root, "dir", "", "root directory to start replacing")
flag.StringVar(&configRaw, "config", "", "raw config")
flag.Parse()
err := json.Unmarshal([]byte(configRaw), &config)
if err != nil {
log.Printf("config raw:\n%s", configRaw)
log.Fatalf("json: %s", err)
}
for i, mapping := range config.Mappings {
source := []byte(mapping.Source)
if path := mapping.SourcePath; path != "" {
source, err = os.ReadFile(path)
if err != nil {
log.Fatalf("mapping %d: %s", i, err)
}
}
startKey := fmt.Sprintf(startKeyF, mapping.Slug)
endKey := fmt.Sprintf(endKeyF, mapping.Slug)
matches, err := filepath.Glob(filepath.Join(root, mapping.TargetGlob))
if err != nil {
log.Fatalf("mapping %d: %s", i, err)
}
tmpl, err := template.New("").Parse(string(source))
if err != nil {
log.Fatalf("mapping %d: tmpl: %s", i, err)
}
for _, path := range matches {
dest := new(bytes.Buffer)
src, err := ioutil.ReadFile(path)
if err != nil {
log.Fatalf("mapping %d match %s: %s", i, path, err)
}
src2 := src
for {
{
startIndex := bytes.Index(src2, []byte(startKey))
if startIndex == -1 {
dest.Write(src2)
break
}
dest.Write(src2[:startIndex])
src2 = src2[startIndex:]
}
{
endIndex := bytes.Index(src2, []byte(endKey))
if endIndex == -1 {
log.Fatalf("mapping %d match %s: end key not found", i, path)
}
io.WriteString(dest, startKey)
err = tmpl.Execute(dest, TmplData{
Mapping: mapping,
Path: path,
})
if err != nil {
log.Fatalf("mapping %d match %s: tmpl: %s", i, path, err)
}
src2 = src2[endIndex:]
}
}
err = os.WriteFile(path, dest.Bytes(), 0)
if err != nil {
log.Fatalf("mapping %d match %s: %s", i, path, err)
}
}
}
}