UNPKG

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