diff --git a/src/lando/pushlog/pushlog.py b/src/lando/pushlog/pushlog.py index 263bf406..e1c8cea2 100644 --- a/src/lando/pushlog/pushlog.py +++ b/src/lando/pushlog/pushlog.py @@ -1,5 +1,7 @@ +from datetime import datetime import logging from contextlib import contextmanager +from typing import Optional from django.db import transaction @@ -11,8 +13,8 @@ @contextmanager -def PushLogForRepo(repo: Repo): - pushlog = PushLog(repo) +def PushLogForRepo(repo: Repo, user: str): + pushlog = PushLog(repo, user) try: yield pushlog except Exception as e: @@ -31,31 +33,53 @@ def PushLogForRepo(repo: Repo): class PushLog: repo: Repo push: Push + user: str commits: list + files: dict[str, list[str]] - def __repr__(self): - return f"<{self.__class__.__name__}({self.repo}, {self.commits})>" - - def __init__(self, repo: Repo): + def __init__(self, repo: Repo, user: str, commits: list = [], + files: dict[str, list[str]] = {}): self.repo = repo - self.commits = [] + self.user = user + + if not commits: + # We cannot us the default value of the argument as a mutable type, and will + # get reused on every initialisation. + commits = [] + self.commits = commits + + if not files: + # Same a commits above. + files = {} + self.files = files + + def __repr__(self): + return f"<{self.__class__.__name__}({self.repo}, {self.user}, {self.commits})>" # def add_commit(self, revision: Revision) -> Commit: - def add_commit(self, hash: str): + def add_commit(self, hash: str, files: list[str]): # XXX need a container with # author # date # desc # files # PARENTS - self.commits.append(hash) + + # We create a commit object in memory, but will only write it into the DB when + # the whole push is done, and we have a transaction open. + self.commits.append(Commit(hash=hash, date=datetime.now())) + # We can only attach files to the Commit when it exists in the DB, so we hold + # them here in the meantime. + self.files[hash] = files @transaction.atomic def record_push(self): - push = Push.objects.create(self.repo) + """Flush all push data to the database""" + push = Push.objects.create(repo=self.repo, user=self.user) for commit in self.commits: - commit = Commit.objects.create(self.repo, hash=hash) + commit.save() + commit.add_files(self.files[commit.hash]) push.commits.add(commit) push.save() diff --git a/src/lando/pushlog/tests/conftest.py b/src/lando/pushlog/tests/conftest.py index ea15b235..a5e3592d 100644 --- a/src/lando/pushlog/tests/conftest.py +++ b/src/lando/pushlog/tests/conftest.py @@ -1,5 +1,4 @@ from datetime import datetime - import pytest from lando.main.models import Repo diff --git a/src/lando/pushlog/tests/test_pushlog.py b/src/lando/pushlog/tests/test_pushlog.py index a9dd7f03..0f97b928 100644 --- a/src/lando/pushlog/tests/test_pushlog.py +++ b/src/lando/pushlog/tests/test_pushlog.py @@ -7,25 +7,26 @@ def test__pushlog__PushLog(make_repo): repo = make_repo(1) - with PushLogForRepo(repo) as pushlog: + with PushLogForRepo(repo, 'user@moz.test') as pushlog: print(pushlog) # r = pushlog.add_revision(...) # r.add_files( ...) + raise AssertionError('unfinished') @pytest.mark.django_db() def test__pushlog__PushLog_no_commit_on_exception(make_repo): repo = make_repo(1) try: - with PushLogForRepo(repo) as pushlog: + with PushLogForRepo(repo, 'user@moz.test') as pushlog: print(pushlog) raise Exception() except Exception: pass - assert False # XXX test that pushlog not updated + raise AssertionError('unfinished') @pytest.mark.django_db() @@ -33,9 +34,11 @@ def test__pushlog__PushLog__no_deadlock(make_repo): repo1 = make_repo(1) repo2 = make_repo(2) - with PushLogForRepo(repo1) as pushlog1: - with PushLogForRepo(repo2) as pushlog2: + with PushLogForRepo(repo1, 'user1@moz.test') as pushlog1: + with PushLogForRepo(repo2, 'user2@moz.test') as pushlog2: print(pushlog1) print(pushlog2) # r = pushlog.add_revision(...) # r.add_files( ...) + + raise AssertionError('unfinished')