-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
branch-name.ts
118 lines (102 loc) · 3.86 KB
/
branch-name.ts
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
// TODO #7154
import cleanGitRef from 'clean-git-ref';
import slugify from 'slugify';
import type { RenovateConfig } from '../../../config/types';
import { logger } from '../../../logger';
import { hash } from '../../../util/hash';
import { regEx } from '../../../util/regex';
import * as template from '../../../util/template';
const MIN_HASH_LENGTH = 6;
const RE_MULTIPLE_DASH = regEx(/--+/g);
const RE_SPECIAL_CHARS_STRICT = regEx(/[`~!@#$%^&*()_=+[\]\\|{};':",.<>?]/g);
/**
* Clean git branch name
*
* Remove what clean-git-ref fails to:
* - leading dot/leading dot after slash
* - trailing dot
* - whitespace
* - special characters
* - leading or trailing dashes
* - chained dashes(breaks markdown comments) are replaced by single dash
*/
function cleanBranchName(
branchName: string,
branchNameStrict?: boolean
): string {
let cleanedBranchName = branchName;
if (branchNameStrict) {
cleanedBranchName = cleanedBranchName.replace(RE_SPECIAL_CHARS_STRICT, '-'); // massage out all special characters that slip through slugify
}
return cleanGitRef
.clean(cleanedBranchName)
.replace(regEx(/^\.|\.$/), '') // leading or trailing dot
.replace(regEx(/\/\./g), '/') // leading dot after slash
.replace(regEx(/\s/g), '') // whitespace
.replace(regEx(/[[\]?:\\^~]/g), '-') // massage out all these characters: [ ] ? : \ ^ ~
.replace(regEx(/(^|\/)-+/g), '$1') // leading dashes
.replace(regEx(/-+(\/|$)/g), '$1') // trailing dashes
.replace(RE_MULTIPLE_DASH, '-'); // chained dashes
}
export function generateBranchName(update: RenovateConfig): void {
// Check whether to use a group name
if (update.groupName) {
logger.trace('Using group branchName template');
// TODO: types (#7154)
logger.trace(
`Dependency ${update.depName!} is part of group ${update.groupName}`
);
update.groupSlug = slugify(update.groupSlug ?? update.groupName, {
lower: true,
});
if (update.updateType === 'major' && update.separateMajorMinor) {
if (update.separateMultipleMajor) {
const newMajor = String(update.newMajor);
update.groupSlug = `major-${newMajor}-${update.groupSlug}`;
} else {
update.groupSlug = `major-${update.groupSlug}`;
}
}
if (update.updateType === 'patch' && update.separateMinorPatch) {
update.groupSlug = `patch-${update.groupSlug}`;
}
update.branchTopic = update.group!.branchTopic ?? update.branchTopic;
update.branchName = update.group!.branchName ?? update.branchName;
}
if (update.hashedBranchLength) {
let hashLength = update.hashedBranchLength - update.branchPrefix!.length;
if (hashLength < MIN_HASH_LENGTH) {
logger.warn(
`\`hashedBranchLength\` must allow for at least ${MIN_HASH_LENGTH} characters hashing in addition to \`branchPrefix\`. Using ${MIN_HASH_LENGTH} character hash instead.`
);
hashLength = MIN_HASH_LENGTH;
}
const additionalBranchPrefix = template.compile(
String(update.additionalBranchPrefix ?? ''),
update
);
const branchTopic = template.compile(
String(update.branchTopic ?? ''),
update
);
let hashInput = additionalBranchPrefix + branchTopic;
// Compile extra times in case of nested templates
hashInput = template.compile(hashInput, update);
hashInput = template.compile(hashInput, update);
const hashedInput = hash(hashInput);
// TODO: types (#7154)
update.branchName = `${update.branchPrefix!}${hashedInput.slice(
0,
hashLength
)}`;
} else {
update.branchName = template.compile(update.branchName!, update);
// Compile extra times in case of nested templates
update.branchName = template.compile(update.branchName, update);
update.branchName = template.compile(update.branchName, update);
}
update.branchName = cleanBranchName(
update.branchName,
update.branchNameStrict
);
}