mirror of
https://github.com/di-sukharev/opencommit.git
synced 2026-01-13 07:38:01 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a0a384cbe | ||
|
|
a8839353f7 | ||
|
|
88006b8693 | ||
|
|
5d9d1c972a | ||
|
|
3892bd0e69 | ||
|
|
2b6cc5c360 | ||
|
|
c4c2600cf6 | ||
|
|
c361aaa914 | ||
|
|
f3d673185e | ||
|
|
5615bdce86 | ||
|
|
68b327bee7 |
@@ -13,7 +13,7 @@
|
||||
|
||||
## Examples
|
||||
|
||||
Look into [the commits](https://github.com/di-sukharev/opencommit/commit/eae7618d575ee8d2e9fff5de56da79d40c4bc5fc) to see how OpenCommit works. Emoji and long commit description text is configurable.
|
||||
All the commits in this repo are done with OpenCommit — look into [the commits](https://github.com/di-sukharev/opencommit/commit/eae7618d575ee8d2e9fff5de56da79d40c4bc5fc) to see how OpenCommit works. Emoji and long commit description text is configurable.
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
120
di.txt
120
di.txt
@@ -1,120 +0,0 @@
|
||||
diff --git a/src/generateCommitMessageFromGitDiff.ts b/src/generateCommitMessageFromGitDiff.ts
|
||||
index c3fb638..82b8bde 100644
|
||||
--- a/src/generateCommitMessageFromGitDiff.ts
|
||||
+++ b/src/generateCommitMessageFromGitDiff.ts
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
} from 'openai';
|
||||
import { api } from './api';
|
||||
import { getConfig } from './commands/config';
|
||||
+import { mergeStrings } from './utils/mergeStrings';
|
||||
|
||||
const config = getConfig();
|
||||
|
||||
@@ -88,37 +89,64 @@ export const generateCommitMessageWithChatCompletion = async (
|
||||
): Promise<string | GenerateCommitMessageError> => {
|
||||
try {
|
||||
if (diff.length >= MAX_REQ_TOKENS) {
|
||||
- const separator = 'diff --git ';
|
||||
-
|
||||
- const diffByFiles = diff.split(separator).slice(1);
|
||||
-
|
||||
- const commitMessagePromises = diffByFiles
|
||||
- .map((fileDiff) => {
|
||||
- // TODO: split by files
|
||||
- if (fileDiff.length >= MAX_REQ_TOKENS) return null;
|
||||
-
|
||||
- const messages = generateCommitMessageChatCompletionPrompt(
|
||||
- separator + fileDiff
|
||||
- );
|
||||
-
|
||||
- return api.generateCommitMessage(messages);
|
||||
- })
|
||||
- .filter(Boolean);
|
||||
+ const commitMessagePromises = getCommitMsgsPromisesFromFileDiffs(diff);
|
||||
|
||||
const commitMessages = await Promise.all(commitMessagePromises);
|
||||
|
||||
return commitMessages.join('\n\n');
|
||||
- }
|
||||
-
|
||||
- const messages = generateCommitMessageChatCompletionPrompt(diff);
|
||||
+ } else {
|
||||
+ const messages = generateCommitMessageChatCompletionPrompt(diff);
|
||||
|
||||
- const commitMessage = await api.generateCommitMessage(messages);
|
||||
+ const commitMessage = await api.generateCommitMessage(messages);
|
||||
|
||||
- if (!commitMessage)
|
||||
- return { error: GenerateCommitMessageErrorEnum.emptyMessage };
|
||||
+ if (!commitMessage)
|
||||
+ return { error: GenerateCommitMessageErrorEnum.emptyMessage };
|
||||
|
||||
- return commitMessage;
|
||||
+ return commitMessage;
|
||||
+ }
|
||||
} catch (error) {
|
||||
return { error: GenerateCommitMessageErrorEnum.internalError };
|
||||
}
|
||||
};
|
||||
+
|
||||
+function getMessagesPromisesByLines(fileDiff: string, separator: string) {
|
||||
+ const [fileHeader, ...fileDiffByLines] = fileDiff.split('@@');
|
||||
+ const lineDiffsWithHeader = fileDiffByLines.map((d) => fileHeader + '@@' + d);
|
||||
+
|
||||
+ const mergedLines = mergeStrings(lineDiffsWithHeader, MAX_REQ_TOKENS);
|
||||
+
|
||||
+ const commitMsgsFromFileLineDiffs = mergedLines.map((d) => {
|
||||
+ const messages = generateCommitMessageChatCompletionPrompt(separator + d);
|
||||
+
|
||||
+ return api.generateCommitMessage(messages);
|
||||
+ });
|
||||
+
|
||||
+ return commitMsgsFromFileLineDiffs;
|
||||
+}
|
||||
+
|
||||
+function getCommitMsgsPromisesFromFileDiffs(diff: string) {
|
||||
+ const separator = 'diff --git ';
|
||||
+
|
||||
+ const diffByFiles = diff.split(separator).slice(1);
|
||||
+
|
||||
+ const mergedDiffs = mergeStrings(diffByFiles, MAX_REQ_TOKENS);
|
||||
+
|
||||
+ const commitMessagePromises = [];
|
||||
+
|
||||
+ for (const fileDiff of mergedDiffs) {
|
||||
+ if (fileDiff.length >= MAX_REQ_TOKENS) {
|
||||
+ // split fileDiff into lineDiff
|
||||
+ const messagesPromises = getMessagesPromisesByLines(fileDiff, separator);
|
||||
+
|
||||
+ commitMessagePromises.push(...messagesPromises);
|
||||
+ } else {
|
||||
+ // generate commits for files
|
||||
+ const messages = generateCommitMessageChatCompletionPrompt(
|
||||
+ separator + fileDiff
|
||||
+ );
|
||||
+
|
||||
+ commitMessagePromises.push(api.generateCommitMessage(messages));
|
||||
+ }
|
||||
+ }
|
||||
+ return commitMessagePromises;
|
||||
+}
|
||||
diff --git a/src/utils/mergeStrings.ts b/src/utils/mergeStrings.ts
|
||||
new file mode 100644
|
||||
index 0000000..a8beb37
|
||||
--- /dev/null
|
||||
+++ b/src/utils/mergeStrings.ts
|
||||
@@ -0,0 +1,14 @@
|
||||
+export function mergeStrings(arr: string[], maxStringLength: number): string[] {
|
||||
+ const mergedArr: string[] = [];
|
||||
+ let currentItem: string = arr[0];
|
||||
+ for (const item of arr.slice(1)) {
|
||||
+ if (currentItem.length + item.length <= maxStringLength) {
|
||||
+ currentItem += item;
|
||||
+ } else {
|
||||
+ mergedArr.push(currentItem);
|
||||
+ currentItem = item;
|
||||
+ }
|
||||
+ }
|
||||
+ mergedArr.push(currentItem);
|
||||
+ return mergedArr;
|
||||
+}
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "open-commit",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "open-commit",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.6",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^0.6.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "opencommit",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.6",
|
||||
"description": "AI generates conventional commits with mind-blowing accuracy.",
|
||||
"keywords": [
|
||||
"git",
|
||||
|
||||
@@ -44,8 +44,20 @@ ${chalk.grey('——————————————————')}`
|
||||
});
|
||||
|
||||
if (isCommitConfirmedByUser && !isCancel(isCommitConfirmedByUser)) {
|
||||
await execa('git', ['commit', '-m', commitMessage]);
|
||||
const { stdout } = await execa('git', ['commit', '-m', commitMessage]);
|
||||
outro(`${chalk.green('✔')} successfully committed`);
|
||||
outro(stdout);
|
||||
const isPushConfirmedByUser = await confirm({
|
||||
message: 'Do you want to run `git push`?'
|
||||
});
|
||||
|
||||
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
|
||||
const pushSpinner = spinner();
|
||||
pushSpinner.start('Running `git push`');
|
||||
const { stdout } = await execa('git', ['push']);
|
||||
pushSpinner.stop(`${chalk.green('✔')} successfully pushed all commits`);
|
||||
outro(stdout);
|
||||
}
|
||||
} else outro(`${chalk.gray('✖')} process cancelled`);
|
||||
};
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ export const prepareCommitMessageHook = async () => {
|
||||
messageFilePath,
|
||||
commitMessage + '\n' + fileContent.toString()
|
||||
);
|
||||
|
||||
outro(`${chalk.green('✔')} commit done`);
|
||||
} catch (error) {
|
||||
outro(`${chalk.red('✖')} ${error}`);
|
||||
process.exit(1);
|
||||
|
||||
@@ -110,14 +110,20 @@ export const generateCommitMessageWithChatCompletion = async (
|
||||
};
|
||||
|
||||
function getMessagesPromisesByLines(fileDiff: string, separator: string) {
|
||||
const [fileHeader, ...fileDiffByLines] = fileDiff.split('\n@@');
|
||||
const lineDiffsWithHeader = fileDiffByLines.map(
|
||||
(d) => fileHeader + '\n@@' + d
|
||||
const lineSeparator = '\n@@';
|
||||
const [fileHeader, ...fileDiffByLines] = fileDiff.split(lineSeparator);
|
||||
|
||||
// merge multiple line-diffs into 1 to save tokens
|
||||
const mergedLines = mergeStrings(
|
||||
fileDiffByLines.map((line) => lineSeparator + line),
|
||||
MAX_REQ_TOKENS
|
||||
);
|
||||
|
||||
const mergedLines = mergeStrings(lineDiffsWithHeader, MAX_REQ_TOKENS);
|
||||
const lineDiffsWithHeader = mergedLines.map(
|
||||
(d) => fileHeader + lineSeparator + d
|
||||
);
|
||||
|
||||
const commitMsgsFromFileLineDiffs = mergedLines.map((d) => {
|
||||
const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map((d) => {
|
||||
const messages = generateCommitMessageChatCompletionPrompt(separator + d);
|
||||
|
||||
return api.generateCommitMessage(messages);
|
||||
@@ -131,18 +137,18 @@ function getCommitMsgsPromisesFromFileDiffs(diff: string) {
|
||||
|
||||
const diffByFiles = diff.split(separator).slice(1);
|
||||
|
||||
const mergedDiffs = mergeStrings(diffByFiles, MAX_REQ_TOKENS);
|
||||
// merge multiple files-diffs into 1 prompt to save tokens
|
||||
const mergedFilesDiffs = mergeStrings(diffByFiles, MAX_REQ_TOKENS);
|
||||
|
||||
const commitMessagePromises = [];
|
||||
|
||||
for (const fileDiff of mergedDiffs) {
|
||||
for (const fileDiff of mergedFilesDiffs) {
|
||||
if (fileDiff.length >= MAX_REQ_TOKENS) {
|
||||
// split fileDiff into lineDiff
|
||||
// if file-diff is bigger than gpt context — split fileDiff into lineDiff
|
||||
const messagesPromises = getMessagesPromisesByLines(fileDiff, separator);
|
||||
|
||||
commitMessagePromises.push(...messagesPromises);
|
||||
} else {
|
||||
// generate commits for files
|
||||
const messages = generateCommitMessageChatCompletionPrompt(
|
||||
separator + fileDiff
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user