Skip to content

Commit

Permalink
Fix relative submodule resolution
Browse files Browse the repository at this point in the history
With the current behavior, the config will always hold the resolved,
absolute URL, leavin the user of go-git no choice to determine whether
the original URL is relative or not.

This changes to employ relative URL resolution only when resolving
a submodule to a repository to keep the correct configuration
'unresolved' and intact.

Change relative resolution using `filepath.Dir` to `path.Join` while
parsing both the 'root' and the relative URL with `net/url.URL`.

Adapt test to verify the new behavior.

Re-fixes go-git#184 (see comments).
  • Loading branch information
Axel Christ committed Oct 28, 2020
1 parent 15aedd2 commit 81d429b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 27 deletions.
24 changes: 23 additions & 1 deletion submodule.go
Expand Up @@ -5,6 +5,8 @@ import (
"context"
"errors"
"fmt"
"net/url"
"path"

"github.com/go-git/go-billy/v5"
"github.com/go-git/go-git/v5/config"
Expand Down Expand Up @@ -131,9 +133,29 @@ func (s *Submodule) Repository() (*Repository, error) {
return nil, err
}

moduleURL, err := url.Parse(s.c.URL)
if err != nil {
return nil, err
}

if !path.IsAbs(moduleURL.Path) {
remotes, err := s.w.r.Remotes()
if err != nil {
return nil, err
}

rootURL, err := url.Parse(remotes[0].c.URLs[0])
if err != nil {
return nil, err
}

rootURL.Path = path.Join(rootURL.Path, moduleURL.Path)
*moduleURL = *rootURL
}

_, err = r.CreateRemote(&config.RemoteConfig{
Name: DefaultRemoteName,
URLs: []string{s.c.URL},
URLs: []string{moduleURL.String()},
})

return r, err
Expand Down
22 changes: 0 additions & 22 deletions worktree.go
Expand Up @@ -720,31 +720,9 @@ func (w *Worktree) readGitmodulesFile() (*config.Modules, error) {
return m, err
}

w.resolveRelativeSubmodulePaths(m)

return m, nil
}


// resolveRelativeSubmodulePaths is to replace any relative submodule URL (../foobar.git) in .gitmodules
// to the accessible repository URL
func (w *Worktree) resolveRelativeSubmodulePaths(m *config.Modules) {
origin, err := w.r.Remotes()
// remote is not associated with this worktree. we don't need to process any futher more
if err != nil {
return
}

parentURL := filepath.Dir(origin[0].c.URLs[0])

for i := range m.Submodules {
if strings.HasPrefix(m.Submodules[i].URL, "../") {
child := strings.Replace(m.Submodules[i].URL, "../", "", 1)
m.Submodules[i].URL = fmt.Sprintf("%s/%s", parentURL, child)
}
}
}

// Clean the worktree by removing untracked files.
// An empty dir could be removed - this is what `git clean -f -d .` does.
func (w *Worktree) Clean(opts *CleanOptions) error {
Expand Down
23 changes: 19 additions & 4 deletions worktree_test.go
Expand Up @@ -520,7 +520,6 @@ func (s *WorktreeSuite) TestCheckoutSubmoduleInitialized(c *C) {
c.Assert(status.IsClean(), Equals, true)
}


func (s *WorktreeSuite) TestCheckoutRelativePathSubmoduleInitialized(c *C) {
url := "https://github.com/git-fixtures/submodule.git"
r := s.NewRepository(fixtures.ByURL(url).One())
Expand All @@ -547,13 +546,29 @@ func (s *WorktreeSuite) TestCheckoutRelativePathSubmoduleInitialized(c *C) {
// test submodule path
modules, err := w.readGitmodulesFile()

c.Assert(modules.Submodules["basic"].URL, Equals, "git@github.com:git-fixtures/basic.git")
c.Assert(modules.Submodules["itself"].URL, Equals, "git@github.com:git-fixtures/submodule.git")
c.Assert(modules.Submodules["basic"].URL, Equals, "../basic.git")
c.Assert(modules.Submodules["itself"].URL, Equals, "../submodule.git")

basicSubmodule, err := w.Submodule("basic")
c.Assert(err, IsNil)
basicRepo, err := basicSubmodule.Repository()
c.Assert(err, IsNil)
basicRemotes, err := basicRepo.Remotes()
c.Assert(err, IsNil)
c.Assert(basicRemotes[0].Config().URLs[0], Equals, "https://github.com/git-fixtures/basic.git")

itselfSubmodule, err := w.Submodule("itself")
c.Assert(err, IsNil)
itselfRepo, err := itselfSubmodule.Repository()
c.Assert(err, IsNil)
itselfRemotes, err := itselfRepo.Remotes()
c.Assert(err, IsNil)
c.Assert(itselfRemotes[0].Config().URLs[0], Equals, "https://github.com/git-fixtures/submodule.git")

sub, err := w.Submodules()
c.Assert(err, IsNil)

err = sub.Update(&SubmoduleUpdateOptions{Init: true, RecurseSubmodules:DefaultSubmoduleRecursionDepth})
err = sub.Update(&SubmoduleUpdateOptions{Init: true, RecurseSubmodules: DefaultSubmoduleRecursionDepth})
c.Assert(err, IsNil)

status, err := w.Status()
Expand Down

0 comments on commit 81d429b

Please sign in to comment.