Skip to content

Commit b241607

Browse files
Implemented the Git logic
1 parent 861c016 commit b241607

5 files changed

Lines changed: 124 additions & 19 deletions

File tree

src/git.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import * as ezSpawn from "ez-spawn";
2+
import { Options } from "./options";
3+
4+
type Params = Options & { files: string[]; newVersion: string };
5+
6+
/**
7+
* Commits the modififed files to Git, if the `commit` option is enabled.
8+
*
9+
* @returns - The commit message, or `false` if nothing was committed
10+
*/
11+
export async function gitCommit({ commit, files, newVersion }: Params): Promise<string | false> {
12+
if (!commit) {
13+
return false;
14+
}
15+
16+
let { all, noVerify, message } = commit;
17+
let args = [];
18+
19+
if (all) {
20+
// Commit ALL files, not just the ones that were bumped
21+
args.push("--all");
22+
}
23+
24+
if (noVerify) {
25+
// Bypass git commit hooks
26+
args.push("--no-verify");
27+
}
28+
29+
// Create the commit message
30+
message = formatVersionString(message, newVersion);
31+
args.push("--message", message);
32+
33+
// Append the file names last, as variadic arguments
34+
if (!all) {
35+
args = args.concat(files);
36+
}
37+
38+
await ezSpawn.async("git", ["commit", ...args]);
39+
return message;
40+
}
41+
42+
/**
43+
* Tags the Git commit, if the `tag` option is enabled.
44+
*
45+
* @returns - The tag name, or `false` if no tag was created
46+
*/
47+
export async function gitTag({ commit, tag, newVersion }: Params): Promise<string | false> {
48+
if (!commit || !tag) {
49+
return false;
50+
}
51+
52+
let args = [
53+
// Create an annotated tag, which is recommended for releases.
54+
// See https://git-scm.com/docs/git-tag
55+
"--annotate",
56+
57+
// Use the same commit message for the tag
58+
"--message", formatVersionString(commit.message, newVersion),
59+
];
60+
61+
// Create the Tag name
62+
let name = formatVersionString(tag.name, newVersion);
63+
args.push(name);
64+
65+
await ezSpawn.async("git", ["tag", ...args]);
66+
return name;
67+
}
68+
69+
/**
70+
* Pushes the Git commit and tag, if the `push` option is enabled.
71+
*/
72+
export async function gitPush({ push, tag }: Options): Promise<void> {
73+
if (!push) {
74+
return;
75+
}
76+
77+
// Push the commit
78+
await ezSpawn.async("git", "push");
79+
80+
if (tag) {
81+
// Push the tag
82+
await ezSpawn.async("git", ["push", "--tags"]);
83+
}
84+
}
85+
86+
/**
87+
* Accepts a version string template (e.g. "release v" or "This is the %s release").
88+
* If the template contains any "%s" placeholders, then they are replaced with the version number;
89+
* otherwise, the version number is appended to the string.
90+
*/
91+
function formatVersionString(template: string, newVersion: string): string {
92+
if (template.includes("%s")) {
93+
return template.replace(/%s/g, newVersion);
94+
}
95+
else {
96+
return template + newVersion;
97+
}
98+
}

src/options.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ export class Options {
1818
public preid!: string;
1919
public commit?: {
2020
message: string;
21+
noVerify: boolean;
22+
all: boolean;
2123
};
2224
public tag?: {
2325
name: string;
2426
};
2527
public push!: boolean;
26-
public all!: boolean;
27-
public noVerify!: boolean;
2828
public files!: string[];
2929
public cwd!: string;
3030
public interface!: Interface;
@@ -70,10 +70,10 @@ export class Options {
7070
// NOTE: This must come AFTER `tag` and `push`, because it relies on them
7171
let commit;
7272
if (typeof raw.commit === "string") {
73-
commit = { message: raw.commit };
73+
commit = { all, noVerify, message: raw.commit };
7474
}
7575
else if (raw.commit || tag || push) {
76-
commit = { message: "release v" };
76+
commit = { all, noVerify, message: "release v" };
7777
}
7878

7979
let files;
@@ -106,7 +106,7 @@ export class Options {
106106
}
107107

108108
return new Options({
109-
release, preid, commit, tag, push, all, noVerify, files, cwd, interface: ui
109+
release, preid, commit, tag, push, files, cwd, interface: ui
110110
});
111111
}
112112
}

src/update-files.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ type FileParams = Params & { name: string };
99
/**
1010
* Updates the version number in the specified files.
1111
*
12-
* @returns - The files that were actually modified
12+
* @returns - The relative paths of the files that were actually modified
1313
*/
1414
export async function updateFiles(params: Params): Promise<string[]> {
1515
let { files } = params;

src/version-bump-options.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,19 @@ export interface VersionBumpOptions {
2323

2424
/**
2525
* Indicates whether to create a git commit. Can be set to a custom commit message string
26-
* or `true` to use "release v" (the version number will be appended).
26+
* or `true` to use "release v". Any `%s` placeholders in the message string will be replaced
27+
* with the new version number. If the message string does _not_ contain any `%s` placeholders,
28+
* then the new version number will be appended to the message.
2729
*
2830
* Defaults to `false`.
2931
*/
3032
commit?: boolean | string;
3133

3234
/**
3335
* Indicates whether to tag the git commit. Can be set to a custom tag string
34-
* or `true` to use "v" (the version number will be appended).
36+
* or `true` to use "v". Any `%s` placeholders in the tag string will be replaced
37+
* with the new version number. If the tag string does _not_ contain any `%s` placeholders,
38+
* then the new version number will be appended to the tag.
3539
*
3640
* Defaults to `false`.
3741
*/
@@ -45,15 +49,15 @@ export interface VersionBumpOptions {
4549
push?: boolean;
4650

4751
/**
48-
* Indicates whether the git commit should include ALL files (`git commit -a`)
52+
* Indicates whether the git commit should include ALL files (`git commit --all`)
4953
* rather than just the files that were modified by `versionBump()`.
5054
*
5155
* Defaults to `false`.
5256
*/
5357
all?: boolean;
5458

5559
/**
56-
* Indicates whether to bypass git commit hooks (`git commit --noverify`).
60+
* Indicates whether to bypass git commit hooks (`git commit --no-verify`).
5761
*
5862
* Defaults to `false`.
5963
*/

src/version-bump.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getNewVersion } from "./get-new-version";
22
import { getOldVersion } from "./get-old-version";
3+
import { gitCommit, gitPush, gitTag } from "./git";
34
import { Options } from "./options";
45
import { updateFiles } from "./update-files";
56
import { VersionBumpOptions } from "./version-bump-options";
@@ -39,25 +40,27 @@ export async function versionBump(arg: VersionBumpOptions | string = {}): Promis
3940
arg = { release: arg };
4041
}
4142

43+
// Validate and normalize the options
4244
let options = await Options.normalize(arg);
45+
46+
// Get the old and new version numbers
4347
let oldVersion = await getOldVersion(options);
4448
let [newVersion, release] = await getNewVersion({ ...options, oldVersion });
45-
let files = await updateFiles({ ...options, oldVersion, newVersion });
4649

47-
if (options.commit) {
48-
options.commit.message += newVersion;
49-
}
50+
// Update the version number in all files
51+
let files = await updateFiles({ ...options, oldVersion, newVersion });
5052

51-
if (options.tag) {
52-
options.tag.name += newVersion;
53-
}
53+
// Git commit, tag, push (if enabled)
54+
let commit = await gitCommit({ ...options, files, newVersion });
55+
let tag = await gitTag({ ...options, newVersion });
56+
await gitPush(options);
5457

5558
return {
5659
release,
5760
oldVersion,
5861
newVersion,
59-
commit: options.commit ? options.commit.message : false,
60-
tag: options.tag ? options.tag.name : false,
62+
commit,
63+
tag,
6164
files,
6265
};
6366
}

0 commit comments

Comments
 (0)