cacache 11.0.3 → 11.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/get.js +49 -0
- package/lib/content/read.js +67 -1
- package/lib/entry-index.js +82 -25
- package/lib/util/fix-owner.js +46 -0
- package/locales/en.js +3 -0
- package/locales/es.js +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
<a name="11.3.1"></a>
|
|
6
|
+
## [11.3.1](https://github.com/zkat/cacache/compare/v11.3.0...v11.3.1) (2018-11-05)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **get:** export hasContent.sync properly ([d76c920](https://github.com/zkat/cacache/commit/d76c920))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
<a name="11.3.0"></a>
|
|
16
|
+
# [11.3.0](https://github.com/zkat/cacache/compare/v11.2.0...v11.3.0) (2018-11-05)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **get:** add sync API for reading ([db1e094](https://github.com/zkat/cacache/commit/db1e094))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
<a name="11.2.0"></a>
|
|
26
|
+
# [11.2.0](https://github.com/zkat/cacache/compare/v11.1.0...v11.2.0) (2018-08-08)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* **read:** add sync support to other internal read.js fns ([fe638b6](https://github.com/zkat/cacache/commit/fe638b6))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
<a name="11.1.0"></a>
|
|
36
|
+
# [11.1.0](https://github.com/zkat/cacache/compare/v11.0.3...v11.1.0) (2018-08-01)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Features
|
|
40
|
+
|
|
41
|
+
* **read:** add sync support for low-level content read ([b43af83](https://github.com/zkat/cacache/commit/b43af83))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
5
45
|
<a name="11.0.3"></a>
|
|
6
46
|
## [11.0.3](https://github.com/zkat/cacache/compare/v11.0.2...v11.0.3) (2018-08-01)
|
|
7
47
|
|
package/get.js
CHANGED
|
@@ -63,6 +63,55 @@ function getData (byDigest, cache, key, opts) {
|
|
|
63
63
|
})
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
module.exports.sync = function get (cache, key, opts) {
|
|
67
|
+
return getDataSync(false, cache, key, opts)
|
|
68
|
+
}
|
|
69
|
+
module.exports.sync.byDigest = function getByDigest (cache, digest, opts) {
|
|
70
|
+
return getDataSync(true, cache, digest, opts)
|
|
71
|
+
}
|
|
72
|
+
function getDataSync (byDigest, cache, key, opts) {
|
|
73
|
+
opts = GetOpts(opts)
|
|
74
|
+
const memoized = (
|
|
75
|
+
byDigest
|
|
76
|
+
? memo.get.byDigest(cache, key, opts)
|
|
77
|
+
: memo.get(cache, key, opts)
|
|
78
|
+
)
|
|
79
|
+
if (memoized && opts.memoize !== false) {
|
|
80
|
+
return byDigest ? memoized : {
|
|
81
|
+
metadata: memoized.entry.metadata,
|
|
82
|
+
data: memoized.data,
|
|
83
|
+
integrity: memoized.entry.integrity,
|
|
84
|
+
size: memoized.entry.size
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const entry = !byDigest && index.find.sync(cache, key, opts)
|
|
88
|
+
if (!entry && !byDigest) {
|
|
89
|
+
throw new index.NotFoundError(cache, key)
|
|
90
|
+
}
|
|
91
|
+
const data = read.sync(
|
|
92
|
+
cache,
|
|
93
|
+
byDigest ? key : entry.integrity,
|
|
94
|
+
{
|
|
95
|
+
integrity: opts.integrity,
|
|
96
|
+
size: opts.size
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
const res = byDigest
|
|
100
|
+
? data
|
|
101
|
+
: {
|
|
102
|
+
metadata: entry.metadata,
|
|
103
|
+
data: data,
|
|
104
|
+
size: entry.size,
|
|
105
|
+
integrity: entry.integrity
|
|
106
|
+
}
|
|
107
|
+
if (opts.memoize && byDigest) {
|
|
108
|
+
memo.put.byDigest(cache, key, res, opts)
|
|
109
|
+
} else if (opts.memoize) {
|
|
110
|
+
memo.put(cache, entry, res.data, opts)
|
|
111
|
+
}
|
|
112
|
+
return res
|
|
113
|
+
}
|
|
114
|
+
|
|
66
115
|
module.exports.stream = getStream
|
|
67
116
|
function getStream (cache, key, opts) {
|
|
68
117
|
opts = GetOpts(opts)
|
package/lib/content/read.js
CHANGED
|
@@ -33,6 +33,21 @@ function read (cache, integrity, opts) {
|
|
|
33
33
|
})
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
module.exports.sync = readSync
|
|
37
|
+
function readSync (cache, integrity, opts) {
|
|
38
|
+
opts = ReadOpts(opts)
|
|
39
|
+
return withContentSriSync(cache, integrity, (cpath, sri) => {
|
|
40
|
+
const data = fs.readFileSync(cpath)
|
|
41
|
+
if (typeof opts.size === 'number' && opts.size !== data.length) {
|
|
42
|
+
throw sizeError(opts.size, data.length)
|
|
43
|
+
} else if (ssri.checkData(data, sri)) {
|
|
44
|
+
return data
|
|
45
|
+
} else {
|
|
46
|
+
throw integrityError(sri, cpath)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
36
51
|
module.exports.stream = readStream
|
|
37
52
|
module.exports.readStream = readStream
|
|
38
53
|
function readStream (cache, integrity, opts) {
|
|
@@ -58,8 +73,10 @@ function readStream (cache, integrity, opts) {
|
|
|
58
73
|
let copyFileAsync
|
|
59
74
|
if (fs.copyFile) {
|
|
60
75
|
module.exports.copy = copy
|
|
76
|
+
module.exports.copy.sync = copySync
|
|
61
77
|
copyFileAsync = BB.promisify(fs.copyFile)
|
|
62
78
|
}
|
|
79
|
+
|
|
63
80
|
function copy (cache, integrity, dest, opts) {
|
|
64
81
|
opts = ReadOpts(opts)
|
|
65
82
|
return withContentSri(cache, integrity, (cpath, sri) => {
|
|
@@ -67,11 +84,18 @@ function copy (cache, integrity, dest, opts) {
|
|
|
67
84
|
})
|
|
68
85
|
}
|
|
69
86
|
|
|
87
|
+
function copySync (cache, integrity, dest, opts) {
|
|
88
|
+
opts = ReadOpts(opts)
|
|
89
|
+
return withContentSriSync(cache, integrity, (cpath, sri) => {
|
|
90
|
+
return fs.copyFileSync(cpath, dest)
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
module.exports.hasContent = hasContent
|
|
71
95
|
function hasContent (cache, integrity) {
|
|
72
96
|
if (!integrity) { return BB.resolve(false) }
|
|
73
97
|
return withContentSri(cache, integrity, (cpath, sri) => {
|
|
74
|
-
return lstatAsync(cpath).then(stat => ({size: stat.size, sri}))
|
|
98
|
+
return lstatAsync(cpath).then(stat => ({size: stat.size, sri, stat}))
|
|
75
99
|
}).catch(err => {
|
|
76
100
|
if (err.code === 'ENOENT') { return false }
|
|
77
101
|
if (err.code === 'EPERM') {
|
|
@@ -84,6 +108,26 @@ function hasContent (cache, integrity) {
|
|
|
84
108
|
})
|
|
85
109
|
}
|
|
86
110
|
|
|
111
|
+
module.exports.hasContent.sync = hasContentSync
|
|
112
|
+
function hasContentSync (cache, integrity) {
|
|
113
|
+
if (!integrity) { return false }
|
|
114
|
+
return withContentSriSync(cache, integrity, (cpath, sri) => {
|
|
115
|
+
try {
|
|
116
|
+
const stat = fs.lstatSync(cpath)
|
|
117
|
+
return {size: stat.size, sri, stat}
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (err.code === 'ENOENT') { return false }
|
|
120
|
+
if (err.code === 'EPERM') {
|
|
121
|
+
if (process.platform !== 'win32') {
|
|
122
|
+
throw err
|
|
123
|
+
} else {
|
|
124
|
+
return false
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
87
131
|
function withContentSri (cache, integrity, fn) {
|
|
88
132
|
return BB.try(() => {
|
|
89
133
|
const sri = ssri.parse(integrity)
|
|
@@ -112,6 +156,28 @@ function withContentSri (cache, integrity, fn) {
|
|
|
112
156
|
})
|
|
113
157
|
}
|
|
114
158
|
|
|
159
|
+
function withContentSriSync (cache, integrity, fn) {
|
|
160
|
+
const sri = ssri.parse(integrity)
|
|
161
|
+
// If `integrity` has multiple entries, pick the first digest
|
|
162
|
+
// with available local data.
|
|
163
|
+
const algo = sri.pickAlgorithm()
|
|
164
|
+
const digests = sri[algo]
|
|
165
|
+
if (digests.length <= 1) {
|
|
166
|
+
const cpath = contentPath(cache, digests[0])
|
|
167
|
+
return fn(cpath, digests[0])
|
|
168
|
+
} else {
|
|
169
|
+
let lastErr = null
|
|
170
|
+
for (const meta of sri[sri.pickAlgorithm()]) {
|
|
171
|
+
try {
|
|
172
|
+
return withContentSriSync(cache, meta, fn)
|
|
173
|
+
} catch (err) {
|
|
174
|
+
lastErr = err
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (lastErr) { throw lastErr }
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
115
181
|
function sizeError (expected, found) {
|
|
116
182
|
var err = new Error(Y`Bad data size: expected inserted data to be ${expected} bytes, but got ${found} instead`)
|
|
117
183
|
err.expected = expected
|
package/lib/entry-index.js
CHANGED
|
@@ -75,10 +75,36 @@ function insert (cache, key, integrity, opts) {
|
|
|
75
75
|
})
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
module.exports.insert.sync = insertSync
|
|
79
|
+
function insertSync (cache, key, integrity, opts) {
|
|
80
|
+
opts = IndexOpts(opts)
|
|
81
|
+
const bucket = bucketPath(cache, key)
|
|
82
|
+
const entry = {
|
|
83
|
+
key,
|
|
84
|
+
integrity: integrity && ssri.stringify(integrity),
|
|
85
|
+
time: Date.now(),
|
|
86
|
+
size: opts.size,
|
|
87
|
+
metadata: opts.metadata
|
|
88
|
+
}
|
|
89
|
+
fixOwner.mkdirfix.sync(path.dirname(bucket), opts.uid, opts.gid)
|
|
90
|
+
const stringified = JSON.stringify(entry)
|
|
91
|
+
fs.appendFileSync(
|
|
92
|
+
bucket, `\n${hashEntry(stringified)}\t${stringified}`
|
|
93
|
+
)
|
|
94
|
+
try {
|
|
95
|
+
fixOwner.chownr.sync(bucket, opts.uid, opts.gid)
|
|
96
|
+
} catch (err) {
|
|
97
|
+
if (err.code !== 'ENOENT') {
|
|
98
|
+
throw err
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return formatEntry(cache, entry)
|
|
102
|
+
}
|
|
103
|
+
|
|
78
104
|
module.exports.find = find
|
|
79
105
|
function find (cache, key) {
|
|
80
106
|
const bucket = bucketPath(cache, key)
|
|
81
|
-
return bucketEntries(
|
|
107
|
+
return bucketEntries(bucket).then(entries => {
|
|
82
108
|
return entries.reduce((latest, next) => {
|
|
83
109
|
if (next && next.key === key) {
|
|
84
110
|
return formatEntry(cache, next)
|
|
@@ -95,11 +121,36 @@ function find (cache, key) {
|
|
|
95
121
|
})
|
|
96
122
|
}
|
|
97
123
|
|
|
124
|
+
module.exports.find.sync = findSync
|
|
125
|
+
function findSync (cache, key) {
|
|
126
|
+
const bucket = bucketPath(cache, key)
|
|
127
|
+
try {
|
|
128
|
+
return bucketEntriesSync(bucket).reduce((latest, next) => {
|
|
129
|
+
if (next && next.key === key) {
|
|
130
|
+
return formatEntry(cache, next)
|
|
131
|
+
} else {
|
|
132
|
+
return latest
|
|
133
|
+
}
|
|
134
|
+
}, null)
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err.code === 'ENOENT') {
|
|
137
|
+
return null
|
|
138
|
+
} else {
|
|
139
|
+
throw err
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
98
144
|
module.exports.delete = del
|
|
99
145
|
function del (cache, key, opts) {
|
|
100
146
|
return insert(cache, key, null, opts)
|
|
101
147
|
}
|
|
102
148
|
|
|
149
|
+
module.exports.delete.sync = delSync
|
|
150
|
+
function delSync (cache, key, opts) {
|
|
151
|
+
return insertSync(cache, key, null, opts)
|
|
152
|
+
}
|
|
153
|
+
|
|
103
154
|
module.exports.lsStream = lsStream
|
|
104
155
|
function lsStream (cache) {
|
|
105
156
|
const indexDir = bucketDir(cache)
|
|
@@ -116,7 +167,6 @@ function lsStream (cache) {
|
|
|
116
167
|
// "/cachename/<bucket 0xFF>/<bucket 0xFF>/*"
|
|
117
168
|
return readdirOrEmpty(subbucketPath).map(entry => {
|
|
118
169
|
const getKeyToEntry = bucketEntries(
|
|
119
|
-
cache,
|
|
120
170
|
path.join(subbucketPath, entry)
|
|
121
171
|
).reduce((acc, entry) => {
|
|
122
172
|
acc.set(entry.key, entry)
|
|
@@ -152,32 +202,39 @@ function ls (cache) {
|
|
|
152
202
|
})
|
|
153
203
|
}
|
|
154
204
|
|
|
155
|
-
function bucketEntries (
|
|
205
|
+
function bucketEntries (bucket, filter) {
|
|
156
206
|
return readFileAsync(
|
|
157
207
|
bucket, 'utf8'
|
|
158
|
-
).then(data =>
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
208
|
+
).then(data => _bucketEntries(data, filter))
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function bucketEntriesSync (bucket, filter) {
|
|
212
|
+
const data = fs.readFileSync(bucket, 'utf8')
|
|
213
|
+
return _bucketEntries(data, filter)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function _bucketEntries (data, filter) {
|
|
217
|
+
let entries = []
|
|
218
|
+
data.split('\n').forEach(entry => {
|
|
219
|
+
if (!entry) { return }
|
|
220
|
+
const pieces = entry.split('\t')
|
|
221
|
+
if (!pieces[1] || hashEntry(pieces[1]) !== pieces[0]) {
|
|
222
|
+
// Hash is no good! Corruption or malice? Doesn't matter!
|
|
223
|
+
// EJECT EJECT
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
let obj
|
|
227
|
+
try {
|
|
228
|
+
obj = JSON.parse(pieces[1])
|
|
229
|
+
} catch (e) {
|
|
230
|
+
// Entry is corrupted!
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
if (obj) {
|
|
234
|
+
entries.push(obj)
|
|
235
|
+
}
|
|
180
236
|
})
|
|
237
|
+
return entries
|
|
181
238
|
}
|
|
182
239
|
|
|
183
240
|
module.exports._bucketDir = bucketDir
|
package/lib/util/fix-owner.js
CHANGED
|
@@ -31,6 +31,34 @@ function fixOwner (filepath, uid, gid) {
|
|
|
31
31
|
)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
module.exports.chownr.sync = fixOwnerSync
|
|
35
|
+
function fixOwnerSync (filepath, uid, gid) {
|
|
36
|
+
if (!process.getuid) {
|
|
37
|
+
// This platform doesn't need ownership fixing
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if (typeof uid !== 'number' && typeof gid !== 'number') {
|
|
41
|
+
// There's no permissions override. Nothing to do here.
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
if ((typeof uid === 'number' && process.getuid() === uid) &&
|
|
45
|
+
(typeof gid === 'number' && process.getgid() === gid)) {
|
|
46
|
+
// No need to override if it's already what we used.
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
chownr.sync(
|
|
51
|
+
filepath,
|
|
52
|
+
typeof uid === 'number' ? uid : process.getuid(),
|
|
53
|
+
typeof gid === 'number' ? gid : process.getgid()
|
|
54
|
+
)
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err.code === 'ENOENT') {
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
34
62
|
module.exports.mkdirfix = mkdirfix
|
|
35
63
|
function mkdirfix (p, uid, gid, cb) {
|
|
36
64
|
return mkdirp(p).then(made => {
|
|
@@ -42,3 +70,21 @@ function mkdirfix (p, uid, gid, cb) {
|
|
|
42
70
|
return fixOwner(p, uid, gid).then(() => null)
|
|
43
71
|
})
|
|
44
72
|
}
|
|
73
|
+
|
|
74
|
+
module.exports.mkdirfix.sync = mkdirfixSync
|
|
75
|
+
function mkdirfixSync (p, uid, gid) {
|
|
76
|
+
try {
|
|
77
|
+
const made = mkdirp.sync(p)
|
|
78
|
+
if (made) {
|
|
79
|
+
fixOwnerSync(made, uid, gid)
|
|
80
|
+
return made
|
|
81
|
+
}
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (err.code === 'EEXIST') {
|
|
84
|
+
fixOwnerSync(p, uid, gid)
|
|
85
|
+
return null
|
|
86
|
+
} else {
|
|
87
|
+
throw err
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
package/locales/en.js
CHANGED
|
@@ -18,12 +18,15 @@ x.ls.stream = cache => ls.stream(cache)
|
|
|
18
18
|
|
|
19
19
|
x.get = (cache, key, opts) => get(cache, key, opts)
|
|
20
20
|
x.get.byDigest = (cache, hash, opts) => get.byDigest(cache, hash, opts)
|
|
21
|
+
x.get.sync = (cache, key, opts) => get.sync(cache, key, opts)
|
|
22
|
+
x.get.sync.byDigest = (cache, key, opts) => get.sync.byDigest(cache, key, opts)
|
|
21
23
|
x.get.stream = (cache, key, opts) => get.stream(cache, key, opts)
|
|
22
24
|
x.get.stream.byDigest = (cache, hash, opts) => get.stream.byDigest(cache, hash, opts)
|
|
23
25
|
x.get.copy = (cache, key, dest, opts) => get.copy(cache, key, dest, opts)
|
|
24
26
|
x.get.copy.byDigest = (cache, hash, dest, opts) => get.copy.byDigest(cache, hash, dest, opts)
|
|
25
27
|
x.get.info = (cache, key) => get.info(cache, key)
|
|
26
28
|
x.get.hasContent = (cache, hash) => get.hasContent(cache, hash)
|
|
29
|
+
x.get.hasContent.sync = (cache, hash) => get.hasContent.sync(cache, hash)
|
|
27
30
|
|
|
28
31
|
x.put = (cache, key, data, opts) => put(cache, key, data, opts)
|
|
29
32
|
x.put.stream = (cache, key, opts) => put.stream(cache, key, opts)
|
package/locales/es.js
CHANGED
|
@@ -18,12 +18,15 @@ x.ls.flujo = cache => ls.stream(cache)
|
|
|
18
18
|
|
|
19
19
|
x.saca = (cache, clave, ops) => get(cache, clave, ops)
|
|
20
20
|
x.saca.porHacheo = (cache, hacheo, ops) => get.byDigest(cache, hacheo, ops)
|
|
21
|
+
x.saca.sinc = (cache, clave, ops) => get.sync(cache, clave, ops)
|
|
22
|
+
x.saca.sinc.porHacheo = (cache, hacheo, ops) => get.sync.byDigest(cache, hacheo, ops)
|
|
21
23
|
x.saca.flujo = (cache, clave, ops) => get.stream(cache, clave, ops)
|
|
22
24
|
x.saca.flujo.porHacheo = (cache, hacheo, ops) => get.stream.byDigest(cache, hacheo, ops)
|
|
23
25
|
x.sava.copia = (cache, clave, destino, opts) => get.copy(cache, clave, destino, opts)
|
|
24
26
|
x.sava.copia.porHacheo = (cache, hacheo, destino, opts) => get.copy.byDigest(cache, hacheo, destino, opts)
|
|
25
27
|
x.saca.info = (cache, clave) => get.info(cache, clave)
|
|
26
28
|
x.saca.tieneDatos = (cache, hacheo) => get.hasContent(cache, hacheo)
|
|
29
|
+
x.saca.tieneDatos.sinc = (cache, hacheo) => get.hasContent.sync(cache, hacheo)
|
|
27
30
|
|
|
28
31
|
x.mete = (cache, clave, datos, ops) => put(cache, clave, datos, ops)
|
|
29
32
|
x.mete.flujo = (cache, clave, ops) => put.stream(cache, clave, ops)
|