Parent directory

urls.go

1940 bytes
 1package pages
 2
 3import "net/url"
 4
 5// RepositoryURL builds a repository overview URL without interpolating a name.
 6func RepositoryURL(repository string) string {
 7	return (&url.URL{Path: "/"}).JoinPath(splitRepositoryName(repository)...).String()
 8}
 9
10// PageURL builds a page operation URL without interpolating untrusted values.
11func PageURL(repository, operation string, query url.Values) string {
12	segments := append(splitRepositoryName(repository), "@", operation)
13	u := (&url.URL{Path: "/"}).JoinPath(segments...)
14	if query != nil {
15		u.RawQuery = query.Encode()
16	}
17	return u.String()
18}
19
20// TreeURL builds a tree-browser URL for a selected repository, ref, and path.
21func TreeURL(repository, ref, treePath string) string {
22	return PageURL(repository, "tree", url.Values{"ref": {ref}, "path": {treePath}})
23}
24
25// RawURL builds a raw-file URL for a selected repository, ref, and path.
26func RawURL(repository, ref, treePath string) string {
27	return PageURL(repository, "raw", url.Values{"ref": {ref}, "path": {treePath}})
28}
29
30func AbsoluteRawURL(publicURL, repository, ref, treePath string) string {
31	base, err := url.Parse(publicURL)
32	if err != nil || base.Scheme == "" || base.Host == "" {
33		return RawURL(repository, ref, treePath)
34	}
35	raw, err := url.Parse(RawURL(repository, ref, treePath))
36	if err != nil {
37		return RawURL(repository, ref, treePath)
38	}
39	return base.ResolveReference(raw).String()
40}
41
42func splitRepositoryName(name string) []string {
43	// A repository name may be nested. URL.JoinPath escapes each component and
44	// preserves only the deliberate repository separators.
45	return splitNonEmpty(name)
46}
47
48func splitNonEmpty(value string) []string {
49	segments := make([]string, 0, 1)
50	start := 0
51	for i := range value {
52		if value[i] == '/' {
53			if i > start {
54				segments = append(segments, value[start:i])
55			}
56			start = i + 1
57		}
58	}
59	if start < len(value) {
60		segments = append(segments, value[start:])
61	}
62	return segments
63}