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