Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rvagg/readfiletree
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0
Choose a base ref
...
head repository: rvagg/readfiletree
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.1.0
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Jul 1, 2023

  1. Copy the full SHA
    c276720 View commit details
  2. Partially verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    1c842d5 View commit details
Showing with 137 additions and 122 deletions.
  1. +16 −0 .github/dependabot.yml
  2. +61 −0 .github/workflows/test-and-release.yml
  3. +6 −14 README.md
  4. +28 −25 package.json
  5. +15 −59 readfiletree.js
  6. +11 −24 tests.js
16 changes: 16 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'daily'
commit-message:
prefix: 'chore'
include: 'scope'
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'daily'
commit-message:
prefix: 'chore'
include: 'scope'
61 changes: 61 additions & 0 deletions .github/workflows/test-and-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Test & Maybe Release
on: [push, pull_request]
jobs:
test:
strategy:
fail-fast: false
matrix:
node: [16.x, 18.x, lts/*, current]
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@v3.6.0
with:
node-version: ${{ matrix.node }}
- name: Install Dependencies
run: |
npm install --no-progress
- name: Run tests
run: |
npm config set script-shell bash
npm run test:ci
release:
name: Release
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v3.6.0
with:
node-version: lts/*
- name: Install dependencies
run: |
npm install --no-progress --no-package-lock --no-save
- name: Build
run: |
npm run build
- name: Install plugins
run: |
npm install \
@semantic-release/commit-analyzer \
conventional-changelog-conventionalcommits \
@semantic-release/release-notes-generator \
@semantic-release/npm \
@semantic-release/github \
@semantic-release/git \
@semantic-release/changelog \
--no-progress --no-package-lock --no-save
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release

20 changes: 6 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -6,17 +6,17 @@ Deserialise an file/directory tree into an object. Available in npm as *readfile

Particularly useful for testing where you need to do a `deepStrictEqual()` on a simple tree of files. **See [mkfiletree](https://github.com/rvagg/mkfiletree) for file tree serialisation.**

### require('readfiletree')(directory[, callback])
### async readfiletree(directory)

Read the directory and the files it contains, recursively, and return an object representing the directory structure with nodes containing the utf8 string contents of each file. The arguments of the optional callback are: `(err, object)`. If no callback is supplied, a `Promise` is returned which can be used to `await` the serialised `object`.
Read the directory and the files it contains, recursively, and return an object representing the directory structure with nodes containing the utf8 string contents of each file.

Using both *mkfiletree* and *readfiletree* we can do the following:

```js
const mkfiletree = require('mkfiletree')
const readfiletree = require('readfiletree')
import * as mkfiletree from 'mkfiletree'
import { readfiletree } from 'readfiletree'

let dir = await mkfiletree.makeTemp('testfiles',
const dir = await mkfiletree.makeTemp('testfiles',
{
'adir': {
'one.txt': '1\n2\n3\n',
@@ -28,7 +28,7 @@ let dir = await mkfiletree.makeTemp('testfiles',
'afile.txt': 'file contents'
})

let obj = await readfiletree(dir)
const obj = await readfiletree(dir)
console.log(obj)
```

@@ -67,14 +67,6 @@ And the output of the program should be the same as the input to *mkfiletree*:
}
```

## Contributing

Tests can be run with `npm test`. I'm more than happy to receive contributions so fork away!

## Synchronous version

No, there is no sync version, do it async, it's good for your health and contains additional vitamin C, B1, B2 and folate.

*Copyright (c) 2012 [Rod Vagg](https://github.com/rvagg)

Made available under the MIT licence:
53 changes: 28 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
{
"author": "Rod Vagg @rvagg <rod@vagg.org>",
"name": "readfiletree",
"description": "Serialize a tree of files and directories into object form",
"keywords": [
"temp",
"tree",
"test",
"serialize",
"deserialize"
],
"version": "1.0.0",
"main": "readfiletree.js",
"scripts": {
"test": "node tests.js"
},
"dependencies": {
"after": "~0.8.2"
},
"devDependencies": {
"mkfiletree": "~2.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/rvagg/node-readfiletree.git"
}
"author": "Rod Vagg @rvagg <rod@vagg.org>",
"name": "readfiletree",
"description": "Serialize a tree of files and directories into object form",
"keywords": [
"temp",
"tree",
"test",
"serialize",
"deserialize"
],
"version": "1.0.0",
"main": "readfiletree.js",
"type": "module",
"license": "MIT",
"scripts": {
"lint": "standard",
"test": "npm run lint && node tests.js",
"test:ci": "npm run lint && node tests.js",
"build": "true"
},
"devDependencies": {
"mkfiletree": "^3.0.0",
"standard": "^17.1.0"
},
"repository": {
"type": "git",
"url": "https://github.com/rvagg/node-readfiletree.git"
}
}
74 changes: 15 additions & 59 deletions readfiletree.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,21 @@
/* Copyright (c) 2012 Rod Vagg <@rvagg> */
const fs = require('fs')
const path = require('path')
const after = require('after')
import fs from 'fs/promises'
import path from 'path'

function readfiletree (dir, obj, callback) {
if (typeof obj === 'function') {
callback = obj
export async function readfiletree (dir, obj) {
if (obj == null) {
obj = {}
}

fs.readdir(dir, afterReaddir)

function afterReaddir (err, list) {
if (err) {
return callback(err)
}

const done = after(list.length, (err) => {
if (err) {
return callback(err)
}
callback(null, obj)
})
list.forEach((f) => eachFile(f, done))
}

function eachFile (f, callback) {
var p = path.join(dir, f)
fs.stat(p, (err, stat) => {
if (err) {
return callback(err)
}
if (stat.isDirectory()) {
obj[f] = {}
return readfiletree(p, obj[f], callback)
} else if (stat.isFile()) {
fs.readFile(p, 'utf8', (err, data) => {
if (err) {
return callback(err)
}
obj[f] = data
callback()
})
}
})
}
}

module.exports = function maybePromiseWrap (dir, callback) {
if (typeof callback === 'function') {
return readfiletree(dir, callback)
}

return new Promise((resolve, reject) => {
callback = (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
const list = await fs.readdir(dir)
await Promise.all(list.map(async (f) => {
const p = path.join(dir, f)
const stat = await fs.stat(p)
if (stat.isDirectory()) {
obj[f] = {}
await readfiletree(p, obj[f])
} else if (stat.isFile()) {
obj[f] = await fs.readFile(p, 'utf8')
}

readfiletree(dir, callback)
})
}))
return obj
}
35 changes: 11 additions & 24 deletions tests.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,29 @@
const assert = require('assert')
const mkfiletree = require('mkfiletree')
const readfiletree = require('./readfiletree')
import assert from 'assert'
import * as mkfiletree from 'mkfiletree'
import { readfiletree } from './readfiletree.js'

function mkfixture () { // make a new copy each time, ensure no edits at any depth
return {
'foo.txt': 'FOO!',
'bar': {
'bang': {
bar: {
bang: {
'1.dat': '1\n',
'2.dat': '2\n\n',
'3.dat': '3\n\n\n'
},
'BAM': 'WOO HOO!!!\n'
BAM: 'WOO HOO!!!\n'
}
}
}

async function test (asPromises) {
async function test () {
const dir = await mkfiletree.makeTemp('readfiletree_test', mkfixture())
assert(dir)

if (!asPromises) {
readfiletree(dir, (err, obj) => {
assert(!err)
verify(obj)
})
} else {
readfiletree(dir)
.then(verify)
}

function verify (obj) {
assert.deepStrictEqual(obj, mkfixture())
}
const obj = await readfiletree(dir)
assert.deepStrictEqual(obj, mkfixture())
}

test(false).then(() => {
return test(true)
}).catch((err) => {
test().catch((err) => {
console.error(err)
process.exit(1)
})