From e0bd4e88b649faf6ed4196a9d02913110f6974d0 Mon Sep 17 00:00:00 2001 From: Mitsutaka Naito <4987502+mikyk10@users.noreply.github.com> Date: Tue, 13 Oct 2020 09:54:44 +0900 Subject: [PATCH] git: worktree, Support relative submodule URL. --- worktree.go | 28 +++++++++++++++++++++++++++- worktree_test.go | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/worktree.go b/worktree.go index 62ad03b95..c79e71583 100644 --- a/worktree.go +++ b/worktree.go @@ -716,7 +716,33 @@ func (w *Worktree) readGitmodulesFile() (*config.Modules, error) { } m := config.NewModules() - return m, m.Unmarshal(input) + if err := m.Unmarshal(input); err != nil { + 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. diff --git a/worktree_test.go b/worktree_test.go index 59c80affc..93a4a9a37 100644 --- a/worktree_test.go +++ b/worktree_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "io" "io/ioutil" "os" "path/filepath" @@ -12,7 +13,7 @@ import ( "testing" "time" - fixtures "github.com/go-git/go-git-fixtures/v4" + "github.com/go-git/go-git-fixtures/v4" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/filemode" @@ -519,6 +520,47 @@ 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()) + + // modify the .gitmodules from original one + file, err := r.wt.OpenFile(".gitmodules", os.O_WRONLY|os.O_TRUNC, 0666) + c.Assert(err, IsNil) + + n, err := io.WriteString(file, `[submodule "basic"] + path = basic + url = ../basic.git +[submodule "itself"] + path = itself + url = ../submodule.git`) + c.Assert(err, IsNil) + c.Assert(n, Not(Equals), 0) + + w, err := r.Worktree() + c.Assert(err, IsNil) + + w.Add(".gitmodules") + w.Commit("test", &CommitOptions{}) + + // 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") + + sub, err := w.Submodules() + c.Assert(err, IsNil) + + err = sub.Update(&SubmoduleUpdateOptions{Init: true, RecurseSubmodules:DefaultSubmoduleRecursionDepth}) + c.Assert(err, IsNil) + + status, err := w.Status() + c.Assert(err, IsNil) + c.Assert(status.IsClean(), Equals, true) +} + func (s *WorktreeSuite) TestCheckoutIndexMem(c *C) { fs := memfs.New() w := &Worktree{