Skip to content

Commit

Permalink
feat: getDir is now recursive
Browse files Browse the repository at this point in the history
  • Loading branch information
msimerson committed May 2, 2024
1 parent 4b53048 commit db23fe6
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 44 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

### Unreleased

### [1.3.0] - 2024-05-02

- feat: getDir is now recursive

### [1.2.4] - 2024-04-26

- fix(watch): callback was losing context. Use explicit obj
Expand Down Expand Up @@ -134,3 +138,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
[1.2.1]: https://github.com/haraka/haraka-config/releases/tag/v1.2.1
[1.2.2]: https://github.com/haraka/haraka-config/releases/tag/v1.2.2
[1.2.4]: https://github.com/haraka/haraka-config/releases/tag/v1.2.4
[1.3.0]: https://github.com/haraka/haraka-config/releases/tag/v1.3.0
50 changes: 26 additions & 24 deletions lib/reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,30 +137,32 @@ class Reader {
return result
}

read_dir(name, opts = {}) {
return new Promise((resolve, reject) => {
this._read_args[name] = { opts }

fsp
.stat(name)
.then((stat) => stat.isDirectory())
.then(() => fsp.readdir(name))
.then(async (fileList) => {
const contents = []
for (const file of fileList) {
const type = opts.type ?? this.getType(file)
contents.push({
path: file,
data: this.load_config(path.resolve(name, file), type, opts),
})
}
return contents
})
.then(resolve)
.catch(reject)

if (opts.watchCb) watch.dir2(this, name)
})
async read_dir(name, opts = {}) {
this._read_args[name] = { opts }

const contents = []
const dirs = []

const stat = await fsp.stat(name)
if (stat.isDirectory()) dirs.push(name)

for (const dir of dirs) {
for (const entry of await fsp.readdir(dir)) {
const entryPath = path.join(dir, entry)
const stat = await fsp.stat(entryPath)
if (stat.isDirectory()) dirs.push(entryPath) // recursion
if (stat.isFile()) {
const type = opts.type ?? this.getType(entry)
contents.push({
path: entryPath,
data: this.load_config(entryPath, type, opts),
})
}
}
}

if (opts.watchCb) watch.dir2(this, name)
return contents
}

get_filetype_reader(type) {
Expand Down
3 changes: 2 additions & 1 deletion lib/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Watch.dir2 = (reader, dirPath) => {
const watchOpts = { persistent: false, recursive: true }

// recursive is only supported on Windows (win32, win64) and macOS (darwin)
if (!/win/.test(process.platform)) watchOpts.recursive = false
if (!/win|darwin/.test(process.platform)) watchOpts.recursive = false

watchers[dirPath] = fs.watch(dirPath, watchOpts, (fse, filename) => {
// console.log(`event: ${fse}, ${filename}`);
Expand All @@ -105,6 +105,7 @@ Watch.dir2 = (reader, dirPath) => {
args.opts.watchCb()
}, 2 * 1000)
})
watchers[dirPath].unref()
}

Watch.onEvent = (reader, name, args) => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "haraka-config",
"license": "MIT",
"description": "Haraka's config file loader",
"version": "1.2.4",
"version": "1.3.0",
"homepage": "http://haraka.github.io",
"repository": {
"type": "git",
Expand Down
11 changes: 5 additions & 6 deletions test/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ describe('getDir', function () {
if (err) console.error(err)
assert.ifError(err)
assert.equal(err, null)
assert.equal(files.length, 3)
assert.equal(files.length, 4)
assert.equal(files[0].data, `contents1${os.EOL}`)
assert.equal(files[2].data, `contents3${os.EOL}`)
done()
Expand All @@ -484,8 +484,8 @@ describe('getDir', function () {
it('reloads when file in dir is touched', function (done) {
this.timeout(3500)

// due to differences in fs.watch, this test is not reliable on Mac OS X
if (/darwin/.test(process.platform)) return done()
// due to differences in fs.watch, this test is unreliable on Mac OS X
// if (/darwin/.test(process.platform)) return done()

let callCount = 0

Expand All @@ -496,17 +496,16 @@ describe('getDir', function () {
if (err) console.error(err)
callCount++
if (callCount === 1) {
// console.log(files);
assert.equal(err, null)
assert.equal(files.length, 3)
assert.equal(files.length, 4)
assert.equal(files[0].data, `contents1${os.EOL}`)
assert.equal(files[2].data, `contents3${os.EOL}`)
fs.writeFile(tmpFile, 'contents4\n', (err2) => {
assert.equal(err2, null)
// console.log('file touched, waiting for callback');
})
}
if (callCount === 2) {
else if (callCount === 2) {
assert.equal(files[3].data, 'contents4\n')
fs.unlink(tmpFile, () => {})
done()
Expand Down
1 change: 1 addition & 0 deletions test/config/dir/subdir/4.flat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contents4
25 changes: 13 additions & 12 deletions test/reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,22 +170,23 @@ describe('reader', function () {

describe('read_dir', function () {
it('returns dir contents', async function () {
// may have race collission with config.getDir test
const result = await this.cfreader.read_dir(
path.resolve('test/config/dir'),
)
assert.deepEqual(result, [
{ data: 'contents1', path: '1.ext' },
{ data: 'contents2', path: '2.ext' },
{ data: 'contents3', path: '3.ext' },
const dir = path.resolve('test/config/dir')
assert.deepEqual(await this.cfreader.read_dir(dir), [
{ data: 'contents1', path: path.join(dir, '1.ext') },
{ data: 'contents2', path: path.join(dir, '2.ext') },
{ data: 'contents3', path: path.join(dir, '3.ext') },
{ data: 'contents4', path: path.join(dir, 'subdir', '4.flat') },
])
})

it('returns dir with mixed types', async function () {
const result = await this.cfreader.read_dir('test/config/mixed')
assert.deepEqual(result, [
{ data: { main: {}, sect: { one: 'true' } }, path: '1.ini' },
{ data: { main: { two: false } }, path: '2.yml' },
const dir = path.join('test', 'config', 'mixed')
assert.deepEqual(await this.cfreader.read_dir(dir), [
{
data: { main: {}, sect: { one: 'true' } },
path: path.join(dir, '1.ini'),
},
{ data: { main: { two: false } }, path: path.join(dir, '2.yml') },
])
})
})
Expand Down

0 comments on commit db23fe6

Please sign in to comment.