1
1
'use strict'
2
2
3
- const asyncMap = require ( 'slide/lib/async-map' )
4
3
const contentPath = require ( './content/path' )
5
4
const crypto = require ( 'crypto' )
6
5
const fixOwner = require ( './util/fix-owner' )
7
6
const fs = require ( 'graceful-fs' )
8
7
const path = require ( 'path' )
9
8
const Promise = require ( 'bluebird' )
10
- const through = require ( 'mississippi' ) . through
9
+ const ms = require ( 'mississippi' )
10
+ const hashToSegments = require ( './util/hash-to-segments' )
11
11
12
12
const indexV = require ( '../package.json' ) [ 'cache-version' ] . index
13
13
14
14
const appendFileAsync = Promise . promisify ( fs . appendFile )
15
15
const readFileAsync = Promise . promisify ( fs . readFile )
16
+ const readdirAsync = Promise . promisify ( fs . readdir )
17
+ const concat = ms . concat
18
+ const from = ms . from
19
+
20
+ module . exports . NotFoundError = class NotFoundError extends Error {
21
+ constructor ( cache , key ) {
22
+ super ( 'content not found' )
23
+ this . code = 'ENOENT'
24
+ this . cache = cache
25
+ this . key = key
26
+ }
27
+ }
16
28
17
29
module . exports . insert = insert
18
30
function insert ( cache , key , digest , opts ) {
@@ -74,71 +86,54 @@ function del (cache, key) {
74
86
module . exports . lsStream = lsStream
75
87
function lsStream ( cache ) {
76
88
const indexDir = bucketDir ( cache )
77
- const stream = through . obj ( )
78
- fs . readdir ( indexDir , function ( err , buckets ) {
79
- if ( err && err . code === 'ENOENT' ) {
80
- return stream . end ( )
81
- } else if ( err ) {
82
- return stream . emit ( 'error' , err )
83
- } else {
84
- asyncMap ( buckets , ( bucket , cb ) => {
85
- fs . readdir ( path . join ( indexDir , bucket ) , ( err , files ) => {
86
- if ( err && err . code === 'ENOENT' ) {
87
- return cb ( )
88
- } else if ( err ) {
89
- return cb ( err )
90
- } else {
91
- asyncMap ( files , function ( f , cb ) {
92
- const bpath = path . join ( indexDir , bucket , f )
93
- bucketEntries ( cache , bpath ) . then ( _entries => {
94
- const entries = _entries . reduce ( ( acc , entry ) => {
95
- acc [ entry . key ] = entry
96
- return acc
97
- } , { } )
98
- Object . keys ( entries ) . forEach ( function ( k ) {
99
- stream . write ( formatEntry ( cache , entries [ k ] ) )
100
- } )
101
- cb ( )
102
- } , err => {
103
- if ( err . code === 'ENOENT' ) {
104
- cb ( )
105
- } else {
106
- cb ( err )
107
- }
108
- } )
109
- } , cb )
110
- }
111
- } )
112
- } , function ( err ) {
113
- if ( err ) { stream . emit ( 'error' ) }
114
- stream . end ( )
89
+ const stream = from . obj ( )
90
+
91
+ // "/cachename/*"
92
+ readdirOrEmpty ( indexDir ) . map ( bucket => {
93
+ const bucketPath = path . join ( indexDir , bucket )
94
+
95
+ // "/cachename/<bucket 0xFF>/*"
96
+ return readdirOrEmpty ( bucketPath ) . map ( subbucket => {
97
+ const subbucketPath = path . join ( bucketPath , subbucket )
98
+
99
+ // "/cachename/<bucket 0xFF>/<bucket 0xFF>/*"
100
+ return readdirOrEmpty ( subbucketPath ) . map ( entry => {
101
+ const getKeyToEntry = bucketEntries (
102
+ cache ,
103
+ path . join ( subbucketPath , entry )
104
+ ) . reduce ( ( acc , entry ) => {
105
+ acc . set ( entry . key , entry )
106
+ return acc
107
+ } , new Map ( ) )
108
+
109
+ return getKeyToEntry . then ( reduced => {
110
+ return Array . from ( reduced . values ( ) ) . map (
111
+ entry => stream . push ( formatEntry ( cache , entry ) )
112
+ )
113
+ } ) . catch ( { code : 'ENOENT' } , nop )
115
114
} )
116
- }
115
+ } )
116
+ } ) . then ( ( ) => {
117
+ stream . push ( null )
118
+ } , err => {
119
+ stream . emit ( 'error' , err )
117
120
} )
121
+
118
122
return stream
119
123
}
120
124
121
125
module . exports . ls = ls
122
126
function ls ( cache ) {
123
- const entries = { }
124
127
return Promise . fromNode ( cb => {
125
- lsStream ( cache ) . on ( 'finish' , function ( ) {
126
- cb ( null , entries )
127
- } ) . on ( 'data' , function ( d ) {
128
- entries [ d . key ] = d
129
- } ) . on ( 'error' , cb )
128
+ lsStream ( cache ) . on ( 'error' , cb ) . pipe ( concat ( entries => {
129
+ cb ( null , entries . reduce ( ( acc , xs ) => {
130
+ acc [ xs . key ] = xs
131
+ return acc
132
+ } , { } ) )
133
+ } ) )
130
134
} )
131
135
}
132
136
133
- module . exports . notFoundError = notFoundError
134
- function notFoundError ( cache , key ) {
135
- const err = new Error ( 'content not found' )
136
- err . code = 'ENOENT'
137
- err . cache = cache
138
- err . key = key
139
- return err
140
- }
141
-
142
137
function bucketEntries ( cache , bucket , filter ) {
143
138
return readFileAsync (
144
139
bucket , 'utf8'
@@ -172,7 +167,9 @@ function bucketDir (cache) {
172
167
module . exports . _bucketPath = bucketPath
173
168
function bucketPath ( cache , key ) {
174
169
const hashed = hashKey ( key )
175
- return path . join ( bucketDir ( cache ) , hashed . slice ( 0 , 2 ) , hashed . slice ( 2 ) )
170
+ return path . join . apply ( path , [ bucketDir ( cache ) ] . concat (
171
+ hashToSegments ( hashed )
172
+ ) )
176
173
}
177
174
178
175
module . exports . _hashKey = hashKey
@@ -193,3 +190,10 @@ function formatEntry (cache, entry) {
193
190
metadata : entry . metadata
194
191
}
195
192
}
193
+
194
+ function readdirOrEmpty ( dir ) {
195
+ return readdirAsync ( dir ) . catch ( { code : 'ENOENT' } , ( ) => [ ] )
196
+ }
197
+
198
+ function nop ( ) {
199
+ }
0 commit comments