프로젝트

일반

사용자정보

통계
| 개정판:

root / HServer / 00.Server / 00.Program / node_modules / mv / index.js

이력 | 보기 | 이력해설 | 다운로드 (2.47 KB)

1
var fs = require('fs');
2
var ncp = require('ncp').ncp;
3
var path = require('path');
4
var rimraf = require('rimraf');
5
var mkdirp = require('mkdirp');
6

    
7
module.exports = mv;
8

    
9
function mv(source, dest, options, cb){
10
  if (typeof options === 'function') {
11
    cb = options;
12
    options = {};
13
  }
14
  var shouldMkdirp = !!options.mkdirp;
15
  var clobber = options.clobber !== false;
16
  var limit = options.limit || 16;
17

    
18
  if (shouldMkdirp) {
19
    mkdirs();
20
  } else {
21
    doRename();
22
  }
23

    
24
  function mkdirs() {
25
    mkdirp(path.dirname(dest), function(err) {
26
      if (err) return cb(err);
27
      doRename();
28
    });
29
  }
30

    
31
  function doRename() {
32
    if (clobber) {
33
      fs.rename(source, dest, function(err) {
34
        if (!err) return cb();
35
        if (err.code !== 'EXDEV') return cb(err);
36
        moveFileAcrossDevice(source, dest, clobber, limit, cb);
37
      });
38
    } else {
39
      fs.link(source, dest, function(err) {
40
        if (err) {
41
          if (err.code === 'EXDEV') {
42
            moveFileAcrossDevice(source, dest, clobber, limit, cb);
43
            return;
44
          }
45
          if (err.code === 'EISDIR' || err.code === 'EPERM') {
46
            moveDirAcrossDevice(source, dest, clobber, limit, cb);
47
            return;
48
          }
49
          cb(err);
50
          return;
51
        }
52
        fs.unlink(source, cb);
53
      });
54
    }
55
  }
56
}
57

    
58
function moveFileAcrossDevice(source, dest, clobber, limit, cb) {
59
  var outFlags = clobber ? 'w' : 'wx';
60
  var ins = fs.createReadStream(source);
61
  var outs = fs.createWriteStream(dest, {flags: outFlags});
62
  ins.on('error', function(err){
63
    ins.destroy();
64
    outs.destroy();
65
    outs.removeListener('close', onClose);
66
    if (err.code === 'EISDIR' || err.code === 'EPERM') {
67
      moveDirAcrossDevice(source, dest, clobber, limit, cb);
68
    } else {
69
      cb(err);
70
    }
71
  });
72
  outs.on('error', function(err){
73
    ins.destroy();
74
    outs.destroy();
75
    outs.removeListener('close', onClose);
76
    cb(err);
77
  });
78
  outs.once('close', onClose);
79
  ins.pipe(outs);
80
  function onClose(){
81
    fs.unlink(source, cb);
82
  }
83
}
84

    
85
function moveDirAcrossDevice(source, dest, clobber, limit, cb) {
86
  var options = {
87
    stopOnErr: true,
88
    clobber: false,
89
    limit: limit,
90
  };
91
  if (clobber) {
92
    rimraf(dest, { disableGlob: true }, function(err) {
93
      if (err) return cb(err);
94
      startNcp();
95
    });
96
  } else {
97
    startNcp();
98
  }
99
  function startNcp() {
100
    ncp(source, dest, options, function(errList) {
101
      if (errList) return cb(errList[0]);
102
      rimraf(source, { disableGlob: true }, cb);
103
    });
104
  }
105
}