start rewriting Cache based on git, __init__ and put_tree
tree_status()
tree_status returns a proper TreeStatus tuple
put_tree() using git commit
get_tree()
put_key() and get_key()
have put_key() write to a temp file for safety
Remote.get_tree()
separate KeyVal into its own class, with a dict interface
Rule.get_tree()

Neither Rule.get_tree nor Remote.get_tree is currently handling imports.
We need to add that back in next.
prevent git from reading global configs
reimplement export_tree with git-checkout

export_tree() now takes an optional previous_hash (defaults to a hash
representing the empty commit). The export is then implemented as a
checkout from the previous_hash to the hash being exported. That means
we get status checking for free. We will also use this feature to keep
imports clean in local modules.
a very temporary test.py to sanity check these big changes
always pass around tree hashes

We want to create commits, to avoid garbage collection and to give some
visibility into the state of the cache. But we don't want commit hashes
to make their way into cache keys, because those hashes won't be
consistent from one repo to another (timestamps etc). Keep the commits
hidden in the internals of Cache, and only return tree hashes to
callers.
make Rule and Remote fields more explicit

Preparing for a proper parser class, to handle all the YAML details.
first version of Parser, splitting out RemoteModule
Resolver
handle imports
create LocalModule, and make Parser return one
update main