summaryrefslogtreecommitdiff
path: root/parseURL.go
blob: e8b133b1a4e15498119a3fe6888399aa2f8a3e54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package gitpb

import (
	"fmt"
	"net/url"
	"regexp"
	"strings"
)

// scpLikeURLRegex is a regex to parse scp-like URLs, e.g., "[email protected]:user/repo.git".
// It captures the user, host, and path.
var scpLikeURLRegex = regexp.MustCompile(`^([^@]+)@([^:]+):(.+)$`)

// ParseGitURL parses a Git URL, handling both standard schemes (http, https, ssh)
// and the scp-like syntax (e.g., [email protected]:user/repo.git).
func ParseGitURL(rawURL string) (*url.URL, error) {
	// First, try to parse it as a standard URL.
	// This will handle http://, https://, ssh://, git://, etc.
	parsedURL, err := url.Parse(rawURL)
	if err == nil && parsedURL.Scheme != "" {
		return parsedURL, nil
	}

	// If parsing failed or the scheme is missing, it might be an scp-like URL.
	// Try to match it against our regex.
	matches := scpLikeURLRegex.FindStringSubmatch(rawURL)

	if len(matches) != 4 {
		// If it doesn't match, we return the original parsing error or a new one.
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("invalid or unsupported URL format: %s", rawURL)
	}

	// If it matches, we manually construct a url.URL struct.
	// We'll use the "ssh" scheme to represent this connection type.
	user := matches[1]
	host := matches[2]
	path := matches[3]

	// The path might have a ".git" suffix, which we can optionally remove.
	path = strings.TrimSuffix(path, ".git")

	return &url.URL{
		Scheme: "ssh",
		User:   url.User(user),
		Host:   host,
		Path:   "/" + path, // Standard URL paths start with a slash.
	}, nil
}

/*
func parsemain() {
	urlsToTest := []string{
		// The problematic scp-like syntax
		"[email protected]:jcarr/jcarr.git",
		// A standard HTTPS URL
		"https://gitea.wit.com/wit/bash.git",
		// A standard SSH URL
		"ssh://[email protected]/golang/go.git",
		// An invalid URL
		"this is not a url",
	}

	for _, u := range urlsToTest {
		fmt.Printf("Parsing URL: %s\n", u)
		parsed, err := ParseGitURL(u)
		if err != nil {
			fmt.Printf("  Error: %v\n\n", err)
			continue
		}
		fmt.Printf("  Scheme: %s\n", parsed.Scheme)
		fmt.Printf("  User:   %s\n", parsed.User.Username())
		fmt.Printf("  Host:   %s\n", parsed.Host)
		fmt.Printf("  Path:   %s\n\n", parsed.Path)
	}
}
*/