Make revision/release identifiers explicitly the hash of a manifest
This collapses the shared logic between these two identifier computations into a
few more explicit steps:
- generate data for the manifest (in either identifier computation);
- format the manifest (in the new format_manifest function);
- hash the manifest (in the new hash_manifest function).
This will enable reusing this logic for more object types, as well as stronger
typing for the manifest computation.