From b3b6e51565dcdbf81546f1d8f0121874a4e4fce9 Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Sun, 12 Feb 2017 23:03:47 +0100 Subject: submodule init implementation --- submodule.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 submodule.go (limited to 'submodule.go') diff --git a/submodule.go b/submodule.go new file mode 100644 index 0000000..32f730b --- /dev/null +++ b/submodule.go @@ -0,0 +1,30 @@ +package git + +import "srcd.works/go-git.v4/plumbing" + +type Submodule struct { + Name string + Branch string + URL string + + r *Repository +} + +func (s *Submodule) Init() error { + return s.r.clone(&CloneOptions{ + URL: s.URL, + ReferenceName: plumbing.ReferenceName(s.Branch), + }) +} + +type Submodules []*Submodule + +func (s Submodules) Init() error { + for _, sub := range s { + if err := sub.Init(); err != nil { + return err + } + } + + return nil +} -- cgit From c551c29a93882658d4b34860b5300de0f3456059 Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Mon, 13 Feb 2017 00:40:14 +0100 Subject: submodule init implementation --- submodule.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'submodule.go') diff --git a/submodule.go b/submodule.go index 32f730b..ea099f0 100644 --- a/submodule.go +++ b/submodule.go @@ -1,6 +1,10 @@ package git -import "srcd.works/go-git.v4/plumbing" +import ( + "fmt" + + "srcd.works/go-git.v4/plumbing" +) type Submodule struct { Name string @@ -21,7 +25,9 @@ type Submodules []*Submodule func (s Submodules) Init() error { for _, sub := range s { + fmt.Println("clone", sub.URL) if err := sub.Init(); err != nil { + fmt.Println(err) return err } } -- cgit From 7e990a811d9e23b5a3573c405b70f06a1be9e7b6 Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Tue, 14 Feb 2017 00:25:09 +0100 Subject: submodule init and update implementation --- submodule.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 11 deletions(-) (limited to 'submodule.go') diff --git a/submodule.go b/submodule.go index ea099f0..83c28b7 100644 --- a/submodule.go +++ b/submodule.go @@ -1,33 +1,79 @@ package git import ( - "fmt" - + "srcd.works/go-git.v4/config" "srcd.works/go-git.v4/plumbing" ) +// Submodule a submodule allows you to keep another Git repository in a +// subdirectory of your repository. type Submodule struct { - Name string - Branch string - URL string - + m *config.Submodule + w *Worktree + // r is the submodule repository r *Repository } +// Config returns the submodule config +func (s *Submodule) Config() *config.Submodule { + return s.m +} + +// Init initialize the submodule reading the recoreded Entry in the index for +// the given submodule func (s *Submodule) Init() error { - return s.r.clone(&CloneOptions{ - URL: s.URL, - ReferenceName: plumbing.ReferenceName(s.Branch), + e, err := s.w.readIndexEntry(s.m.Path) + if err != nil { + return err + } + + _, err = s.r.CreateRemote(&config.RemoteConfig{ + Name: DefaultRemoteName, + URL: s.m.URL, }) + + if err != nil { + return err + } + + return s.fetchAndCheckout(e.Hash) +} + +// Update the registered submodule to match what the superproject expects +func (s *Submodule) Update() error { + e, err := s.w.readIndexEntry(s.m.Path) + if err != nil { + return err + } + + return s.fetchAndCheckout(e.Hash) +} + +func (s *Submodule) fetchAndCheckout(hash plumbing.Hash) error { + if err := s.r.Fetch(&FetchOptions{}); err != nil && err != NoErrAlreadyUpToDate { + return err + } + + w, err := s.r.Worktree() + if err != nil { + return err + } + + if err := w.Checkout(hash); err != nil { + return err + } + + head := plumbing.NewHashReference(plumbing.HEAD, hash) + return s.r.Storer.SetReference(head) } +// Submodules list of several submodules from the same repository type Submodules []*Submodule +// Init initialize the submodule recorded in the index func (s Submodules) Init() error { for _, sub := range s { - fmt.Println("clone", sub.URL) if err := sub.Init(); err != nil { - fmt.Println(err) return err } } -- cgit From d6a6decd1be0515faf36256ce06c58c7d662bbd0 Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Tue, 14 Feb 2017 19:26:32 +0100 Subject: submodule update implementation --- submodule.go | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 110 insertions(+), 18 deletions(-) (limited to 'submodule.go') diff --git a/submodule.go b/submodule.go index 83c28b7..b6cc045 100644 --- a/submodule.go +++ b/submodule.go @@ -1,60 +1,141 @@ package git import ( + "errors" + "srcd.works/go-git.v4/config" "srcd.works/go-git.v4/plumbing" ) +var ( + ErrSubmoduleAlreadyInitialized = errors.New("submodule already initialized") + ErrSubmoduleNotInitialized = errors.New("submodule not initialized") +) + // Submodule a submodule allows you to keep another Git repository in a // subdirectory of your repository. type Submodule struct { - m *config.Submodule + initialized bool + + c *config.Submodule w *Worktree - // r is the submodule repository - r *Repository } // Config returns the submodule config func (s *Submodule) Config() *config.Submodule { - return s.m + return s.c } // Init initialize the submodule reading the recoreded Entry in the index for // the given submodule func (s *Submodule) Init() error { - e, err := s.w.readIndexEntry(s.m.Path) + cfg, err := s.w.r.Storer.Config() if err != nil { return err } - _, err = s.r.CreateRemote(&config.RemoteConfig{ + _, ok := cfg.Submodules[s.c.Name] + if ok { + return ErrSubmoduleAlreadyInitialized + } + + s.initialized = true + + cfg.Submodules[s.c.Name] = s.c + return s.w.r.Storer.SetConfig(cfg) +} + +// Repository returns the Repository represented by this submodule +func (s *Submodule) Repository() (*Repository, error) { + storer, err := s.w.r.Storer.Module(s.c.Name) + if err != nil { + return nil, err + } + + _, err = storer.Reference(plumbing.HEAD) + if err != nil && err != plumbing.ErrReferenceNotFound { + return nil, err + } + + worktree := s.w.fs.Dir(s.c.Path) + if err == nil { + return Open(storer, worktree) + } + + r, err := Init(storer, worktree) + if err != nil { + return nil, err + } + + _, err = r.CreateRemote(&config.RemoteConfig{ Name: DefaultRemoteName, - URL: s.m.URL, + URL: s.c.URL, }) + return r, err +} + +// Update the registered submodule to match what the superproject expects, the +// submodule should be initilized first calling the Init method or setting in +// the options SubmoduleUpdateOptions.Init equals true +func (s *Submodule) Update(o *SubmoduleUpdateOptions) error { + if !s.initialized && !o.Init { + return ErrSubmoduleNotInitialized + } + + if !s.initialized && o.Init { + if err := s.Init(); err != nil { + return err + } + } + + e, err := s.w.readIndexEntry(s.c.Path) if err != nil { return err } - return s.fetchAndCheckout(e.Hash) + r, err := s.Repository() + if err != nil { + return err + } + + if err := s.fetchAndCheckout(r, o, e.Hash); err != nil { + return err + } + + return s.doRecrusiveUpdate(r, o) } -// Update the registered submodule to match what the superproject expects -func (s *Submodule) Update() error { - e, err := s.w.readIndexEntry(s.m.Path) +func (s *Submodule) doRecrusiveUpdate(r *Repository, o *SubmoduleUpdateOptions) error { + if o.RecurseSubmodules == NoRecursivity { + return nil + } + + w, err := r.Worktree() if err != nil { return err } - return s.fetchAndCheckout(e.Hash) + l, err := w.Submodules() + if err != nil { + return err + } + + new := &SubmoduleUpdateOptions{} + *new = *o + new.RecurseSubmodules-- + return l.Update(new) } -func (s *Submodule) fetchAndCheckout(hash plumbing.Hash) error { - if err := s.r.Fetch(&FetchOptions{}); err != nil && err != NoErrAlreadyUpToDate { - return err +func (s *Submodule) fetchAndCheckout(r *Repository, o *SubmoduleUpdateOptions, hash plumbing.Hash) error { + if !o.NoFetch { + err := r.Fetch(&FetchOptions{}) + if err != nil && err != NoErrAlreadyUpToDate { + return err + } } - w, err := s.r.Worktree() + w, err := r.Worktree() if err != nil { return err } @@ -64,13 +145,13 @@ func (s *Submodule) fetchAndCheckout(hash plumbing.Hash) error { } head := plumbing.NewHashReference(plumbing.HEAD, hash) - return s.r.Storer.SetReference(head) + return r.Storer.SetReference(head) } // Submodules list of several submodules from the same repository type Submodules []*Submodule -// Init initialize the submodule recorded in the index +// Init initializes the submodules in this list func (s Submodules) Init() error { for _, sub := range s { if err := sub.Init(); err != nil { @@ -80,3 +161,14 @@ func (s Submodules) Init() error { return nil } + +// Update updates all the submodules in this list +func (s Submodules) Update(o *SubmoduleUpdateOptions) error { + for _, sub := range s { + if err := sub.Update(o); err != nil { + return err + } + } + + return nil +} -- cgit From ed288b30de1ac3dcb3ce675c4b9af89eb4e6fcba Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Tue, 21 Feb 2017 16:03:39 +0100 Subject: documentation and API improvements --- submodule.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'submodule.go') diff --git a/submodule.go b/submodule.go index b6cc045..e329fda 100644 --- a/submodule.go +++ b/submodule.go @@ -107,7 +107,7 @@ func (s *Submodule) Update(o *SubmoduleUpdateOptions) error { } func (s *Submodule) doRecrusiveUpdate(r *Repository, o *SubmoduleUpdateOptions) error { - if o.RecurseSubmodules == NoRecursivity { + if o.RecurseSubmodules == NoRecurseSubmodules { return nil } -- cgit