diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2017-02-14 19:26:32 +0100 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2017-02-15 09:30:05 +0100 |
commit | d6a6decd1be0515faf36256ce06c58c7d662bbd0 (patch) | |
tree | b91c4f618470c7cf1ef9547b9146d08e30df6204 /submodule.go | |
parent | 09110d8e6d1ddb6f6a22867dcedeebd8f2262780 (diff) | |
download | go-git-d6a6decd1be0515faf36256ce06c58c7d662bbd0.tar.gz |
submodule update implementation
Diffstat (limited to 'submodule.go')
-rw-r--r-- | submodule.go | 128 |
1 files changed, 110 insertions, 18 deletions
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 +} |