From 9488c59834f6a2591910b7b360721cec2c16c548 Mon Sep 17 00:00:00 2001 From: "Santiago M. Mola" Date: Mon, 24 Jul 2017 10:51:01 +0200 Subject: config: multiple values in RemoteConfig (URLs and Fetch) * Change `URL string` to `URL []string` in `RemoteConfig`, since git allows multiple URLs per remote. See: http://marc.info/?l=git&m=116231242118202&w=2 * Fix marshalling of multiple fetch refspecs. --- config/config.go | 23 +++++++++++++++++------ config/config_test.go | 27 +++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) (limited to 'config') diff --git a/config/config.go b/config/config.go index bcea63e..1f3cd77 100644 --- a/config/config.go +++ b/config/config.go @@ -187,8 +187,9 @@ func (c *Config) marshalSubmodules() { type RemoteConfig struct { // Name of the remote Name string - // URL the URL of a remote repository - URL string + // URLs the URLs of a remote repository. It must be non-empty. Fetch will + // always use the first URL, while push will use all of them. + URLs []string // Fetch the default set of "refspec" for fetch operation Fetch []RefSpec @@ -203,7 +204,7 @@ func (c *RemoteConfig) Validate() error { return ErrRemoteConfigEmptyName } - if c.URL == "" { + if len(c.URLs) == 0 { return ErrRemoteConfigEmptyURL } @@ -233,8 +234,13 @@ func (c *RemoteConfig) unmarshal(s *format.Subsection) error { fetch = append(fetch, rs) } + var urls []string + for _, f := range c.raw.Options.GetAll(urlKey) { + urls = append(urls, f) + } + c.Name = c.raw.Name - c.URL = c.raw.Option(urlKey) + c.URLs = urls c.Fetch = fetch return nil @@ -246,9 +252,14 @@ func (c *RemoteConfig) marshal() *format.Subsection { } c.raw.Name = c.Name - c.raw.SetOption(urlKey, c.URL) + c.raw.RemoveOption(urlKey) + for _, url := range c.URLs { + c.raw.AddOption(urlKey, url) + } + + c.raw.RemoveOption(fetchKey) for _, rs := range c.Fetch { - c.raw.SetOption(fetchKey, rs.String()) + c.raw.AddOption(fetchKey, rs.String()) } return c.raw diff --git a/config/config_test.go b/config/config_test.go index cfab36d..e958677 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -13,6 +13,11 @@ func (s *ConfigSuite) TestUnmarshall(c *C) { [remote "origin"] url = git@github.com:mcuadros/go-git.git fetch = +refs/heads/*:refs/remotes/origin/* +[remote "alt"] + url = git@github.com:mcuadros/go-git.git + url = git@github.com:src-d/go-git.git + fetch = +refs/heads/*:refs/remotes/origin/* + fetch = +refs/pull/*:refs/remotes/origin/pull/* [submodule "qux"] path = qux url = https://github.com/foo/qux.git @@ -28,10 +33,13 @@ func (s *ConfigSuite) TestUnmarshall(c *C) { c.Assert(cfg.Core.IsBare, Equals, true) c.Assert(cfg.Core.Worktree, Equals, "foo") - c.Assert(cfg.Remotes, HasLen, 1) + c.Assert(cfg.Remotes, HasLen, 2) c.Assert(cfg.Remotes["origin"].Name, Equals, "origin") - c.Assert(cfg.Remotes["origin"].URL, Equals, "git@github.com:mcuadros/go-git.git") + c.Assert(cfg.Remotes["origin"].URLs, DeepEquals, []string{"git@github.com:mcuadros/go-git.git"}) c.Assert(cfg.Remotes["origin"].Fetch, DeepEquals, []RefSpec{"+refs/heads/*:refs/remotes/origin/*"}) + c.Assert(cfg.Remotes["alt"].Name, Equals, "alt") + c.Assert(cfg.Remotes["alt"].URLs, DeepEquals, []string{"git@github.com:mcuadros/go-git.git", "git@github.com:src-d/go-git.git"}) + c.Assert(cfg.Remotes["alt"].Fetch, DeepEquals, []RefSpec{"+refs/heads/*:refs/remotes/origin/*", "+refs/pull/*:refs/remotes/origin/pull/*"}) c.Assert(cfg.Submodules, HasLen, 1) c.Assert(cfg.Submodules["qux"].Name, Equals, "qux") c.Assert(cfg.Submodules["qux"].URL, Equals, "https://github.com/foo/qux.git") @@ -45,6 +53,11 @@ func (s *ConfigSuite) TestMarshall(c *C) { worktree = bar [remote "origin"] url = git@github.com:mcuadros/go-git.git +[remote "alt"] + url = git@github.com:mcuadros/go-git.git + url = git@github.com:src-d/go-git.git + fetch = +refs/heads/*:refs/remotes/origin/* + fetch = +refs/pull/*:refs/remotes/origin/pull/* [submodule "qux"] url = https://github.com/foo/qux.git `) @@ -54,7 +67,13 @@ func (s *ConfigSuite) TestMarshall(c *C) { cfg.Core.Worktree = "bar" cfg.Remotes["origin"] = &RemoteConfig{ Name: "origin", - URL: "git@github.com:mcuadros/go-git.git", + URLs: []string{"git@github.com:mcuadros/go-git.git"}, + } + + cfg.Remotes["alt"] = &RemoteConfig{ + Name: "alt", + URLs: []string{"git@github.com:mcuadros/go-git.git", "git@github.com:src-d/go-git.git"}, + Fetch: []RefSpec{"+refs/heads/*:refs/remotes/origin/*", "+refs/pull/*:refs/remotes/origin/pull/*"}, } cfg.Submodules["qux"] = &Submodule{ @@ -122,7 +141,7 @@ func (s *ConfigSuite) TestRemoteConfigValidateMissingName(c *C) { } func (s *ConfigSuite) TestRemoteConfigValidateDefault(c *C) { - config := &RemoteConfig{Name: "foo", URL: "http://foo/bar"} + config := &RemoteConfig{Name: "foo", URLs: []string{"http://foo/bar"}} c.Assert(config.Validate(), IsNil) fetch := config.Fetch -- cgit From e5c6fa237776870483cbe227d7f7ea943f35cb12 Mon Sep 17 00:00:00 2001 From: "Santiago M. Mola" Date: Thu, 27 Jul 2017 17:17:34 +0200 Subject: config: preserve option order on config marshalling Do not change order of options (e.g. in RemoteConfig) when serializing for any option whose value has not changed. --- config/config.go | 38 +++++++++++++++++++++++++++----------- config/config_test.go | 2 +- 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'config') diff --git a/config/config.go b/config/config.go index 1f3cd77..cb10738 100644 --- a/config/config.go +++ b/config/config.go @@ -159,13 +159,22 @@ func (c *Config) marshalCore() { func (c *Config) marshalRemotes() { s := c.Raw.Section(remoteSection) - s.Subsections = make(format.Subsections, len(c.Remotes)) + newSubsections := make(format.Subsections, 0, len(c.Remotes)) + added := make(map[string]bool) + for _, subsection := range s.Subsections { + if remote, ok := c.Remotes[subsection.Name]; ok { + newSubsections = append(newSubsections, remote.marshal()) + added[subsection.Name] = true + } + } - var i int - for _, r := range c.Remotes { - s.Subsections[i] = r.marshal() - i++ + for name, remote := range c.Remotes { + if !added[name] { + newSubsections = append(newSubsections, remote.marshal()) + } } + + s.Subsections = newSubsections } func (c *Config) marshalSubmodules() { @@ -252,14 +261,21 @@ func (c *RemoteConfig) marshal() *format.Subsection { } c.raw.Name = c.Name - c.raw.RemoveOption(urlKey) - for _, url := range c.URLs { - c.raw.AddOption(urlKey, url) + if len(c.URLs) == 0 { + c.raw.RemoveOption(urlKey) + } else { + c.raw.SetOption(urlKey, c.URLs...) } - c.raw.RemoveOption(fetchKey) - for _, rs := range c.Fetch { - c.raw.AddOption(fetchKey, rs.String()) + if len(c.Fetch) == 0 { + c.raw.RemoveOption(fetchKey) + } else { + var values []string + for _, rs := range c.Fetch { + values = append(values, rs.String()) + } + + c.raw.SetOption(fetchKey, values...) } return c.raw diff --git a/config/config_test.go b/config/config_test.go index e958677..97f4bbf 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -107,7 +107,7 @@ func (s *ConfigSuite) TestUnmarshallMarshall(c *C) { output, err := cfg.Marshal() c.Assert(err, IsNil) - c.Assert(output, DeepEquals, input) + c.Assert(string(output), DeepEquals, string(input)) } func (s *ConfigSuite) TestValidateInvalidRemote(c *C) { -- cgit