copydirSync.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. var fs = require('fs');
  2. var path = require('path');
  3. /*
  4. options: {
  5. utimes: false, // Boolean | Object, keep utimes if true
  6. mode: false, // Boolean | Number, keep file mode if true
  7. cover: true, // Boolean, cover if file exists
  8. filter: true, // Boolean | Function, file filter
  9. }
  10. */
  11. function copydirSync(from, to, options) {
  12. if (typeof options === 'function') {
  13. options = {
  14. filter: options
  15. };
  16. }
  17. if(typeof options === 'undefined') options = {};
  18. if(typeof options.cover === 'undefined') {
  19. options.cover = true;
  20. }
  21. options.filter = typeof options.filter === 'function' ? options.filter : function(state, filepath, filename) {
  22. return options.filter;
  23. };
  24. var stats = fs.lstatSync(from);
  25. var statsname = stats.isDirectory() ? 'directory' :
  26. stats.isFile() ? 'file' :
  27. stats.isSymbolicLink() ? 'symbolicLink' :
  28. '';
  29. var valid = options.filter(statsname, from, path.dirname(from), path.basename(from));
  30. if (statsname === 'directory' || statsname === 'symbolicLink') {
  31. // Directory or SymbolicLink
  32. if(valid) {
  33. try {
  34. fs.statSync(to);
  35. } catch(err) {
  36. if(err.code === 'ENOENT') {
  37. fs.mkdirSync(to);
  38. options.debug && console.log('>> ' + to);
  39. } else {
  40. throw err;
  41. }
  42. }
  43. rewriteSync(to, options, stats);
  44. if (statsname != 'symbolicLink')
  45. listDirectorySync(from, to, options);
  46. }
  47. } else if(stats.isFile()) {
  48. // File
  49. if(valid) {
  50. if(options.cover) {
  51. writeFileSync(from, to, options, stats);
  52. } else {
  53. try {
  54. fs.statSync(to);
  55. } catch(err) {
  56. if(err.code === 'ENOENT') {
  57. writeFileSync(from, to, options, stats);
  58. } else {
  59. throw err;
  60. }
  61. }
  62. }
  63. }
  64. } else {
  65. throw new Error('stats invalid: '+ from);
  66. }
  67. };
  68. function listDirectorySync(from, to, options) {
  69. var files = fs.readdirSync(from);
  70. copyFromArraySync(files, from, to, options);
  71. }
  72. function copyFromArraySync(files, from, to, options) {
  73. if(files.length === 0) return true;
  74. var f = files.shift();
  75. copydirSync(path.join(from, f), path.join(to, f), options);
  76. copyFromArraySync(files, from, to, options);
  77. }
  78. function writeFileSync(from, to, options, stats) {
  79. fs.writeFileSync(to, fs.readFileSync(from, 'binary'), 'binary');
  80. options.debug && console.log('>> ' + to);
  81. rewriteSync(to, options, stats);
  82. }
  83. function rewriteSync(f, options, stats, callback) {
  84. if(options.cover) {
  85. var mode = options.mode === true ? stats.mode : options.mode;
  86. var utimes = options.utimes === true ? {
  87. atime: stats.atime,
  88. mtime: stats.mtime
  89. } : options.utimes;
  90. mode && fs.chmodSync(f, mode);
  91. utimes && fs.utimesSync(f, utimes.atime, utimes.mtime);
  92. }
  93. return true;
  94. }
  95. module.exports = copydirSync;