That try/except block in repo.py is confusing but I think it is correct. Note that RefsContainer.__getitem__ and RefsContainer.set_if_equals follow all symbolic refs. By definition, committing a tree means advancing HEAD, whether or not it is a symbolic ref.
The "try" block first tries an atomic compare-and-swap of HEAD with the new commit. If that fails due to a KeyError, it means there is either no ref named HEAD, or HEAD is a broken symref (which is the default state in a new repo created). Then we do an atomic compare-and-add of HEAD. If HEAD didn't exist, this creates HEAD as a non-symref. If HEAD was a dangling symref, this writes through the symref, e.g. to refs/heads/master.
Following the tutorial as of a383e450, it seems to work. However, there is still a bug: the tutorial tells you to set "repo.refs['HEAD'] = 'ref: refs/heads/master'", which is wrong for two reasons:
1. HEAD is already set in a new repo, cf. Repo._init_maybe_bare.
2. Symbolic refs should be set with set_symbolic_ref; the 'ref: foo' syntax should be considered an implementation detail.
(3. There is no atomic compare-and-swap version of set_symbolic_ref, but we'll ignore that for this bug.)
I'll mail a patch for the tutorial that clarifies the setting of HEAD.
That try/except block in repo.py is confusing but I think it is correct. Note that RefsContainer. __getitem_ _ and RefsContainer. set_if_ equals follow all symbolic refs. By definition, committing a tree means advancing HEAD, whether or not it is a symbolic ref.
The "try" block first tries an atomic compare-and-swap of HEAD with the new commit. If that fails due to a KeyError, it means there is either no ref named HEAD, or HEAD is a broken symref (which is the default state in a new repo created). Then we do an atomic compare-and-add of HEAD. If HEAD didn't exist, this creates HEAD as a non-symref. If HEAD was a dangling symref, this writes through the symref, e.g. to refs/heads/master.
Following the tutorial as of a383e450, it seems to work. However, there is still a bug: the tutorial tells you to set "repo.refs['HEAD'] = 'ref: refs/heads/ master' ", which is wrong for two reasons: maybe_bare.
1. HEAD is already set in a new repo, cf. Repo._init_
2. Symbolic refs should be set with set_symbolic_ref; the 'ref: foo' syntax should be considered an implementation detail.
(3. There is no atomic compare-and-swap version of set_symbolic_ref, but we'll ignore that for this bug.)
I'll mail a patch for the tutorial that clarifies the setting of HEAD.