1 |
|
2 |
|
3 |
|
4 |
|
5 | var component = require('component')
|
6 | , fs = require('fs')
|
7 | , exists = fs.existsSync
|
8 | , utils = component.utils
|
9 | , log = utils.log
|
10 | , error = utils.error
|
11 | , url = require('url')
|
12 | , path = require('path')
|
13 | , resolve = path.resolve
|
14 | , async = require('async');
|
15 |
|
16 |
|
17 |
|
18 | module.exports = function (config, opts, callback){
|
19 |
|
20 |
|
21 |
|
22 | var pkgs = opts.args;
|
23 |
|
24 |
|
25 |
|
26 | var local = 0 == pkgs.length;
|
27 |
|
28 |
|
29 |
|
30 | if (local && !config) utils.fatal('missing config');
|
31 |
|
32 |
|
33 |
|
34 | var conf = config;
|
35 |
|
36 |
|
37 |
|
38 | if (local) {
|
39 | if (conf.dependencies) {
|
40 | pkgs = normalize(conf.dependencies);
|
41 | }
|
42 |
|
43 | if (conf.development && opts.dev) {
|
44 | pkgs = pkgs.concat(normalize(conf.development));
|
45 | }
|
46 |
|
47 | if (conf.local) {
|
48 | conf.local.forEach(function(pkg){
|
49 | try {
|
50 | var deps = component.dependenciesOf(pkg, conf.paths);
|
51 | deps.map(normalize).forEach(function(deps){
|
52 | pkgs = pkgs.concat(deps);
|
53 | });
|
54 | } catch (err) {
|
55 | utils.fatal(err.message);
|
56 | }
|
57 | });
|
58 | }
|
59 | }
|
60 |
|
61 |
|
62 | var deps = null;
|
63 |
|
64 | if (!local) {
|
65 | deps = conf.dependencies;
|
66 | var key = opts.dev ? 'development' : 'dependencies';
|
67 |
|
68 | conf[key] = conf[key] || {};
|
69 | pkgs.forEach(function(pkg){
|
70 | pkg = parsePackage(pkg);
|
71 | conf[key][pkg.name] = pkg.version || '*';
|
72 | deps[pkg.name] = pkg.version || '*';
|
73 | });
|
74 |
|
75 | if (exists('component.json')) saveConfig();
|
76 | }
|
77 |
|
78 |
|
79 |
|
80 | conf.remotes = conf.remotes || [];
|
81 |
|
82 |
|
83 |
|
84 | if (opts.remotes) {
|
85 | conf.remotes = opts.remotes.split(',').concat(conf.remotes);
|
86 | }
|
87 |
|
88 |
|
89 |
|
90 | conf.remotes.push('https://raw.github.com');
|
91 |
|
92 |
|
93 |
|
94 | async.each(pkgs, function(pkg, callback){
|
95 | pkg = parsePackage(pkg);
|
96 | install(pkg.name, pkg.version || 'master', callback);
|
97 | }, installDone);
|
98 |
|
99 | function installDone(err){
|
100 | if(err) return console.log(err);
|
101 | log('install',"DONE");
|
102 | callback(null, deps);
|
103 | }
|
104 |
|
105 |
|
106 |
|
107 | function parsePackage(pkg) {
|
108 | var parts = pkg.split('@');
|
109 | return {
|
110 | name: parts.shift(),
|
111 | version: parts.shift()
|
112 | };
|
113 | }
|
114 |
|
115 |
|
116 |
|
117 | function normalize(deps) {
|
118 | return Object.keys(deps).map(function(name){
|
119 | return name + '@' + deps[name];
|
120 | });
|
121 | }
|
122 |
|
123 |
|
124 |
|
125 | function report(pkg, options) {
|
126 | options = options || {};
|
127 | if (pkg.inFlight) return;
|
128 | log('install', pkg.name + '@' + pkg.version);
|
129 |
|
130 | pkg.on('error', function(err){
|
131 | if (err.fatal) {
|
132 | error(err.message);
|
133 | process.exit(1);
|
134 | }
|
135 |
|
136 | error(err.message);
|
137 | });
|
138 |
|
139 | if (opts.verbose) {
|
140 | pkg.on('dep', function(dep){
|
141 | log('dep', dep.name + '@' + dep.version);
|
142 | report(dep, options);
|
143 | });
|
144 |
|
145 | pkg.on('exists', function(dep){
|
146 | log('exists', dep.name + '@' + dep.version);
|
147 | });
|
148 |
|
149 | pkg.on('file', function(file){
|
150 | log('fetch', pkg.name + ':' + file);
|
151 | });
|
152 | }
|
153 |
|
154 | pkg.on('end', function(){
|
155 | log('complete', pkg.name);
|
156 | });
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 | process.on('exit', function(){
|
162 |
|
163 | });
|
164 |
|
165 | |
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 | function install(name, version, callback) {
|
175 | touch(opts.out);
|
176 |
|
177 |
|
178 | var pkg = component.install(name, version, {
|
179 | dest: opts.out,
|
180 | force: opts.force,
|
181 | dev: opts.dev,
|
182 | remotes: conf.remotes
|
183 | });
|
184 | pkg.force = opts.force;
|
185 | report(pkg);
|
186 |
|
187 | pkg.on('end', function(){
|
188 | setTimeout(callback, 200);
|
189 | });
|
190 |
|
191 | pkg.on('exists', function(){
|
192 | setTimeout(callback, 200);
|
193 | })
|
194 |
|
195 |
|
196 | pkg.install();
|
197 | }
|
198 |
|
199 | |
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | function touch(path) {
|
207 | try {
|
208 | fs.utimesSync(path, new Date, new Date);
|
209 | } catch (err) {
|
210 |
|
211 | }
|
212 | }
|
213 |
|
214 | |
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | function saveConfig() {
|
221 | var path = resolve('component.json');
|
222 | fs.writeFileSync(path, JSON.stringify(conf, null, 2));
|
223 | }
|
224 |
|
225 | }
|