Refactor to split functions up into more re-usable chunks.

Also, you can override getHashForInput in order to base the input file hash off more than just the input file (eg. if you want to invalidate the cache if any of the file’s dependencies change).