Skip to content

Commit

Permalink
executor: fix race condition with forked git repos
Browse files Browse the repository at this point in the history
When installing packages from different directories of a forked
monorepo, a race condition may occur, where multiple git clients
are interacting in parallel with the same git repository.

Fix by serializing git operations that interact with the same
git repository.

This makes the test succeed. Remove xfail.

Links:
#9658 (comment)
https://github.com/orgs/python-poetry/discussions/9718#discussioncomment-10785589
  • Loading branch information
TheSven73 committed Sep 29, 2024
1 parent c67c10d commit cc45daf
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 5 deletions.
14 changes: 10 additions & 4 deletions src/poetry/installation/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from poetry.utils.helpers import remove_directory
from poetry.utils.isolated_build import IsolatedBuildError
from poetry.utils.isolated_build import IsolatedBuildInstallError
from poetry.vcs.git import Git


if TYPE_CHECKING:
Expand All @@ -46,6 +47,12 @@
from poetry.utils.env import Env


def _package_get_name(package: Package) -> str | None:
if url := package.repository_url:
return Git.get_name_from_source_url(url)
return None


class Executor:
def __init__(
self,
Expand Down Expand Up @@ -167,8 +174,9 @@ def execute(self, operations: list[Operation]) -> int:
if is_parallel_unsafe:
serial_operations.append(operation)
elif operation.package.source_type == "git":
# Git operations on the same repository should be executed serially
serial_git_operations[operation.package.source_url].append(
# Serially execute git operations that get cloned to the same directory,
# to prevent multiple parallel git operations in the same repo.
serial_git_operations[_package_get_name(operation.package)].append(
operation
)
else:
Expand Down Expand Up @@ -604,8 +612,6 @@ def _prepare_archive(
)

def _prepare_git_archive(self, operation: Install | Update) -> Path:
from poetry.vcs.git import Git

package = operation.package
assert package.source_url is not None

Expand Down
1 change: 0 additions & 1 deletion tests/installation/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,6 @@ def test_executor_should_install_multiple_packages_from_same_git_repository(
assert len(spy.call_args_list) == 2


@pytest.mark.xfail
def test_executor_should_install_multiple_packages_from_forked_git_repository(
mocker: MockerFixture,
tmp_venv: VirtualEnv,
Expand Down

0 comments on commit cc45daf

Please sign in to comment.