Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dulwich does not support Dumb Git transport #6999

Closed
4 tasks done
rruiter87 opened this issue Nov 10, 2022 · 23 comments
Closed
4 tasks done

Dulwich does not support Dumb Git transport #6999

rruiter87 opened this issue Nov 10, 2022 · 23 comments
Labels
area/vcs Related to support for VCS dependencies (Git and Dulwich) status/external-issue Issue is caused by external project (platform, dep, etc)

Comments

@rruiter87
Copy link

  • I am on the latest stable Poetry version, installed using a recommended method.
  • I have searched the issues of this repo and believe that this is not a duplicate.
  • I have consulted the FAQ and blog for any relevant entries or release notes.
  • If an exception occurs when executing a command, I executed it again in debug mode (-vvv option) and have included the output below.

Issue

I'm unable to add git dependencies both via https and ssh. If I just do a regular git clone <repo> it works for ssh.

HTTPS

❯ poetry add git+https://github.com:mbuesch/pyprofibus.git -vvv
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310
[keyring.backend] Loading KWallet
[keyring.backend] Loading SecretService
[keyring.backend] Loading Windows
[keyring.backend] Loading chainer
[keyring.backend] Loading libsecret
[keyring.backend] Loading macOS
[urllib3.connectionpool] Starting new HTTPS connection (1): github.com:443
[urllib3.connectionpool] https://github.com:443 "GET /mbuesch/pyprofibus.git/info/refs?service=git-upload-pack HTTP/1.1" 200 None
Cloning https://github.com/mbuesch/pyprofibus.git at 'HEAD' to C:\Users\rruiter\Miniconda3\envs\profinet310\src\pyprofibus
[urllib3.connectionpool] Starting new HTTPS connection (1): git.bues.ch:443
[urllib3.connectionpool] https://git.bues.ch:443 "GET /git/crcgen.git/info/refs?service=git-upload-pack HTTP/1.1" 200 817

  Stack trace:

  23  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:329 in run
       327│
       328│             try:
     → 329│                 exit_code = self._run(io)
       330│             except Exception as e:
       331│                 if not self._catch_exceptions:

  22  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\application.py:185 in _run
       183│         self._load_plugins(io)
       184│
     → 185│         exit_code: int = super()._run(io)
       186│         return exit_code
       187│

  21  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:423 in _run
       421│             io.input.set_stream(stream)
       422│
     → 423│         exit_code = self._run_command(command, io)
       424│         self._running_command = None
       425│

  20  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:465 in _run_command
       463│
       464│         if error is not None:
     → 465│             raise error
       466│
       467│         return event.exit_code

  19  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:449 in _run_command
       447│
       448│             if event.command_should_run():
     → 449│                 exit_code = command.run(io)
       450│             else:
       451│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

  18  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\base_command.py:119 in run
       117│         io.input.validate()
       118│
     → 119│         status_code = self.execute(io)
       120│
       121│         if status_code is None:

  17  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\command.py:83 in execute
        81│
        82│         try:
     →  83│             return self.handle()
        84│         except KeyboardInterrupt:
        85│             return 1

  16  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\add.py:158 in handle
       156│             return 0
       157│
     → 158│         requirements = self._determine_requirements(
       159│             packages,
       160│             allow_prereleases=self.option("allow-prereleases"),

  15  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:357 in _determine_requirements
       355│
       356│         result = []
     → 357│         for requirement in self._parse_requirements(requires):
       358│             if "git" in requirement or "url" in requirement or "path" in requirement:
       359│                 result.append(requirement)

  14  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:416 in _parse_requirements
       414│             cwd = Path.cwd()
       415│
     → 416│         return [
       417│             parse_dependency_specification(
       418│                 requirement=requirement,

  13  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:417 in <listcomp>
       415│
       416│         return [
     → 417│             parse_dependency_specification(
       418│                 requirement=requirement,
       419│                 env=self.env if isinstance(self, EnvCommand) else None,

  12  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:216 in parse_dependency_specification
       214│
       215│     specification = (
     → 216│         _parse_dependency_specification_url(requirement, env=env)
       217│         or _parse_dependency_specification_path(requirement, cwd=cwd)
       218│         or _parse_dependency_specification_simple(requirement)

  11  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:68 in _parse_dependency_specification_url
        66│
        67│     if url_parsed.scheme in ["git+https", "git+ssh"]:
     →  68│         return _parse_dependency_specification_git_url(requirement, env)
        69│
        70│     if url_parsed.scheme in ["http", "https"]:

  10  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:49 in _parse_dependency_specification_git_url
        47│
        48│     source_root = env.path.joinpath("src") if env else None
     →  49│     package = Provider.get_package_from_vcs(
        50│         "git",
        51│         url=url.url,

   9  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:341 in get_package_from_vcs
       339│             raise ValueError(f"Unsupported VCS dependency {vcs}")
       340│
     → 341│         return _get_package_from_git(
       342│             url=url,
       343│             branch=branch,

   8  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:95 in _get_package_from_git
        93│     source_root: Path | None = None,
        94│ ) -> Package:
     →  95│     source = Git.clone(
        96│         url=url,
        97│         source_root=source_root,

   7  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:427 in clone
       425│             if not cls.is_using_legacy_client():
       426│                 local = cls._clone(url=url, refspec=refspec, target=target)
     → 427│                 cls._clone_submodules(repo=local)
       428│                 return local
       429│         except HTTPUnauthorized:

   6  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:356 in _clone_submodules
       354│                         continue
       355│
     → 356│                 cls.clone(
       357│                     url=url.decode("utf-8"),
       358│                     source_root=source_root,

   5  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:426 in clone
       424│         try:
       425│             if not cls.is_using_legacy_client():
     → 426│                 local = cls._clone(url=url, refspec=refspec, target=target)
       427│                 cls._clone_submodules(repo=local)
       428│                 return local

   4  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:258 in _clone
       256│             local = Repo(str(target))
       257│
     → 258│         remote_refs = cls._fetch_remote_refs(url=url, local=local)
       259│
       260│         logger.debug(

   3  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:201 in _fetch_remote_refs
       199│
       200│         with local:
     → 201│             result: FetchPackResult = client.fetch(
       202│                 path,
       203│                 local,

   2  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:837 in fetch
        835│             f, commit, abort = target.object_store.add_pack()
        836│         try:
     →  837│             result = self.fetch_pack(
        838│                 path,
        839│                 determine_wants,

   1  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:2076 in fetch_pack
       2074│         """
       2075│         url = self._get_url(path)
     → 2076│         refs, server_capabilities, url = self._discover_references(
       2077│             b"git-upload-pack", url
       2078│         )

  AttributeError

  'NoneType' object has no attribute 'startswith'

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1946 in _discover_references
      1942│                 )
      1943│             base_url = resp.redirect_location[: -len(tail)]
      1944│
      1945│         try:
    → 1946│             self.dumb = not resp.content_type.startswith("application/x-git-")
      1947│             if not self.dumb:
      1948│                 proto = Protocol(read, None)
      1949│                 # The first line should mention the service
      1950│                 try:

SSH

❯ poetry add git+ssh://github.com:mbuesch/pyprofibus.git -vvv
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310

  Stack trace:

  3  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1149 in fetch_pack
      1147│         with proto:
      1148│             try:
    → 1149│                 refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
      1150│             except HangupException as exc:
      1151│                 raise _remote_error_from_stderr(stderr) from exc

  2  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:253 in read_pkt_refs
       251│     refs = {}
       252│     # Receive refs from server
    →  253│     for pkt in pkt_seq:
       254│         (sha, ref) = pkt.rstrip(b"\n").split(None, 1)
       255│         if sha == b"ERR":

  1  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\protocol.py:277 in read_pkt_seq
      275│             flush-pkt.
      276│         """
    → 277│         pkt = self.read_pkt_line()
      278│         while pkt:
      279│             yield pkt

  HangupException

  The remote server unexpectedly closed the connection.

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\protocol.py:220 in read_pkt_line
      216│
      217│         try:
      218│             sizestr = read(4)
      219│             if not sizestr:
    → 220│                 raise HangupException()
      221│             size = int(sizestr, 16)
      222│             if size == 0:
      223│                 if self.report_activity:
      224│                     self.report_activity(4, "read")

The following error occurred when trying to handle this error:


  Stack trace:

  20  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:329 in run
       327│
       328│             try:
     → 329│                 exit_code = self._run(io)
       330│             except Exception as e:
       331│                 if not self._catch_exceptions:

  19  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\application.py:185 in _run
       183│         self._load_plugins(io)
       184│
     → 185│         exit_code: int = super()._run(io)
       186│         return exit_code
       187│

  18  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:423 in _run
       421│             io.input.set_stream(stream)
       422│
     → 423│         exit_code = self._run_command(command, io)
       424│         self._running_command = None
       425│

  17  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:465 in _run_command
       463│
       464│         if error is not None:
     → 465│             raise error
       466│
       467│         return event.exit_code

  16  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:449 in _run_command
       447│
       448│             if event.command_should_run():
     → 449│                 exit_code = command.run(io)
       450│             else:
       451│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

  15  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\base_command.py:119 in run
       117│         io.input.validate()
       118│
     → 119│         status_code = self.execute(io)
       120│
       121│         if status_code is None:

  14  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\command.py:83 in execute
        81│
        82│         try:
     →  83│             return self.handle()
        84│         except KeyboardInterrupt:
        85│             return 1

  13  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\add.py:158 in handle
       156│             return 0
       157│
     → 158│         requirements = self._determine_requirements(
       159│             packages,
       160│             allow_prereleases=self.option("allow-prereleases"),

  12  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:357 in _determine_requirements
       355│
       356│         result = []
     → 357│         for requirement in self._parse_requirements(requires):
       358│             if "git" in requirement or "url" in requirement or "path" in requirement:
       359│                 result.append(requirement)

  11  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:416 in _parse_requirements
       414│             cwd = Path.cwd()
       415│
     → 416│         return [
       417│             parse_dependency_specification(
       418│                 requirement=requirement,

  10  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:417 in <listcomp>
       415│
       416│         return [
     → 417│             parse_dependency_specification(
       418│                 requirement=requirement,
       419│                 env=self.env if isinstance(self, EnvCommand) else None,

   9  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:216 in parse_dependency_specification
       214│
       215│     specification = (
     → 216│         _parse_dependency_specification_url(requirement, env=env)
       217│         or _parse_dependency_specification_path(requirement, cwd=cwd)
       218│         or _parse_dependency_specification_simple(requirement)

   8  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:68 in _parse_dependency_specification_url
        66│
        67│     if url_parsed.scheme in ["git+https", "git+ssh"]:
     →  68│         return _parse_dependency_specification_git_url(requirement, env)
        69│
        70│     if url_parsed.scheme in ["http", "https"]:

   7  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:49 in _parse_dependency_specification_git_url
        47│
        48│     source_root = env.path.joinpath("src") if env else None
     →  49│     package = Provider.get_package_from_vcs(
        50│         "git",
        51│         url=url.url,

   6  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:341 in get_package_from_vcs
       339│             raise ValueError(f"Unsupported VCS dependency {vcs}")
       340│
     → 341│         return _get_package_from_git(
       342│             url=url,
       343│             branch=branch,

   5  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:95 in _get_package_from_git
        93│     source_root: Path | None = None,
        94│ ) -> Package:
     →  95│     source = Git.clone(
        96│         url=url,
        97│         source_root=source_root,

   4  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:426 in clone
       424│         try:
       425│             if not cls.is_using_legacy_client():
     → 426│                 local = cls._clone(url=url, refspec=refspec, target=target)
       427│                 cls._clone_submodules(repo=local)
       428│                 return local

   3  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:258 in _clone
       256│             local = Repo(str(target))
       257│
     → 258│         remote_refs = cls._fetch_remote_refs(url=url, local=local)
       259│
       260│         logger.debug(

   2  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:201 in _fetch_remote_refs
       199│
       200│         with local:
     → 201│             result: FetchPackResult = client.fetch(
       202│                 path,
       203│                 local,

   1  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:837 in fetch
        835│             f, commit, abort = target.object_store.add_pack()
        836│         try:
     →  837│             result = self.fetch_pack(
        838│                 path,
        839│                 determine_wants,

  HangupException

  d\\rruiter@github.com: Permission denied (publickey).

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1151 in fetch_pack
      1147│         with proto:
      1148│             try:
      1149│                 refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
      1150│             except HangupException as exc:
    → 1151│                 raise _remote_error_from_stderr(stderr) from exc
      1152│             (
      1153│                 negotiated_capabilities,
      1154│                 symrefs,
      1155│                 agent,
@rruiter87 rruiter87 added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Nov 10, 2022
@finswimmer
Copy link
Member

Hey @rruiter87,

does it work if you set experimental.system-git-client to true (https://python-poetry.org/docs/configuration/#experimentalsystem-git-client)?

fin swimmer

@rruiter87
Copy link
Author

SSH no, HTTPS yes

I set the option with

 ❯ poetry config experimental.system-git-client true

SSH 🔴

❯ poetry add git+ssh://github.com:mbuesch/pyprofibus.git -vvv
Loading configuration file C:\Users\rruiter\AppData\Roaming\pypoetry\config.toml
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310
Cloning 'github.com:mbuesch/pyprofibus.git' using system git client

Failed to clone github.com:mbuesch/pyprofibus.git, check your git configuration and permissions for this repository.

HTTPS 🟢

❯ poetry add git+https://github.com:mbuesch/pyprofibus.git -vvv
Loading configuration file C:\Users\rruiter\AppData\Roaming\pypoetry\config.toml
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310
Cloning 'https://github.com/mbuesch/pyprofibus.git' using system git client

Updating dependencies
Resolving dependencies...
   1: fact: profinettest is 0.1.0
   1: derived: profinettest
   1: fact: profinettest depends on pyprofibus (1.11)
   1: selecting profinettest (0.1.0)
   1: derived: pyprofibus (1.11) @ git+https://github.com/mbuesch/pyprofibus.git
   1: selecting pyprofibus (1.11 78f06da)
   1: Version solving took 0.004 seconds.
   1: Tried 1 solutions.

Writing lock file

Finding the necessary packages for the current system

Package operations: 1 install, 0 updates, 0 removals

  • Installing pyprofibus (1.11 78f06da)

@neersighted
Copy link
Member

neersighted commented Nov 10, 2022

It looks like something to do with your network and/or remote Git service; this will be very hard to debug for anyone but you as you have not provided a repo to test against.

cc @jelmer

@neersighted neersighted added status/needs-reproduction Issue needs a minimal reproduction to be confirmed area/vcs Related to support for VCS dependencies (Git and Dulwich) and removed status/triage This issue needs to be triaged labels Nov 10, 2022
@rruiter87
Copy link
Author

rruiter87 commented Nov 10, 2022

Hi @neersighted. The repo was local only and still very new. I only did:

> conda create --name profinet310 python=3.10
> conda env export > conda.yml
> poetry init
> git init; git add . ; git commit -m "initial commit"
> poetry add git+ssh://github.com:mbuesch/pyprofibus.git

For completeness

> git --version
git version 2.33.0.windows.2
> conda --version
conda 4.13.0

Might be the university network though. It is not the first time it causes strange issues :p.

@neersighted
Copy link
Member

https://git.bues.ch/git/crcgen.git/ is what stood out to me specifically, however, I did not realize it was a public repo; my bad. It looks like this is a submodule using the 'dumb' HTTP transport -- I'm honestly not sure if Dulwich supports dumb HTTP as it's generally considered deprecated, but it helps that everything is publicly visible.

@dimbleby
Copy link
Contributor

dimbleby commented Nov 10, 2022

the error looks exactly as though it's in the dulwich code that's trying to handle the dumb transport:

AttributeError

  'NoneType' object has no attribute 'startswith'

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1946 in _discover_references
      1942│                 )
      1943│             base_url = resp.redirect_location[: -len(tail)]
      1944│
      1945│         try:
    → 1946│             self.dumb = not resp.content_type.startswith("application/x-git-")
      1947│             if not self.dumb:
      1948│                 proto = Protocol(read, None)
      1949│                 # The first line should mention the service
      1950│                 try:

@neersighted
Copy link
Member

Looks like a poorly configured HTTP server that's not returning a content type at all, honestly:

$ curl --head https://git.bues.ch:443/git/crcgen.git/info/refs?service=git-upload-pack
HTTP/1.1 200 OK
Date: Thu, 10 Nov 2022 15:24:40 GMT
Server: Apache/2.4.54
Last-Modified: Fri, 02 Sep 2022 20:08:07 GMT
ETag: "331-5e7b749dcff07"
Accept-Ranges: bytes
Content-Length: 817

As Content-Type is not mandated by HTTP, Dulwich should be handling this gracefully.

As to the system Git client failing over SSH, that smells more like a configuration issue to me, as the invocation is brutally simple:

return cls.run("clone", "--recurse-submodules", "--", repository, str(dest))

e.g.

$ git clone --recurse-submodules -- git+ssh://github.com:mbuesch/pyprofibus.git C:\Users\rruiter\Miniconda3\envs\profinet310\src\pyprofibus

Could you give it a go manually, @rruiter87?

@rruiter87
Copy link
Author

rruiter87 commented Nov 10, 2022

❯ git clone --recurse-submodules -- git+ssh://github.com:mbuesch/pyprofibus.git C:\Users\rruiter\Downloads\empty
Cloning into 'C:\Users\rruiter\Downloads\empty'...
ssh: Could not resolve hostname github.com:mbuesch: Name or service not known
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

But this works

> git clone git@github.com:mbuesch/pyprofibus.git C:\Users\rruiter\Downloads\emptry1
Cloning into 'C:\Users\rruiter\Downloads\emptry1'...
remote: Enumerating objects: 2104, done.
remote: Counting objects: 100% (291/291), done.
remote: Compressing objects: 100% (109/109), done.
remote: Total 2104 (delta 181), reused 291 (delta 181), pack-reused 1813
Receiving objects: 100% (2104/2104), 677.44 KiB | 17.37 MiB/s, done.
Resolving deltas: 100% (1381/1381), done.

@neersighted
Copy link
Member

Ah, I see a critical typo everyone missed:

github.com:mbuesch

In all cases, a / should be used instead of : -- : is only used in the SCP/SFTP path notation that Poetry does not use.

Can you try again with a well-formed URL?

@rruiter87
Copy link
Author

SSH failed, HTTPS worked.

❯ poetry add git+ssh://github.com/mbuesch/pyprofibus.git -vvv
Loading configuration file C:\Users\rruiter\AppData\Roaming\pypoetry\config.toml
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310
Cloning 'ssh://github.com/mbuesch/pyprofibus.git' using system git client

Failed to clone ssh://github.com/mbuesch/pyprofibus.git, check your git configuration and permissions for this repository.
❯ poetry add git+https://github.com/mbuesch/pyprofibus.git -vvv
Loading configuration file C:\Users\rruiter\AppData\Roaming\pypoetry\config.toml
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310
Cloning 'https://github.com/mbuesch/pyprofibus.git' using system git client
...

@neersighted
Copy link
Member

And the example Git clone based on Poetry's invocation?

@jelmer
Copy link
Contributor

jelmer commented Nov 10, 2022

Those two commands say "system git" though, implying it's not related to Dulwich?

@neersighted
Copy link
Member

Those two commands say "system git" though, implying it's not related to Dulwich?

I was hoping you could look at the unhandled None Content-Type in the issue body; that being said, attempts with the unmangled URL and Dulwich would also be appreciated @rruiter87.

@jelmer
Copy link
Contributor

jelmer commented Nov 10, 2022

The None Content-Type is an error handling bug; I agree Dulwich should raise a different exception, but it's not the root cause of the issues @rruiter87 is hitting

@rruiter87
Copy link
Author

Reactivate Dulwich

❯ poetry config experimental.system-git-client false

add with ssh

❯ poetry add git+ssh://github.com/mbuesch/pyprofibus.git -vvv
Loading configuration file C:\Users\rruiter\AppData\Roaming\pypoetry\config.toml
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310

  Stack trace:

  3  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1149 in fetch_pack
      1147│         with proto:
      1148│             try:
    → 1149│                 refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
      1150│             except HangupException as exc:
      1151│                 raise _remote_error_from_stderr(stderr) from exc

  2  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:253 in read_pkt_refs
       251│     refs = {}
       252│     # Receive refs from server
    →  253│     for pkt in pkt_seq:
       254│         (sha, ref) = pkt.rstrip(b"\n").split(None, 1)
       255│         if sha == b"ERR":

  1  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\protocol.py:277 in read_pkt_seq
      275│             flush-pkt.
      276│         """
    → 277│         pkt = self.read_pkt_line()
      278│         while pkt:
      279│             yield pkt

  HangupException

  The remote server unexpectedly closed the connection.

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\protocol.py:220 in read_pkt_line
      216│
      217│         try:
      218│             sizestr = read(4)
      219│             if not sizestr:
    → 220│                 raise HangupException()
      221│             size = int(sizestr, 16)
      222│             if size == 0:
      223│                 if self.report_activity:
      224│                     self.report_activity(4, "read")

The following error occurred when trying to handle this error:


  Stack trace:

  20  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:329 in run
       327│
       328│             try:
     → 329│                 exit_code = self._run(io)
       330│             except Exception as e:
       331│                 if not self._catch_exceptions:

  19  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\application.py:185 in _run
       183│         self._load_plugins(io)
       184│
     → 185│         exit_code: int = super()._run(io)
       186│         return exit_code
       187│

  18  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:423 in _run
       421│             io.input.set_stream(stream)
       422│
     → 423│         exit_code = self._run_command(command, io)
       424│         self._running_command = None
       425│

  17  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:465 in _run_command
       463│
       464│         if error is not None:
     → 465│             raise error
       466│
       467│         return event.exit_code

  16  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:449 in _run_command
       447│
       448│             if event.command_should_run():
     → 449│                 exit_code = command.run(io)
       450│             else:
       451│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

  15  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\base_command.py:119 in run
       117│         io.input.validate()
       118│
     → 119│         status_code = self.execute(io)
       120│
       121│         if status_code is None:

  14  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\command.py:83 in execute
        81│
        82│         try:
     →  83│             return self.handle()
        84│         except KeyboardInterrupt:
        85│             return 1

  13  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\add.py:158 in handle
       156│             return 0
       157│
     → 158│         requirements = self._determine_requirements(
       159│             packages,
       160│             allow_prereleases=self.option("allow-prereleases"),

  12  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:357 in _determine_requirements
       355│
       356│         result = []
     → 357│         for requirement in self._parse_requirements(requires):
       358│             if "git" in requirement or "url" in requirement or "path" in requirement:
       359│                 result.append(requirement)

  11  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:416 in _parse_requirements
       414│             cwd = Path.cwd()
       415│
     → 416│         return [
       417│             parse_dependency_specification(
       418│                 requirement=requirement,

  10  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:417 in <listcomp>
       415│
       416│         return [
     → 417│             parse_dependency_specification(
       418│                 requirement=requirement,
       419│                 env=self.env if isinstance(self, EnvCommand) else None,

   9  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:216 in parse_dependency_specification
       214│
       215│     specification = (
     → 216│         _parse_dependency_specification_url(requirement, env=env)
       217│         or _parse_dependency_specification_path(requirement, cwd=cwd)
       218│         or _parse_dependency_specification_simple(requirement)

   8  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:68 in _parse_dependency_specification_url
        66│
        67│     if url_parsed.scheme in ["git+https", "git+ssh"]:
     →  68│         return _parse_dependency_specification_git_url(requirement, env)
        69│
        70│     if url_parsed.scheme in ["http", "https"]:

   7  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:49 in _parse_dependency_specification_git_url
        47│
        48│     source_root = env.path.joinpath("src") if env else None
     →  49│     package = Provider.get_package_from_vcs(
        50│         "git",
        51│         url=url.url,

   6  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:341 in get_package_from_vcs
       339│             raise ValueError(f"Unsupported VCS dependency {vcs}")
       340│
     → 341│         return _get_package_from_git(
       342│             url=url,
       343│             branch=branch,

   5  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:95 in _get_package_from_git
        93│     source_root: Path | None = None,
        94│ ) -> Package:
     →  95│     source = Git.clone(
        96│         url=url,
        97│         source_root=source_root,

   4  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:426 in clone
       424│         try:
       425│             if not cls.is_using_legacy_client():
     → 426│                 local = cls._clone(url=url, refspec=refspec, target=target)
       427│                 cls._clone_submodules(repo=local)
       428│                 return local

   3  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:258 in _clone
       256│             local = Repo(str(target))
       257│
     → 258│         remote_refs = cls._fetch_remote_refs(url=url, local=local)
       259│
       260│         logger.debug(

   2  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:201 in _fetch_remote_refs
       199│
       200│         with local:
     → 201│             result: FetchPackResult = client.fetch(
       202│                 path,
       203│                 local,

   1  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:837 in fetch
        835│             f, commit, abort = target.object_store.add_pack()
        836│         try:
     →  837│             result = self.fetch_pack(
        838│                 path,
        839│                 determine_wants,

  HangupException

  d\\rruiter@github.com: Permission denied (publickey).

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1151 in fetch_pack
      1147│         with proto:
      1148│             try:
      1149│                 refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
      1150│             except HangupException as exc:
    → 1151│                 raise _remote_error_from_stderr(stderr) from exc
      1152│             (
      1153│                 negotiated_capabilities,
      1154│                 symrefs,
      1155│                 agent,

add with https

❯ poetry add git+https://github.com/mbuesch/pyprofibus.git -vvv
Loading configuration file C:\Users\rruiter\AppData\Roaming\pypoetry\config.toml
Using virtualenv: C:\Users\rruiter\Miniconda3\envs\profinet310
[keyring.backend] Loading KWallet
[keyring.backend] Loading SecretService
[keyring.backend] Loading Windows
[keyring.backend] Loading chainer
[keyring.backend] Loading libsecret
[keyring.backend] Loading macOS
[urllib3.connectionpool] Starting new HTTPS connection (1): github.com:443
[urllib3.connectionpool] https://github.com:443 "GET /mbuesch/pyprofibus.git/info/refs?service=git-upload-pack HTTP/1.1" 200 None
[urllib3.connectionpool] Starting new HTTPS connection (2): github.com:443
[urllib3.connectionpool] https://github.com:443 "POST /mbuesch/pyprofibus.git/git-upload-pack HTTP/1.1" 200 None
Cloning https://github.com/mbuesch/pyprofibus.git at 'HEAD' to C:\Users\rruiter\Miniconda3\envs\profinet310\src\pyprofibus
[urllib3.connectionpool] Starting new HTTPS connection (1): git.bues.ch:443
[urllib3.connectionpool] https://git.bues.ch:443 "GET /git/crcgen.git/info/refs?service=git-upload-pack HTTP/1.1" 200 817

  Stack trace:

  23  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:329 in run
       327│
       328│             try:
     → 329│                 exit_code = self._run(io)
       330│             except Exception as e:
       331│                 if not self._catch_exceptions:

  22  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\application.py:185 in _run
       183│         self._load_plugins(io)
       184│
     → 185│         exit_code: int = super()._run(io)
       186│         return exit_code
       187│

  21  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:423 in _run
       421│             io.input.set_stream(stream)
       422│
     → 423│         exit_code = self._run_command(command, io)
       424│         self._running_command = None
       425│

  20  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:465 in _run_command
       463│
       464│         if error is not None:
     → 465│             raise error
       466│
       467│         return event.exit_code

  19  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\application.py:449 in _run_command
       447│
       448│             if event.command_should_run():
     → 449│                 exit_code = command.run(io)
       450│             else:
       451│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

  18  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\base_command.py:119 in run
       117│         io.input.validate()
       118│
     → 119│         status_code = self.execute(io)
       120│
       121│         if status_code is None:

  17  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\cleo\commands\command.py:83 in execute
        81│
        82│         try:
     →  83│             return self.handle()
        84│         except KeyboardInterrupt:
        85│             return 1

  16  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\add.py:158 in handle
       156│             return 0
       157│
     → 158│         requirements = self._determine_requirements(
       159│             packages,
       160│             allow_prereleases=self.option("allow-prereleases"),

  15  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:357 in _determine_requirements
       355│
       356│         result = []
     → 357│         for requirement in self._parse_requirements(requires):
       358│             if "git" in requirement or "url" in requirement or "path" in requirement:
       359│                 result.append(requirement)

  14  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:416 in _parse_requirements
       414│             cwd = Path.cwd()
       415│
     → 416│         return [
       417│             parse_dependency_specification(
       418│                 requirement=requirement,

  13  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\console\commands\init.py:417 in <listcomp>
       415│
       416│         return [
     → 417│             parse_dependency_specification(
       418│                 requirement=requirement,
       419│                 env=self.env if isinstance(self, EnvCommand) else None,

  12  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:216 in parse_dependency_specification
       214│
       215│     specification = (
     → 216│         _parse_dependency_specification_url(requirement, env=env)
       217│         or _parse_dependency_specification_path(requirement, cwd=cwd)
       218│         or _parse_dependency_specification_simple(requirement)

  11  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:68 in _parse_dependency_specification_url
        66│
        67│     if url_parsed.scheme in ["git+https", "git+ssh"]:
     →  68│         return _parse_dependency_specification_git_url(requirement, env)
        69│
        70│     if url_parsed.scheme in ["http", "https"]:

  10  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\utils\dependency_specification.py:49 in _parse_dependency_specification_git_url
        47│
        48│     source_root = env.path.joinpath("src") if env else None
     →  49│     package = Provider.get_package_from_vcs(
        50│         "git",
        51│         url=url.url,

   9  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:341 in get_package_from_vcs
       339│             raise ValueError(f"Unsupported VCS dependency {vcs}")
       340│
     → 341│         return _get_package_from_git(
       342│             url=url,
       343│             branch=branch,

   8  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\puzzle\provider.py:95 in _get_package_from_git
        93│     source_root: Path | None = None,
        94│ ) -> Package:
     →  95│     source = Git.clone(
        96│         url=url,
        97│         source_root=source_root,

   7  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:427 in clone
       425│             if not cls.is_using_legacy_client():
       426│                 local = cls._clone(url=url, refspec=refspec, target=target)
     → 427│                 cls._clone_submodules(repo=local)
       428│                 return local
       429│         except HTTPUnauthorized:

   6  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:356 in _clone_submodules
       354│                         continue
       355│
     → 356│                 cls.clone(
       357│                     url=url.decode("utf-8"),
       358│                     source_root=source_root,

   5  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:426 in clone
       424│         try:
       425│             if not cls.is_using_legacy_client():
     → 426│                 local = cls._clone(url=url, refspec=refspec, target=target)
       427│                 cls._clone_submodules(repo=local)
       428│                 return local

   4  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:258 in _clone
       256│             local = Repo(str(target))
       257│
     → 258│         remote_refs = cls._fetch_remote_refs(url=url, local=local)
       259│
       260│         logger.debug(

   3  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\poetry\vcs\git\backend.py:201 in _fetch_remote_refs
       199│
       200│         with local:
     → 201│             result: FetchPackResult = client.fetch(
       202│                 path,
       203│                 local,

   2  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:837 in fetch
        835│             f, commit, abort = target.object_store.add_pack()
        836│         try:
     →  837│             result = self.fetch_pack(
        838│                 path,
        839│                 determine_wants,

   1  ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:2076 in fetch_pack
       2074│         """
       2075│         url = self._get_url(path)
     → 2076│         refs, server_capabilities, url = self._discover_references(
       2077│             b"git-upload-pack", url
       2078│         )

  AttributeError

  'NoneType' object has no attribute 'startswith'

  at ~\AppData\Roaming\pypoetry\venv\lib\site-packages\dulwich\client.py:1946 in _discover_references
      1942│                 )
      1943│             base_url = resp.redirect_location[: -len(tail)]
      1944│
      1945│         try:
    → 1946│             self.dumb = not resp.content_type.startswith("application/x-git-")
      1947│             if not self.dumb:
      1948│                 proto = Protocol(read, None)
      1949│                 # The first line should mention the service
      1950│                 try:

@neersighted
Copy link
Member

The first one is definitively local config, @rruiter87

@jelmer
Copy link
Contributor

jelmer commented Nov 11, 2022

The None Content-Type is an error handling bug; I agree Dulwich should raise a different exception, but it's not the root cause of the issues @rruiter87 is hitting

Ah, I think the number of different combinations of protocols/repositories mentioned here confused me. If it is actually a dumb repository then this might be caused by the missing content type.

@jelmer
Copy link
Contributor

jelmer commented Nov 11, 2022

See jelmer/dulwich#1097 for "dumb" remote access support in Dulwich

@rruiter87
Copy link
Author

Thanks for the help people. I'm not going to try and figure it out for now @neersighted, because at least something worked.

@jelmer
Copy link
Contributor

jelmer commented Nov 14, 2022

Glancing over the comments here, it looks like the cause was a mix of two things: an invalidly formatted URL and lack of dumb remote repository support in dulwich (masked by incorrect handling of a missing Content-Type header).

@neersighted neersighted changed the title Unable to add git dependencies Dulwich does not support Dumb Git transport Nov 14, 2022
@neersighted neersighted added status/external-issue Issue is caused by external project (platform, dep, etc) and removed kind/bug Something isn't working as expected status/needs-reproduction Issue needs a minimal reproduction to be confirmed labels Nov 14, 2022
@abn
Copy link
Member

abn commented Nov 14, 2022

I can confirm that is the case. The output is with the Content-Type patch added.

$ poetry add git+https://git.bues.ch/git/crcgen.git -v
Using virtualenv: /tmp/foobar/.venv

  NotImplementedError

  <bound method AbstractHttpGitClient.fetch_pack of Urllib3HttpGitClient('https://git.bues.ch/git/crcgen.git/', dumb=True)>

  at python-poetry/poetry/.venv/lib64/python3.10/site-packages/dulwich/client.py:2092 in fetch_pack
      2088│             wants = [cid for cid in wants if cid != ZERO_SHA]
      2089│         if not wants:
      2090│             return FetchPackResult(refs, symrefs, agent)
      2091│         if self.dumb:
    → 2092│             raise NotImplementedError(self.fetch_pack)
      2093│         req_data = BytesIO()
      2094│         req_proto = Protocol(None, req_data.write)
      2095│         (new_shallow, new_unshallow) = _handle_upload_pack_head(
      2096│             req_proto,

@Secrus
Copy link
Member

Secrus commented Jun 6, 2024

Poetry will support this once Dulwich adds support: jelmer/dulwich#1097

@Secrus Secrus closed this as not planned Won't fix, can't repro, duplicate, stale Jun 6, 2024
Copy link

github-actions bot commented Jul 7, 2024

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area/vcs Related to support for VCS dependencies (Git and Dulwich) status/external-issue Issue is caused by external project (platform, dep, etc)
Projects
None yet
Development

No branches or pull requests

7 participants