UNPKG

5.82 kBJavaScriptView Raw
1var path = require('path'),
2 fs = require('fs'),
3 exec = require('child_process').exec,
4 async = require('async'),
5 walk = require('./lib/walk');
6
7var defaultRegExcludes = [/^\.+.*/, /node_modules/]
8
9module.exports = exports = function(currentDir, originalFilePath, newFilePath, options, cb) {
10 validatePaths(originalFilePath, newFilePath, function(err) {
11 if (err) return cb(err);
12
13 fs.stat(originalFilePath, function (err, stat) {
14 if (err) return cb(err);
15
16 if (stat.isDirectory()) {
17 mvDir(currentDir, originalFilePath, newFilePath, options, cb)
18 } else {
19 mvFile(currentDir, originalFilePath, newFilePath, options, cb)
20 }
21 });
22 })
23};
24
25function mvFile(currentDir, originalFilePath, newFilePath, options, cb) {
26 steps = [function(cb) {
27 rename(originalFilePath, newFilePath, options.git, cb)
28 }];
29
30 excludes = getExcludes(options);
31 steps.push(function(cb) {updateReferencesInMovedFile(originalFilePath, newFilePath, null, cb)});
32 steps.push(function(cb) {updateReferencesToMovedFile(currentDir, originalFilePath, newFilePath, excludes, cb)});
33
34 async.series(steps, cb);
35}
36
37function getExcludes(options) {
38 var excludes = defaultRegExcludes, steps = [];
39 if (options.excludes) {
40 excludes = excludes.concat(options.excludes);
41 }
42 return excludes;
43}
44
45function validatePaths(originalFilePath, newFilePath, cb) {
46 async.series({
47 srcExists: function(cb) {fs.exists(originalFilePath, function(exists) {cb(null, exists)})},
48 destExists: function(cb) {fs.exists(newFilePath, function(exists) {cb(null, exists)})}
49 }, function(err, result) {
50 var srcExists = result.srcExists,
51 destExists = result.destExists;
52
53 if (!srcExists) return cb(new Error(originalFilePath + ' does not exist!'));
54 if (destExists) return cb(new Error(newFilePath + ' is already exist!'));
55 return cb(null, true);
56 });
57}
58
59function mvDir(currentDir, originalDirPath, newDirPath, options, cb) {
60 originalDirPath = originalDirPath.replace(/\/$/, '');
61 if (newDirPath[newDirPath.length - 1] === '/') {
62 newDirPath = newDirPath + path.basename(originalDirPath)
63 }
64
65 validatePaths(originalDirPath, newDirPath, function(err) {
66 if (err) return cb(err);
67
68 walk(originalDirPath, [], function(err, files) {
69 if (err) return cb(err);
70
71 rename(originalDirPath, newDirPath, options.git, function(err) {
72 if (err) return cb(err);
73
74 async.eachSeries(files, function(file, cb) {
75 var newFilePath = file.replace(originalDirPath, newDirPath);
76
77 steps = [];
78 steps.push(function(cb) {
79 var excludeRequires = '^' + originalDirPath;
80 updateReferencesInMovedFile(file, newFilePath, new RegExp(excludeRequires), cb)
81 });
82 searchExcludes = getExcludes(options);
83 steps.push(function(cb) {
84 updateReferencesToMovedFile(currentDir, file, newFilePath, searchExcludes, cb)
85 });
86
87 async.parallel(steps, cb);
88
89 }, cb)
90 })
91 })
92 });
93}
94
95function rename(originalPath, newPath, supportGit, cb) {
96 if (supportGit) {
97 exec('git mv ' + originalPath + ' ' + newPath, function(err, stdout, stderr) {
98 if (err) return cb(err);
99 if (stderr) return cb(stderr);
100 cb();
101 })
102 } else {
103 fs.rename(originalPath, newPath, cb);
104 }
105}
106
107function updateReferencesInMovedFile(originalFilePath, newFilePath, excludes, cb) {
108 fs.readFile(newFilePath, 'utf8', function(err, data) {
109 if (err) return cb(err);
110
111 var requires = getRequires(data);
112
113 if (requires) {
114 requires.forEach(function(oldRequire) {
115 var newRequire = generateNewRequire(oldRequire, originalFilePath, newFilePath, excludes);
116 if (newRequire)
117 data = data.replace(oldRequire, newRequire);
118 })
119 }
120 fs.writeFile(newFilePath, data, {encoding: 'utf8'}, cb);
121 });
122}
123
124function getRequires(fileData) {
125 var re = /require(\(|\s)('|")(\.\S+)('|")(\))?/g;
126 return fileData.match(re);
127}
128
129function generateNewRequire(oldRequire, originalFilePath, newFilePath, excludes) {
130 var re = /require(\(|\s)('|")(\.\S+)('|")(\))?/,
131 groups = re.exec(oldRequire),
132 oldPath = groups[3],
133 oldAsbPath = path.join(path.dirname(originalFilePath), oldPath);
134 if (excludes && excludes.test(oldAsbPath)) return null;
135 newRelativePath = path.relative(path.dirname(newFilePath), oldAsbPath);
136
137 if (newRelativePath.indexOf('.') != 0 ) {
138 newRelativePath = './' + newRelativePath;
139 }
140
141 return oldRequire.replace(re, 'require$1$2' + newRelativePath + '$4$5');
142}
143
144function updateReferencesToMovedFile(currentDir, originalFilePath, newFilePath, regExcludes, cb) {
145 walk(currentDir, regExcludes, function(err, files) {
146 if (err) return cb(err);
147
148 function updateReferenceForFile(file, cb) {
149 var oldRelativePath = path.relative(path.dirname(file), originalFilePath).replace(/\.(js|coffee)$/, ''),
150 newRelativePath = path.relative(path.dirname(file), newFilePath).replace(/\.(js|coffee)$/, '');
151 if (oldRelativePath.indexOf(".") != 0 ) {
152 oldRelativePath = './' + oldRelativePath;
153 }
154 if (newRelativePath.indexOf(".") != 0 ) {
155 newRelativePath = './' + newRelativePath;
156 }
157
158 var regex = exports.generateRequireRegex(oldRelativePath);
159 fs.readFile(file, 'utf8', function(err, data) {
160 if (err) return cb(err);
161 if (data.indexOf(regex)) {
162 var result = data.replace(regex, 'require$1$2' + newRelativePath + '$4$5');
163 return fs.writeFile(file, result, {encoding: 'utf8'}, cb);
164 } else {
165 return cb()
166 }
167 })
168 }
169 async.eachSeries(files, updateReferenceForFile, cb);
170 })
171}
172
173exports.generateRequireRegex = function(filePath) {
174 return new RegExp("require(\\(|\\s)('|\")(" + filePath + ")('|\")(\\))?", "g");
175}