Welcome to mirror list, hosted at ThFree Co, Russian Federation.

rimraf.js « rimraf « node_modules - github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e8104e9e4b3bf8e7fa1d232d2ade3bc41e2578a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
module.exports = rimraf
rimraf.sync = rimrafSync

var path = require("path")
  , fs

try {
  // optional dependency
  fs = require("graceful-fs")
} catch (er) {
  fs = require("fs")
}

var lstat = process.platform === "win32" ? "stat" : "lstat"
  , lstatSync = lstat + "Sync"

// for EMFILE handling
var timeout = 0
  , EMFILE_MAX = 1000

function rimraf (p, opts, cb) {
  if (typeof opts === "function") cb = opts, opts = {}

  if (!cb) throw new Error("No callback passed to rimraf()")
  if (!opts) opts = {}

  var busyTries = 0
  opts.maxBusyTries = opts.maxBusyTries || 3

  if (opts.gently) opts.gently = path.resolve(opts.gently)

  rimraf_(p, opts, function CB (er) {
    if (er) {
      if (er.code === "EBUSY" && busyTries < opts.maxBusyTries) {
        var time = (opts.maxBusyTries - busyTries) * 100
        busyTries ++
        // try again, with the same exact callback as this one.
        return setTimeout(function () {
          rimraf_(p, opts, CB)
        })
      }

      // this one won't happen if graceful-fs is used.
      if (er.code === "EMFILE" && timeout < EMFILE_MAX) {
        return setTimeout(function () {
          rimraf_(p, opts, CB)
        }, timeout ++)
      }

      // already gone
      if (er.code === "ENOENT") er = null
    }

    timeout = 0
    cb(er)
  })
}

function rimraf_ (p, opts, cb) {
  fs[lstat](p, function (er, s) {
    // if the stat fails, then assume it's already gone.
    if (er) {
      // already gone
      if (er.code === "ENOENT") return cb()
      // some other kind of error, permissions, etc.
      return cb(er)
    }

    // don't delete that don't point actually live in the "gently" path
    if (opts.gently) return clobberTest(p, s, opts, cb)
    return rm_(p, s, opts, cb)
  })
}

function rm_ (p, s, opts, cb) {
  if (!s.isDirectory()) return fs.unlink(p, cb)
  fs.readdir(p, function (er, files) {
    if (er) return cb(er)
    asyncForEach(files.map(function (f) {
      return path.join(p, f)
    }), function (file, cb) {
      rimraf(file, opts, cb)
    }, function (er) {
      if (er) return cb(er)
      fs.rmdir(p, cb)
    })
  })
}

function clobberTest (p, s, opts, cb) {
  var gently = opts.gently
  if (!s.isSymbolicLink()) next(null, path.resolve(p))
  else realish(p, next)

  function next (er, rp) {
    if (er) return rm_(p, s, cb)
    if (rp.indexOf(gently) !== 0) return clobberFail(p, gently, cb)
    else return rm_(p, s, opts, cb)
  }
}

function realish (p, cb) {
  fs.readlink(p, function (er, r) {
    if (er) return cb(er)
    return cb(null, path.resolve(path.dirname(p), r))
  })
}

function clobberFail (p, g, cb) {
  var er = new Error("Refusing to delete: "+p+" not in "+g)
    , constants = require("constants")
  er.errno = constants.EEXIST
  er.code = "EEXIST"
  er.path = p
  return cb(er)
}

function asyncForEach (list, fn, cb) {
  if (!list.length) cb()
  var c = list.length
    , errState = null
  list.forEach(function (item, i, list) {
    fn(item, function (er) {
      if (errState) return
      if (er) return cb(errState = er)
      if (-- c === 0) return cb()
    })
  })
}

// this looks simpler, but it will fail with big directory trees,
// or on slow stupid awful cygwin filesystems
function rimrafSync (p) {
  try {
    var s = fs[lstatSync](p)
  } catch (er) {
    if (er.code === "ENOENT") return
    throw er
  }
  if (!s.isDirectory()) return fs.unlinkSync(p)
  fs.readdirSync(p).forEach(function (f) {
    rimrafSync(path.join(p, f))
  })
  fs.rmdirSync(p)
}