Skip to content

Commit

Permalink
feat: use a cache to avoid directory scan if not necessary
Browse files Browse the repository at this point in the history
  • Loading branch information
mjeanroy committed Nov 21, 2016
1 parent 8ae542b commit 79b2379
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
41 changes: 36 additions & 5 deletions src/license-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class LicensePlugin {
this._cwd = process.cwd();
this._dependencies = {};
this._pkg = require(path.join(this._cwd, 'package.json'));

// This is a cache storing a directory path to associated package.
// This is an improvement to avoid looking for package information for
// already scanned directory.
this._cache = {};
}

/**
Expand All @@ -61,18 +66,44 @@ class LicensePlugin {
load(id) {
// Look for the `package.json` file
let dir = path.parse(id).dir;
let pkg = null;

const scannedDirs = [];

while (dir && dir !== this._cwd) {
const pkg = path.join(dir, 'package.json');
const exists = fs.existsSync(pkg);
// Try the cache.
if (_.has(this._cache, dir)) {
pkg = this._cache[dir];
if (pkg) {
this.addDependency(pkg);
}

break;
}

scannedDirs.push(dir);

const pkgPath = path.join(dir, 'package.json');
const exists = fs.existsSync(pkgPath);
if (exists) {
this.addDependency(require(pkg));
// Read `package.json` file
pkg = require(pkgPath);

// Add the new dependency to the set of third-party dependencies.
this.addDependency(pkg);

// We can stop now.
break;
}

const parent = path.join(dir, '..');
dir = path.normalize(parent);
// Go up in the directory tree.
dir = path.normalize(path.join(dir, '..'));
}

// Update the cache
_.forEach(scannedDirs, (scannedDir) => {
this._cache[scannedDir] = pkg;
});
}

/**
Expand Down
48 changes: 48 additions & 0 deletions test/license-plugin.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
* SOFTWARE.
*/

const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const moment = require('moment');
const LicensePlugin = require('../dist/license-plugin.js');

Expand Down Expand Up @@ -69,6 +71,52 @@ describe('LicensePlugin', () => {
expect(plugin._dependencies).toEqual({});
});

it('should load pkg and update cache', () => {
const plugin = new LicensePlugin();
const fakePackage = path.join(__dirname, 'fixtures', 'fake-package');
const id = path.join(fakePackage, 'src', 'index.js');
const pkg = require(path.join(fakePackage, 'package.json'));

plugin.load(id);

expect(plugin._dependencies).toEqual({
'fake-package': _.pick(pkg, ['name', 'author', 'version', 'description', 'license', 'private']),
});

expect(plugin._cache).toEqual({
[path.join(__dirname, 'fixtures', 'fake-package', 'src')]: pkg,
[path.join(__dirname, 'fixtures', 'fake-package')]: pkg,
});
});

it('should load pkg and put null without package', () => {
const plugin = new LicensePlugin();
const id = path.join(__dirname, '..', 'src', 'index.js');

plugin.load(id);

expect(plugin._dependencies).toEqual({});
expect(plugin._cache).toEqual({
[path.normalize(path.join(__dirname, '..', 'src'))]: null,
});
});

it('should load pkg and use the cache if available', () => {
const plugin = new LicensePlugin();
const fakePackage = path.join(__dirname, 'fixtures', 'fake-package');
const id = path.join(fakePackage, 'src', 'index.js');

plugin._cache[path.join(fakePackage, 'src')] = null;
plugin._cache[fakePackage] = null;

spyOn(fs, 'existsSync').and.callThrough();

plugin.load(id);

expect(plugin._dependencies).toEqual({});
expect(fs.existsSync).not.toHaveBeenCalled();
});

it('should add dependency', () => {
const plugin = new LicensePlugin();
const pkg = {
Expand Down

0 comments on commit 79b2379

Please sign in to comment.