-
Notifications
You must be signed in to change notification settings - Fork 498
Expand file tree
/
Copy pathRefName.cs
More file actions
84 lines (69 loc) · 2.72 KB
/
Copy pathRefName.cs
File metadata and controls
84 lines (69 loc) · 2.72 KB
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
using System;
namespace SourceGit.Models
{
/// <summary>
/// Validates branch and tag names using the same rules that git itself enforces,
/// mirroring `git check-ref-format --allow-onelevel`. Rules are taken from the git-check-ref-format documentation.
/// Rule 2 (a refname must contain at least one slash) is intentionally waived, matching `--allow-onelevel`.
/// </summary>
public static class RefName
{
public static bool IsValidBranchName(string name)
{
if (string.Equals(name, "HEAD", StringComparison.Ordinal))
return false;
return IsValidRefName(name);
}
public static bool IsValidTagName(string name) => IsValidRefName(name);
private static bool IsValidRefName(string name)
{
if (string.IsNullOrEmpty(name))
return false;
// Anything starting with '-' is treated as a CLI option.
if (name.StartsWith('-'))
return false;
// Rule 9: cannot be the single character '@'.
if (name.Equals("@", StringComparison.Ordinal))
return false;
// Rule 6: cannot begin or end with '/', or contain consecutive slashes.
if (name[0] == '/' || name[^1] == '/' || name.Contains("//", StringComparison.Ordinal))
return false;
// Rule 7: cannot end with a dot.
if (name[^1] == '.')
return false;
// Rule 3: cannot contain two consecutive dots.
if (name.Contains("..", StringComparison.Ordinal))
return false;
// Rule 8: cannot contain the sequence '@{'.
if (name.Contains("@{", StringComparison.Ordinal))
return false;
// Rules 4, 5 & 10: no control chars, DEL, space, or ~ ^ : ? * [ \.
foreach (var ch in name)
{
if (ch is < ' ' or '\x7f')
return false;
switch (ch)
{
case ' ':
case '~':
case '^':
case ':':
case '?':
case '*':
case '[':
case '\\':
return false;
}
}
// Rule 1: no slash-separated component may begin with a dot or end with ".lock".
foreach (var component in name.Split('/'))
{
if (component[0] == '.')
return false;
if (component.EndsWith(".lock", StringComparison.Ordinal))
return false;
}
return true;
}
}
}