-
Notifications
You must be signed in to change notification settings - Fork 7
/
client.go
120 lines (100 loc) · 3.36 KB
/
client.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
package compilers
import (
"io/ioutil"
"path"
"github.com/eris-ltd/eris-compilers/Godeps/_workspace/src/github.com/eris-ltd/common/go/common"
)
// ClientCache location in eris tree
var ClientCache = path.Join(common.LllcScratchPath, "client")
// filename is either a filename or literal code
func resolveCode(filename string, literal bool) (code []byte, err error) {
if !literal {
code, err = ioutil.ReadFile(filename)
} else {
code = []byte(filename)
}
logger.Debugf("Code that is read =>\t%s\n", code)
return
}
// send compile request to server or compile directly
func (c *CompileClient) compileRequest(req *Request) (resp *Response, err error) {
if c.config.Net {
logger.Infof("Compiling code remotely =>\t%s\n", c.config.URL)
resp, err = requestResponse(req)
} else {
logger.Infoln("Compiling code locally.")
resp = compileServerCore(req)
}
return
}
// Compile takes a dir and some code, replaces all includes, checks cache, compiles, caches
func (c *CompileClient) Compile(dir string, code []byte, libraries string) (*Response, error) {
// replace includes with hash of included contents and add those contents to Includes (recursive)
var includes = make(map[string][]byte) // hashes to code
var includeNames = make(map[string]string) //hashes before replace to hashes after
var err error
// logger.Debugf("Before parsing includes =>\n\n%s", string(code))
code, err = c.replaceIncludes(code, dir, includes, includeNames)
if err != nil {
return nil, err
}
// logger.Debugf("After parsing includes =>\t\t%s\n\n%s", includes, string(code))
// go through all includes, check if they have changed
hash, cached := c.checkCached(code, includes)
logger.Debugf("Files [Hash, Cached?] =>\t%s:%v\n", hash, cached)
// if everything is cached, no need for request
if cached {
// TODO: need to return all contracts/libs tied to the original src file
return c.cachedResponse(hash)
}
req := NewRequest(code, includes, c.Lang(), libraries)
// response struct (returned)
resp, err := c.compileRequest(req)
if err != nil {
return nil, err
}
if resp.Error == "" {
for _, r := range resp.Objects {
// fill in cached values, cache new values
if r.Bytecode != nil {
if err := c.cacheFile(r.Bytecode, hash, r.Objectname, "bin"); err != nil {
return nil, err
}
if err := c.cacheFile([]byte(r.ABI), hash, r.Objectname, "abi"); err != nil {
return nil, err
}
}
}
}
return resp, nil
}
// create a new compiler for the language and compile the code
func compile(filename string, code []byte, lang, dir string, libraries string) *Response {
c, err := NewCompileClient(lang)
if err != nil {
return NewResponse("", nil, "", err)
}
r, err := c.Compile(dir, code, libraries)
if err != nil {
return NewResponse("", nil, "", err)
}
return r
}
// Compile a file and resolve includes
func Compile(filename string, libraries string) *Response {
lang, err := LangFromFile(filename)
if err != nil {
return NewResponse("", nil, "", err)
}
logger.Infof("Language to use =>\t\t%s\n", lang)
code, err := ioutil.ReadFile(filename)
if err != nil {
return NewResponse("", nil, "", err)
}
dir := path.Dir(filename)
return compile(filename, code, lang, dir, libraries)
}
// Compile a literal piece of code
func CompileLiteral(code string, lang string) *Response {
return compile("Literal", []byte(code), lang, common.LllcScratchPath, "")
}