Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

fix(hooks): run .hooks scripts even if package.json script is not present #13

Merged
merged 1 commit into from
Mar 15, 2018

Conversation

mikesherov
Copy link
Collaborator

Fixes: npm/npm#19258

@mikesherov
Copy link
Collaborator Author

@zkat this should be good to land after your review.

Copy link
Contributor

@zkat zkat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this patch! I'd like some implementation changes to go with this, but I really appreciate that you put up a test too <3

index.js Outdated
function hookExists (dir, stage) {
const hook = path.join(dir, '.hooks', stage)
if (_hookExistsCache[hook] === undefined) {
_hookExistsCache[hook] = fs.existsSync(hook)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd feel much more comfortable if this were an async operation. Also, fs.exists is deprecated in Node, so you'll have to use fs.stat with a catcher for err.code === 'ENOENT'.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think sync is fine here considering the cache may only get 3 or 4 values in it (opts.dir is constant, so the size of the cache is like 3 or 4), but happy to go async. I’ll do the change.

index.js Outdated
if (!pkg.scripts[stage]) return resolve()
// makeEnv is a slow operation. This guard clause prevents makeEnv being called
// and avoids a ton of unnecessary work, and results in a major perf boost.
if (!pkg.scripts[stage] && !hookExists(opts.dir, stage)) return resolve()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above comment about async-ifying this.

index.js Outdated
@@ -16,6 +16,7 @@ const byline = require('byline')
const resolveFrom = require('resolve-from')

const DEFAULT_NODE_GYP_PATH = resolveFrom(__dirname, 'node-gyp/bin/node-gyp')
const _hookExistsCache = {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather this be a new Set(), since that's gonna be pretty efficient for this use-cases. There's a good chance we might be hammering this cache a lot.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has that been benchmarked? for string keys, Object.create(null) might actually be faster than a Set.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to cache positive and negative values, so Set seems inappropriate here. Also, the perf overhead here is peanuts, but I wouldn’t mind switching it out for Object.create(null) if that satisfies the micro optimization gods :-)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or I can use Map, but all-in-all I think any of the 3 choices is ok. Make the call and I’ll switch it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Map is conceptually correct since you need more than just presence; a null object is likely to be faster based on recent benchmarks on a recent aphrodite PR - either seems fine to me, but I’d suggest not using a normal object.

Copy link
Contributor

@zkat zkat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more tiny change and we're all set!

index.js Outdated
})
}

return cb(cachedStatError)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you dezalgo this? (just setImmediate the callback)

Copy link
Contributor

@zkat zkat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay! This looks great! Thanks for the great work as always, Mike!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants