Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
config: support insteadOf for remotes' URLs (#79)
- Loading branch information
Showing
4 changed files
with
239 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
"strings" | ||
|
||
format "github.com/go-git/go-git/v5/plumbing/format/config" | ||
) | ||
|
||
var ( | ||
errURLEmptyInsteadOf = errors.New("url config: empty insteadOf") | ||
) | ||
|
||
// Url defines Url rewrite rules | ||
type URL struct { | ||
// Name new base url | ||
Name string | ||
// Any URL that starts with this value will be rewritten to start, instead, with <base>. | ||
// When more than one insteadOf strings match a given URL, the longest match is used. | ||
InsteadOf string | ||
|
||
// raw representation of the subsection, filled by marshal or unmarshal are | ||
// called. | ||
raw *format.Subsection | ||
} | ||
|
||
// Validate validates fields of branch | ||
func (b *URL) Validate() error { | ||
if b.InsteadOf == "" { | ||
return errURLEmptyInsteadOf | ||
} | ||
|
||
return nil | ||
} | ||
|
||
const ( | ||
insteadOfKey = "insteadOf" | ||
) | ||
|
||
func (u *URL) unmarshal(s *format.Subsection) error { | ||
u.raw = s | ||
|
||
u.Name = s.Name | ||
u.InsteadOf = u.raw.Option(insteadOfKey) | ||
return nil | ||
} | ||
|
||
func (u *URL) marshal() *format.Subsection { | ||
if u.raw == nil { | ||
u.raw = &format.Subsection{} | ||
} | ||
|
||
u.raw.Name = u.Name | ||
u.raw.SetOption(insteadOfKey, u.InsteadOf) | ||
|
||
return u.raw | ||
} | ||
|
||
func findLongestInsteadOfMatch(remoteURL string, urls map[string]*URL) *URL { | ||
var longestMatch *URL | ||
for _, u := range urls { | ||
if !strings.HasPrefix(remoteURL, u.InsteadOf) { | ||
continue | ||
} | ||
|
||
// according to spec if there is more than one match, take the logest | ||
if longestMatch == nil || len(longestMatch.InsteadOf) < len(u.InsteadOf) { | ||
longestMatch = u | ||
} | ||
} | ||
|
||
return longestMatch | ||
} | ||
|
||
func (u *URL) ApplyInsteadOf(url string) string { | ||
if !strings.HasPrefix(url, u.InsteadOf) { | ||
return url | ||
} | ||
|
||
return u.Name + url[len(u.InsteadOf):] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package config | ||
|
||
import ( | ||
. "gopkg.in/check.v1" | ||
) | ||
|
||
type URLSuite struct{} | ||
|
||
var _ = Suite(&URLSuite{}) | ||
|
||
func (b *URLSuite) TestValidateInsteadOf(c *C) { | ||
goodURL := URL{ | ||
Name: "ssh://github.com", | ||
InsteadOf: "http://github.com", | ||
} | ||
badURL := URL{} | ||
c.Assert(goodURL.Validate(), IsNil) | ||
c.Assert(badURL.Validate(), NotNil) | ||
} | ||
|
||
func (b *URLSuite) TestMarshal(c *C) { | ||
expected := []byte(`[core] | ||
bare = false | ||
[url "ssh://git@github.com/"] | ||
insteadOf = https://github.com/ | ||
`) | ||
|
||
cfg := NewConfig() | ||
cfg.URLs["ssh://git@github.com/"] = &URL{ | ||
Name: "ssh://git@github.com/", | ||
InsteadOf: "https://github.com/", | ||
} | ||
|
||
actual, err := cfg.Marshal() | ||
c.Assert(err, IsNil) | ||
c.Assert(string(actual), Equals, string(expected)) | ||
} | ||
|
||
func (b *URLSuite) TestUnmarshal(c *C) { | ||
input := []byte(`[core] | ||
bare = false | ||
[url "ssh://git@github.com/"] | ||
insteadOf = https://github.com/ | ||
`) | ||
|
||
cfg := NewConfig() | ||
err := cfg.Unmarshal(input) | ||
c.Assert(err, IsNil) | ||
url := cfg.URLs["ssh://git@github.com/"] | ||
c.Assert(url.Name, Equals, "ssh://git@github.com/") | ||
c.Assert(url.InsteadOf, Equals, "https://github.com/") | ||
} | ||
|
||
func (b *URLSuite) TestApplyInsteadOf(c *C) { | ||
urlRule := URL{ | ||
Name: "ssh://github.com", | ||
InsteadOf: "http://github.com", | ||
} | ||
|
||
c.Assert(urlRule.ApplyInsteadOf("http://google.com"), Equals, "http://google.com") | ||
c.Assert(urlRule.ApplyInsteadOf("http://github.com/myrepo"), Equals, "ssh://github.com/myrepo") | ||
} |