index: write blobs via git hash-object, not gitdb's odb.store - #2209
Merged
Conversation
caroescm
force-pushed
the
fix-index-add-chmod
branch
from
August 10, 2026 04:56
4dbefc1 to
7ab02c6
Compare
Byron
force-pushed
the
fix-index-add-chmod
branch
from
August 10, 2026 08:28
7ab02c6 to
139d0b1
Compare
Member
|
Thanks a lot for tackling this! I will see if an alternative solution can do the trick, as such a localized override goes against the original architecture. |
Byron
force-pushed
the
fix-index-add-chmod
branch
from
August 10, 2026 09:11
139d0b1 to
f202503
Compare
This is done by calling into `git hash-object` for correctness, instead of using a mostly incorrect custom implementation for this (lacks filters). <!-- agent --> GitCmdObjectDB inherited LooseObjectDB.store(), so despite its name, object writes bypassed Git and used gitdb's loose-object implementation. That path creates and chmods object files itself, which can fail during Index.add() on filesystems where those permission changes are unsupported. Override store() to stream new objects through `git hash-object -w --stdin`. This lets Git manage object creation and permissions consistently with the repository configuration. Retain the inherited implementation for pre-hashed objects and custom output streams, whose existing semantics hash-object cannot provide. Assisted-by: GPT 5.6 Co-authored-by: GPT 5.6 <codex@openai.com>
Byron
force-pushed
the
fix-index-add-chmod
branch
from
August 10, 2026 09:54
f202503 to
93677a0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
repo.index.add()is GitPython's own way of adding files, separate from just runninggit add. To do that, it writes the file's content into.git/objectsitself using Python, instead of askinggitto do it. As part of that, it also tries to change the new file's permissions (chmod) — and in some setups, that permission change isn't allowed, even though writing the file itself worked fine.So
index.add()can crash withPermissionErrorin situations where plaingit add(andrepo.git.add(...), which just runsgit adddirectly) work without any problem, on the same file.There's also a smaller side effect: because GitPython reads the file itself instead of asking
git, it skips any.gitattributesrules (like converting line endings), so the content it stores can end up slightly different from whatgit addwould store.What I changed
I changed
index.add()to use the realgit hash-object -wcommand to write the file into the object database, instead of doing it in Python. This means:chmod, so the crash goes away.git addwould store, filters included.Symlinks needed a small extra step:
git hash-objectnormally follows a symlink and hashes the file it points to, but Git is supposed to store the symlink's target path itself, not the pointed-to file. So for symlinks, I write the target path to a temporary file and hash that instead.Fixes #2021
Testing
test_index.py,test_base.py,test_repo.py) — all still pass.index.add()'s output to realgit addfor a normal file, a symlink, and a file in a subfolder — identical results.chmodonly on.git/objectsfiles (same as the error in repo.index.add() method attempts to chmod files which it should not #2021) —index.add()now works instead of crashing.