Skip to content

Commit ca425f7

Browse files
fix: fix git url parsing (#188)
1 parent 51e54f2 commit ca425f7

File tree

6 files changed

+75
-14
lines changed

6 files changed

+75
-14
lines changed

envbuilder.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"maps"
1515
"net"
1616
"net/http"
17-
"net/url"
1817
"os"
1918
"os/exec"
2019
"os/user"
@@ -50,6 +49,7 @@ import (
5049
"github.com/google/go-containerregistry/pkg/v1/remote"
5150
"github.com/sirupsen/logrus"
5251
"github.com/tailscale/hujson"
52+
giturls "github.com/whilp/git-urls"
5353
"golang.org/x/xerrors"
5454
)
5555

@@ -863,14 +863,19 @@ func Run(ctx context.Context, options Options) error {
863863
// for a given repository URL.
864864
func DefaultWorkspaceFolder(repoURL string) (string, error) {
865865
if repoURL == "" {
866-
return "/workspaces/empty", nil
866+
return EmptyWorkspaceDir, nil
867867
}
868-
parsed, err := url.Parse(repoURL)
868+
parsed, err := giturls.Parse(repoURL)
869869
if err != nil {
870870
return "", err
871871
}
872872
name := strings.Split(parsed.Path, "/")
873-
return fmt.Sprintf("/workspaces/%s", name[len(name)-1]), nil
873+
hasOwnerAndRepo := len(name) >= 2
874+
if !hasOwnerAndRepo {
875+
return EmptyWorkspaceDir, nil
876+
}
877+
repo := strings.TrimSuffix(name[len(name)-1], ".git")
878+
return fmt.Sprintf("/workspaces/%s", repo), nil
874879
}
875880

876881
type userInfo struct {

envbuilder_test.go

+59-6
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,64 @@ import (
99

1010
func TestDefaultWorkspaceFolder(t *testing.T) {
1111
t.Parallel()
12-
dir, err := envbuilder.DefaultWorkspaceFolder("https://github.com/coder/coder")
13-
require.NoError(t, err)
14-
require.Equal(t, "/workspaces/coder", dir)
1512

16-
dir, err = envbuilder.DefaultWorkspaceFolder("")
17-
require.NoError(t, err)
18-
require.Equal(t, envbuilder.EmptyWorkspaceDir, dir)
13+
successTests := []struct {
14+
name string
15+
gitURL string
16+
expected string
17+
}{
18+
{
19+
name: "HTTP",
20+
gitURL: "https://github.com/coder/envbuilder.git",
21+
expected: "/workspaces/envbuilder",
22+
},
23+
{
24+
name: "SSH",
25+
gitURL: "[email protected]:coder/envbuilder.git",
26+
expected: "/workspaces/envbuilder",
27+
},
28+
{
29+
name: "username and password",
30+
gitURL: "https://username:[email protected]/coder/envbuilder.git",
31+
expected: "/workspaces/envbuilder",
32+
},
33+
{
34+
name: "fragment",
35+
gitURL: "https://github.com/coder/envbuilder.git#feature-branch",
36+
expected: "/workspaces/envbuilder",
37+
},
38+
{
39+
name: "empty",
40+
gitURL: "",
41+
expected: envbuilder.EmptyWorkspaceDir,
42+
},
43+
}
44+
for _, tt := range successTests {
45+
t.Run(tt.name, func(t *testing.T) {
46+
dir, err := envbuilder.DefaultWorkspaceFolder(tt.gitURL)
47+
require.NoError(t, err)
48+
require.Equal(t, tt.expected, dir)
49+
})
50+
}
51+
52+
invalidTests := []struct {
53+
name string
54+
invalidURL string
55+
}{
56+
{
57+
name: "simple text",
58+
invalidURL: "not a valid URL",
59+
},
60+
{
61+
name: "website URL",
62+
invalidURL: "www.google.com",
63+
},
64+
}
65+
for _, tt := range invalidTests {
66+
t.Run(tt.name, func(t *testing.T) {
67+
dir, err := envbuilder.DefaultWorkspaceFolder(tt.invalidURL)
68+
require.NoError(t, err)
69+
require.Equal(t, envbuilder.EmptyWorkspaceDir, dir)
70+
})
71+
}
1972
}

git.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"io"
88
"net"
9-
"net/url"
109
"os"
1110
"strings"
1211

@@ -22,6 +21,7 @@ import (
2221
gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
2322
"github.com/go-git/go-git/v5/storage/filesystem"
2423
"github.com/skeema/knownhosts"
24+
giturls "github.com/whilp/git-urls"
2525
"golang.org/x/crypto/ssh"
2626
gossh "golang.org/x/crypto/ssh"
2727
)
@@ -46,7 +46,7 @@ type CloneRepoOptions struct {
4646
//
4747
// The bool returned states whether the repository was cloned or not.
4848
func CloneRepo(ctx context.Context, opts CloneRepoOptions) (bool, error) {
49-
parsed, err := url.Parse(opts.RepoURL)
49+
parsed, err := giturls.Parse(opts.RepoURL)
5050
if err != nil {
5151
return false, fmt.Errorf("parse url %q: %w", opts.RepoURL, err)
5252
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ require (
4040
github.com/skeema/knownhosts v1.2.2
4141
github.com/stretchr/testify v1.9.0
4242
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
43+
github.com/whilp/git-urls v1.0.0
4344
go.uber.org/mock v0.4.0
4445
golang.org/x/crypto v0.22.0
4546
golang.org/x/sync v0.7.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,8 @@ github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vb
842842
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
843843
github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSVP061Ry2PX0/ON6I=
844844
github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ=
845+
github.com/whilp/git-urls v1.0.0 h1:95f6UMWN5FKW71ECsXRUd3FVYiXdrE7aX4NZKcPmIjU=
846+
github.com/whilp/git-urls v1.0.0/go.mod h1:J16SAmobsqc3Qcy98brfl5f5+e0clUvg1krgwk/qCfE=
845847
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
846848
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
847849
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=

integration/integration_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func TestSucceedsGitAuth(t *testing.T) {
160160
envbuilderEnv("GIT_PASSWORD", "testing"),
161161
}})
162162
require.NoError(t, err)
163-
gitConfig := execContainer(t, ctr, "cat /workspaces/.git/config")
163+
gitConfig := execContainer(t, ctr, "cat /workspaces/empty/.git/config")
164164
require.Contains(t, gitConfig, srv.URL)
165165
}
166166

@@ -182,7 +182,7 @@ func TestSucceedsGitAuthInURL(t *testing.T) {
182182
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
183183
}})
184184
require.NoError(t, err)
185-
gitConfig := execContainer(t, ctr, "cat /workspaces/.git/config")
185+
gitConfig := execContainer(t, ctr, "cat /workspaces/empty/.git/config")
186186
require.Contains(t, gitConfig, u.String())
187187
}
188188

0 commit comments

Comments
 (0)