Skip to content

Commit f0b3974

Browse files
committed
feat(verify): converted to Promises
BREAKING CHANGE: API is now promise-based
1 parent 697aa38 commit f0b3974

File tree

1 file changed

+106
-111
lines changed

1 file changed

+106
-111
lines changed

Diff for: lib/verify.js

+106-111
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,168 @@
11
'use strict'
22

3-
var asyncMap = require('slide').asyncMap
3+
const Promise = require('bluebird')
4+
45
var checksumStream = require('checksum-stream')
56
var fixOwner = require('./util/fix-owner')
67
var fs = require('graceful-fs')
78
var index = require('./entry-index')
8-
var lockfile = require('lockfile')
9+
var lockfile = Promise.promisifyAll(require('lockfile'))
910
var path = require('path')
10-
var pipe = require('mississippi').pipe
11-
var rimraf = require('rimraf')
11+
var pipe = Promise.promisify(require('mississippi').pipe)
12+
var rimraf = Promise.promisify(require('rimraf'))
13+
14+
Promise.promisifyAll(fs)
1215

1316
module.exports = verify
14-
function verify (cache, opts, _cb) {
15-
if (!_cb) {
16-
_cb = opts
17-
opts = null
18-
}
17+
function verify (cache, opts) {
1918
opts = opts || {}
20-
var lock = path.join(cache, 'verify.lock')
21-
var cb = function (err, stats) {
22-
lockfile.unlock(lock, function (er) {
23-
_cb(er || err, stats)
19+
opts.log && opts.log.verbose('verify', 'verifying content cache at', cache)
20+
const startTime = +(new Date())
21+
return fixOwner.mkdirfix(
22+
cache, opts.uid, opts.gid
23+
).then(() => {
24+
const lockPath = path.join(cache, 'verify.lock')
25+
const lock = lockfile.lockAsync(lockPath).disposer(() => {
26+
return lockfile.unlock(lockPath)
2427
})
25-
}
26-
fixOwner.mkdirfix(cache, opts.uid, opts.gid, function (err) {
27-
if (err) { return _cb(err) }
28-
lockfile.lock(lock, function (err) {
29-
if (err) { return _cb(err) }
30-
garbageCollect(cache, opts, function (err, gcStats) {
31-
if (err) { return cb(err) }
32-
tidyIndex(cache, opts, function (err, tidyStats) {
33-
if (err) { return cb(err) }
28+
return Promise.using(lock, () => {
29+
return garbageCollect(cache, opts).then(gcStats => {
30+
return tidyIndex(cache, opts).then(tidyStats => {
3431
var stats = tidyStats
3532
Object.keys(gcStats).forEach(function (key) {
3633
stats[key] = gcStats[key]
3734
})
38-
var verifile = path.join(cache, '_lastverified')
39-
fs.writeFile(verifile, '' + (+(new Date())), function (err) {
40-
if (err) { return cb(err) }
41-
fixOwner.chownr(cache, opts.uid, opts.gid, function (err) {
42-
if (err) { return cb(err) }
43-
rimraf(path.join(cache, 'tmp'), function (err) {
44-
if (err) { return cb(err) }
45-
cb(null, stats)
46-
})
47-
})
48-
})
35+
return stats
4936
})
37+
}).then(stats => {
38+
var verifile = path.join(cache, '_lastverified')
39+
opts.log && opts.log.verbose('verify', 'writing verifile to ' + verifile)
40+
return fs.writeFileAsync(
41+
verifile, '' + (+(new Date()))
42+
).then(() => {
43+
opts.log && opts.log.verbose('verify', 'fixing cache ownership')
44+
return fixOwner.chownr(cache, opts.uid, opts.gid)
45+
}).then(() => {
46+
opts.log && opts.log.verbose('verify', 'clearing out tmp')
47+
return rimraf(path.join(cache, 'tmp'))
48+
}).then(() => stats)
5049
})
5150
})
51+
}).then(stats => {
52+
stats.runTime = (+(new Date()) - startTime) / 1000
53+
opts.log && opts.log.verbose('verify', 'final stats:', stats)
54+
return stats
5255
})
5356
}
5457

55-
function tidyIndex (cache, opts, cb) {
56-
index.ls(cache, function (err, entries) {
57-
if (err) { return cb(err) }
58-
rimraf(path.join(cache, 'index'), function (err) {
59-
if (err) { return cb(err) }
58+
function tidyIndex (cache, opts) {
59+
opts.log && opts.log.verbose('verify', 'tidying index')
60+
return index.ls(cache).then(entries => {
61+
return rimraf(path.join(cache, 'index')).then(() => {
6062
var stats = {
6163
entriesRemoved: 0,
6264
digestMissing: 0,
6365
totalEntries: 0
6466
}
65-
asyncMap(Object.keys(entries), function (key, cb) {
67+
return Promise.reduce(Object.keys(entries), (stats, key) => {
6668
var entry = entries[key]
6769
if (!entry.digest) {
6870
stats.digestMissing++
69-
return cb()
71+
return stats
7072
}
7173
var content = path.join(cache, 'content', entries[key].digest)
72-
fs.stat(content, function (err) {
73-
if (err && err.code === 'ENOENT') {
74-
stats.entriesRemoved++
75-
return cb()
76-
} else {
77-
stats.totalEntries++
78-
index.insert(cache, key, entry.digest, {
79-
uid: opts.uid,
80-
gid: opts.gid,
81-
metadata: entry.metadata
82-
}, cb)
74+
return fs.statAsync(content).catch(err => {
75+
if (err.code === 'ENOENT') {
76+
stats.entriesRemoves++
77+
return stats
8378
}
79+
}).then(() => {
80+
stats.totalEntries++
81+
return index.insert(cache, key, entry.digest, {
82+
uid: opts.uid,
83+
gid: opts.gid,
84+
metadata: entry.metadata
85+
}).then(() => stats)
8486
})
85-
}, function (err) {
86-
if (err) { return cb(err) }
87-
cb(null, stats)
88-
})
87+
}, stats)
8988
})
9089
})
9190
}
9291

93-
function garbageCollect (cache, opts, cb) {
94-
index.ls(cache, function (err, entries) {
92+
function garbageCollect (cache, opts) {
93+
opts.log && opts.log.verbose('verify', 'garbage collecting content')
94+
return index.ls(cache).then(entries => {
9595
var byDigest = {}
9696
Object.keys(entries).forEach(function (k) {
9797
byDigest[entries[k].digest] = entries[k]
9898
})
99-
if (err) { return cb(err) }
100-
var stats = {
101-
verifiedContent: 0,
102-
collectedCount: 0,
103-
reclaimedSize: 0
104-
}
10599
var contentDir = path.join(cache, 'content')
106-
fs.readdir(contentDir, function (err, files) {
107-
if (err && err.code === 'ENOENT') {
108-
return cb(null, stats)
109-
} else if (err) {
110-
return cb(err)
100+
return fs.readdirAsync(contentDir).catch(err => {
101+
if (err.code === 'ENOENT') {
102+
return
111103
} else {
112-
asyncMap(files, function (f, cb) {
113-
var fullPath = path.join(contentDir, f)
114-
if (byDigest[f]) {
115-
var algo = opts.hashAlgorithm || 'sha1'
116-
verifyContent(fullPath, algo, function (err, collected) {
117-
if (err) { return cb(err) }
118-
if (collected != null) {
119-
stats.collectedCount++
120-
stats.reclaimedSize += collected
121-
} else {
122-
stats.verifiedContent++
123-
}
124-
cb()
125-
})
126-
} else {
127-
stats.collectedCount++
128-
fs.stat(fullPath, function (err, s) {
129-
if (err) { return cb(err) }
130-
stats.reclaimedSize += s.size
131-
rimraf(path.join(contentDir, f), cb)
132-
})
133-
}
134-
}, function (err) {
135-
if (err) { return cb(err) }
136-
cb(null, stats)
137-
})
104+
throw err
138105
}
106+
}).then(files => {
107+
var stats = {
108+
verifiedContent: 0,
109+
collectedCount: 0,
110+
reclaimedSize: 0,
111+
keptSize: 0
112+
}
113+
return Promise.reduce(files, (stats, f) => {
114+
var fullPath = path.join(contentDir, f)
115+
if (byDigest[f]) {
116+
var algo = opts.hashAlgorithm || 'sha1'
117+
return verifyContent(fullPath, algo).then(info => {
118+
if (!info.valid) {
119+
stats.collectedCount++
120+
stats.reclaimedSize += info.size
121+
} else {
122+
stats.verifiedContent++
123+
stats.keptSize += info.size
124+
}
125+
return stats
126+
})
127+
} else {
128+
stats.collectedCount++
129+
return fs.statAsync(fullPath).then(s => {
130+
stats.reclaimedSize += s.size
131+
return rimraf(path.join(contentDir, f)).then(() => stats)
132+
})
133+
}
134+
}, stats)
139135
})
140136
})
141137
}
142138

143-
function verifyContent (filepath, algo, cb) {
144-
fs.stat(filepath, function (err, stat) {
145-
if (err) { return cb(err) }
139+
function verifyContent (filepath, algo) {
140+
return fs.statAsync(filepath).then(stat => {
146141
var reader = fs.createReadStream(filepath)
147142
var checksummer = checksumStream({
148143
digest: path.basename(filepath),
149144
algorithm: algo
150145
})
151-
checksummer.on('data', function () {})
152-
pipe(reader, checksummer, function (err) {
146+
var contentInfo = {
147+
size: stat.size,
148+
valid: true
149+
}
150+
checksummer.on('data', () => {})
151+
return pipe(reader, checksummer).catch(err => {
153152
if (err && err.code === 'EBADCHECKSUM') {
154-
rimraf(filepath, function (err) {
155-
if (err) { return cb(err) }
156-
cb(null, stat.size)
153+
return rimraf(filepath).then(() => {
154+
contentInfo.valid = false
157155
})
158-
} else if (err) {
159-
return cb(err)
160156
} else {
161-
cb(null, null)
157+
throw err
162158
}
163-
})
159+
}).then(() => contentInfo)
164160
})
165161
}
166162

167163
module.exports.lastRun = lastRun
168-
function lastRun (cache, cb) {
169-
fs.readFile(path.join(cache, '_lastverified'), 'utf8', function (err, data) {
170-
if (err) { return cb(err) }
171-
cb(null, new Date(+data))
172-
})
164+
function lastRun (cache) {
165+
return fs.readFileAsync(
166+
path.join(cache, '_lastverified'), 'utf8'
167+
).then(data => new Date(+data))
173168
}

0 commit comments

Comments
 (0)