0f0eeca56074296a4c65cee0fb2ec4dc6b4a9a08
[yaffs-website] / node_modules / grunt / node_modules / resolve / lib / async.js
1 var core = require('./core');
2 var fs = require('fs');
3 var path = require('path');
4 var caller = require('./caller.js');
5 var nodeModulesPaths = require('./node-modules-paths.js');
6 var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;
7
8 module.exports = function resolve (x, opts, cb) {
9     if (typeof opts === 'function') {
10         cb = opts;
11         opts = {};
12     }
13     if (!opts) opts = {};
14     if (typeof x !== 'string') {
15         return process.nextTick(function () {
16             cb(new Error('path must be a string'));
17         });
18     }
19     
20     var isFile = opts.isFile || function (file, cb) {
21         fs.stat(file, function (err, stat) {
22             if (err && err.code === 'ENOENT') cb(null, false)
23             else if (err) cb(err)
24             else cb(null, stat.isFile() || stat.isFIFO())
25         });
26     };
27     var readFile = opts.readFile || fs.readFile;
28     
29     var extensions = opts.extensions || [ '.js' ];
30     var y = opts.basedir || path.dirname(caller());
31     
32     opts.paths = opts.paths || [];
33     
34     if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[\\\/])/.test(x)) {
35         var res = path.resolve(y, x);
36         if (x === '..') res += '/';
37         if (/\/$/.test(x) && res === y) {
38             loadAsDirectory(res, opts.package, onfile);
39         }
40         else loadAsFile(res, opts.package, onfile);
41     }
42     else loadNodeModules(x, y, function (err, n, pkg) {
43         if (err) cb(err)
44         else if (n) cb(null, n, pkg)
45         else if (core[x]) return cb(null, x);
46         else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
47     });
48     
49     function onfile (err, m, pkg) {
50         if (err) cb(err)
51         else if (m) cb(null, m, pkg)
52         else loadAsDirectory(res, function (err, d, pkg) {
53             if (err) cb(err)
54             else if (d) cb(null, d, pkg)
55             else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
56         })
57     }
58     
59     function loadAsFile (x, pkg, cb) {
60         if (typeof pkg === 'function') {
61             cb = pkg;
62             pkg = undefined;
63         }
64         
65         var exts = [''].concat(extensions);
66         load(exts, x, pkg)
67                 
68                 function load (exts, x, pkg) {
69             if (exts.length === 0) return cb(null, undefined, pkg);
70             var file = x + exts[0];
71             
72             if (pkg) onpkg(null, pkg)
73             else loadpkg(path.dirname(file), onpkg);
74             
75             function onpkg (err, pkg_, dir) {
76                 pkg = pkg_;
77                 if (err) return cb(err)
78                 if (dir && pkg && opts.pathFilter) {
79                     var rfile = path.relative(dir, file);
80                     var rel = rfile.slice(0, rfile.length - exts[0].length);
81                     var r = opts.pathFilter(pkg, x, rel);
82                     if (r) return load(
83                         [''].concat(extensions.slice()),
84                         path.resolve(dir, r),
85                         pkg
86                     );
87                 }
88                 isFile(file, onex);
89             }
90             function onex (err, ex) {
91                 if (err) cb(err)
92                 else if (!ex) load(exts.slice(1), x, pkg)
93                 else cb(null, file, pkg)
94             }
95         }
96     }
97     
98     function loadpkg (dir, cb) {
99         if (dir === '' || dir === '/') return cb(null);
100         if (process.platform === 'win32' && /^\w:[\\\/]*$/.test(dir)) {
101             return cb(null);
102         }
103         if (/[\\\/]node_modules[\\\/]*$/.test(dir)) return cb(null);
104         
105         var pkgfile = path.join(dir, 'package.json');
106         isFile(pkgfile, function (err, ex) {
107             // on err, ex is false
108             if (!ex) return loadpkg(
109                 path.dirname(dir), cb
110             );
111             
112             readFile(pkgfile, function (err, body) {
113                 if (err) cb(err);
114                 try { var pkg = JSON.parse(body) }
115                 catch (err) {}
116                 
117                 if (pkg && opts.packageFilter) {
118                     pkg = opts.packageFilter(pkg, pkgfile);
119                 }
120                 cb(null, pkg, dir);
121             });
122         });
123     }
124     
125     function loadAsDirectory (x, fpkg, cb) {
126         if (typeof fpkg === 'function') {
127             cb = fpkg;
128             fpkg = opts.package;
129         }
130         
131         var pkgfile = path.join(x, '/package.json');
132         isFile(pkgfile, function (err, ex) {
133             if (err) return cb(err);
134             if (!ex) return loadAsFile(path.join(x, '/index'), fpkg, cb);
135             
136             readFile(pkgfile, function (err, body) {
137                 if (err) return cb(err);
138                 try {
139                     var pkg = JSON.parse(body);
140                 }
141                 catch (err) {}
142                 
143                 if (opts.packageFilter) {
144                     pkg = opts.packageFilter(pkg, pkgfile);
145                 }
146                 
147                 if (pkg.main) {
148                     if (pkg.main === '.' || pkg.main === './'){
149                         pkg.main = 'index'
150                     }
151                     loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) {
152                         if (err) return cb(err);
153                         if (m) return cb(null, m, pkg);
154                         if (!pkg) return loadAsFile(path.join(x, '/index'), pkg, cb);
155
156                         var dir = path.resolve(x, pkg.main);
157                         loadAsDirectory(dir, pkg, function (err, n, pkg) {
158                             if (err) return cb(err);
159                             if (n) return cb(null, n, pkg);
160                             loadAsFile(path.join(x, '/index'), pkg, cb);
161                         });
162                     });
163                     return;
164                 }
165                 
166                 loadAsFile(path.join(x, '/index'), pkg, cb);
167             });
168         });
169     }
170     
171     function loadNodeModules (x, start, cb) {
172         (function process (dirs) {
173             if (dirs.length === 0) return cb(null, undefined);
174             var dir = dirs[0];
175             
176             var file = path.join(dir, '/', x);
177             loadAsFile(file, undefined, onfile);
178             
179             function onfile (err, m, pkg) {
180                 if (err) return cb(err);
181                 if (m) return cb(null, m, pkg);
182                 loadAsDirectory(path.join(dir, '/', x), undefined, ondir);
183             }
184             
185             function ondir (err, n, pkg) {
186                 if (err) return cb(err);
187                 if (n) return cb(null, n, pkg);
188                 process(dirs.slice(1));
189             }
190         })(nodeModulesPaths(start, opts));
191     }
192 };