1 | var 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 |
|
12 | var $global = common.$global;
|
13 |
|
14 | var FileTask = function (cfg) {
|
15 | this.init(cfg);
|
16 | };
|
17 |
|
18 | function 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 |
|
26 | util.inherits (FileTask, task);
|
27 |
|
28 | function mkdirParent (dirPath, mode, callback) {
|
29 |
|
30 | if (!callback) {
|
31 | callback = mode;
|
32 | mode = undefined;
|
33 | }
|
34 | fs.mkdir(dirPath, mode, function(error) {
|
35 |
|
36 | if (error && error.code === 'ENOENT') {
|
37 |
|
38 | mkdirParent (path.dirname (dirPath), mode, function (err) {
|
39 |
|
40 | mkdirParent (dirPath, mode, callback);
|
41 | });
|
42 | return;
|
43 | }
|
44 |
|
45 | callback && callback(error);
|
46 | });
|
47 | }
|
48 |
|
49 | util.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 |
|
142 | readStream.pause();
|
143 | var writeStream = fs.createWriteStream (dst);
|
144 | writeStream.on ('open', function (wrid) {
|
145 |
|
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 |
|
153 | });
|
154 |
|
155 | readStream.on ('error', self.failed.bind (self));
|
156 |
|
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 |
|
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 |
|
190 | module.exports = FileTask;
|