Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
fdbced0453
|
|||
| e8160a6f33 | |||
| a576725506 | |||
|
1bce93a24e
|
|||
| f767b846d8 | |||
| 0cac22a7e0 |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,9 +1,20 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
Generation of this changelog is based on commits
|
Generation of this changelog is based on commits
|
||||||
|
## v1.15.0
|
||||||
|
### Features
|
||||||
|
- [e8160a6f3] - **commands**: trim body, footer (#24)
|
||||||
|
- [a57672550] - **commands**: open default editor upon footer/body writing (#24)
|
||||||
|
## v1.14.0
|
||||||
|
### Features
|
||||||
|
- [f767b846d] - **commands**: add ability to choose files to stage (#22)
|
||||||
|
### Miscellaneous
|
||||||
|
- [1bce93a24] - **release**: v1.14.0
|
||||||
|
- [0cac22a7e] - **changelog**: improve generation time by ~2800 times (#23)
|
||||||
## v1.13.1
|
## v1.13.1
|
||||||
### Fixes
|
### Fixes
|
||||||
- [87edf8cfa] - **changelog**: wrong semver sequence generation (#21)
|
- [87edf8cfa] - **changelog**: wrong semver sequence generation (#21)
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
- [6df102156] - **release**: v1.13.1
|
||||||
- [47a8b0585] - **commands**: change head error message
|
- [47a8b0585] - **commands**: change head error message
|
||||||
- [b6d749bea] - fix version regex to include pre-releases
|
- [b6d749bea] - fix version regex to include pre-releases
|
||||||
## v1.13.0
|
## v1.13.0
|
||||||
@@ -115,13 +126,13 @@ Generation of this changelog is based on commits
|
|||||||
- [2670f79e2] - Merge pull request 'Release v1.3.0' (#5) from develop into main
|
- [2670f79e2] - Merge pull request 'Release v1.3.0' (#5) from develop into main
|
||||||
- [3afc2ed07] - Merge branch 'main' into develop
|
- [3afc2ed07] - Merge branch 'main' into develop
|
||||||
- [45458d14e] - **changelog**: generate for v1.3.0
|
- [45458d14e] - **changelog**: generate for v1.3.0
|
||||||
- [d61c9ecf2] - Merge pull request 'Make commit signing possible' (#3) from develop into main
|
|
||||||
## v1.3.0
|
## v1.3.0
|
||||||
### Features
|
### Features
|
||||||
- [755da3bb5] - **commands**: add ability to write a footer
|
- [755da3bb5] - **commands**: add ability to write a footer
|
||||||
- [9311be80b] - **commands**: add commit message validation command (#4)
|
- [9311be80b] - **commands**: add commit message validation command (#4)
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
- [f3c55fac3] - **release**: v1.3.0
|
- [f3c55fac3] - **release**: v1.3.0
|
||||||
|
- [d61c9ecf2] - Merge pull request 'Make commit signing possible' (#3) from develop into main
|
||||||
- [8816db86f] - **changelog**: generate
|
- [8816db86f] - **changelog**: generate
|
||||||
## v1.2.0
|
## v1.2.0
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@resultium/rcz",
|
"name": "@resultium/rcz",
|
||||||
"version": "1.13.1",
|
"version": "1.15.0",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"description": "Resultium commit standardization library, inspired by conventional commits",
|
"description": "Resultium commit standardization library, inspired by conventional commits",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@@ -51,63 +51,34 @@ const command = new Command("changelog")
|
|||||||
|
|
||||||
for (const commit of commits) {
|
for (const commit of commits) {
|
||||||
const tag =
|
const tag =
|
||||||
sort((await simpleGit().tags([`--contains=${commit.hash}`])).all)[0]! ||
|
(commit.refs.match(/tag: (\S+)(?:,|$)/)?.[1] ?? lastTag) || unreleased;
|
||||||
unreleased;
|
|
||||||
|
|
||||||
const currentCommitStack = parsedCommitStacks.find(
|
let currentCommitStackIndex = parsedCommitStacks.findIndex(
|
||||||
(commitStack) => commitStack.version === tag,
|
(commitStack) => commitStack.version === tag,
|
||||||
) || {
|
);
|
||||||
|
|
||||||
|
if (currentCommitStackIndex === -1) {
|
||||||
|
parsedCommitStacks.push({
|
||||||
version: tag || unreleased,
|
version: tag || unreleased,
|
||||||
breaking: [],
|
breaking: [],
|
||||||
features: [],
|
features: [],
|
||||||
fixes: [],
|
fixes: [],
|
||||||
miscellaneous: [],
|
miscellaneous: [],
|
||||||
};
|
});
|
||||||
|
|
||||||
if (lastTag !== tag) {
|
currentCommitStackIndex = parsedCommitStacks.findIndex(
|
||||||
parsedCommitStacks = [currentCommitStack, ...parsedCommitStacks];
|
(commitStack) => commitStack.version === tag,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commit.message.includes("!:")) {
|
if (commit.message.includes("!:")) {
|
||||||
parsedCommitStacks = [
|
parsedCommitStacks[currentCommitStackIndex].breaking.push(commit);
|
||||||
{
|
|
||||||
...currentCommitStack,
|
|
||||||
breaking: [...currentCommitStack.breaking, commit],
|
|
||||||
},
|
|
||||||
...parsedCommitStacks.filter(
|
|
||||||
(commitStack) => commitStack.version !== tag,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
} else if (commit.message.startsWith("feat")) {
|
} else if (commit.message.startsWith("feat")) {
|
||||||
parsedCommitStacks = [
|
parsedCommitStacks[currentCommitStackIndex].features.push(commit);
|
||||||
{
|
|
||||||
...currentCommitStack,
|
|
||||||
features: [...currentCommitStack.features, commit],
|
|
||||||
},
|
|
||||||
...parsedCommitStacks.filter(
|
|
||||||
(commitStack) => commitStack.version !== tag,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
} else if (commit.message.startsWith("fix")) {
|
} else if (commit.message.startsWith("fix")) {
|
||||||
parsedCommitStacks = [
|
parsedCommitStacks[currentCommitStackIndex].fixes.push(commit);
|
||||||
{
|
|
||||||
...currentCommitStack,
|
|
||||||
fixes: [...currentCommitStack.fixes, commit],
|
|
||||||
},
|
|
||||||
...parsedCommitStacks.filter(
|
|
||||||
(commitStack) => commitStack.version !== tag,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
} else {
|
} else {
|
||||||
parsedCommitStacks = [
|
parsedCommitStacks[currentCommitStackIndex].miscellaneous.push(commit);
|
||||||
{
|
|
||||||
...currentCommitStack,
|
|
||||||
miscellaneous: [...currentCommitStack.miscellaneous, commit],
|
|
||||||
},
|
|
||||||
...parsedCommitStacks.filter(
|
|
||||||
(commitStack) => commitStack.version !== tag,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTag = tag;
|
lastTag = tag;
|
||||||
|
|||||||
@@ -18,12 +18,17 @@ along with RCZ. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command } from "commander";
|
import { Command } from "commander";
|
||||||
import { checkForUpdates, getConfig } from "../utils/functions";
|
import {
|
||||||
|
checkForUpdates,
|
||||||
|
getConfig,
|
||||||
|
getDefaultEditor,
|
||||||
|
} from "../utils/functions";
|
||||||
import {
|
import {
|
||||||
cancel,
|
cancel,
|
||||||
confirm,
|
confirm,
|
||||||
intro,
|
intro,
|
||||||
isCancel,
|
isCancel,
|
||||||
|
multiselect,
|
||||||
note,
|
note,
|
||||||
outro,
|
outro,
|
||||||
select,
|
select,
|
||||||
@@ -31,7 +36,33 @@ import {
|
|||||||
} from "@clack/prompts";
|
} from "@clack/prompts";
|
||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import simpleGit from "simple-git";
|
import simpleGit, { ResetMode } from "simple-git";
|
||||||
|
import { readFile, writeFile } from "fs/promises";
|
||||||
|
import { tmpdir } from "os";
|
||||||
|
import { spawn } from "child_process";
|
||||||
|
|
||||||
|
const getEditorInput = async (defaultValue = "") => {
|
||||||
|
const tempFilePath = join(tmpdir(), `io.resultium.rcz-${Date.now()}.txt`);
|
||||||
|
await writeFile(tempFilePath, defaultValue);
|
||||||
|
|
||||||
|
const editor = spawn(getDefaultEditor(), [tempFilePath], {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
return await new Promise<string>((resolve) => {
|
||||||
|
editor.on("exit", async (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
throw new Error(`Editor exited with code ${code}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve((await readFile(tempFilePath)).toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.on("error", (err) => {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const command = new Command("commit")
|
const command = new Command("commit")
|
||||||
.alias("c")
|
.alias("c")
|
||||||
@@ -69,6 +100,37 @@ const command = new Command("commit")
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const stageableFiles = (await simpleGit().status()).files;
|
||||||
|
if (stageAll === false) {
|
||||||
|
const stagedFiles = (await simpleGit().diff(["--name-only", "--cached"]))
|
||||||
|
.split("\n")
|
||||||
|
.filter((file) => file);
|
||||||
|
|
||||||
|
const filesToStage = await multiselect({
|
||||||
|
message: "Which files would you like to stash?",
|
||||||
|
options: stageableFiles.map((file) => ({
|
||||||
|
value: file.path,
|
||||||
|
label: file.path,
|
||||||
|
hint: file.from,
|
||||||
|
})),
|
||||||
|
initialValues: stagedFiles,
|
||||||
|
required: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isCancel(filesToStage)) {
|
||||||
|
cancel("Commit creation cancelled");
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
await simpleGit().reset(ResetMode.MIXED);
|
||||||
|
await simpleGit().add(filesToStage);
|
||||||
|
} else if (stageAll === true) {
|
||||||
|
note(
|
||||||
|
stageableFiles.map((file) => file.path).join("\n"),
|
||||||
|
"Committing following files",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const changedLines = (
|
const changedLines = (
|
||||||
(
|
(
|
||||||
@@ -192,27 +254,60 @@ const command = new Command("commit")
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = await text({
|
let body: null | string = null;
|
||||||
message: `Insert a commit body (motivation or elaboration for the change), can be left empty`,
|
const writeBody = await confirm({
|
||||||
placeholder:
|
message: `Would you like to insert a commit body (elaboration for the change)?`,
|
||||||
"improves regex for suspicious character check in router requests",
|
initialValue: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isCancel(body)) {
|
if (isCancel(writeBody)) {
|
||||||
cancel("Commit creation cancelled");
|
cancel("Commit creation cancelled");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const footer = await text({
|
if (writeBody) {
|
||||||
message: `Insert commit footer, can be left empty, e.g. Acked-by: @johndoe`,
|
// Stop clack input
|
||||||
placeholder: "Acked-by: @security",
|
process.stdin.pause();
|
||||||
|
|
||||||
|
body = (
|
||||||
|
await getEditorInput(
|
||||||
|
`e.g.
|
||||||
|
* Revert "Guard against SMTP smuggling", commit faf23f1, by restoring the setting to its default.
|
||||||
|
* Revert "[security] SMTP smuggling: update short term fix (#2346)", commmit e931e10, by restoring the setting to its default.
|
||||||
|
* Set smtpd_forbid_bare_newline=normalize.
|
||||||
|
|
||||||
|
Fixes #444
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
).trim();
|
||||||
|
|
||||||
|
// Resume clack input
|
||||||
|
process.stdin.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
let footer: null | string = null;
|
||||||
|
const writeFooter = await confirm({
|
||||||
|
message: `Would you like to insert a commit footer?`,
|
||||||
|
initialValue: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isCancel(footer)) {
|
if (isCancel(writeFooter)) {
|
||||||
cancel("Commit creation cancelled");
|
cancel("Commit creation cancelled");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (writeFooter) {
|
||||||
|
process.stdin.pause();
|
||||||
|
footer = (
|
||||||
|
await getEditorInput(
|
||||||
|
`e.g.
|
||||||
|
Co-authored-by: @john
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
).trim();
|
||||||
|
process.stdin.resume();
|
||||||
|
}
|
||||||
|
|
||||||
const isBreaking = await confirm({
|
const isBreaking = await confirm({
|
||||||
message: "Does this commit have breaking changes?",
|
message: "Does this commit have breaking changes?",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import { join } from "path";
|
|||||||
program
|
program
|
||||||
.name("rcz")
|
.name("rcz")
|
||||||
.description("Resultium commit standardization command-line interface")
|
.description("Resultium commit standardization command-line interface")
|
||||||
.version("1.13.1");
|
.version("1.15.0");
|
||||||
|
|
||||||
const commandFiles = await readdir(join(__dirname, "commands"));
|
const commandFiles = await readdir(join(__dirname, "commands"));
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { join } from "path";
|
|||||||
import { cwd } from "process";
|
import { cwd } from "process";
|
||||||
import { Config } from "../types";
|
import { Config } from "../types";
|
||||||
import { request } from "http";
|
import { request } from "http";
|
||||||
import { tmpdir } from "os";
|
import { platform, tmpdir } from "os";
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
import { gt } from "semver";
|
import { gt } from "semver";
|
||||||
import { note } from "@clack/prompts";
|
import { note } from "@clack/prompts";
|
||||||
@@ -110,3 +110,20 @@ export const checkForUpdates = async () => {
|
|||||||
if (gt(cachedVersion, localVersion)) note(updateText);
|
if (gt(cachedVersion, localVersion)) note(updateText);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDefaultEditor = () => {
|
||||||
|
if (process.env.EDITOR) {
|
||||||
|
return process.env.EDITOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.VISUAL) {
|
||||||
|
return process.env.VISUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows as always being the special kid
|
||||||
|
if (platform() === "win32") {
|
||||||
|
return "notepad";
|
||||||
|
} else {
|
||||||
|
return "vi";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user