TreeEntry: keep a copy of the underlying git_tree_entry

The tree entries exist more or less independently of the index they were
retrieved from. The idea behind them is that they can be kept by a
binding without needing to refer to the original anymore, which may
disappear at any moment if the index is modified.

Keep a copy of the data in TreeEntry instead of pointing to the one
retrieved from the index, which is not safe to keep around.
TreeEntry: allow creation of this object

They are not required to belong to a particular index, so it should be
possible to create them at runtime in order to insert them.
TreeEntry: make the attributes writable

When updating entries in an index, it is necessary to modify the
attributes of tree entries. make it possible to do so.
TreeEntry: accept either a path or a TreeEntry

A path is only useful if we have the file on the worktree. Passing a
TreeEntry allows us to add an entry with arbitrary attributes.
Index: allow writing the tree to a particular repository

Take an optional repository in Index.write_tree() to serialize to a tree
into a particular repository's odb.