From d436e03f328a7d37426d52d59c034c2580e00c8b Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Wed, 30 Sep 2020 11:37:30 +0200 Subject: [PATCH] feat(detector): provide a detector for repository hosted on GitLab.com (#259) (#281) * feat(detector): provide a detector for repository hosted on GitLab.com (#259) * remove hg test after #276 Co-authored-by: Davin Kevin --- README.md | 2 ++ detect_gitlab.go | 47 ++++++++++++++++++++++++++++++++++++++ detect_gitlab_test.go | 44 +++++++++++++++++++++++++++++++++++ get.go | 1 + get_hg_test.go | 53 ------------------------------------------- 5 files changed, 94 insertions(+), 53 deletions(-) create mode 100644 detect_gitlab.go create mode 100644 detect_gitlab_test.go diff --git a/README.md b/README.md index 151b56bb4..b62a8fc55 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ is built-in by default: file URLs. * GitHub URLs, such as "github.com/mitchellh/vagrant" are automatically changed to Git protocol over HTTP. + * GitLab URLs, such as "gitlab.com/inkscape/inkscape" are automatically + changed to Git protocol over HTTP. * BitBucket URLs, such as "bitbucket.org/mitchellh/vagrant" are automatically changed to a Git or mercurial protocol using the BitBucket API. diff --git a/detect_gitlab.go b/detect_gitlab.go new file mode 100644 index 000000000..9d1e8d83c --- /dev/null +++ b/detect_gitlab.go @@ -0,0 +1,47 @@ +package getter + +import ( + "fmt" + "net/url" + "strings" +) + +// GitLabDetector implements Detector to detect GitLab URLs and turn +// them into URLs that the Git Getter can understand. +type GitLabDetector struct{} + +func (d *GitLabDetector) Detect(src, _ string) (string, bool, error) { + if len(src) == 0 { + return "", false, nil + } + + if strings.HasPrefix(src, "gitlab.com/") { + return d.detectHTTP(src) + } + + return "", false, nil +} + +func (d *GitLabDetector) detectHTTP(src string) (string, bool, error) { + parts := strings.Split(src, "/") + if len(parts) < 3 { + return "", false, fmt.Errorf( + "GitLab URLs should be gitlab.com/username/repo") + } + + urlStr := fmt.Sprintf("https://%s", strings.Join(parts[:3], "/")) + repoUrl, err := url.Parse(urlStr) + if err != nil { + return "", true, fmt.Errorf("error parsing GitLab URL: %s", err) + } + + if !strings.HasSuffix(repoUrl.Path, ".git") { + repoUrl.Path += ".git" + } + + if len(parts) > 3 { + repoUrl.Path += "//" + strings.Join(parts[3:], "/") + } + + return "git::" + repoUrl.String(), true, nil +} diff --git a/detect_gitlab_test.go b/detect_gitlab_test.go new file mode 100644 index 000000000..f1f85af3c --- /dev/null +++ b/detect_gitlab_test.go @@ -0,0 +1,44 @@ +package getter + +import ( + "testing" +) + +func TestGitLabDetector(t *testing.T) { + cases := []struct { + Input string + Output string + }{ + // HTTP + {"gitlab.com/hashicorp/foo", "git::https://gitlab.com/hashicorp/foo.git"}, + {"gitlab.com/hashicorp/foo.git", "git::https://gitlab.com/hashicorp/foo.git"}, + { + "gitlab.com/hashicorp/foo/bar", + "git::https://gitlab.com/hashicorp/foo.git//bar", + }, + { + "gitlab.com/hashicorp/foo?foo=bar", + "git::https://gitlab.com/hashicorp/foo.git?foo=bar", + }, + { + "gitlab.com/hashicorp/foo.git?foo=bar", + "git::https://gitlab.com/hashicorp/foo.git?foo=bar", + }, + } + + pwd := "/pwd" + f := new(GitLabDetector) + for i, tc := range cases { + output, ok, err := f.Detect(tc.Input, pwd) + if err != nil { + t.Fatalf("err: %s", err) + } + if !ok { + t.Fatal("not ok") + } + + if output != tc.Output { + t.Fatalf("%d: bad: %#v", i, output) + } + } +} diff --git a/get.go b/get.go index c599a6f6a..ac5b9f4cc 100644 --- a/get.go +++ b/get.go @@ -80,6 +80,7 @@ func init() { new(GitHubDetector), new(GitDetector), new(BitBucketDetector), + new(GitLabDetector), }, }, new(HgGetter), diff --git a/get_hg_test.go b/get_hg_test.go index a9b9f9bc7..41486bc30 100644 --- a/get_hg_test.go +++ b/get_hg_test.go @@ -2,11 +2,9 @@ package getter import ( "context" - "net/http" "os" "os/exec" "path/filepath" - "strings" "testing" testing_helper "github.com/hashicorp/go-getter/v2/helper/testing" @@ -120,54 +118,3 @@ func TestHgGetter_GetFile(t *testing.T) { } testing_helper.AssertContents(t, dst, "Hello\n") } - -func TestHgGetter_DetectBitBucketDetector(t *testing.T) { - t.Parallel() - - if _, err := http.Get(testBBUrl); err != nil { - t.Log("internet may not be working, skipping BB tests") - t.Skip() - } - - cases := []struct { - Input string - Output string - }{ - { - "bitbucket.org/hashicorp/tf-test-hg", - "https://bitbucket.org/hashicorp/tf-test-hg", - }, - } - - pwd := "/pwd" - for i, tc := range cases { - var err error - for i := 0; i < 3; i++ { - var ok bool - req := &Request{ - Src: tc.Input, - Pwd: pwd, - } - ok, err = Detect(req, new(HgGetter)) - if err != nil { - if strings.Contains(err.Error(), "invalid character") { - continue - } - - t.Fatalf("err: %s", err) - } - if !ok { - t.Fatal("not ok") - } - - if req.Src != tc.Output { - t.Fatalf("%d: bad: %#v", i, req.Src) - } - - break - } - if i >= 3 { - t.Fatalf("failure from bitbucket: %s", err) - } - } -}