Skip to content

Commit d53784a

Browse files
jonschlinkertphated
authored andcommitted
Breaking: Refactor and cleanup library
1 parent 977a271 commit d53784a

4 files changed

Lines changed: 160 additions & 59 deletions

File tree

README.md

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
44
[![NPM](https://nodei.co/npm/empty-dir.png)](https://nodei.co/npm/empty-dir/)
55

6-
Note that directories with `.DS_Store` on mac are considered empty.
6+
## Install
7+
8+
Install with [npm](https://www.npmjs.com/):
9+
10+
```sh
11+
$ npm install --save empty-dir
12+
```
13+
14+
## Usage
715

8-
## Example
916
```js
10-
const emptyDir = require('empty-dir');
17+
var emptyDir = require('empty-dir');
1118

1219
emptyDir('./', function (err, result) {
1320
if (err) {
@@ -21,32 +28,32 @@ var result = emptyDir.sync('./test/empty');
2128
console.log('Directory is empty:', result);
2229
```
2330

24-
**Filter function**
31+
## Filter function
2532

26-
Both async and sync take a filter function as the second argument.
33+
Both async and sync take a filter function as the second argument, to ignore files like `.DS_Store` on mac or `Thumbs.db` on windows from causing false-negatives.
2734

28-
_(This gives you the ability to eliminate files like `.DS_Store` on mac, or `Thumbs.db` on windows from causing the result to be "not empty" (`.DS_Store` is already filtered by default).)_
2935

3036
```js
31-
const emptyDir = require('empty-dir');
37+
var emptyDir = require('empty-dir');
3238

3339
function filter(filepath) {
34-
return !/Thumbs\.db$/i.test(filepath);
40+
return !/(Thumbs\.db|\.DS_Store)$/i.test(filepath);
3541
}
3642

37-
emptyDir('./', filter, function (err, result) {
43+
emptyDir('./', filter, function (err, isEmpty) {
3844
if (err) {
3945
console.error(err);
4046
} else {
41-
console.log('Directory is empty:', result);
47+
console.log('Directory is empty:', isEmpty);
4248
}
4349
});
4450

45-
var result = emptyDir.sync('./test/empty', filter);
46-
console.log('Directory is empty:', result);
51+
var isEmpty = emptyDir.sync('./test/empty', filter);
52+
console.log('Directory is empty:', isEmpty);
4753
```
4854

4955
## Release History
5056

51-
* 2014-05-08 - v0.1.0 - initial release
57+
* 2018-03-09 - v1.0.0 - refactored "isEmpty" logic so that it returns early, as soon as a non-filtered file is encountered, instead of filtering the entire list and comparing against length. Also allows an array to be passed (this avoids having to call `fs.readdir()` multiple times).
5258
* 2016-02-07 - v0.2.0 - add filter support
59+
* 2014-05-08 - v0.1.0 - initial release

index.js

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,98 @@
1-
const fs = require('fs');
2-
const exists = require('fs-exists-sync');
1+
'use strict';
32

4-
function isEmpty(path, fn, callback) {
3+
var fs = require('fs');
4+
5+
function emptyDir(dir, filter, cb) {
56
if (arguments.length === 2) {
6-
callback = fn;
7-
fn = null;
7+
cb = filter;
8+
filter = null;
9+
}
10+
11+
if (typeof cb !== 'function') {
12+
throw new TypeError('expected callback to be a function');
813
}
914

10-
if (!exists(path)) {
11-
callback(null, false);
15+
if (Array.isArray(dir)) {
16+
cb(null, isEmpty(dir, filter));
1217
return;
1318
}
1419

15-
fs.readdir(path, function(err, files) {
16-
if (err) {
17-
callback(err);
18-
return;
19-
}
20+
if (typeof dir !== 'string') {
21+
cb(new TypeError('expected a directory or array of files'));
22+
return;
23+
}
2024

21-
if (typeof fn === 'function') {
22-
files = files.filter(fn);
25+
fs.stat(dir, function(err, stat) {
26+
if (err || !stat.isDirectory()) {
27+
cb(null, false);
28+
return;
2329
}
2430

25-
callback(null, files.length === 0);
31+
fs.readdir(dir, function(err, files) {
32+
cb(err, isEmpty(files, filter));
33+
});
2634
});
2735
}
2836

29-
isEmpty.sync = function(path, fn) {
30-
if (!exists(path)) {
37+
/**
38+
* Return true if the given `files` array has zero length or only
39+
* includes unwanted files.
40+
*/
41+
42+
function emptyDirSync(dir, filter) {
43+
if (Array.isArray(dir)) {
44+
return isEmpty(dir, filter);
45+
}
46+
47+
if (typeof dir !== 'string') {
48+
throw new TypeError('expected a directory or array of files');
49+
}
50+
51+
if (!isDirectory(dir)) {
3152
return false;
3253
}
33-
try {
34-
var files = fs.readdirSync(path);
35-
if (typeof fn === 'function') {
36-
files = files.filter(fn);
54+
55+
var files = fs.readdirSync(dir);
56+
return isEmpty(files, filter);
57+
}
58+
59+
/**
60+
* Returns true if the given "files" array is empty or only
61+
* contains unwanted files.
62+
*/
63+
64+
function isEmpty(files, filter) {
65+
if (files.length === 0) {
66+
return true;
67+
}
68+
69+
if (typeof filter !== 'function') {
70+
return false;
71+
}
72+
73+
for (var i = 0; i < files.length; ++i) {
74+
if (filter(files[i]) === false) {
75+
return false;
3776
}
38-
return files.length === 0;
77+
}
78+
return true;
79+
}
80+
81+
/**
82+
* Returns true if the filepath exists and is a directory
83+
*/
84+
85+
function isDirectory(filepath) {
86+
try {
87+
return fs.statSync(filepath).isDirectory();
3988
} catch (err) {}
4089
return false;
41-
};
90+
}
91+
92+
/**
93+
* Expose `emptyDir`
94+
*/
4295

43-
module.exports = isEmpty;
96+
module.exports = emptyDir;
97+
module.exports.sync = emptyDirSync;
98+
module.exports.isEmpty = isEmpty;

package.json

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,13 @@
1919
"scripts": {
2020
"test": "mocha"
2121
},
22-
"dependencies": {
23-
"fs-exists-sync": "^0.1.0"
24-
},
25-
"devDependencies": {
26-
"chai": "^3.5.0",
27-
"mocha": "^3.2.0"
28-
},
2922
"keywords": [
30-
"empty directory",
31-
"empty dir",
32-
"empty folder"
33-
]
23+
"empty",
24+
"is-empty",
25+
"directory",
26+
"folder"
27+
],
28+
"devDependencies": {
29+
"mocha": "^3.5.3"
30+
}
3431
}

test/index.js

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,74 @@
1-
const emptyDir = require('../');
2-
const expect = require('chai').expect;
3-
const fs = require('fs');
1+
var emptyDir = require('../');
2+
var assert = require('assert');
3+
var path = require('path');
4+
var fs = require('fs');
45

56
try {
6-
fs.mkdirSync('./test/empty');
7+
fs.mkdirSync(path.join(__dirname, 'empty'));
78
} catch (e) {}
89

10+
function isGarbageFile(filename) {
11+
return /(?:Thumbs\.db|\.DS_Store)$/i.test(filename);
12+
}
13+
914
describe('emptyDir', function () {
15+
it('should throw when a callback is not passed', function () {
16+
assert.throws(function() {
17+
emptyDir('./')
18+
}, /expected/);
19+
});
20+
21+
it('should throw when invalid arguments are passed', function (done) {
22+
assert.throws(function() {
23+
emptyDir.sync(null);
24+
});
25+
26+
emptyDir(null, function(err) {
27+
assert(err);
28+
assert(/expected/.test(err.message));
29+
done();
30+
});
31+
});
32+
33+
it('should take an array', function (done) {
34+
assert(!emptyDir.sync(['Thumbs.db', '.DS_Store']));
35+
emptyDir(['Thumbs.db', '.DS_Store'], function(err, empty) {
36+
assert(!empty);
37+
done();
38+
});
39+
});
40+
41+
it('should take a filter function to exclude files', function (done) {
42+
assert(emptyDir.sync(['Thumbs.db', '.DS_Store'], isGarbageFile));
43+
assert(!emptyDir.sync(['Thumbs.db', '.DS_Store', 'foo'], isGarbageFile));
44+
45+
emptyDir(['Thumbs.db', '.DS_Store'], isGarbageFile, function(err, empty) {
46+
assert(empty);
47+
done();
48+
});
49+
});
50+
1051
it('should call back with true if a directory is empty', function (done) {
11-
expect(emptyDir.sync('./')).to.be.false;
12-
emptyDir('./', function (err, empty) {
13-
expect(empty).to.be.false;
52+
assert(!emptyDir.sync('./'));
53+
emptyDir('./', function(err, empty) {
54+
assert(!empty);
1455
done();
1556
});
1657
});
1758

1859
it('should be false if a directory does not exist', function (done) {
19-
expect(emptyDir.sync('./foo/bar/baz')).to.be.false;
60+
assert(!emptyDir.sync('./foo/bar/baz'));
2061
emptyDir('./foo/bar/baz', function (err, empty) {
21-
expect(empty).to.be.false;
62+
assert(!empty);
2263
done();
2364
});
2465
});
2566

2667
it('should call back with false if a directory is not empty', function (done) {
27-
expect(emptyDir.sync('./test/empty')).to.be.true;
68+
assert(!emptyDir.sync('./test'));
69+
assert(emptyDir.sync('./test/empty'));
2870
emptyDir('./test/empty', function (err, empty) {
29-
expect(empty).to.be.true;
71+
assert(empty);
3072
done();
3173
});
3274
});

0 commit comments

Comments
 (0)