Как получить последний коммит для указанного файла с python(dulwich)?
Мне нужно имя автора и время последнего принятия для указанного файла с Python. В настоящее время я пытаюсь использовать Дульвич.
Существует множество API для извлечения объектов для определенного SHA, например:
repo = Repo("myrepo")
head = repo.head()
object = repo.get_object(head)
author = object.author
time = object.commit_time
Но как мне узнать недавний коммит для конкретного файла? Есть ли способ получить его, как:
repo = Repo("myrepo")
commit = repo.get_commit('a.txt')
author = commit.author
time = commit.commit_time
или же
repo = Repo("myrepo")
sha = repo.get_sha_for('a.txt')
object = repo.get_object(sha)
author = object.author
time = object.commit_time
Спасибо.
3 ответа
Решение
Нечто подобное похоже на работу:
from dulwich import repo, diff_tree
fn = 'a.txt'
r = repo.Repo('.')
prev = None
walker = r.get_graph_walker()
cset = walker.next()
while cset is not None:
commit = r.get_object(cset)
if prev is None:
prev = commit.tree
cset = walker.next()
continue
res = None
delta = diff_tree.tree_changes(r, prev, commit.tree)
for x in diff_tree.tree_changes(r, prev, commit.tree):
if x.new.path == fn:
res = cset
break
if res:
break
prev = commit.tree
cset = walker.next()
print fn, res
Более короткий пример, используя Repo.get_walker
:
r = Repo(".")
p = "the/file/to/look/for"
w = r.get_walker(paths=[p], max_entries=1)
try:
c = iter(w).next().commit
except StopIteration:
print "No file %s anywhere in history." % p
else:
print "%s was last changed at %s by %s (commit %s)" % (
p, time.ctime(c.author_time), c.author, c.id)
Ответ, обновленный для python 3.10 и Dulwich 0.20.32 или более поздней версии , основан на ответе user291383 здесь .
from dulwich import repo
import datetime
r = repo.Repo("path/to/repo")
p = b"relative/path/to/file/in/repo" # Must be bytes not string
w = r.get_walker(paths=[p], max_entries=1)
l = list(w)
if l:
c = l[0].commit
when = datetime.datetime.fromtimestamp(c.author_time)
print(f"{p} last modified {when} by {c.author} in {c.id}")
else:
print(f"No file called {p} found in repo")
Однако я нахожу это очень медленным (в моем тестовом репозитории 0,688 секунды) , эквивалент с использованием GitPython для меня быстрее (0,453 секунды) :
import git # import of GitPython
repo = git.repo.Repo("path/to/repo")
p = "relative/path/to/file/in/repo" # Note string rather than bytes
walker = repo.iter_commits(paths=[p, ], max_count=1)
l = list(walker)
if l:
c = l[0]
print(f"{p} last modified {c.authored_datetime} by {c.author} in {c}")
else:
print(f"No file called {p} found in repo")