-
Notifications
You must be signed in to change notification settings - Fork 16
/
patch_support.go
70 lines (59 loc) · 1.61 KB
/
patch_support.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
package main
import (
"fmt"
"github.com/xhd2015/xgo/support/goinfo"
)
type FilePatch struct {
FilePath _FilePath
Patches []*Patch
}
type Patch struct {
Mark string
InsertIndex int // insert before which anchor, 0: insert at head, -1: tail
InsertBefore bool
// anchor should be unique
// appears exactly once
Anchors []string
Content string
CheckGoVersion func(goVersion *goinfo.GoVersion) bool
}
func (c *FilePatch) Apply(goroot string, goVersion *goinfo.GoVersion) error {
if goroot == "" {
return fmt.Errorf("requires goroot")
}
if len(c.FilePath) == 0 {
return fmt.Errorf("invalid file path")
}
if len(c.Patches) == 0 {
return nil
}
file := c.FilePath.Join(goroot)
// validate patch mark
seenMark := make(map[string]bool, len(c.Patches))
for i, patch := range c.Patches {
if patch.Content == "" {
return fmt.Errorf("empty content at: %d", i)
}
if patch.Mark == "" {
return fmt.Errorf("empty mark at %d", i)
}
if len(patch.Anchors) == 0 {
return fmt.Errorf("empty anchors at: %d", i)
}
if _, ok := seenMark[patch.Mark]; ok {
return fmt.Errorf("duplicate mark: %s", patch.Mark)
}
seenMark[patch.Mark] = true
}
return editFile(file, func(content string) (string, error) {
for _, patch := range c.Patches {
if patch.CheckGoVersion != nil && !patch.CheckGoVersion(goVersion) {
continue
}
beginMark := fmt.Sprintf("/*<begin %s>*/", patch.Mark)
endMark := fmt.Sprintf("/*<end %s>*/", patch.Mark)
content = addContentAtIndex(content, beginMark, endMark, patch.Anchors, patch.InsertIndex, patch.InsertBefore, patch.Content)
}
return content, nil
})
}