2

Does gitpython (or at a pinch any of the python git APIs) provide a way to stage selected hunks from a file in the working tree, like git add -i lets you do?

I think I can sort of see how to get an iterable of hunked changes by using difflib on the git.diff.Diff's a_blob and b_blob properties, but then how do I stage a particular hunk?

And, for bonus points, is there a better way to iterate over changes in a file than:

diff = repo.head.commit.diff(None)[0]
a = diff.a_blob.read().split(b'\n')
b = diff.b_blob.read().split(b'\n')
diff_generator = difflib.Differ().compare(a, b)

I'm thinking something that compares the streams, rather than having to load the whole lot into memory and then splitting it into lines.

Tom
  • 7,269
  • 1
  • 42
  • 69

1 Answers1

0

I haven't found a better way to construct an iterator over changes in a file. But this is how you would stage an in-memory version of the file:

new_version = '........'.encode('utf-8') # Or whatever encoding you use
istream = repo.odb.store(gitdb.IStream(git.Blob.type, len(new_version), BytesIO(new_version)))
file_mode = ... # eg os.stat(file_path).st_mode
entry = git.BaseIndexEntry((file_mode, istream.binsha, 0, file_path))
repo.index.add([entry])

The repo.odb.store call stores the version in the git database, but at this point it's not linked to anything. Creating the BaseIndexEntry object and adding it to the index then links that stored version into the index - the link is by the file path and the binsha hash.

It seems that this won't work on bare repositories.

Tom
  • 7,269
  • 1
  • 42
  • 69