aboutsummaryrefslogtreecommitdiff
path: root/ref/name/worktree.go
blob: dbc8cf3911733445228c60286d170b49090010f7 (about) (plain) (blame)
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
80
81
82
package name

import "strings"

// WorktreeType classifies a worktree-qualified name prefix.
type WorktreeType uint8

const (
	// WorktreeShared is an ordinary shared name.
	WorktreeShared WorktreeType = iota

	// WorktreeCurrent is a current-worktree-only name like HEAD or refs/worktree/...
	WorktreeCurrent

	// WorktreeMain is a main-worktree-qualified name like main-worktree/HEAD.
	WorktreeMain

	// WorktreeOther is another-worktree-qualified name like worktrees/wt1/HEAD.
	WorktreeOther
)

// IsPerWorktree reports whether name is a per-worktree ref namespace.
func IsPerWorktree(name string) bool {
	return strings.HasPrefix(name, "refs/worktree/") ||
		strings.HasPrefix(name, "refs/bisect/") ||
		strings.HasPrefix(name, "refs/rewritten/")
}

func isCurrentWorktreeRef(name string) bool {
	return IsRootSyntax(name) || IsPerWorktree(name)
}

// ParsedWorktreeRef is the result of parsing a worktree-qualified name.
type ParsedWorktreeRef struct {
	Type         WorktreeType
	WorktreeName string
	BareRefName  string
}

// ParseWorktree parses Git's worktree ref prefixes.
func ParseWorktree(name string) ParsedWorktreeRef {
	if bare, ok := strings.CutPrefix(name, "worktrees/"); ok {
		worktreeName, rest, found := strings.Cut(bare, "/")
		if !found {
			return ParsedWorktreeRef{
				Type:         WorktreeOther,
				WorktreeName: worktreeName,
				BareRefName:  "",
			}
		}

		if isCurrentWorktreeRef(rest) {
			return ParsedWorktreeRef{
				Type:         WorktreeOther,
				WorktreeName: worktreeName,
				BareRefName:  rest,
			}
		}
	}

	if bare, ok := strings.CutPrefix(name, "main-worktree/"); ok && isCurrentWorktreeRef(bare) {
		return ParsedWorktreeRef{
			Type:         WorktreeMain,
			WorktreeName: "",
			BareRefName:  bare,
		}
	}

	if isCurrentWorktreeRef(name) {
		return ParsedWorktreeRef{
			Type:         WorktreeCurrent,
			WorktreeName: "",
			BareRefName:  name,
		}
	}

	return ParsedWorktreeRef{
		Type:         WorktreeShared,
		WorktreeName: "",
		BareRefName:  name,
	}
}