Skip to content

Add test for Git LFS repository cloning

dc35ae0
Select commit
Loading
Failed to load commit list.
Open

Add test for Git LFS repository cloning #10724

Add test for Git LFS repository cloning
dc35ae0
Select commit
Loading
Failed to load commit list.
Cirrus CI / Tests / FreeBSD (Python 3.11) / pytest failed Feb 9, 2026 in 5m 22s

Task Summary

Instruction pytest failed in 02:38

Details

✅ 00:05 clone
✅ 01:42 bootstrap_poetry
✅ 00:53 setup_environment
❌ 02:38 pytest

              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:636: in download
    batch_resp = self.batch("download", [{"oid": oid, "size": size}], ref)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:581: in batch
    response = self._make_request(
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:548: in _make_request
    response = pool_manager.request(method, url, headers=req_headers, body=data)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/_request_methods.py:143: in request
    return self.request_encode_body(
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/_request_methods.py:278: in request_encode_body
    return self.urlopen(method, url, **extra_kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/poolmanager.py:446: in urlopen
    conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib3.poolmanager.PoolManager object at 0x2f96d861bb10>, host = None
port = None, scheme = 'file', pool_kwargs = None

    def connection_from_host(
        self,
        host: str | None,
        port: int | None = None,
        scheme: str | None = "http",
        pool_kwargs: dict[str, typing.Any] | None = None,
    ) -> HTTPConnectionPool:
        """
        Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme.
    
        If ``port`` isn't given, it will be derived from the ``scheme`` using
        ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is
        provided, it is merged with the instance's ``connection_pool_kw``
        variable and used to create the new connection pool, if one is
        needed.
        """
    
        if not host:
>           raise LocationValueError("No host specified.")
E           urllib3.exceptions.LocationValueError: No host specified.

/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/poolmanager.py:308: LocationValueError
-------------- generated xml file: /tmp/cirrus-ci-build/junit.xml --------------
=========================== short test summary info ============================
SKIPPED [1] tests/utils/test_python_manager.py:104: Windows only
SKIPPED [1] tests/utils/env/test_env_manager.py:1269: requires darwin
SKIPPED [1] tests/integration/test_utils_vcs_git.py:324: HTTP authentication credentials not available
SKIPPED [1] tests/console/commands/test_run.py:158: Poetry only installs CMD script files for console scripts of editable dependencies on Windows
SKIPPED [1] tests/installation/test_executor.py:506: https://github.com/python-poetry/poetry/issues/7983
SKIPPED [1] tests/console/commands/self/test_sync.py:26: Only relevant for `poetry self install`
SKIPPED [1] tests/console/commands/test_sync.py:26: Only relevant for `poetry install`
SKIPPED [3] tests/console/commands/env/test_activate.py:54: Only Windows shells
FAILED tests/vcs/git/test_backend.py::test_clone_with_lfs_files - urllib3.exceptions.LocationValueError: No host specified.
============ 1 failed, 2933 passed, 10 skipped in 154.29s (0:02:34) ============

Annotations

Check failure on line 149 in lfs.py

See this annotation in the file changed.

@cirrus-ci cirrus-ci / Tests / FreeBSD (Python 3.11) / pytest

lfs.py#L149

tests.vcs.git.test_backend.test_clone_with_lfs_files
Raw output
self = <dulwich.lfs.LFSStore object at 0x2f96d93538d0>
sha = '5afb784414f946b679ffef3b9b45da7915e3b95e1c56e6a9da0678ce98d3b271'

    def open_object(self, sha: str) -> BinaryIO:
        """Open an object by sha."""
        try:
>           return open(self._sha_path(sha), "rb")
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E           FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-root/pytest-0/popen-gw1/test_clone_with_lfs_files0/clone-root/clone-test/.git/lfs/objects/5a/fb/5afb784414f946b679ffef3b9b45da7915e3b95e1c56e6a9da0678ce98d3b271'

/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:149: FileNotFoundError

The above exception was the direct cause of the following exception:

self = <dulwich.lfs.LFSFilterDriver object at 0x2f96d8619c10>
data = b'version https://git-lfs.github.com/spec/v1\noid sha256:5afb784414f946b679ffef3b9b45da7915e3b95e1c56e6a9da0678ce98d3b271\nsize 51\n'
path = b'large.bin'

    def smudge(self, data: bytes, path: bytes = b"") -> bytes:
        """Convert LFS pointer to file content (smudge filter)."""
        # Try to parse as LFS pointer
        pointer = LFSPointer.from_bytes(data)
        if pointer is None:
            # Not an LFS pointer, return as-is
            return data
    
        # Validate the pointer
        if not pointer.is_valid_oid():
            return data
    
        try:
            # Read the actual content from LFS store
>           with self.lfs_store.open_object(pointer.oid) as f:
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:294: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dulwich.lfs.LFSStore object at 0x2f96d93538d0>
sha = '5afb784414f946b679ffef3b9b45da7915e3b95e1c56e6a9da0678ce98d3b271'

    def open_object(self, sha: str) -> BinaryIO:
        """Open an object by sha."""
        try:
            return open(self._sha_path(sha), "rb")
        except FileNotFoundError as exc:
>           raise KeyError(sha) from exc
E           KeyError: '5afb784414f946b679ffef3b9b45da7915e3b95e1c56e6a9da0678ce98d3b271'

/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:151: KeyError

During handling of the above exception, another exception occurred:

tmp_path = PosixPath('/tmp/pytest-of-root/pytest-0/popen-gw1/test_clone_with_lfs_files0')

    @pytest.mark.skip_git_mock
    def test_clone_with_lfs_files(tmp_path: Path) -> None:
        """Test cloning a repository with Git LFS files (issue #8723)."""
        from dulwich import porcelain
        from dulwich.lfs import LFSStore
    
        # Create a source repository with LFS support
        source_path = tmp_path / "source-repo"
        source_path.mkdir()
        repo = Repo.init(str(source_path))
    
        # Set up LFS in the repository
        lfs_dir = source_path / ".git" / "lfs"
        lfs_dir.mkdir(parents=True)
        lfs_store = LFSStore.create(str(lfs_dir))
    
        # Configure LFS URL in the repository config
        config = repo.get_config()
        config.set((b"lfs",), b"url", lfs_dir.as_uri().encode())
        config.write_to_path()
    
        # Configure .gitattributes to track large files with LFS
        gitattributes = source_path / ".gitattributes"
        gitattributes.write_text("*.bin filter=lfs diff=lfs merge=lfs -text\n")
        porcelain.add(repo, str(gitattributes))
    
        # Create a regular file
        regular_file = source_path / "regular.txt"
        regular_file.write_text("This is a regular file")
        porcelain.add(repo, str(regular_file))
    
        # Create an LFS file with a pointer
        lfs_content = b"This is a large binary file content for LFS storage"
        lfs_file = source_path / "large.bin"
    
        # Store the actual content in LFS store and create pointer
        lfs_object_id = lfs_store.write_object([lfs_content])
        lfs_pointer = (
            f"version https://git-lfs.github.com/spec/v1\n"
            f"oid sha256:{lfs_object_id}\n"
            f"size {len(lfs_content)}\n"
        )
        lfs_file.write_text(lfs_pointer)
        porcelain.add(repo, str(lfs_file))
    
        # Commit the files
        porcelain.commit(
            repo,
            message=b"Add files with LFS support",
            author=b"Test <test@example.com>",
            committer=b"Test <test@example.com>",
        )
    
        # Clone the repository
        source_root_dir = tmp_path / "clone-root"
        source_root_dir.mkdir()
>       Git.clone(
            url=source_path.as_uri(),
            source_root=source_root_dir,
            name="clone-test",
        )

/tmp/cirrus-ci-build/tests/vcs/git/test_backend.py:351: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/tmp/cirrus-ci-build/src/poetry/vcs/git/backend.py:556: in clone
    local = cls._clone(url=url, refspec=refspec, target=target)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/tmp/cirrus-ci-build/src/poetry/vcs/git/backend.py:402: in _clone
    local.get_worktree().reset_index()
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/worktree.py:744: in reset_index
    return build_index_from_tree(
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/index.py:2030: in build_index_from_tree
    obj = blob_normalizer.checkout_normalize(obj, entry.path)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/filters.py:983: in checkout_normalize
    filtered_data = filter_driver.smudge(blob.data, path)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:299: in smudge
    content = self._download_object(pointer)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:327: in _download_object
    content = client.download(pointer.oid, pointer.size)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:636: in download
    batch_resp = self.batch("download", [{"oid": oid, "size": size}], ref)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:581: in batch
    response = self._make_request(
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/dulwich/lfs.py:548: in _make_request
    response = pool_manager.request(method, url, headers=req_headers, body=data)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/_request_methods.py:143: in request
    return self.request_encode_body(
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/_request_methods.py:278: in request_encode_body
    return self.urlopen(method, url, **extra_kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/poolmanager.py:446: in urlopen
    conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <urllib3.poolmanager.PoolManager object at 0x2f96d861bb10>, host = None
port = None, scheme = 'file', pool_kwargs = None

    def connection_from_host(
        self,
        host: str | None,
        port: int | None = None,
        scheme: str | None = "http",
        pool_kwargs: dict[str, typing.Any] | None = None,
    ) -> HTTPConnectionPool:
        """
        Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme.
    
        If ``port`` isn't given, it will be derived from the ``scheme`` using
        ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is
        provided, it is merged with the instance's ``connection_pool_kw``
        variable and used to create the new connection pool, if one is
        needed.
        """
    
        if not host:
>           raise LocationValueError("No host specified.")
E           urllib3.exceptions.LocationValueError: No host specified.

/.cache/pypoetry/virtualenvs/poetry-XZqP7kBn-py3.11/lib/python3.11/site-packages/urllib3/poolmanager.py:308: LocationValueError