question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. Itย collects links to all the places you might be looking at while hunting down a tough bug.

And, if youโ€™re still stuck at the end, weโ€™re happy to hop on a call to see how we can help out.

Git dependencies' submodules with relative URLs handled incorrectly (regression from 1.1)

See original GitHub issue
  • I am on the latest Poetry version.

  • I have searched the issues of this repo and believe that this is not a duplicate.

  • If an exception occurs when executing a command, I executed it again in debug mode (-vvv option).

  • OS version and name: Ubuntu 20.04

  • Poetry version: 1.2.0

Issue

I have a project with a git dependency. The dependency uses git submodules, and the dependencyโ€™s .gitmodules file contains a submodule using a relative URL, e.g.:

[submodule "foo/bar"]
    path = foo/bar
    url = ../bar.git

When Poetry attempts to install the dependency, it clones the repository and then attempts to clone each submodule, but it passes the raw relative URL from the configuration to _clone() and thus _fetch_remote_refs(), which calls Dulwichโ€™s get_transport_and_path(), which decides the URL is for a local repository so it attempts to find ../bar.git on the filesystem, which fails. I think it should instead detect relative URLs and append them to the root repositoryโ€™s URL so that Dulwich will realise itโ€™s a remote repo and return the appropriate client.

If I clone the dependency using git on the command line, with --recurse-submodules, git correctly uses a relative URL to fetch the submodule. If I force Poetry to use the legacy system git instead of Dulwich, it doesnโ€™t seem to clone the submodules at all, so also doesnโ€™t run into trouble (in this case the dependencyโ€™s submodule isnโ€™t needed to install the dependency, just for testing). Similarly this also worked OK on poetry 1.1 which I think used the system git to recursively clone submodules.

It looks like this is from #5428.

Hereโ€™s a representative traceback:

Traceback
$ poetry lock -vvv
Using virtualenv: /home/x/.cache/pypoetry/virtualenvs/baz-Nz-qS6ut-py3.8
Updating dependencies
Resolving dependencies...
   1: fact: baz is 0.1.0
   1: derived: baz
Cloning ssh://git@github.com/x/foo.git at 'master' to /home/x/.cache/pypoetry/virtualenvs/baz-Nz-qS6ut-py3.8/src/foo
   1: Version solving took 1.496 seconds.
   1: Tried 1 solutions.

Stack trace:

28 ~/.local/lib/python3.8/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:

27 ~/.local/lib/python3.8/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โ”‚

26 ~/.local/lib/python3.8/site-packages/poethepoet/plugin.py:249 in _run 247โ”‚ tokens.insert(task_name_index, โ€œโ€“โ€) 248โ”‚ โ†’ 249โ”‚ continue_run(self, io) 250โ”‚ 251โ”‚ # Apply the patch

25 ~/.local/lib/python3.8/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โ”‚

24 ~/.local/lib/python3.8/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

23 ~/.local/lib/python3.8/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

22 ~/.local/lib/python3.8/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:

21 ~/.local/lib/python3.8/site-packages/cleo/commands/command.py:83 in execute 81โ”‚ 82โ”‚ try: โ†’ 83โ”‚ return self.handle() 84โ”‚ except KeyboardInterrupt: 85โ”‚ return 1

20 ~/.local/lib/python3.8/site-packages/poetry/console/commands/lock.py:54 in handle 52โ”‚ self.installer.lock(update=not self.option(โ€œno-updateโ€)) 53โ”‚ โ†’ 54โ”‚ return self.installer.run() 55โ”‚

19 ~/.local/lib/python3.8/site-packages/poetry/installation/installer.py:111 in run 109โ”‚ self._execute_operations = False 110โ”‚ โ†’ 111โ”‚ return self._do_install() 112โ”‚ 113โ”‚ def dry_run(self, dry_run: bool = True) -> Installer:

18 ~/.local/lib/python3.8/site-packages/poetry/installation/installer.py:244 in _do_install 242โ”‚ source_root=self._env.path.joinpath(โ€œsrcโ€) 243โ”‚ ): โ†’ 244โ”‚ ops = solver.solve(use_latest=self._whitelist).calculate_operations() 245โ”‚ else: 246โ”‚ self._io.write_line(โ€œInstalling dependencies from lock fileโ€)

17 ~/.local/lib/python3.8/site-packages/poetry/puzzle/solver.py:73 in solve 71โ”‚ with self._provider.progress(): 72โ”‚ start = time.time() โ†’ 73โ”‚ packages, depths = self._solve(use_latest=use_latest) 74โ”‚ end = time.time() 75โ”‚

16 ~/.local/lib/python3.8/site-packages/poetry/puzzle/solver.py:151 in _solve 149โ”‚ 150โ”‚ try: โ†’ 151โ”‚ result = resolve_version( 152โ”‚ self._package, self._provider, locked=locked, use_latest=use_latest 153โ”‚ )

15 ~/.local/lib/python3.8/site-packages/poetry/mixology/init.py:24 in resolve_version 22โ”‚ solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest) 23โ”‚ โ†’ 24โ”‚ return solver.solve() 25โ”‚

14 ~/.local/lib/python3.8/site-packages/poetry/mixology/version_solver.py:127 in solve 125โ”‚ while next is not None: 126โ”‚ self._propagate(next) โ†’ 127โ”‚ next = self._choose_package_version() 128โ”‚ 129โ”‚ return self._result()

13 ~/.local/lib/python3.8/site-packages/poetry/mixology/version_solver.py:446 in _choose_package_version 444โ”‚ package = locked 445โ”‚ โ†’ 446โ”‚ package = self._provider.complete_package(package) 447โ”‚ 448โ”‚ conflict = False

12 ~/.local/lib/python3.8/site-packages/poetry/puzzle/provider.py:556 in complete_package 554โ”‚ for r in requires: 555โ”‚ if r.is_direct_origin(): โ†’ 556โ”‚ self.search_for_direct_origin_dependencyยฎ 557โ”‚ 558โ”‚ optional_dependencies = []

11 ~/.local/lib/python3.8/site-packages/poetry/puzzle/provider.py:230 in search_for_direct_origin_dependency 228โ”‚ elif dependency.is_vcs(): 229โ”‚ dependency = cast(โ€œVCSDependencyโ€, dependency) โ†’ 230โ”‚ package = self._search_for_vcs(dependency) 231โ”‚ 232โ”‚ elif dependency.is_file():

10 ~/.local/lib/python3.8/site-packages/poetry/puzzle/provider.py:312 in _search_for_vcs 310โ”‚ and get the information we need by checking out the specified reference. 311โ”‚ โ€œโ€" โ†’ 312โ”‚ package = self.get_package_from_vcs( 313โ”‚ dependency.vcs, 314โ”‚ dependency.source,

9 ~/.local/lib/python3.8/site-packages/poetry/puzzle/provider.py:342 in get_package_from_vcs 340โ”‚ raise ValueError(f"Unsupported VCS dependency {vcs}") 341โ”‚ โ†’ 342โ”‚ return _get_package_from_git( 343โ”‚ url=url, 344โ”‚ branch=branch,

8 ~/.local/lib/python3.8/site-packages/poetry/puzzle/provider.py:96 in _get_package_from_git 94โ”‚ source_root: Path | None = None, 95โ”‚ ) -> Package: โ†’ 96โ”‚ source = Git.clone( 97โ”‚ url=url, 98โ”‚ source_root=source_root,

7 ~/.local/lib/python3.8/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 ~/.local/lib/python3.8/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 ~/.local/lib/python3.8/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 ~/.local/lib/python3.8/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 ~/.local/lib/python3.8/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 ~/.local/lib/python3.8/site-packages/dulwich/client.py:1501 in fetch 1499โ”‚ 1500โ”‚ โ€œโ€" โ†’ 1501โ”‚ with self._open_repo(path) as r: 1502โ”‚ refs = r.fetch( 1503โ”‚ target,

1 ~/.local/lib/python3.8/site-packages/dulwich/client.py:1423 in _open_repo 1421โ”‚ if not isinstance(path, str): 1422โ”‚ path = os.fsdecode(path) โ†’ 1423โ”‚ return closing(Repo(path)) 1424โ”‚ 1425โ”‚ def send_pack(self, path, update_refs, generate_pack_data, progress=None):

NotGitRepository

No git repository was found at โ€ฆ/bar.git

at ~/.local/lib/python3.8/site-packages/dulwich/repo.py:1090 in init 1086โ”‚ elif (os.path.isdir(os.path.join(root, OBJECTDIR)) 1087โ”‚ and os.path.isdir(os.path.join(root, REFSDIR))): 1088โ”‚ bare = True 1089โ”‚ else: โ†’ 1090โ”‚ raise NotGitRepository( 1091โ”‚ โ€œNo git repository was found at %(path)sโ€ % dict(path=root) 1092โ”‚ ) 1093โ”‚ 1094โ”‚ self.bare = bare

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:14 (13 by maintainers)

github_iconTop GitHub Comments

1reaction
jelmercommented, Oct 6, 2022

The issue on the Dulwich side is for porcelain; poetry uses the plumbing from Dulwich directly. Thereโ€™s already a function in the plumbing for getting o list of submodules.

0reactions
evanrittenhousecommented, Oct 31, 2022

Apologies for the delay, work has been crazy. Commenting here so the issue doesnโ€™t get picked up by someone else as Iโ€™m basically code complete - will hopefully be able to submit a PR next weekend.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Changing URLs of Git submodules - Damir's Corner
Git submodules are defined in the .gitmodules file in the repository. ... repository URL as base onto which the relative path is applied....
Read more >
Git - Submodules - Git SCM
Submodules allow you to keep a Git repository as a subdirectory of another Git repository. ... When applicable, a relative URL can be...
Read more >
node_modules/express/History.md ... - Etulab
Fix incorrect end tag in default error & redirects; deps: depd@~1.1.2 ... Fix regression for empty string path in app.use; Fix router.use to...
Read more >
node_modules/express/History.md ... - edu-sharing
Fix regression when root is incorrectly set to a file; deps: send@0.16.1 ... Accept options directly to send module; Resolve relative paths at...
Read more >
Mastering Git submodules - Medium
In this post, we'll dive deep into Git submodules, starting by making ... .git file with a single gitdir: line mentioning a relative...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found