Skip to content

Commit 7e990a8

Browse files
committed
submodule init and update implementation
1 parent 65351f8 commit 7e990a8

File tree

5 files changed

+263
-32
lines changed

5 files changed

+263
-32
lines changed

common.go

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package git
22

33
import "strings"
44

5+
const defaultDotGitPath = ".git"
6+
57
// countLines returns the number of lines in a string à la git, this is
68
// The newline character is assumed to be '\n'. The empty string
79
// contains 0 lines. If the last line of the string doesn't end with a

submodule.go

+57-11
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,79 @@
11
package git
22

33
import (
4-
"fmt"
5-
4+
"srcd.works/go-git.v4/config"
65
"srcd.works/go-git.v4/plumbing"
76
)
87

8+
// Submodule a submodule allows you to keep another Git repository in a
9+
// subdirectory of your repository.
910
type Submodule struct {
10-
Name string
11-
Branch string
12-
URL string
13-
11+
m *config.Submodule
12+
w *Worktree
13+
// r is the submodule repository
1414
r *Repository
1515
}
1616

17+
// Config returns the submodule config
18+
func (s *Submodule) Config() *config.Submodule {
19+
return s.m
20+
}
21+
22+
// Init initialize the submodule reading the recoreded Entry in the index for
23+
// the given submodule
1724
func (s *Submodule) Init() error {
18-
return s.r.clone(&CloneOptions{
19-
URL: s.URL,
20-
ReferenceName: plumbing.ReferenceName(s.Branch),
25+
e, err := s.w.readIndexEntry(s.m.Path)
26+
if err != nil {
27+
return err
28+
}
29+
30+
_, err = s.r.CreateRemote(&config.RemoteConfig{
31+
Name: DefaultRemoteName,
32+
URL: s.m.URL,
2133
})
34+
35+
if err != nil {
36+
return err
37+
}
38+
39+
return s.fetchAndCheckout(e.Hash)
40+
}
41+
42+
// Update the registered submodule to match what the superproject expects
43+
func (s *Submodule) Update() error {
44+
e, err := s.w.readIndexEntry(s.m.Path)
45+
if err != nil {
46+
return err
47+
}
48+
49+
return s.fetchAndCheckout(e.Hash)
50+
}
51+
52+
func (s *Submodule) fetchAndCheckout(hash plumbing.Hash) error {
53+
if err := s.r.Fetch(&FetchOptions{}); err != nil && err != NoErrAlreadyUpToDate {
54+
return err
55+
}
56+
57+
w, err := s.r.Worktree()
58+
if err != nil {
59+
return err
60+
}
61+
62+
if err := w.Checkout(hash); err != nil {
63+
return err
64+
}
65+
66+
head := plumbing.NewHashReference(plumbing.HEAD, hash)
67+
return s.r.Storer.SetReference(head)
2268
}
2369

70+
// Submodules list of several submodules from the same repository
2471
type Submodules []*Submodule
2572

73+
// Init initialize the submodule recorded in the index
2674
func (s Submodules) Init() error {
2775
for _, sub := range s {
28-
fmt.Println("clone", sub.URL)
2976
if err := sub.Init(); err != nil {
30-
fmt.Println(err)
3177
return err
3278
}
3379
}

submodule_test.go

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package git
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
9+
"github.com/src-d/go-git-fixtures"
10+
11+
. "gopkg.in/check.v1"
12+
"srcd.works/go-git.v4/plumbing"
13+
)
14+
15+
type SubmoduleSuite struct {
16+
BaseSuite
17+
Worktree *Worktree
18+
path string
19+
}
20+
21+
var _ = Suite(&SubmoduleSuite{})
22+
23+
func (s *SubmoduleSuite) SetUpTest(c *C) {
24+
path := fixtures.ByTag("submodule").One().Worktree().Base()
25+
26+
dir, err := ioutil.TempDir("", "submodule")
27+
c.Assert(err, IsNil)
28+
29+
r, err := PlainClone(dir, false, &CloneOptions{
30+
URL: fmt.Sprintf("file://%s", filepath.Join(path)),
31+
})
32+
33+
c.Assert(err, IsNil)
34+
35+
s.Repository = r
36+
s.Worktree, err = r.Worktree()
37+
c.Assert(err, IsNil)
38+
39+
s.path = path
40+
}
41+
42+
func (s *SubmoduleSuite) TearDownTest(c *C) {
43+
err := os.RemoveAll(s.path)
44+
c.Assert(err, IsNil)
45+
}
46+
47+
func (s *SubmoduleSuite) TestInit(c *C) {
48+
sm, err := s.Worktree.Submodule("basic")
49+
c.Assert(err, IsNil)
50+
51+
_, err = sm.r.Reference(plumbing.HEAD, true)
52+
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
53+
54+
err = sm.Init()
55+
c.Assert(err, IsNil)
56+
57+
ref, err := sm.r.Reference(plumbing.HEAD, true)
58+
c.Assert(err, IsNil)
59+
c.Assert(ref.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
60+
61+
w, err := sm.r.Worktree()
62+
c.Assert(err, IsNil)
63+
64+
status, err := w.Status()
65+
c.Assert(err, IsNil)
66+
c.Assert(status.IsClean(), Equals, true)
67+
}
68+
69+
func (s *SubmoduleSuite) TestUpdate(c *C) {
70+
sm, err := s.Worktree.Submodule("basic")
71+
c.Assert(err, IsNil)
72+
73+
_, err = sm.r.Reference(plumbing.HEAD, true)
74+
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
75+
76+
err = sm.Init()
77+
c.Assert(err, IsNil)
78+
79+
idx, err := s.Repository.Storer.Index()
80+
c.Assert(err, IsNil)
81+
82+
for i, e := range idx.Entries {
83+
if e.Name == "basic" {
84+
e.Hash = plumbing.NewHash("b029517f6300c2da0f4b651b8642506cd6aaf45d")
85+
}
86+
87+
idx.Entries[i] = e
88+
}
89+
90+
err = s.Repository.Storer.SetIndex(idx)
91+
c.Assert(err, IsNil)
92+
93+
err = sm.Update()
94+
c.Assert(err, IsNil)
95+
96+
ref, err := sm.r.Reference(plumbing.HEAD, true)
97+
c.Assert(err, IsNil)
98+
c.Assert(ref.Hash().String(), Equals, "b029517f6300c2da0f4b651b8642506cd6aaf45d")
99+
100+
}
101+
102+
func (s *SubmoduleSuite) TestSubmodulesInit(c *C) {
103+
sm, err := s.Worktree.Submodules()
104+
c.Assert(err, IsNil)
105+
106+
err = sm.Init()
107+
c.Assert(err, IsNil)
108+
109+
for _, m := range sm {
110+
ref, err := m.r.Reference(plumbing.HEAD, true)
111+
c.Assert(err, IsNil)
112+
c.Assert(ref.Hash(), Not(Equals), plumbing.ZeroHash)
113+
}
114+
}

0 commit comments

Comments
 (0)