1 | 'use strict';
|
2 |
|
3 | var VM = require('vm'),
|
4 | Q = require('q'),
|
5 | QFS = require('q-io/fs'),
|
6 | INHERIT = require('inherit'),
|
7 | APW = require('apw'),
|
8 | PATH = require('./path'),
|
9 | UTIL = require('util'),
|
10 | BEMUTIL = require('./util'),
|
11 | REGISTRY = require('./nodesregistry'),
|
12 | LOGGER = require('./logger'),
|
13 | reqf = require('reqf');
|
14 |
|
15 | exports.DEFAULT_WORKERS = 10;
|
16 |
|
17 | exports.APW = INHERIT(APW, {
|
18 |
|
19 | findAndProcess: function(targets) {
|
20 | if (!Array.isArray(targets)) targets = [targets];
|
21 |
|
22 |
|
23 |
|
24 | var re = new RegExp(PATH.dirSep + '$');
|
25 | targets = targets.map(function(t) {
|
26 | return t.replace(re, '');
|
27 | });
|
28 |
|
29 | var _this = this,
|
30 | foundNodes = targets.map(function(t) {
|
31 | return _this.findNode(t);
|
32 | });
|
33 | return Q.all(foundNodes)
|
34 | .fail(function(err) {
|
35 | if (typeof err === 'string') return;
|
36 | return Q.reject(err);
|
37 | })
|
38 | .then(function() {
|
39 | return _this.process(targets);
|
40 | });
|
41 | },
|
42 |
|
43 |
|
44 | findNode: function(id, head, tail) {
|
45 | head = head || '';
|
46 | tail = tail || id;
|
47 |
|
48 | if (this.arch.hasNode(id)) return Q.resolve(id);
|
49 | if (head === id) return Q.reject(UTIL.format('Node "%s" not found', id));
|
50 |
|
51 | var parts = tail.split(PATH.dirSep),
|
52 | p = parts.shift();
|
53 | head = (head? [head, p] : [p]).join(PATH.dirSep);
|
54 | tail = parts.join(PATH.dirSep);
|
55 |
|
56 | var _this = this,
|
57 | magicHead = head + '*';
|
58 | if (!this.arch.hasNode(magicHead)) {
|
59 | return this.findNode(id, head, tail);
|
60 | }
|
61 |
|
62 | return this.process(magicHead).then(function() {
|
63 | return _this.findNode(id, head, tail);
|
64 | });
|
65 | }
|
66 |
|
67 | }, {
|
68 |
|
69 | Workers: INHERIT(APW.Workers, {
|
70 |
|
71 | start: function(plan) {
|
72 |
|
73 | LOGGER.finfo("[i] Going to build '%s' [%s]", plan.getTargets().join("', '"), plan.getId());
|
74 |
|
75 | return this.__base(plan);
|
76 | }
|
77 |
|
78 | })
|
79 |
|
80 | });
|
81 |
|
82 | exports.createArch = function(opts) {
|
83 |
|
84 | var arch = new APW.Arch(),
|
85 | DefaultArch = require('./default-arch'),
|
86 | rootMakefile = PATH.join(opts.root, '.bem', 'make.js');
|
87 |
|
88 | return QFS.exists(rootMakefile)
|
89 | .then(function(exists) {
|
90 |
|
91 |
|
92 | LOGGER.fsilly("File '%s' %s", rootMakefile, exists? 'exists' : "doesn't exist");
|
93 |
|
94 | if (exists) return include(rootMakefile);
|
95 |
|
96 | })
|
97 | .then(function() {
|
98 | return new (DefaultArch.Arch)(arch, opts).alterArch();
|
99 | });
|
100 |
|
101 | };
|
102 |
|
103 | function getPathResolver(base) {
|
104 |
|
105 | return function(path) {
|
106 | return path.match(/^\./)? PATH.resolve(PATH.dirname(base), path) : path;
|
107 | };
|
108 |
|
109 | }
|
110 |
|
111 | function getIncludeFunc(resolvePath) {
|
112 |
|
113 | return function(path) {
|
114 | return include(resolvePath(path));
|
115 | };
|
116 |
|
117 | }
|
118 |
|
119 | function include(path) {
|
120 | return evalConfig(require('fs').readFileSync(path, 'utf8'), path);
|
121 | }
|
122 |
|
123 | function evalConfig(content, path) {
|
124 |
|
125 |
|
126 | LOGGER.fsilly("File '%s' read, evaling", path);
|
127 |
|
128 | var resolvePath = getPathResolver(path);
|
129 |
|
130 | VM.runInNewContext(
|
131 | content,
|
132 | BEMUTIL.extend({}, global, {
|
133 | MAKE: REGISTRY,
|
134 | module: null,
|
135 | __filename: path,
|
136 | __dirname: PATH.dirname(path),
|
137 | require: reqf(path, module),
|
138 | include: getIncludeFunc(resolvePath)
|
139 | }),
|
140 | path);
|
141 |
|
142 | LOGGER.fsilly("File '%s' evaled", path);
|
143 |
|
144 |
|
145 | }
|