UNPKG

5.65 kBJavaScriptView Raw
1var path = require('path');
2var fs = require('fs');
3var assert = require("assert");
4
5// file.mkdirs
6//
7// Given a path to a directory, create it, and all the intermediate directories
8// as well
9//
10// @path: the path to create
11// @mode: the file mode to create the directory with:
12// ex: file.mkdirs("/tmp/dir", 755, function () {})
13// @callback: called when finished.
14exports.mkdirs = function (_path, mode, callback) {
15 _path = exports.path.abspath(_path);
16
17 var dirs = _path.split("/");
18 var walker = [dirs.shift()];
19
20 // walk
21 // @ds: A list of directory names
22 // @acc: An accumulator of walked dirs
23 // @m: The mode
24 // @cb: The callback
25 var walk = function (ds, acc, m, cb) {
26 if (ds.length > 0) {
27 var d = ds.shift();
28
29 acc.push(d);
30 var dir = acc.join("/");
31
32 // look for dir on the fs, if it doesn't exist then create it, and
33 // continue our walk, otherwise if it's a file, we have a name
34 // collision, so exit.
35 fs.stat(dir, function (err, stat) {
36 // if the directory doesn't exist then create it
37 if (err) {
38 // 2 means it's wasn't there
39 if (err.errno == 2 || err.errno == 34) {
40 fs.mkdir(dir, m, function (erro) {
41 if (erro && erro.errno != 17 && erro.errno != 34) {
42 assert(false)
43 return cb(erro);
44 } else {
45 return walk(ds, acc, m, cb);
46 }
47 });
48 } else {
49 return cb(err);
50 }
51 } else {
52 if (stat.isDirectory()) {
53 return walk(ds, acc, m, cb);
54 } else {
55 return cb(new Error("Failed to mkdir " + dir + ": File exists\n"));
56 }
57 }
58 });
59 } else {
60 return cb();
61 }
62 };
63 return walk(dirs, walker, mode, callback);
64};
65
66// file.mkdirsSync
67//
68// Synchronus version of file.mkdirs
69//
70// Given a path to a directory, create it, and all the intermediate directories
71// as well
72//
73// @path: the path to create
74// @mode: the file mode to create the directory with:
75// ex: file.mkdirs("/tmp/dir", 755, function () {})
76exports.mkdirsSync = function (_path, mode) {
77 if (_path[0] !== "/") {
78 _path = path.join(process.cwd(), _path)
79 }
80
81 var dirs = _path.split("/");
82 var walker = [dirs.shift()];
83
84 dirs.reduce(function (acc, d) {
85 acc.push(d);
86 var dir = acc.join("/");
87
88 try {
89 var stat = fs.statSync(dir);
90 if (!stat.isDirectory()) {
91 throw "Failed to mkdir " + dir + ": File exists";
92 }
93 } catch (err) {
94 fs.mkdirSync(dir, mode);
95 }
96 return acc;
97 }, walker);
98};
99
100// file.walk
101//
102// Given a path to a directory, walk the fs below that directory
103//
104// @start: the path to startat
105// @callback: called for each new directory we enter
106// ex: file.walk("/tmp", function(error, path, dirs, name) {})
107//
108// path is the current directory we're in
109// dirs is the list of directories below it
110// names is the list of files in it
111//
112exports.walk = function (start, callback) {
113 fs.lstat(start, function (err, stat) {
114 if (err) { return callback(err) }
115 if (stat.isDirectory()) {
116
117 fs.readdir(start, function (err, files) {
118 var coll = files.reduce(function (acc, i) {
119 var abspath = path.join(start, i);
120
121 if (fs.statSync(abspath).isDirectory()) {
122 exports.walk(abspath, callback);
123 acc.dirs.push(abspath);
124 } else {
125 acc.names.push(abspath);
126 }
127
128 return acc;
129 }, {"names": [], "dirs": []});
130
131 return callback(null, start, coll.dirs, coll.names);
132 });
133 } else {
134 return callback(new Error("path: " + start + " is not a directory"));
135 }
136 });
137};
138
139// file.walkSync
140//
141// Synchronus version of file.walk
142//
143// Given a path to a directory, walk the fs below that directory
144//
145// @start: the path to startat
146// @callback: called for each new directory we enter
147// ex: file.walk("/tmp", function(error, path, dirs, name) {})
148//
149// path is the current directory we're in
150// dirs is the list of directories below it
151// names is the list of files in it
152//
153exports.walkSync = function (start, callback) {
154 var stat = fs.statSync(start);
155
156 if (stat.isDirectory()) {
157 var filenames = fs.readdirSync(start);
158
159 var coll = filenames.reduce(function (acc, name) {
160 var abspath = path.join(start, name);
161
162 if (fs.statSync(abspath).isDirectory()) {
163 acc.dirs.push(name);
164 } else {
165 acc.names.push(name);
166 }
167
168 return acc;
169 }, {"names": [], "dirs": []});
170
171 callback(start, coll.dirs, coll.names);
172
173 coll.dirs.forEach(function (d) {
174 var abspath = path.join(start, d);
175 exports.walkSync(abspath, callback);
176 });
177
178 } else {
179 throw new Error("path: " + start + " is not a directory");
180 }
181};
182
183exports.path = {};
184
185exports.path.abspath = function (to) {
186 var from;
187 switch (to.charAt(0)) {
188 case "~": from = process.env.HOME; to = to.substr(1); break
189 case "/": from = ""; break
190 default : from = process.cwd(); break
191 }
192 return path.join(from, to);
193}
194
195exports.path.relativePath = function (base, compare) {
196 base = base.split("/");
197 compare = compare.split("/");
198
199 if (base[0] == "") {
200 base.shift();
201 }
202
203 if (compare[0] == "") {
204 compare.shift();
205 }
206
207 var l = compare.length;
208
209 for (var i = 0; i < l; i++) {
210 if (!base[i] || (base[i] != compare[i])) {
211 return compare.slice(i).join("/");
212 }
213 }
214
215 return ""
216};
217
218exports.path.join = function (head, tail) {
219 if (head == "") {
220 return tail;
221 } else {
222 return path.join(head, tail);
223 }
224};
225