(c *C)
| 548 | } |
| 549 | |
| 550 | func (s *SubmoduleSuite) TestSubmoduleRelativeURLRemoteWithoutURLs(c *C) { |
| 551 | // Defense in depth: a relative submodule URL must be joined onto |
| 552 | // the chosen parent remote. If that remote has no configured URL, |
| 553 | // earlier code panicked on `base.URLs[0]`. Mutating the in-memory |
| 554 | // config directly bypasses SetConfig's validation, mirroring the |
| 555 | // on-disk case where a `[remote "origin"]` section with no |
| 556 | // `url =` entry could be loaded. |
| 557 | parent := &Repository{ |
| 558 | Storer: memory.NewStorage(), |
| 559 | wt: memfs.New(), |
| 560 | } |
| 561 | cfg, err := parent.Config() |
| 562 | c.Assert(err, IsNil) |
| 563 | cfg.Remotes["origin"] = &config.RemoteConfig{Name: "origin", URLs: nil} |
| 564 | |
| 565 | sub := &Submodule{ |
| 566 | initialized: true, |
| 567 | w: &Worktree{Filesystem: memfs.New(), r: parent}, |
| 568 | c: &config.Submodule{ |
| 569 | Name: "child", |
| 570 | Path: "child", |
| 571 | URL: "../child", |
| 572 | }, |
| 573 | } |
| 574 | |
| 575 | subRepo, err := sub.Repository() |
| 576 | c.Assert(err, NotNil) |
| 577 | c.Assert(subRepo, IsNil) |
| 578 | c.Assert(err, ErrorMatches, |
| 579 | `resolving relative submodule URL: remote "origin" has no configured URL`) |
| 580 | } |
| 581 | |
| 582 | // TestSubmoduleRepositoryRejectsEscapingName covers the storage-layer |
| 583 | // defence against submodule name path traversal. Constructing a |
nothing calls this directly
no test coverage detected