v2.30.0-pre 7341e0e

naming.go RawHistoryFolder

1package preview
2
3import (
4	"fmt"
5	"path/filepath"
6	"strings"
7)
8
9// ExtractPreviewName strips the matched pattern prefix from a tag.
10// Only simple trailing-wildcard patterns like "preview-*" or "pr-*" are supported.
11// Complex globs (e.g., "pr-*-test", "*-preview") are not supported.
12// "preview-login-redesign" with pattern "preview-*" → "login-redesign"
13func ExtractPreviewName(tag string, patterns []string) string {
14	for _, pattern := range patterns {
15		matched, err := filepath.Match(pattern, tag)
16		if err != nil {
17			continue // skip malformed patterns
18		}
19		if matched {
20			prefix := strings.TrimSuffix(pattern, "*")
21			return strings.TrimPrefix(tag, prefix)
22		}
23	}
24	return tag
25}
26
27// GeneratePreviewDomain creates the preview domain from a base route domain.
28// "myapp.example.com" + "login" + "--" → "myapp--login.example.com"
29func GeneratePreviewDomain(baseRoute, previewName, separator string) (string, error) {
30	dot := strings.Index(baseRoute, ".")
31	if dot < 0 {
32		return "", fmt.Errorf("invalid base route domain: %s", baseRoute)
33	}
34	app := baseRoute[:dot]
35	rest := baseRoute[dot:] // includes leading dot
36	return app + separator + previewName + rest, nil
37}
38
39// SanitizeBranchName converts a git branch name to a valid DNS-safe preview name.
40// "feat/login-redesign" → "login-redesign"
41func SanitizeBranchName(branch string) string {
42	branch = strings.ToLower(branch)
43	for _, prefix := range []string{"feat/", "fix/", "feature/", "hotfix/", "release/", "chore/"} {
44		if strings.HasPrefix(branch, prefix) {
45			branch = strings.TrimPrefix(branch, prefix)
46			break
47		}
48	}
49	// Replace disallowed characters with dashes
50	branch = strings.ReplaceAll(branch, "/", "-")
51	branch = strings.ReplaceAll(branch, "_", "-")
52	branch = strings.ReplaceAll(branch, ".", "-")
53
54	// Remove any remaining non DNS-safe characters
55	var result strings.Builder
56	for _, c := range branch {
57		if (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' {
58			result.WriteRune(c)
59		}
60	}
61	branch = result.String()
62
63	// Collapse consecutive dashes and trim
64	for strings.Contains(branch, "--") {
65		branch = strings.ReplaceAll(branch, "--", "-")
66	}
67	branch = strings.Trim(branch, "-")
68
69	// Truncate to 63 chars (DNS label limit)
70	if len(branch) > 63 {
71		branch = branch[:63]
72		branch = strings.TrimRight(branch, "-")
73	}
74	return branch
75}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close