config/config.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
package config import ( "bufio" "fmt" "io" "os" "strings" ) // Block is a list of directives. type Block []*Binary type Fetch struct { Url string Every string } // Binary is a configuration directive. type Binary struct { Name string Fetch Fetch Build string Args []string } // Load loads a configuration file. func Load(path string) (Block, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() return Read(f) } // Read parses a configuration file from an io.Reader. func Read(r io.Reader) (Block, error) { scanner := bufio.NewScanner(r) block, closingBrace, err := readBlock(scanner) if err != nil { return nil, err } else if closingBrace { return nil, fmt.Errorf("unexpected '}'") } return block, scanner.Err() } // readBlock reads a block. closingBrace is true if parsing stopped on '}' // (otherwise, it stopped on Scanner.Scan). func readBlock(scanner *bufio.Scanner) (block Block, closingBrace bool, err error) { for scanner.Scan() { l := scanner.Text() words := strings.Split(l, " ") if err != nil { return nil, false, fmt.Errorf("failed to parse configuration file: %v", err) } if len(words) == 0 { continue } if len(words) == 1 && l == "" { continue } if len(words) == 1 && l[len(l)-1] == '}' { closingBrace = true break } if words[0] == "#" { continue } var fetch Fetch if strings.Contains(words[0], "fetch") { fmt.Println("fetchin") fetch.Url = words[1] fetch.Every = words[3] } var d *Binary if words[len(words)-1] == "{" && l[len(l)-1] == '{' { name := words[0] childBlock, childClosingBrace, err := readBlock(scanner) if err != nil { return nil, false, err } else if !childClosingBrace { return nil, false, io.ErrUnexpectedEOF } // Allows callers to tell apart "no block" and "empty block" if childBlock == nil { childBlock = Block{} } d = &Binary{Name: name} } else { d = &Binary{Name: words[0], Fetch: fetch} fmt.Printf("d: %v\n", d) } block = append(block, d) fmt.Printf("block: %v\n", block) } return block, closingBrace, nil }