/
GitBase.js
111 lines (91 loc) Β· 3.77 KB
/
GitBase.js
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
import { EOL } from 'node:os';
import { format, parseGitUrl } from '../util.js';
import Plugin from './Plugin.js';
const options = { write: false };
const changelogFallback = 'git log --pretty=format:"* %s (%h)"';
class GitBase extends Plugin {
async init() {
const remoteUrl = await this.getRemoteUrl();
await this.fetch(remoteUrl);
const branchName = await this.getBranchName();
const repo = parseGitUrl(remoteUrl);
this.setContext({ remoteUrl, branchName, repo });
this.config.setContext({ remoteUrl, branchName, repo });
const latestTag = await this.getLatestTagName();
const secondLatestTag = !this.config.isIncrement ? await this.getSecondLatestTagName(latestTag) : null;
const tagTemplate = this.options.tagName || ((latestTag || '').match(/^v/) ? 'v${version}' : '${version}');
this.config.setContext({ latestTag, secondLatestTag, tagTemplate });
}
getName() {
return this.getContext('repo.project');
}
getLatestVersion() {
const { tagTemplate, latestTag } = this.config.getContext();
const prefix = tagTemplate.replace(/\$\{version\}/, '');
return latestTag ? latestTag.replace(prefix, '').replace(/^v/, '') : null;
}
async getChangelog() {
const { latestTag, secondLatestTag } = this.config.getContext();
const context = { latestTag, from: latestTag, to: 'HEAD' };
const { changelog } = this.options;
if (!changelog) return null;
if (latestTag && !this.config.isIncrement) {
context.from = secondLatestTag;
context.to = `${latestTag}^1`;
}
if (!context.from && changelog.includes('${from}')) {
return this.exec(changelogFallback);
}
return this.exec(changelog, { context, options });
}
bump(version) {
const { tagTemplate } = this.config.getContext();
const context = Object.assign(this.config.getContext(), { version });
const tagName = format(tagTemplate, context) || version;
this.setContext({ version });
this.config.setContext({ tagName });
}
isRemoteName(remoteUrlOrName) {
return remoteUrlOrName && !remoteUrlOrName.includes('/');
}
async getRemoteUrl() {
const remoteNameOrUrl = this.options.pushRepo || (await this.getRemote()) || 'origin';
return this.isRemoteName(remoteNameOrUrl)
? this.exec(`git remote get-url ${remoteNameOrUrl}`, { options }).catch(() =>
this.exec(`git config --get remote.${remoteNameOrUrl}.url`, { options }).catch(() => null)
)
: remoteNameOrUrl;
}
async getRemote() {
const branchName = await this.getBranchName();
return branchName ? await this.getRemoteForBranch(branchName) : null;
}
getBranchName() {
return this.exec('git rev-parse --abbrev-ref HEAD', { options }).catch(() => null);
}
getRemoteForBranch(branch) {
return this.exec(`git config --get branch.${branch}.remote`, { options }).catch(() => null);
}
fetch(remoteUrl) {
return this.exec('git fetch').catch(err => {
this.debug(err);
throw new Error(`Unable to fetch from ${remoteUrl}${EOL}${err.message}`);
});
}
getLatestTagName() {
const context = Object.assign({}, this.config.getContext(), { version: '*' });
const match = format(this.options.tagMatch || this.options.tagName || '${version}', context);
const exclude = this.options.tagExclude ? `--exclude=${format(this.options.tagExclude, context)}` : '';
return this.exec(`git describe --tags --match=${match} --abbrev=0 ${exclude}`, { options }).then(
stdout => stdout || null,
() => null
);
}
async getSecondLatestTagName(latestTag) {
const sha = await this.exec(`git rev-list ${latestTag || '--skip=1'} --tags --max-count=1`, {
options
});
return this.exec(`git describe --tags --abbrev=0 "${sha}^"`, { options }).catch(() => null);
}
}
export default GitBase;