libgit2 / pygit2

Python bindings for libgit2
https://www.pygit2.org/
Other
1.58k stars 382 forks source link

Add RemoteCollection.names() iterator #1159

Closed agausmann closed 1 year ago

agausmann commented 1 year ago

Motivation

This names() iterator provides a big benefit in performance in my use case, where I want to test whether or not a remote exists for a large number of potential remote names (hundreds)

The first code I used looked something like:

try:
    repo.remotes[remote_name]
except KeyError:
    repo.remotes.create(remote_name, remote_url)

However, this performs a lookup for all remote names, which was prohibitively expensive. So I decided to try collecting all the names into a set beforehand:

existing_remotes = set(remote.name for remote in repo.remotes)

for remote_name, remote_url in wanted_remotes:
    if remote_name not in existing_remotes:
        repo.remotes.create(remote_name, remote_url)

However, this still performs a lookup for each remote to create the Remote objects yielded by the iterator.

With RemoteCollection.names(), I can construct the set much more efficiently:

existing_remotes = set(repo.remotes.names())
jdavid commented 1 year ago

Thanks, please add a unit test.

jdavid commented 1 year ago

For reference I think iteration should yield the names, like references/branches do, but that breaks compatibility. Also I'm unsure which is best names() or keys(), names is more like git, keys is more like python.