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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
package name_test
import (
"testing"
"lindenii.org/go/furgit/internal/testgit"
"lindenii.org/go/furgit/ref/name"
)
func TestValidate(t *testing.T) {
t.Parallel()
repo, err := testgit.NewRepo(t, testgit.RepoOptions{})
if err != nil {
t.Fatalf("NewRepo: %v", err)
}
type testCase struct {
name string
opts name.Options //exhaustruct:optional
}
tests := []testCase{
{name: ""},
{name: "/"},
{name: "/", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "foo/bar/baz"},
{name: "refs/heads/main"},
{name: "refs/tags/v1.0.0"},
{name: "refs///heads/foo"},
{name: "heads/foo/"},
{name: "/heads/foo"},
{name: "///heads/foo"},
{name: "./foo"},
{name: "./foo/bar"},
{name: "foo/./bar"},
{name: "foo/bar/."},
{name: ".refs/foo"},
{name: "refs/heads/foo."},
{name: "HEAD"},
{name: "HEAD", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "refs/heads/.main"},
{name: "heads/foo..bar"},
{name: "refs/heads/main.lock"},
{name: "heads///foo.lock"},
{name: "refs/heads/foo..bar"},
{name: "refs/heads/foo bar"},
{name: "refs/heads/foo@{bar"},
{name: "heads/foo?bar"},
{name: "foo./bar"},
{name: "foo.lock/bar"},
{name: "foo.lock///bar"},
{name: "heads/foo@bar"},
{name: "heads/foo\\bar"},
{name: "heads/foo\tbar"},
{name: "heads/foo\x7fbar"},
{name: "heads/fu\xC3\x9F"},
{name: "heads/*foo/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "heads/foo*/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "heads/f*o/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "heads/f*o*/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "heads/foo*/bar*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "refs/heads/foo/bar."},
{name: "refs//heads///main"},
{name: "foo"},
{name: "foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "foo/bar"},
{name: "foo/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "foo/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "foo/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "refs/heads/*"},
{name: "refs/heads/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "refs/heads/feature*branch", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "refs/heads/foo*bar*baz", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "foo/*"},
{name: "foo/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "foo/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "foo/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "*/foo"},
{name: "*/foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "*/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "*/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "foo/*/bar"},
{name: "foo/*/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "foo/*/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "foo/*/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "*"},
{name: "*", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "foo/*/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "foo/*/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "*/foo/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "*/foo/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "*/*/foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "*/*/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "/foo"},
{name: "/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
{name: "/foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
{name: "/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
{name: "@"},
}
for _, tt := range tests {
t.Run(tt.name+"_"+tt.opts.String(), func(t *testing.T) {
t.Parallel()
err := name.Validate(tt.name, tt.opts)
gitErr := repo.CheckRefFormat(t, tt.name, testgit.RefFormatOptions(tt.opts))
if (err == nil) != (gitErr == nil) {
t.Fatalf("Validate(%q, %+v) err=%v, git err=%v", tt.name, tt.opts, err, gitErr)
}
})
}
}
func TestSanitizeComponent(t *testing.T) {
t.Parallel()
tests := []struct {
component string
want string
}{
{component: ".", want: "-"},
{component: "..", want: "-"},
{component: "foo..bar", want: "foo.bar"},
{component: "foo.lock", want: "foo"},
{component: "foo.lock.lock", want: "foo"},
{component: "foo bar", want: "foo-bar"},
{component: "@", want: "-/@"},
{component: "a@{b", want: "a@-b"},
{component: "a*b", want: "a-b"},
}
for _, tt := range tests {
if got := name.SanitizeComponent(tt.component); got != tt.want {
t.Fatalf("SanitizeComponent(%q) = %q, want %q", tt.component, got, tt.want)
}
}
}
|