1 | _ = require 'underscore'
|
2 | fs = require 'fs-extra'
|
3 | os = require 'os'
|
4 | path = require 'path'
|
5 | shell = require "shelljs"
|
6 | helpers = require '../modules/common/helpers'
|
7 | Processes = require '../lib/processes'
|
8 | EventEmitter = require("events").EventEmitter
|
9 | {spawn} = require 'child_process'
|
10 | {findFile, guard} = require '../modules/common/helpers'
|
11 | urlp = require 'url'
|
12 |
|
13 |
|
14 | url =
|
15 | isAbsolutePath: (s)->
|
16 | s.indexOf '/' > 0
|
17 |
|
18 | isRelativePath: (s)->
|
19 | s.indexOf('./') > 0 or s.indexOf('../') > 0
|
20 |
|
21 | isGitRepo: (s)->
|
22 | s.indexOf('git@') >=0 and s.indexOf('.git') > 0
|
23 |
|
24 | isZipUrl: (s)->
|
25 | s.indexOf('http://') >=0 or s.indexOf('https://')>0
|
26 |
|
27 | class Installer
|
28 | constructor:(@from, @basedir)->
|
29 |
|
30 | getKite:(callback)=>
|
31 | if fs.existsSync @to and fs.existsSync path.join(@to, 'manifest.json')
|
32 | callback new KDKite(@to)
|
33 | else
|
34 | @install(callback)
|
35 |
|
36 | class ZipInstaller extends Installer
|
37 | install: (callback)->
|
38 | pass
|
39 |
|
40 | @test: (src)->
|
41 | url.isZipUrl(src)
|
42 |
|
43 | class GitInstaller extends Installer
|
44 |
|
45 | constructor:(@from, @basedir)->
|
46 | @kiteDir = @getRepoNameFromUrl(@from)
|
47 | @to = path.normalize(path.join(@basedir, 'kites', @kiteDir))
|
48 |
|
49 | getRepoNameFromUrl: (s) ->
|
50 | /\/(.*)\.git$/.exec(s)[1].split('.kite')[0]
|
51 |
|
52 | install:(callback)->
|
53 | guard (not shell.which "git"), "You need git to install dependencies."
|
54 | repoUrl = urlp.parse @from
|
55 | unless repoUrl.hostname
|
56 | console.log "Installing: ", @to
|
57 | shell.mkdir "-p", @to
|
58 | shell.exec "git clone --recursive -q #{@from} #{@to}", (err, res)->
|
59 | console.log "#{@to} installed."
|
60 | callback()
|
61 |
|
62 | @test: (src)->
|
63 | url.isGitRepo(src)
|
64 |
|
65 |
|
66 | class FileSystemInstaller extends Installer
|
67 |
|
68 | constructor:(@from, @basedir)->
|
69 | @to = path.normalize(path.join(@basedir, 'kites', path.basename(@from)))
|
70 |
|
71 | install:(callback)=>
|
72 |
|
73 | fs.mkdirs @to, (err)=>
|
74 | guard err, "directory create failure", err
|
75 | fs.copy @from, @to, (err)=>
|
76 | if err
|
77 | console.log "Error:", err
|
78 | callback(err)
|
79 | kite = new KDKite(@to)
|
80 | callback(false, kite)
|
81 |
|
82 | @test: (src)->
|
83 | url.isAbsolutePath(src)
|
84 |
|
85 | getInstallerClass = (url)->
|
86 | installers = [ZipInstaller, GitInstaller, FileSystemInstaller]
|
87 | for i in installers
|
88 | try
|
89 | if i.test(url)
|
90 | return i
|
91 | catch E
|
92 | console.log E
|
93 |
|
94 |
|
95 | module.exports = class KDKite extends EventEmitter
|
96 |
|
97 | constructor: (dir)->
|
98 | @dir = dir
|
99 | @dependencies = []
|
100 |
|
101 | cloneFrom: (skel, callback)->
|
102 | env =
|
103 | name: @name,
|
104 | username: @username
|
105 | mail: @mail
|
106 | version: @version
|
107 |
|
108 | helpers.createSkeleton
|
109 | skel: skel
|
110 | toPath: @dir
|
111 | env: env
|
112 | callback: (err)=>
|
113 | console.log "err: ", err
|
114 | callback(err)
|
115 |
|
116 | prepare: (callback)=>
|
117 | @manifest = @getManifest =>
|
118 | @findDependencies (err, deps)=>
|
119 | guard err, "Error when installing dependency"
|
120 | @emit "ready"
|
121 | if callback
|
122 | callback(false, @)
|
123 |
|
124 | removeDependency: (depPath, callback)->
|
125 | getManifest =>
|
126 | @manifest.dependencies = _.reject @manifest.dependencies, (el)-> el == depPath
|
127 | @saveManifest callback
|
128 |
|
129 | addDependency: (p, callback)->
|
130 | @getManifest =>
|
131 | if p not in @manifest.dependencies
|
132 | @manifest.dependencies.push p
|
133 | @saveManifest callback
|
134 | else
|
135 | callback()
|
136 |
|
137 | saveManifest: (callback)->
|
138 | data = JSON.stringify @manifest, null, "\t"
|
139 | fs.writeFile @manifestPath.fullpath, data, (err)=>
|
140 | guard err, "Couldn't save manifest file", err
|
141 | callback(err)
|
142 |
|
143 | getManifest: (callback)->
|
144 | @manifestPath = findFile @dir, ['.manifest', 'manifest.json']
|
145 | guard not @manifestPath, "Couldn't find your manifest file - #{@dir}"
|
146 |
|
147 | fs.readFile @manifestPath.fullpath, 'utf-8', (err, content)=>
|
148 | guard err, "Couldnt read your manifest file, io error", err
|
149 | try
|
150 | @manifest = JSON.parse content
|
151 | catch E
|
152 | console.log "Error in your manifest file"
|
153 | throw E
|
154 | @name = @manifest.name
|
155 | @version = @manifest.version
|
156 | @username = @manifest.username
|
157 | @mail = @manifest.mail
|
158 | callback()
|
159 |
|
160 | findDependencies: (callback) ->
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 | if @manifest.dependencies?.length > 0
|
167 | cb = 0
|
168 | for source in @manifest.dependencies
|
169 | klass = getInstallerClass(source)
|
170 | installer = new klass(source, @dir)
|
171 | try
|
172 | cb++
|
173 | installer.getKite (err, kite)=>
|
174 | kite.prepare (err, kite)=>
|
175 | @dependencies.push kite
|
176 | cb--
|
177 | catch e
|
178 | console.log "error", e
|
179 | interval = setInterval =>
|
180 | if cb is 0
|
181 | callback(false, @dependencies)
|
182 | clearInterval interval
|
183 | , 0
|
184 | else
|
185 | callback(false,[])
|
186 |
|
187 | listDependencies:(depth=0)->
|
188 | @getManifest =>
|
189 |
|
190 | pad = ""
|
191 | for i in [0..(depth*2)]
|
192 | pad += " "
|
193 |
|
194 | if @manifest.dependencies?.length > 0
|
195 | for dep in @manifest.dependencies
|
196 | console.log "#{pad}", dep
|
197 | toPath = @getRealPathFromDependency(dep)
|
198 | depKite = new KDKite(toPath)
|
199 | depKite.listDependencies(depth+1)
|
200 |
|
201 |
|
202 | npm: (callback)->
|
203 | curDir = process.cwd()
|
204 | process.chdir(@dir)
|
205 | install = spawn "npm", ["install"]
|
206 | install.stdout.on "data", (data)-> process.stdout.write data
|
207 | install.stderr.on "data", (data)-> process.stdout.write data
|
208 | install.on "close", ->
|
209 | process.stdout.write os.EOL
|
210 | process.chdir(curDir)
|
211 | callback()
|
212 |
|
213 | spawn: (executable, entryPoint, args)=>
|
214 | args = [entryPoint].concat args
|
215 | @processes.spawn {cmd:executable, args, verbose:true, name:path.basename(@dir)}, (err, child)->
|
216 | guard err, "Couldn't run kite #{err}"
|
217 | console.log "now running the kite", entryPoint
|
218 |
|
219 | run:(options)=>
|
220 |
|
221 | tryFiles = (paths)->
|
222 | for p in paths
|
223 | if fs.existsSync p
|
224 | return p
|
225 |
|
226 |
|
227 | coffeePath = tryFiles ["/usr/bin/coffee","/usr/local/bin/coffee"]
|
228 | console.log "coffeePath", coffeePath
|
229 | nodeJsPath = tryFiles ["/usr/bin/nodejs", "/usr/local/bin/nodejs"]
|
230 |
|
231 | @npm =>
|
232 |
|
233 | executablesMap = {'index.coffee': coffeePath, 'index.js': nodeJsPath}
|
234 | entryPoint = findFile(@dir, executablesMap)
|
235 | guard not entryPoint, "Can't find your index.coffee or index.js file"
|
236 | executable = executablesMap[entryPoint.key]
|
237 | guard not executable, "cant find executable for " + JSON.stringify(executablesMap)
|
238 |
|
239 | for dep in @dependencies
|
240 | dep.processes = @processes
|
241 | dep.prepare (err, obj)->
|
242 | console.log "!!!!! prepared", obj.dir
|
243 | obj.run()
|
244 | @spawn executable, entryPoint.fullpath, ['--messagebusport', options.messageBusPort]
|