UNPKG

4.16 kBJavaScriptView Raw
1var fs = require('fs'),
2 path = require('path'),
3 util = require('util'),
4 os = require('os'),
5 exists = fs.exists || path.exists,
6 _c = require('constants'),
7 common = require('../common'),
8 task = require ('./base');
9
10
11var $global = common.$global;
12
13var FileTask = function (cfg) {
14 this.init(cfg);
15};
16
17function resolvePath (pathToResolve) {
18 var resolveArgs = [pathToResolve];
19 if (typeof project !== "undefined") {
20 resolveArgs.unshift ($global.project.root.path);
21 }
22 return path.resolve.apply (path, resolveArgs);
23}
24
25util.inherits (FileTask, task);
26
27function mkdirParent (dirPath, mode, callback) {
28 //Call the standard fs.mkdir
29 if (!callback) {
30 callback = mode;
31 mode = undefined;
32 }
33 fs.mkdir(dirPath, mode, function(error) {
34 //When it fail in this way, do the custom steps
35 if (error && error.code === 'ENOENT') {
36 //Create all the parents recursively
37 mkdirParent (path.dirname (dirPath), mode, function (err) {
38 //And then the directory
39 mkdirParent (dirPath, mode, callback);
40 });
41 return;
42 }
43 //Manually run the callback since we used our own callback to do all these
44 callback && callback(error);
45 });
46}
47
48util.extend(FileTask.prototype, {
49 mkdir: function () {
50 var filePath = resolvePath (this.filePath);
51 var mode = this.mode;
52
53 mkdirParent (filePath, mode, function (err) {
54 if (err && err.code !== "EEXIST") {
55 this.failed (err);
56 } else {
57 this.completed (filePath);
58 }
59 }.bind (this));
60 },
61 run: function () {
62 this.read();
63 },
64
65 read: function () {
66 var self = this;
67 var filePath = resolvePath (this.filePath);
68
69 fs.readFile(filePath, function (err, data) {
70 if (err) {
71 self.failed(err);
72 } else {
73 self.completed(data);
74 }
75 });
76 },
77
78 write: function () {
79 var self = this;
80 var filePath = resolvePath (this.filePath);
81
82 fs.writeFile(filePath, this.fileData, function (err) {
83 if (err) {
84 self.failed(err);
85 } else {
86 self.completed(filePath);
87 }
88 });
89 },
90 _randomName: function () {
91 var fileName = [
92 ('tmp-' || this.prefix),
93 process.pid,
94 (Math.random() * 0x1000000000).toString(36),
95 this.postfix
96 ].join ('');
97
98 return fileName;
99 },
100 _createFile: function (name) {
101 var self = this;
102 fs.open(name, _c.O_CREAT | _c.O_EXCL | _c.O_RDWR, 0600, function _fileCreated(err, fd) {
103 if (err) return self.failed ();
104 self.completed(name);
105 });
106 },
107 tmpFileName: function () {
108 var self = this;
109 var tmpDir = os.tmpDir();
110 var tmpFileName = this._randomName ();
111 var tmpPath = path.join (tmpDir, tmpFileName);
112 exists (tmpPath, function (pathExists) {
113 if (!pathExists) {
114 self._createFile (tmpPath);
115 return;
116 }
117 self.failed ();
118 });
119
120 },
121 unlink: function () {
122 var self = this;
123 var filePath = resolvePath (this.filePath);
124
125 fs.unlink(filePath, function (err) {
126 if (err) {
127 self.failed(err);
128 } else {
129 self.completed(filePath);
130 }
131 });
132 },
133 copy: function () {
134 var self = this;
135 var src = resolvePath (this.filePath);
136 var dst = resolvePath (this.to);
137
138 var readStream = fs.createReadStream (src);
139 readStream.on ('open', function (rdid) {
140 // TODO: check for null id
141 readStream.pause();
142 var writeStream = fs.createWriteStream (dst);
143 writeStream.on ('open', function (wrid) {
144 // TODO: check for null id
145 readStream.pipe (writeStream);
146 readStream.resume ();
147 });
148
149 writeStream.on ('close', self.completed.bind (self, dst));
150 writeStream.on ('error', self.failed.bind (self));
151 // TODO: add handlers for
152 });
153
154 readStream.on ('error', self.failed.bind (self));
155 // TODO: here we need to set timeout
156 },
157 rename: function () {
158 var src = resolvePath (this.filePath);
159 var dst = resolvePath (this.to);
160
161 if (this.verbose) {
162 console.log ("rename", src, "to", dst);
163 }
164
165 fs.rename (src, dst, function (err) {
166 if (err) {
167 if (err.code === "EXDEV") {
168
169 if (this.verbose) {
170 console.log ("fs boundaries rename error, using copy");
171 }
172
173 // rename file between fs boundsries
174 this.copy ();
175
176 return;
177 }
178
179 this.failed(err);
180 return;
181 }
182
183 this.completed (dst);
184 }.bind (this));
185 }
186
187});
188
189module.exports = FileTask;